簡単なウインドウメッセージ処理の流れ

Windowsプログラム

Windows アプリケーションは、マウス操作やキーボード操作などのイベント (event) をきっかけに処理を行います。

イベント発生からウィンドウプロシージャまでの大まかな流れ

  1. キーボードやマウスで操作を行う( ウィンドウに対して発生した操作や処理 :イベント発生)
  2. 操作内容がメッセージキューに格納
  3. メッセージループ
    1. GetMessage 関数でキューにメッセージがないか常にチェック
    2. メッセージが格納されたら、TranslateMessage 関数でキー入力メッセージを文字メッセージに変換
    3. DispatchMessage 関数でシステムに該当ウインドウのウインドウプロシージャを呼び出すように通知
  4. ウィンドウプロシージャは、受け取ったメッセージコードに合わせて処理を行う

メッセージループのソースコード

GetMessage関数は、WM_QUIT メッセージを取り出すと 0 を返し、メッセージループを終了

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}

MSG構造体

typedef struct tagMSG {
    HWND     hwnd;      // ウィンドウハンドル
    UINT     message;   // イベントによって発生したメッセージID
    WPARAM   wParam;    // メッセージに関する追加情報
    LPARAM   lParam;    // メッセージに関する追加情報
    DWORD    time;      // メッセージがポストされた時刻
    POINT    pt;        // メッセージが発生した時のカーソル位置(スクリーン座標)
}

GetMessage関数

メッセージキューからメッセージを取り出します。キューが空の場合は,新たなメッセージがポストされるまで制御を返しません。 この関数は、WM_QUITというメッセージを受信した場合は0を返し、それ以外は0以外の値を返し、MSG構造体の中に該当メッセージの情報が格納されます。失敗した場合はー1が返ります。

BOOL GetMessage(
    LPMSG lpMsg,         // MSG 構造へのポインタ
    HWND hWnd,           // メッセージ取得元のウィンドウハンドル(ウィンドウを指定しない場合はNULL)
    UINT wMsgFilterMin,  // 取得するメッセージの最小値(通常は制限することはないので0)
    UINT wMsgFilterMax   // 取得するメッセージの最大値(通常は制限することはないので0)
);

ウィンドウプロシージャで扱われる値

メッセージコード 説明
WM_CREATE ウィンドウが生成される時に発生
WM_DESTROY ウィンドウが破棄される時に発生
WM_MOVE ウィンドウが移動された後に発生
WM_SIZE ウィンドウサイズが変更された後に発生
WM_PAINT ウィンドウの再描画が必要な時に発生
WM_CLOSE ウィンドウの終了が選択された時に発生
WM_QUIT PostQuitMessage 関数が実行された時に発生
WM_KEYDOWN キーが押された時に発生
WM_KEYUP キーが離された時に発生
WM_MOUSEMOVE マウスが移動した時に発生
WM_LBUTTONDOWN 左マウスボタンが押下された時に発生
WM_LBUTTONUP 左マウスボタンが解放された時に発生

興味のないメッセージの処理

新しいウィンドウプロシージャを作ると、そのプロシージャ内ですべての動作(ウィンドウを移動したり、サイズを変更したりなど)の処理をしなければいけない。すべてのメッセージを解析して処理を独自に作るのは大変なので、基本的な動作を処理してくれるDefWindowProc関数を使って処理を行う。そうすると、作成したアプリケーションに必要なメッセージの処理だけ実装して、興味のない(必要のない)メッセージは DefWindowProc関数 に処理を丸投げすることができる。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR greeting[] = _T("Hello, Windows desktop!");

	switch (message)
	{
	case メッセージ1:
		// メッセージに対応した処理
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
		break;
	}
	return 0;
}

ウィンドウの破棄

ウィンドウの終了ボタンが押されるとWM_CLOSEメッセージが送られます。DefWindowProc関数がこのメッセージを受け取ると、DestroyWindow関数を使ってウィンドウを破棄します。 DestroyWindow関数 を使ってウィンドウが破棄されると、WM_DESTROYメッセージが送られます。

WM_DESTROY メッセージは,ウィンドウの表示が画面から消された後,ウィンドウが破棄される前に送信されます。

アプリケーションの終了

ウィンドウが破棄された場合は、メッセージループから抜け出してアプリケーションを終了させなければいけません。アプリケーションウィンドウが閉じられた場合は、アプリケーション終了を通知するためにPostQuitMessage関数を呼び出します。

VOID PostQuitMessage(int nExitCode); // nExitCodeは、終了コードとなる整数値

PostQuitMessage関数は、WM_QUITメッセージを送ります。さきほど出てきたGetMessage関数は WM_QUITメッセージを受け取ると0を返すのでメッセージループが終了します

PostQuitMessage 関数に渡した終了コード(nExitCode)は,MSG構造体のメンバであるwParam に格納されます。この値は、WinMain 関数の返り値に指定します。

return msg.wParam;

Visual Studio2019を使ってWindowsデスクトップアプリケーション作成を作成する手順はマイクロソフトチュートリアルを参考にしてください。

タイトルとURLをコピーしました