MFCの基礎 - プログラムの終了

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2021年11月24日 (水) 18:08時点におけるWiki (トーク | 投稿記録)による版 (文字列「<source」を「<syntaxhighlight」に置換)
ナビゲーションに移動 検索に移動

概要

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となるため、メッセージループが終了する。

下図に、プログラムの終了確認の流れを示す。

WindowsProgram EndProcess 1.png



サンプルコード

<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>