2016-05-25 14 views
0

WM_NCDESTROYを手作業で送信した後、私は変なウィンドウペインティングをします。これは、ビジュアルスタイルがオンの場合にのみ発生します。 'クラシックスタイル'がオンの場合、ウィンドウには影響しないようです。手動で送信するとWM_NCDESTROYDefWindowProc()に渡すことはありませんが、ウィンドウがまだ奇妙に描画されています。 SendMessage()WM_NCDESTROYのようです。 WM_NCDESTROYDefWindowProc()に渡されても処理されないのはなぜですか?WM_NCDESTROYを送信した後、ウィンドウが奇妙に(ビジュアルスタイルなしで)描かれているのはなぜですか?

enter image description here

右Test2をクリックした後にTest2を右クリックする前に

#include <windows.h> 

HINSTANCE g_hInst; 

LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    static BOOL bProcessMsg = FALSE; 

    switch(msg) 
    { 
    case WM_RBUTTONUP: 
     SendMessage(hwnd, WM_NCDESTROY, 0, 0); 
     //Size window manually after this message is processed to see the effects 
     break; 

    case WM_DESTROY: 
     bProcessMsg = TRUE; 
     break; 

    case WM_NCDESTROY: 
     if(!bProcessMsg) return 0; 
     MessageBox(0, L"Message processed", 0, MB_OK); 
     return DefWindowProc(hwnd, msg, wParam, lParam); 
     break; 

    default: 
     return DefWindowProc(hwnd, msg, wParam, lParam); 
    } 
    return 0; 
} 

LRESULT CALLBACK WndProc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(msg) 
    { 
    case WM_MBUTTONUP: 
     { 
      WNDCLASSEX wc = { 0 }; 
      wc.cbSize  = sizeof(WNDCLASSEX); 
      wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
      wc.hCursor  = LoadCursor(0, IDC_ARROW); 
      wc.hIcon   = LoadIcon(0, IDI_APPLICATION); 
      wc.hInstance  = g_hInst; 
      wc.lpfnWndProc = WndProc2; 
      wc.lpszClassName = L"Testclass2"; 
      if(!RegisterClassEx(&wc)) return 0; 
      CreateWindowEx(0, L"Testclass2", L"Test2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 40, 40, 200, 200, hwnd, 0, g_hInst, 0); 
     } 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 

    default: 
     return DefWindowProc(hwnd, msg, wParam, lParam); 
    } 
    return 0; 
} 

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 
{ 
    WNDCLASSEX wc = { 0 }; 
    HWND hwnd; 
    MSG msg; 

    wc.cbSize  = sizeof(WNDCLASSEX); 
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wc.hCursor  = LoadCursor(0, IDC_ARROW); 
    wc.hIcon   = LoadIcon(0, IDI_APPLICATION); 
    wc.hInstance  = hInstance; 
    wc.lpfnWndProc = WndProc1; 
    wc.lpszClassName = L"Testclass"; 
    if(!RegisterClassEx(&wc)) return 0; 

    g_hInst = hInstance; 
    hwnd = CreateWindowEx(0, L"Testclass", L"Test1", WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, hInstance, 0); 
    if(!hwnd) return 0; 

    ShowWindow(hwnd, nCmdShow); 
    UpdateWindow(hwnd); 

    while(GetMessage(&msg, 0, 0, 0) > 0) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return (int)msg.wParam; 
} 

enter image description here

+4

うーん、なぜあなたは 'WM_NCDESTROY'を自分で送りますか? –

+0

テスト目的です。 'SendMessage()'はそれ自体を処理しているので、どのプロセスもあなたにこのメッセージを送ることができ、それを防ぐ方法がないようです。 – Mike32ab

+1

これは意味をなさないものです。他のプロセスがあなたのプロセス内のウィンドウに 'WM_NCDESTROY'メッセージを送ることを決定した場合、それもそうです。あなたを守ることは何もありません。正常な場合(つまり、不正なアプリケーションが実行されておらず、他のプログラムをスローしているシステム)で動作するようにアプリケーションを実装するだけです。 – IInspectable

答えて

5

WM_NCDESTROYメッセージではなく、特別な、最後のであることが保証されていますウィンドウが破棄される前に受信するというメッセージ。 DestroyWindow()関数によって生成されます。

最後になると、それはやや高貴な状態になります。それは "あなたがやっていることをやめてください"という信号です。たとえば、サブクラスのウィンドウを使用しているときは、常にそれを使用します。このメッセージは、サブクラス化を停止するよう指示します。また、ウィンドウのC++ラッパークラスでは常にこのオブジェクトを使用して、C++オブジェクトをいつ破棄する必要があるかを示します。また、ビジュアルスタイルレンダラがウィンドウが見えなくなるのを止めるために、ビジュアルスタイルレンダラが使用しているという通知は、もう見えなくなる可能性があります。

通知は、何か面白いことが起こったです。 に宛てられたメッセージの種類とは対照的に、はWM_LBUTTONDOWN、WM_KEYDOWN、WM_COMMANDのような何か面白いことが起こります。 WM_CLOSEとWM_DESTROYのメッセージで最も明白です。 WM_CLOSEは "ウィンドウを閉じてください"です。あなたはそれで猿をすることができ、伝統的に "データは保存されていませんでした、あなたは確かです"というメッセージでウィンドウを閉じることを拒否します。 WM_DESTROYは "それは閉じています"。それは岩で、本当に破壊されてしまいました。

偽の通知を生成する場合は、偽の結果を得る準備ができている必要があります。重要なものを混乱させないでください。

関連する問題