发送WM_NCDESTROY后,为什么窗口画得很奇怪(没有视觉样式)?

Mik*_*2ab 0 c winapi

WM_NCDESTROY手动发送后,我得到了奇怪的窗口画.这仅在视觉样式打开时发生.当"经典风格"打开时,它似乎不会影响窗口.我不传递WM_NCDESTROYDefWindowProc()时我手动发送,但窗口仍然得到奇怪的画.好像SendMessage()在处理WM_NCDESTROY.为什么WM_NCDESTROY即使我没有通过它也会得到处理DefWindowProc()

#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;
}
Run Code Online (Sandbox Code Playgroud)

在右键单击Test2之前

在此输入图像描述

右键单击Test2后

在此输入图像描述

Han*_*ant 5

WM_NCDESTROY消息相当特殊,它保证是窗口在销毁之前收到的最后一条消息.它由DestroyWindow()函数生成.

作为最后一个给它一个相当崇高的地位.它标志着"停止做你正在做的事情".例如,在子类化窗口时总是使用它; 此消息告诉您停止继承它.而且你总是在一个窗口的C++包装器类中使用它,它告诉你什么时候需要销毁C++对象.并且它很可能是视觉样式渲染器用于停止使窗口看起来不同的通知,因为它不再存在.

哎呀.

像这样的消息是发生了一些有趣事情的通知.与那些旨在使某些有趣事情发生的消息相反,例如WM_LBUTTONDOWN,WM_KEYDOWN,WM_COMMAND.在WM_CLOSE vs WM_DESTROY消息中最明显.WM_CLOSE是"请关闭窗口".您可以使用它并且拒绝关闭窗口,传统上使用"数据未保存,您确定"消息.WM_DESTROY是"它已关闭".那是一块摇滚乐,它确实被摧毁了,没有任何一点与那个人纠缠在一起.

如果您生成虚假通知,那么您应该准备好获得假结果.不要弄乱重要的人.