Windows API Primer   ウィンドウプロシージャ

ホーム   目次

ウィンドウプロシージャ

ウィンドウから発せられるメッセージを処理する関数をウィンドウプロシージャと言います。

前章では、Windows API が用意している DefWindowProc関数を使いましたが、通常は、アプリケーションに合わせて、独自のウィンドウプロシージャを作ります。

wndproc.c


#include <windows.h>

/* 独自に作るウィンドウプロシージャのプロトタイプ(関数前方宣言) */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

/* メイン関数 */
int WINAPI WinMain      (HINSTANCE hInstance,
			 HINSTANCE hPrevInstance,
			 LPSTR     lpCmdLine,
			 int       nCmdShow)
{
  HWND     hwnd;
  WNDCLASS wc;
  MSG      msg;

  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = NULL;
  wc.hCursor       = NULL;
  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND + 1;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = TEXT("WNDPROC");

  RegisterClass(&wc);

  hwnd             = CreateWindow(TEXT("WNDPROC"),
				  TEXT("Windows API Primer"),
				  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
				  CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
				  NULL, NULL, hInstance, NULL);

  while (GetMessage(&msg, NULL, 0, 0))
    {
      DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND      hwnd,
			 UINT      msg,
			 WPARAM    wParam,
			 LPARAM    lParam)
{
  switch (msg)
    {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
    


実行結果


コード説明

  1. wc.lpfnWndProc = WndProc;
    ウィンドウクラスのlpfnWndProcメンバーには、独自に作成するウィンドウプロシージャを設定します。

  2. while (GetMessage(&msg, NULL, 0, 0))
    今回の while 文では、GetMessage関数を加工せずにそのまま使います。新しく作成するウィンドウプロシージャでは、WM_QUITメッセージに対応するようにしますので、GetMessageは、FALSE (0)を返すことができます。第2引数をNULLとするとすべてのウィンドウのメッセージを取得できます。

  3. DispatchMessage(&msg);
    前章では、DefWindowProcに直接メッセージを送っていましたが、通常は、このDispatchMessage関数を使ってメッセージをウィンドウプロシージャに送信します。DispatchMessage関数を使うと特定のウィンドウプロシージャだけではなく、存在するすべてのウィンドウプロシージャの中から適切なウィンドウプロシージャにメッセージが送られます。

  4. return msg.wParam;
    無限ループを抜けた後の、MSG構造体のwPramメンバーには、メイン関数を正常終了した場合の整数値( 0 )などが入っています。

  5. LRESULT CALLBACK WndProc
    独自に作成するウィンドウプロシージャです。戻り値の LRESULT は整数値型です。この戻り値が何かに利用されることはほとんどないそうです。DefWindowProcもこの LRESULT 型を返してします。
    ウィンドウプロシージャには CALLBACK という呼び出し規約を付けます。この CALLBACK 呼び出し規約は、DefWindowProc の関数定義にもついています。
    引数については次のとおりです。DefWindowProcの場合と同じです。
    1. 第1引数に、メッセージを送ってくるウィンドウのハンドルを指定します。
    2. 第2引数に、MSG構造体のmessageメンバーを指定します。messageメンバーはメッセージの種類を表す、UINT型の整数値です。
    3. 第3引数に、MSG構造体のwParamメンバーを指定します。wParamメンバーは、メッセージに付随するデータを格納する16bitの整数型です。
    4. 第4引数に、MSG構造体のlParamメンバーを指定します。lParamメンバーは、メッセージに付随するデータを格納する32bitの整数型です。

  6. 引数で受け取った msg を switch文で選り分けます。

  7. case WM_DESTROY:
    ウィンドウが閉じられた時のメッセージは WM_DESTROY です。

  8. PostQuitMessage(0);
    PostQutiMessageは WM_QUIT メッセージをメッセージループへ送ります。WM_QUITを受け取ったメッセージループは、FALSEと評価され無限ループを抜けて、アプリケーションが終了します。引数の整数値は、終了コードとして、MSG 構造体の wParam メンバーに格納されます。

  9. return DefWindowProc(hwnd, msg, wParam, lParam);
    その他のメッセージは、システムに用意されている Def WindowProcで処理するようにします。DefWindowProc は、LRESULT型を返します。その値を独自ウィンドウプロシージャの戻り値としてそのまま利用します。この戻り値が何かに使用されることは特にないみたいです。

まとめ

この章で、アプリケーションの土台となる、メインウィンドウが完成しました。
Windows API はウィンドウを表示するだけでも大量のコードが必要になります。今回のコードをひな型として、コピー&ペーストで使い回しても良いでしょう。


4940 visits
Posted: Jun. 01, 2020
Update: Jun. 03, 2020

ホーム   目次