終了処理
正しいアプリケーションの終了
これまでの終了方法が間違いだというわけではありませんが
exit() による終了や、0 を返す終了方法は良いとは言えません
Windows の規則にしたがって、礼儀良く終了させましょう
これまでのサンプルプログラムは、ウィンドウの破棄に対応していませんでした
タスクバーのアイコンや、タイトルバーの × ボタンなどで強制終了した場合
ウィンドウは破棄されますが、メッセージループからは抜け出せないので
結果としてアプリケーションはビジー状態に陥ることになります
DefWindowProc がウィンドウを破棄した時
この関数はウィンドウプロシージャに WM_DESTROY をディスパッチします
ウィンドウプロシージャでこれを監視し、WM_DESTROY メッセージを受け取った時に
適切な終了処理をすれば、スマートにプログラムを終了させることができます
一般的に、終了処理にはPostQuitMessage()関数を使用します
この関数は、メッセージキューに WM_QUIT をポストします
VOID PostQuitMessage(int nExitCode);
戻り値の VOID 型 は、void と同じです
nExitCode は、WM_QUIT に渡されるパラメータです
この値は、WM_QUIT メッセージの wParam パラメータになります
WM_QUIT といえば、GetMessage() 関数の戻り値に影響するメッセージです
GetMessage() 関数は、このメッセージを受け取ると 0 を返しました
GetMessage() の戻り値をチェックし、WM_QUIT が発生した時にループを抜けるようにします
最後に WinMain() 関数が Windows に返す値ですが
終了コードは必ず WS_QUIT の wParam の値でなければならないとされます
//もっとも、多くの場合この値は0になるが…
#include<windows.h>
LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
switch (msg) {
case WM_DESTROY:
MessageBox(hwnd , TEXT("終わるにゃん") ,
TEXT("Kitty") , MB_ICONINFORMATION);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd , msg , wp , lp);
}
int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
PSTR lpCmdLine , int nCmdShow ) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("KITTY");
if (!RegisterClass(&winc)) return 0;
hwnd = CreateWindow(
TEXT("KITTY") , TEXT("Kitty on your lap") ,
WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
100 , 100 , 200 , 200 , NULL , NULL ,
hInstance , NULL
);
if (hwnd == NULL) return 0;
while (GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
return msg.wParam;
}
プロシージャのメッセージの判定に switch を使っています
前回のプログラムや、今回のように一つのメッセージしか処理しないのならば
if などでも問題ありませんが、通常処理するメッセージは複数になります
そのため、一般的にメッセージの判定は switch を使います
このプログラムは、通常のWindowsアプリケーションのように
"閉じる" を選択したり、× ボタンから正常に終了することができます
ウィンドウが破棄されると、DefWindowProc() が WM_DESTROY を送ります
これを、WndProc() で処理しています
PostQuitMessage() 関数で WM_QUIT をメッセージキューにポストし
GetMessage() 関数がそれを受け取り、戻り値に 0 を返します
こうして、メッセージループを抜けてアプリケーションは終了します
PostQuitMessage()
VOID PostQuitMessage(int nExitCode);
メッセージキューに WM_QUIT メッセージをポストします
nExitCode - WM_QUIT の wParam の値を指定します