Windows アプリケーションは、マウス操作やキーボード操作などのイベント (event) をきっかけに処理を行います。
イベント発生からウィンドウプロシージャまでの大まかな流れ

- キーボードやマウスで操作を行う( ウィンドウに対して発生した操作や処理 :イベント発生)
- 操作内容がメッセージキューに格納
- メッセージループ
- GetMessage 関数でキューにメッセージがないか常にチェック
- メッセージが格納されたら、TranslateMessage 関数でキー入力メッセージを文字メッセージに変換
- DispatchMessage 関数でシステムに該当ウインドウのウインドウプロシージャを呼び出すように通知
- ウィンドウプロシージャは、受け取ったメッセージコードに合わせて処理を行う
メッセージループのソースコード
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デスクトップアプリケーション作成を作成する手順はマイクロソフトチュートリアルを参考にしてください。