2. C言語 - MFC - ウィンドウの表示更新

 
2.1 概要
2.2 コーディング

2.1 概要

 タイトルだけだと非常にわかりにくいのですが・・・。  MFC でウィンドウを作成しておいて、ボタンのアクションでループ処理を行うとき。  特にループの時間が長いと、OS から「応答なし」とか言われて、どうしようもなくなることがあります。  ウィンドウにメッセージを出してそれを更新するつもりで、メッセージの中身を更新しても表示が変わらないので焦ることになります。  ひとつの答えは、ループ処理をスレッド化して、AfxBeginThread でスレッドを起動し、通常のイベントを受け入れられるようにするというやり方(うまい説明になっていないなぁ)があります。  だがしかし、スレッドの制御をいれるのはコーディング上いささか面倒なのです。  そこで、Visual Baisic の DoEvent のような処理をいれることで、もっとお手軽に表示更新が行えます。  あくまでスレッドの処理を行う方が、本線でこれは簡単なツールを時間をかけずに作成するときにつかうものです。

2.2 コーディング

 わたしは、ほとんどダイアログベースの画面しか使わないので、ダイアログベースで・・・。  仮に、ダイアログのクラスが testDlg としますわな。  testDlg.h の中で、下記のようなメソッドを定義しておきます。

public:
	void DoEvents();
 testDlg.cpp の中で、下記のように実装します。

void testDlg::DoEvents()
{
    MSG msg;
    while(::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
    {
        if (!AfxGetApp()->PumpMessage())
        return;
    }
}
 ボタン押下時のループの中で

void testDlg::OnBnClickedX()
{
	while (条件)
	{
		なにがしかの処理

		画面のテキストなりリストなりを更新する処理

		this->DoEvents();
	}
}
 てな感じで、コーディングしておけば、ループ一回につき、一度、画面が更新されます。  もちろん、処理は画面更新の前でも後でもよいし、何かある都度、更新と DoEvents の呼び出しをやれば画面は更新されていきます。  呼び出し先の関数やクラスに、自身の this オブジェクトを渡せば、その先で画面の更新を行うこともできます。