|
前回、「窓を開く」プログラムを作りました。ウインドウクラスを「登録」して、そのウインドウクラスに基づいてウインドウを作る。その後作ったウインドウを表示・更新する、という流れを見てみましたが、あの後プログラムは
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ */
TranslateMessage(&msg);
DispatchMessage(&msg);
}
というループに入りましたね。このループはメッセージループと呼ばれ、Windowsのシステムから送られてきたメッセージを、メッセージ処理用の関数に送る処理を行っています。 wndclass.lpfnWndProc = WndProc; /* メッセージ処理関数 */ として設定した関数です。このように、プログラムからではなく、 システムの方から呼ばれる関数はコールバック関数と呼ばれます。 メッセージ処理の流れメッセージとは、あるイベントが起こった事を知らせるために、システムから実行中のプログラム(ウインドウやスレッド)に送られるものです。通知されるイベントは、マウスボタンがクリックされたりマウスカーソルが動いたり、キーボードのキーが押されたり、ウインドウの×ボタンが押されて閉じられようとしたり、とさまざまですがメッセージループはこのメッセージを受け取って、メッセージ処理関数に渡すループなのです(ただし、
メッセージの中にはメッセージループを通さずに、直接メッセージ処理関数に送られるものもあります)。
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
switch (iMsg) {
case WM_DESTROY : /* 終了処理 */
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
メッセージ処理関数は、上のように送られてきたメッセージが何のメッセージかを調べ、メッセージに応じて処理します。
ただし、自分で処理しないメッセージは、そのままDefWindowProcに渡せばWindows の方で処理してくれますので、
すべてのメッセージを処理する必要はありません。wParam とlParamはメッセージのパラメータで、メッセージに関連した情報(例えばマウス関連メッセージの場合なら、マウスカーソルの座標など)が入っています。 これで「窓を開く」プログラム全体をざっと見渡しました。次回からは少しづつ具体的な処理をしてみましょう。
・プログラム(前回と同じ)
=======================================================================
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow){
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof(wndclass); /* 構造体の大きさ */
wndclass.style = CS_HREDRAW | CS_VREDRAW; /* スタイル */
wndclass.lpfnWndProc = WndProc; /* メッセージ処理関数 */
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance; /* プログラムのハンドル */
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); /* アイコン */
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); /* カーソル */
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); /* ブラシ */
wndclass.lpszMenuName = NULL; /* メニュー */
wndclass.lpszClassName = "Test Window"; /* クラス名 */
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
RegisterClassEx (&wndclass); /* ウインドウクラスTest Windowを登録 */
hwnd = CreateWindow (
"Test Window", /* ウインドウクラス名 */
"窓を開く", /* ウインドウのタイトル */
WS_OVERLAPPEDWINDOW, /* ウインドウスタイル */
32,32, /* ウインドウ表示位置 */
256,256, /* ウインドウの大きさ */
NULL, /* 親ウインドウのハンドル */
NULL, /* メニューのハンドル */
hInstance, /* インスタンスのハンドル */
NULL); /* 作成時の引数保存用ポインタ */
ShowWindow (hwnd,iCmdShow); /* ウインドウを表示 */
UpdateWindow (hwnd);
while (GetMessage (&msg,NULL,0,0)) { /* メッセージループ */
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
switch (iMsg) {
case WM_DESTROY : /* 終了処理 */
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
=======================================================================
VC++でビルドしてみましょう。 |