呼び出したら、OKやキャンセルボタンを押すまで処理が返ってこないウィンドウをモーダルダイアログと言う。
プロジェクトを右クリック→[追加]→[リソース...]を選択し、リソースの種類(T)で[Dialog]を選択し、[新規作成]ボタンを押すことでリソースを追加する。
#include "resource.h" //IDD_DIALOG1の定義が入っている
ダイアログプロシージャは普通のウィンドウプロシージャと似ているが、戻り値がINT_PTRとなっている。
この関数では、メッセージを処理した場合はTRUEを、処理しなかった場合はFALSEを返す必要がある。
注意:DefWindowProcで返してはならない。挙動がおかしくなる。
また、モーダルダイアログ呼出中は呼出元は停止しているので、この関数のどこかでEndDialogをしてダイアログを終了しなければならない。
INT_PTR CALLBACK DlgWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ INT_PTR ret = FALSE; switch (msg) { case WM_COMMAND: switch(wp){ case IDOK: EndDialog( hWnd , (INT_PTR)IDOK ); ret = TRUE; break; case IDCANCEL: EndDialog( hWnd , (INT_PTR)IDCANCEL ); ret =TRUE; break; } break; case WM_CLOSE: EndDialog( hWnd , (INT_PTR)WM_CLOSE ); ret =TRUE; break; } return ret; }
DialogBox関数:https://msdn.microsoft.com/ja-jp/library/cc410759.aspx
第二引数は「ダイアログボックステンプレートの名前(文字列)」か「リソース識別子(数値)」を渡す。後者の場合、MAKEINTRESOURCEで変換する。
第三引数はダイアログを呼び出す親ウィンドウのハンドル(HWND)を渡す。この例では親ウィンドウを作っていないのでNULLを渡す。
INT_PTR d = DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),nullptr,(DLGPROC)DlgWndProc );
DialogBox関数の戻り値は、EndDialog関数の第二引数である。INT_PTRにキャストして正常に返せるのならどんな値でもいいが、用途としてはどのボタンで閉じられたかが思いつく。あるいはダイアログ側で設定したデータを収めた構造体のインスタンスへのポインタなどが良いかもしれない。
switch(d){ case IDOK: MessageBox(nullptr,_T("IDOK"),0,0); break; case IDCANCEL: MessageBox(nullptr,_T("IDCANCEL"),0,0); break; case WM_CLOSE: MessageBox(nullptr,_T("WM_CLOSE"),0,0); break; } PostQuitMessage(0);
#include <Windows.h> #include "resource.h" //IDD_DIALOG1の定義が入っている #include <tchar.h> //ウィンドウプロシージャ INT_PTR CALLBACK DlgWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { INT_PTR ret = FALSE; switch (msg) { case WM_COMMAND://ボタンが押された場合、WM_COMMANDのwParamにボタンのIDが入っている switch (wp) { case IDOK://IDOK(値1),IDCANCEL(値2)は初めから定義されている(WinUser.h) EndDialog(hWnd, (INT_PTR)IDOK); ret = TRUE; break; case IDCANCEL: EndDialog(hWnd, (INT_PTR)IDCANCEL);//ダイアログを閉じる。IDOK,IDCANCELはそれぞれ1と2なので、INT_PTRへキャストできる ret = TRUE; break; } break; case WM_CLOSE: EndDialog(hWnd, (INT_PTR)WM_CLOSE); ret = TRUE;//このメッセージを処理したのでTRUEを返す break; } return ret; } //エントリーポイント int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { //ダイアログ表示 INT_PTR d = DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), nullptr, (DLGPROC)DlgWndProc); switch (d) { //ダイアログの戻り値の確認 case IDOK: MessageBox(nullptr, _T("IDOK"), 0, 0); break; case IDCANCEL: MessageBox(nullptr, _T("IDCANCEL"), 0, 0); break; case WM_CLOSE: MessageBox(nullptr, _T("WM_CLOSE"), 0, 0); break; } PostQuitMessage(0); return 0; }