WM_DESTROY 消息混淆

Posted

技术标签:

【中文标题】WM_DESTROY 消息混淆【英文标题】:WM_DESTROY message confusion 【发布时间】:2021-01-04 17:30:55 【问题描述】:

拥有这么简单的 Win 应用程序:

bool continueRunning = true;
...
int APIENTRY wWinMain(...) 
        while (continueRunning) 

            PeekMessage(&msg, 0, 0, 0, PM_REMOVE);

            TranslateMessage(&msg);
            DispatchMessage(&msg);

            if (WM_DESTROY == msg.message) 
                OutputDebugString(L"--- WM_DESTROY (WinMain) ---\n");
               
        

...

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 

    switch (message)       

        case WM_DESTROY:
            OutputDebugString(L"--- WM_DESTROY (WndProc) ---\n");
            continueRunning = false;
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    
    return 0;

我收到了--- WM_DESTROY (WndProc) --- 消息,但没有 --- WM_DESTROY (WinMain) ---

WM_DESTROY 没有收到消息,如何将消息 PeekMessage 传递给应用程序?

【问题讨论】:

WM_DESTROYsent 并直接进入窗口 proc。请参阅docs 中的第一段。 好的,但是由于没有PeekMessage - 窗口进程中的类似功能,应用程序如何获取这样的消息? WM_DESTROY 永远不会进入消息队列。它是一个发送的消息,直接传递给window proc。 但我的代码中没有明确的SendMessage 调用。当我单击“X”按钮时,它只是由系统隐式/默认/自动发送吗? 它是由 Windows “当窗口被销毁时”发送的,引用自相同的文档。在Why can't I get a WM_DESTROY or WM_CLOSE message outside a window procedure? 和WndProc calling mechanism (WinAPI) 上查看更多信息。 【参考方案1】:

PeekMessage(或GetMessage)自行调度发送的消息(来自其他线程)而不返回它们。它只返回已发布的消息。如果消息是由同一个线程发送的,它甚至不会通过PeekMessages,它实际上是一个直接的窗口过程调用。 WM_DESTROY 已发送。

顺便说一句,避免不将系统消息传递给DefWindowProc,包括WM_DESTROY

【讨论】:

抱歉,没听懂。 “自己发消息”和“只发消息”是什么意思? 我已经编辑了我的答案,希望现在更清楚 好的,谢谢。为了澄清。 “它实际上是一个直接的窗口过程调用”,这意味着当我关闭窗口(例如单击X 按钮)时,系统会使用消息参数 == WM_DESTROY 隐式调用 WndProc? 点击X按钮会引发连锁反应,其中一个步骤(但不是第一步)是系统将WM_DESTROY消息发送到窗口。

以上是关于WM_DESTROY 消息混淆的主要内容,如果未能解决你的问题,请参考以下文章

WM_DESTROY没有在包装的WndProc中调用

子窗口没有收到 WM_DESTROY?

Windows的三类消息

Windows 常用消息大全

WM消息大全

WM消息大全