終了処理


正しいアプリケーションの終了

これまでの終了方法が間違いだというわけではありませんが
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 の値を指定します



前のページへ戻る次のページへ