2017-12-29 30 views
0

オブジェクトメソッドとしてWNDPROCを使用するために見つけた典型的な解決策を採用しましたが、WM_DESTROYメッセージがオブジェクトウィンドウ自身に送信されないように見え、プログラムはウィンドウを閉じた後に終了しないでください。WM_DESTROYはラップされたWndProcの中で呼び出されません

私のウィンドウクラスは、この(無関係なコードは削除)のようになります。

class MyWindow : MyApp 
{ 
public: 
    MyWindow(); 
    void Create(void); 
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
private: 
    HWND _hWnd; 
}; 

void MyWindow::Create() 
{ 
    // Here I register my class and call CreateWindowEx 
    // Everything works fine so far 

    // Part of the code where I assign the static WNDPROC 
    WNDCLASSEXW wcex; 

    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = MyApp::WndProc; 
    wcex.cbClsExtra = 0; 
    wcex.cbWndExtra = 0; 
    wcex.hInstance = this->Instance; 
    wcex.hIcon = LoadIcon(this->Instance, MAKEINTRESOURCE(32512)); 
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 
    wcex.lpszMenuName = NULL; 
    wcex.lpszClassName = "MyWindowClass"; 
    wcex.hIconSm = LoadIcon(this->Instance, MAKEINTRESOURCE(32512)); 

    RegisterClassExW(&wcex); 

    this->_hWnd = CreateWindowExW(
     WS_EX_TOOLWINDOW | WS_EX_TOOLWINDOW, 
     wcex.lpszClassName, 
     "Window Title", 
     WS_POPUP, 
     10, 10, 
     600, 400, 
     nullptr, 
     nullptr, 
     this->Instance, 
     nullptr 
    ); 

    ShowWindow(this->_hWnd, SW_SHOW); 
    UpdateWindow(this->_hWnd); 
} 

LRESULT CALLBACK MyWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) 
    { 
    case WM_CREATE: 
    { 
     // If I place a MessageBox here, it shows up 
    } 
    break; 
    case WM_DESTROY: 
     // It never gets to this point 

     // Decrease windows count 
     this->WindowsCount--; 

     PostQuitMessage(0); 
     break; 
    break; 
    default: 
     return DefWindowProc(hWnd, msg, wParam, lParam); 
    } 
    return 0; 
} 

と作成

class MyApp 
{ 
public: 
    static HINSTANCE Instance; 
    static int WindowsCount; 

    MyApp(); 
    static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
}; 

と実装

に割り当てられている静的WNDPROCを保持している今、クラス、
LRESULT CALLBACK MyApp::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // Window object 
    MyWindow* myWindow = NULL; 

    if (msg == WM_CREATE) { 
     myWindow = reinterpret_cast<MyWindow *>(((LPCREATESTRUCT)lParam)->lpCreateParams); 
     SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)myWindow); 
    } 
    else { 
     myWindow = reinterpret_cast<MyWindow *>(GetWindowLongPtr(hWnd, GWLP_USERDATA)); 
    } 

    // If window not identified, identify now 
    if (myWindow) { 
     return myWindow->WndProc(hWnd, msg, wParam, lParam); 
    } 

    // Call window object's processor 
    return DefWindowProc(hWnd, msg, wParam, lParam); 
} 

WM_CLOSEメッセージも捕捉されません。これらのメッセージは

+1

MyApp :: WndProcの最初のifステートメントのロジックは、間違った方法です。 –

+0

申し訳ありません、ありがとうございます。とにかく、それは理由ではありませんでした。 – bMain

+0

がこのウィンドウのダイアログボックスに残りますか? *ウィンドウを閉じた後* - ウィンドウは単純に隠れていても破壊されていない可能性がありますか? – RbMm

答えて

3

に渡されていない理由を私は本当にあなたがnullptrCreateWindowEx()lpParamパラメータを設定しているので、myWindowは常にMyApp::WndProc()nullptrあり、これMyWindow::WndProc()が呼び出されることはありません理解していません。 nullptrの代わりにthisを渡す必要があります。

CreateWindowEx()が成功したことを確認するために、ShowWindow()/UpdateWindow()を呼び出す前にエラーもチェックしていません。

また、(Get|Set)WindowLongPtr(GWLP_USERDATA)の代わりにSetWindowSubclass()を使用することを検討してください。 MSDNのSubclassing ControlsおよびSafer SubclassingのRaymond Chenのブログ記事を参照してください。

+0

ありがとうございます。私は 'SetWindowSubclass()'は、メインウィンドウではなく、子ウィンドウ/コントロールに対してのみ使用すると考えました。私はそれを – bMain

関連する問題