ホームに戻る
1、Windows のメッセージ処理について
入り口は必ず WinMain となる。
キー入力やマウスの操作等をイベントと呼びます。
イベントによりイベントに対応したメッセージが作成されます。
メッセージはキューに蓄えられ、プロシージャが終了するのを待ちます。
プロシージャが終了したら、キューは古いメッセージからプロシージャに送信します。
プロシージャはメッセージを処理するプログラム部分です。
メインループ→イベント→メッセージ→キュー→プロシージャ
キューを経由せずに強制的にメッセージをプロシージャに送ることも可能。
キューに貯めることをポストするといい、強制で送ることをセンドすると呼ぶ。
ルールとしてプロシージャ内の処理はできるだけ短時間で行われるようにすること。
プロシージャ内の処理時間が長いとその間に他の処理が進行できなくなり、
処理が終わるとキューに貯まった処理が一気に行われる現象が起こる。
もし長い処理ならばスレッドを作成することなどを考える。
プロシージャ内ではディフォルトの処理への対応を忘れないように。
WinMain
int WINAPI WinMain(
HINSTANCE hInst,
HINSTANCE hPrevInst,
LPSTR lpCmdLine,
int nCmdShow
);
hInst:API の引数に必要とされる場合があるが、その他の用途には使えない。
hPrevInst:Win32 では必ず 0 となる。Win32 では意味が無い。
lpCmdLine:コマンドライン文字列へのポインタ。main とは違いポインタの配列では無い。
nCmdShow:コマンドプロンプトの start コマンドでの初期状態の指定が入る。
メッセージループに入った場合は WM_QUIT の wParam を返すべきであり、
まだメッセージループに入っていない場合は 0 を返すべきである。
WNDCLASS 構造体
typedef struct{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
}WNDCLASS, *PWNDCLASS;
lpfnWndProc:ウィンドウプロシージャの登録。
hInstance:通常は自分自身である WinMain の hInst を入れる。
lpszClassName:ウィンドウクラスの登録名。
ウィンドウクラスの登録
ATOM RegisterClass(
CONST WNDCLASS *lpWndClass
);
失敗時には 0 を返す。
CreateWindow
HWND CreateWindow(
LPCTSTR lpClassName, // 登録されているクラス名
LPCTSTR lpWindowName, // ウィンドウ名
DWORD dwStyle, // ウィンドウスタイル
int x, // ウィンドウの横方向の位置
int y, // ウィンドウの縦方向の位置
int nWidth, // ウィンドウの幅
int nHeight, // ウィンドウの高さ
HWND hWndParent, // 親ウィンドウまたはオーナーウィンドウのハンドル
HMENU hMenu, // メニューハンドルまたは子ウィンドウ ID
HINSTANCE hInstance, // アプリケーションインスタンスのハンドル
LPVOID lpParam // ウィンドウ作成データ
);
lpClassName:ウィンドウクラスの名前と同じものを指定。
lpWindowName:ウィンドウの名前。タイトルバーに表示される。
hInstance:通常は自分自身である WinMain の hInst を入れる。
lpParam:WM_CREATE に渡すパラメータ。
失敗時には NULL を返す。
MSG 構造体
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG, *NPMSG, *LPMSG;
time:イベント発生時刻
pt:イベント発生時のカーソルの位置
GetMessage
BOOL GetMessage(
LPMSG lpMsg, // メッセージ情報
HWND hWnd, // ウィンドウのハンドル
UINT wMsgFilterMin, // 最初のメッセージ
UINT wMsgFilterMax // 最後のメッセージ
);
lpMsg:キューから拾われたメッセージ。
wMsgFilterMin:wMsgFilterMax:特定のメッセージをフィルター。
キューにメッセージが来るまでそのつど待つ。
メッセージが WM_QUIT の場合だけ 0 を返す。
PeekMessage
BOOL PeekMessage(
LPMSG lpMsg, // メッセージ情報
HWND hWnd, // ウィンドウのハンドル
UINT wMsgFilterMin, // 最初のメッセージ
UINT wMsgFilterMax, // 最後のメッセージ
UINT wRemoveMsg // 削除オプション
);
lpMsg:キューから拾われたメッセージ。
wMsgFilterMin:wMsgFilterMax:特定のメッセージをフィルター。
wRemoveMsg:キューから調べたメッセージの移動の指定。PM_REMOVE か PM_NOREMOVE。
キューにメッセージがあるかを調べる。
メッセージあれば 0 以外の数値を返しメッセージを拾う、無ければ 0 を返す。
WaitMessage
BOOL WaitMessage(VOID);
キューに新しいメッセージが入るまで処理を返さない。
TranslateMessage
BOOL TranslateMessage(
CONST MSG *lpMsg // メッセージ情報
);
lpMsg が WM_KEYDOWN、WM_KEYUPなどのメッセージであった場合、
WM_CHAR などの文字メッセージを作成しキューにポストする。
キューへのポストがあれば 0 以外の値が返り、無ければ 0 が返る。
DispatchMessage
LRESULT DispatchMessage(
CONST MSG *lpmsg // メッセージ情報
);
メッセージの送出。
PostMessage
BOOL PostMessage(
HWND hWnd, // ポスト先ウィンドウのハンドル
UINT Msg, // メッセージ
WPARAM wParam, // メッセージの最初のパラメータ
LPARAM lParam // メッセージの 2 番目のパラメータ
);
キューにメッセージをポストする。制御はすぐに返る。
SendMessage
LRESULT SendMessage(
HWND hWnd, // 送信先ウィンドウのハンドル
UINT Msg, // メッセージ
WPARAM wParam, // メッセージの最初のパラメータ
LPARAM lParam // メッセージの 2 番目のパラメータ
);
プロシージャに直接メッセージを送信。処理が終わるまで待つ。
戻り値はプロシージャの結果。
プロシージャ
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
メッセージを処理した場合には基本的には 0 を返す。
メッセージを処理しない場合は DefWindowProc を呼びその戻り値を返す。
DefWindowProc
LRESULT DefWindowProc(
HWND hWnd, // ウィンドウのハンドル
UINT Msg, // メッセージの識別子
WPARAM wParam, // メッセージの最初のパラメータ
LPARAM lParam // メッセージの 2 番目のパラメータ
);
ディフォルトの処理を行う。
PostQuitMessage
VOID PostQuitMessage(
int nExitCode // 終了コード
);
メッセージループに PostQuitMessage でキューに WM_QUIT をポストします。
通常 WM_DESTROY メッセージに対して処理するのが普通。