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