くだらない質問かもしれませんが、ウィンドウプロシージャへメッセージを転送する場
合は、WinMainで、
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
といったようにメッセージループを行いますよね。
そうではなく、ダイアログ内で、アップダウンコントロールを動かすことでエディット
ボックスの数値を動かすという単純な処理をする場合、WinMainの中でメッセージループ
を行わないでも動いているのですが、これはなぜですか?
たとえば、
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR lpsCmdLine, int nCmdShow)
{
DialogBox(hThisInst,MAINDLG, NULL, (DLGPROC)MainDlgProc);
return 0;
}
/** メインダイアログ関数 **/
LRESULT CALLBACK MainDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wP,LPARAM lP)
{
switch (uMsg) {
case:・・・
switch (LOWORD(wP)){
case IDCANCEL:
EndDialog(hwndDlg,FALSE);
return TRUE;
}
break;
}
return FALSE;
}
DialogBox 関数が作るダイアログボックスは「モーダル・ダイアログ」と呼ばれます
が、こいつは「モーダル・ループ」と言われるメッセージループを内部に持っているか
らです。
ごめんなさい。途中だったのに投稿してしまいました。
『たとえば』から下を訂正です。
************************************************************
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,LPSTR lpsCmdLine,
int nCmdShow)
{
DialogBox(hThisInst,MAINDLG, NULL, (DLGPROC)MainDlgProc);
return 0;
}
/** メインダイアログ関数 **/
LRESULT CALLBACK MainDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wP,LPARAM lP)
{
switch (uMsg) {
case:・・・何らかの処理・・・
・・・・・
case: WM_COMMAND
switch (LOWORD(wP)){
case IDCANCEL:
EndDialog(hwndDlg,FALSE);
return TRUE;
}
break;
}
return FALSE;
}
としたときに、どういったしくみでダイアログの表示を更新したりしているのでしょう
か。
WinMainではDialogBoxを一度だけ呼び出していますよね。DialogBoxはEndDialogを呼び
出さない限りはWinMainはそこから先はとまった状態になると聞きました。
ダイアログボックスに対して、ボタンを押したり、数値を書き込んだりといった処理
(イベントが起こる?)をする度にに、おそらくMainDlgProcが呼び出されているんです
よね?それにはウィンドウプロシージャには必要だったのに、ダイアログにはメッセー
ジループは必要ないのでしょうか?もしくはDialogBoxがそういう仕様になっているので
すか?
混乱していてよくわかりません^^;
分かりにくい質問かもしれませんが、そこはご指摘ください。
開発環境 Visal C++ 6 SDK
OS WinXP
シャノンさんの書き込みにあるとおり、
Windowsはモーダルダイアログを表示している間は、
メッセージループ(GetMessage)を独自に回し、
ダイアログ用ウィンドウプロシージャを呼び出しています。
このダイアログ用のメッセージループ処理と
ウィンドウプロシージャは、通常プログラマが
意識する必要はないので外には見えません。
で、そのダイアログウィンドウプロシージャは
ウィンドウメッセージを受け取ると、
その内容をダイアログ用に変換して
ダイアログプロシージャを呼び出しています。
そして、ダイアログプロシージャ内でEndDialogを呼び出すと、
ダイアログのウィンドウプロシージャはWM_CLOSEを生成して
ウィンドウのクローズ処理を行なうことになります。
箇条書きにすると以下のようなイメージになりますでしょうか?
○ DialogBoxを呼び出す。
(1) ダイアログウィンドウを生成する。
(2) ダイアログ用ウィンドウプロシージャを関連付ける。
(3) ダイアログ用メッセージループを開始する。
(4) Windowsがダイアログウィンドウにメッセージを送る。
(5) ダイアログ用ウィンドウプロシージャがそれを受け取る。
(6) 受け取ったメッセージに対応した
ダイアログプロシージャ用メッセージを作成する。
(ダイアログウィンドウのWM_CREATEメッセージ
→ WM_INITDIALOGメッセージ
ボタンウィンドウのマウスクリック
→ WM_COMMANDメッセージ etc...)
(7) ダイアログプロシージャを呼び出す。
○ EndDialogを呼び出す
(1) ダイアログ用ウィンドウに対してWM_CLOSEを送る。
(2) ダイアログウィンドウを破棄する。
(3) ダイアログ用メッセージループを終了する。
(4) 親ウィンドウに対してフォーカスを設定する。
シャノンさん謎の怪鳥さん、ありがとうございます。
返事遅れてしまいました。
なるほど納得しました^^