今回はメッセージクラッカーについて取り扱います //-----------------------------------------------------// // ウィンドウプロシージャ // デフォルトの処理はDefWindowProc関数で行う // // 引数: hWnd ウィンドウハンドル // msg メッセージ // wParam パラメータ // lParam パラメータ // // 戻り値:処理結果 //-----------------------------------------------------// LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } メッセージクラッカーを使って書きなおすと次のようになります //------------------------------------------------------// // ウィンドウ破棄メッセージ処理 // // 引数: hWnd ウィンドウハンドル //------------------------------------------------------// void OnDestroy(HWND hWnd){ PostQuitMessage(0); } //-----------------------------------------------------// // ウィンドウプロシージャ // デフォルトの処理はDefWindowProc関数で行う // // 引数: hWnd ウィンドウハンドル // msg メッセージ // wParam パラメータ // lParam パラメータ // // 戻り値:処理結果 //-----------------------------------------------------// LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy); } return DefWindowProc(hWnd, msg, wParam, lParam); } ここで HANDLE_MSG(ウィンドウハンドル、メッセージの種類、メッセージを処理する関数) のように使います windowsx.hヘッダーに次のように定義されています #define HANDLE_MSG(hwnd, message, fn) \ case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn)) ここで \は改行されていても一行として認識するために付けてあります ##というマクロはmessageの名前を連結します HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy); は case (WM_DESTROY): return HANDLE_WM_DESTROY((hWnd), (wParam), (lParam), (OnDestroy)); のように展開されます HANDLE_WM_DESTROYはwindowsx.hに次のように定義されています /* void Cls_OnDestroy(HWND hwnd) */ #define HANDLE_WM_DESTROY(hwnd, wParam, lParam, fn) \ ((fn)(hwnd), 0L) それをさらに展開したのが最終的な展開結果です case WM_DESTROY:return ((OnDestroy)(hWnd),0); HANDLE_WM_DESTROYのように ここで話がそれますが 「,」はカンマ演算子とよばれ では、メッセージクラッカーを使うためにはメッセージごとに /* void Cls_OnDestroy(HWND hwnd) */ に書いてあるような つまり、WM_DESTROYに対しては void OnDestroy(HWND hWnd) という関数を用意しました つまり、基本的にコメントアウトに書いてある関数を作成し メッセージクラッカーを使う利点は 全ソースコードは下から
|