ウィンドウプロシージャをどうラップするか? – Life like a clown
そのvirtualなWndProcにだってメッセージクラッカーを使えるよ、むしろ使わない理由がないです。
1 2 3 4 5 6 7 8 9 10 11 12 13 | virtual LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { HANDLE_MSG(this->Handle(), WM_DESTROY, OnDestroy); } return DefWindowProc(this->Handle(), msg, wParam, lParam); } void OnDestroy(HWND) { PostQuitMessage(0); } |
そもそも、HANDLE_MSGの中身は、関数呼出演算子に展開されるマクロなので、メンバ関数以外にもstd::bind, boost::bindやラムダ式(C++11)、Boost.Lambdaでもなんでもござれのはずです。まあ使う機会はないとは思いますけど。
ついでなので、ソースコード全体を下に載せます。この記事を作るにあたってささっと書いたので、綺麗ではないですけど。
std::map方式も良いのですが、ここではGWLP_USERDATAを使ってみました。WNDCLASSのcbWndExtraという手もありますね。
以下余談になりますが、WM_NCCREATEを使っているのは、WM_CREATEより前に呼ばれるという小さな理由です。ただ、WM_NCREATEより前に呼ばれるメッセージ(WM_GETMINMAXINFO)があるので完璧を追求するならこれでも駄目です。本格的なGUIライブラリを作るなら気に掛けたほうが良いかもしれません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <windows.h> #include <windowsx.h> #include <tchar.h> class Window { public: Window() : hwnd() {} static bool InitInstance(HINSTANCE hinst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("Windows Class"); wndClassAtom = RegisterClass(&wc); return wndClassAtom != 0; } bool Create(HINSTANCE hinst) // NT系のみならこの引数は不要。 { return CreateWindow( reinterpret_cast<PCTSTR>(static_cast<ULONG_PTR>(wndClassAtom)), TEXT("Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, this) != NULL; } HWND Handle() const {return hwnd;} private: virtual LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam) { // ここではHandle()の参照にあえてthis->を付加しています。 switch (msg) { HANDLE_MSG(this->Handle(), WM_DESTROY, OnDestroy); } return DefWindowProc(this->Handle(), msg, wParam, lParam); } void OnDestroy(HWND) { PostQuitMessage(0); } // ここから実装 HWND hwnd; static ATOM wndClassAtom; static BOOL OnNCCreate(HWND hwnd, CREATESTRUCT const* pcs) { Window* pwnd = static_cast<Window*>(pcs->lpCreateParams); pwnd->hwnd = hwnd; SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pwnd)); return TRUE; } static LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_NCCREATE) { return OnNCCreate(hwnd, reinterpret_cast<CREATESTRUCT const*>(lParam)); } Window* pwnd = reinterpret_cast<Window*>( GetWindowLongPtr(hwnd, GWLP_USERDATA)); return pwnd->WndProc(msg, wParam, lParam); } }; ATOM Window::wndClassAtom; int WINAPI _tWinMain( HINSTANCE hinst, HINSTANCE, LPTSTR /*cmdLine*/, int cmdShow) { if (!Window::InitInstance(hinst)) { return -1; } Window wnd; if (!wnd.Create(hinst)) { return -2; } ShowWindow(wnd.Handle(), cmdShow); UpdateWindow(wnd.Handle()); MSG msg; for (;;) { int ret = GetMessage(&msg, NULL, 0, 0); if (ret == -1) { return -1; } else if (ret == 0) { return static_cast<int>(msg.wParam); } TranslateMessage(&msg); DispatchMessage(&msg); } } |
スポンサード リンク |