ウィンドウプロシージャ


メッセージのディスパッチ

これまで、何度か出てきましたウィンドウプロシージャを説明しましょう
ウィンドウプロシージャは、メッセージを処理する専用のルーチンです

メッセージループで取得したメッセージをウィンドウプロシージャにディスパッチし
受け取ったメッセージをウィンドウプロシージャで処理します
ウィンドウプロシージャは複数あってもかまいません

ウィンドウプロシージャは、ウィンドウクラスの lpfnWndProc にポインタを渡します
ウィンドウプロシージャの型は次のようになります

LRESULT CALLBACK WndProc(HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam);

プロシージャの名前は任意です
LRESULT 型 は、コールバック関数や
ウィンドウプロシージャから返される32ビットの値です

CALLBACK は WINAPI 同様に、呼び出し規約です
この関数が返すべき値は、メッセージによって異なります

hWnd は、メッセージが発生したウィンドウのハンドルを受け取ります
Msg には、メッセージが、wParam と lParamには、メッセージの付加情報が入ります
引数は、MSG 構造体の最初の4つのメンバと同じです

第二引数の Msg がメッセージなので、それをチェックしてメッセージを判断します
ウィンドウプロシージャが処理しない部分では、デフォルトウィンドウプロシージャに委託します
ウィンドウプロシージャの最後に DefWindowProc() 関数を呼び出しましょう
これがなければ、基本的なウィンドウの動作ができなくなります
#include<windows.h>
#include<stdlib.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	if (msg == WM_LBUTTONUP) {
		MessageBox(hwnd , TEXT("終わるにゃん") ,
			 TEXT("Kitty") , MB_ICONINFORMATION);
		exit(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 (TRUE) {
		GetMessage(&msg , NULL , 0 , 0);
		DispatchMessage(&msg);
	}
	return 0;
}
ウィンドウのクライアントエリアで左クリックすると、強制終了します
この終了方法は推奨されませんが、とりあえずこの場はこうするものとします

基本的な動作もサポートするため、WndProc() 関数の最後で
DefWindowProc() 関数を呼び出し、その戻り値を返しています
たとえウィンドウを破棄しても、プログラムは終了しないので注意してください
このプログラムは、クライアントエリアでマウスを左クリックする以外に終了しません

このように、Windows プログラムではウィンドウプロシージャが処理を行います
今後、処理に関する部分はソースが長くても、ウィンドウプロシージャを見て
プログラムの外装に関する部分は WinMain() を見ていただければわかりやすいでしょう

一見すると長く感じるWindowsプログラムも
中身を知ると非常にわかりやすく、解読しやすいはずです



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