MFCの基礎 - プログラムの終了
概要
Windows APIにおけるプログラムの終了処理の流れを記載する。
ここでは、プログラムをメニュー([ファイル] - [終了])から終了する方法を記載する。
ウィンドウの破棄とプログラムの終了
[ファイル] - [終了]を選択した時のイベントハンドラで、SendMessage関数を使用してメインウィンドウにWM_CLOSEを発行する。
ここで、SendMessage関数のプロトタイプ宣言は以下の通りである。
<syntaxhighlight lang="c++"> LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); </source>
hWndで指定したウィンドウに、メッセージMsgを送る。メッセージに付随するデータがある場合は、wParamおよびlParamに設定する。
ここでは、WM_CLOSEを発行しているが、WM_CLOSEの場合は、wParamおよびlParamは特に使用しないので0を指定する。
サンプルコードでは、WM_CLOSEのイベントハンドラでは、MessageBox関数でメッセージを表示している。
"Are you sure you want to quit thie program?"メッセージにおいて、[はい]ボタンを押下した場合、MessageBox関数は[IDYES]を返す。
ウィンドウを破棄するためには、DestroyWindow関数を使用する。
<syntaxhighlight lang="c++"> BOOL DestroyWindow(HWND hWnd); </source>
DestroyWindow関数は、hWndで指定したウィンドウに、WM_DESTROYを発行してそれを破棄する。
メニューのイベントハンドラで終了の確認を行わない理由は、
[閉じる]ボタンが押下されて終了処理を行う場合、自動的にWM_CLOSEがウィンドウに発行されるからである。
このため、メニューのイベントハンドラでは、WM_CLOSEを発行するだけにして、WM_CLOSEのイベントハンドラでウィンドウの破棄を行う。
WM_DESTROYのイベントハンドラでは、PostQuitMessage関数を使用して、WM_QUITをメッセージキューにポストする。
また、PostQuitMessage関数の引数として、プログラムの終了コードを渡すことができる。ここで渡した値は、WM_QUITのwParam値となる。
WM_QUITを受け取るとGetMessage関数がFALSEとなるため、メッセージループが終了する。
下図に、プログラムの終了確認の流れを示す。
サンプルコード
<syntaxhighlight lang="c++"> LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int id; HWND hwndCtl; UINT codeNotify; PAINTSTRUCT ps; HDC hdc; RECT rect; switch(uMsg) { case WM_CLOSE: if(IDYES == MessageBox(hwnd, TEXT("Are you sure you want to quit this program?"), TEXT("Confirmation"), MB_YESNO)) { DestroyWindow(hwnd); } break; case WM_COMMAND: id = (int) LOWORD(wParam); hwndCtl = (HWND) lParam; codeNotify = (UINT) HIWORD(wParam); switch(id) { case IDM_FILE_EXIT: SendMessage ( hwnd, WM_CLOSE, 0, 0 ); break; case IDM_HELP_ABOUT: ::MessageBox(NULL, TEXT("Hello, About!"), TEXT("About This Program"), MB_OK); break; } break; case WM_PAINT: hdc = BeginPaint ( hwnd, &ps ); GetClientRect ( hwnd, &rect ); DrawText(hdc, TEXT("Hello, world!"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); EndPaint( hwnd, &ps ); break; case WM_SIZE: InvalidateRect( hwnd, NULL, TRUE ); break; case WM_DESTROY: ::PostQuitMessage( 0 ); break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); break; }
return 0; } </source>