在 wndproc 和 MSG 中处理窗口消息,有啥区别?

Posted

技术标签:

【中文标题】在 wndproc 和 MSG 中处理窗口消息,有啥区别?【英文标题】:Handling window messages in wndproc vs MSG, what's the difference?在 wndproc 和 MSG 中处理窗口消息,有什么区别? 【发布时间】:2019-09-22 17:21:49 【问题描述】:

我注意到来自 winuser.h 的 MSG(它是 typedef'd 到 tagMSG)包含来自 wndproc 回调的所有参数。 我想知道在 wndproc 中处理消息与使用 MSG 处理 wndproc 外部是否有任何真正的区别,以及两者之间的不同用例

基本上是这样的

LRESULT WinApp::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   
   switch (uMsg)
   
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        
            DestroyWindow(hwnd);
        
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    

MSG msg;
if ((PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))

    switch (msg.message)
    
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            
            DestroyWindow(hwnd);
            
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    

【问题讨论】:

Nonqueued messages 由PeekMessageW 自动分派到目标窗口过程。它不会返回这些消息。 如果有第二个窗口与您的线程相关联,第二个版本也会导致问题。 【参考方案1】:

不同之处在于,使用普通消息循环将处理涉及多个窗口类的情况,每个类都有自己的 WndProc。只有当所有窗口(包括弹出菜单)都只有一组消息处理程序时,您显示的内容才会起作用。

【讨论】:

【参考方案2】:

每个窗口都与一个WindowProc 函数相关联。分派到窗口的排队和非排队消息都将到达它的 WindowProc。这是处理特定于每个窗口的消息的首选位置。

MSG 用于从线程的消息队列中检索排队的消息,然后将消息分派到其目标窗口(请参阅DispatchMessage())。直接在消息循环中处理消息是处理特定于线程但不一定特定于特定窗口的消息的首选方式。

【讨论】:

“分派到窗口的排队和非排队消息都将到达它的 WindowProc。”我的理解是,排队的消息只有在通过 GetMessage()、DispatchMessage() 消息循环发送到 WindowProc 时才会出现在 WindowProc 中? @Andy 是正确的。是 DispatchMessage 将排队的消息传递到 WindowProc。【参考方案3】:

就代码处理和执行而言,基本上是一样的。

但是,主要区别在于 SendMessage 函数的家族:

SendMessage函数调用指定窗口的窗口过程...

一般来说,在 Windows 世界中,每个窗口都有自己的窗口过程,可以在该窗口所属的线程消息循环之外调用。与PostMessage 函数相反,它:

在与创建指定窗口的线程关联的消息队列中放置(发布)消息

所以现在很清楚,消息可能在主消息循环中处理,但在这种情况下,您只能处理线程的消息。但是您无法处理直接发送到您的WndProc 的消息。

【讨论】:

以上是关于在 wndproc 和 MSG 中处理窗口消息,有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

没有 wndproc 的窗口

一个有用的Win32消息处理宏HANDLE_MSG

C# 重写WndProc 拦截 发送 系统消息 + windows消息常量值

WndProc 消息 = 49619 - 它是啥?

c# winform中怎么截获处理windows关闭的消息 C#

DUILIB消息处理过程