Win32:将子消息转发给父 - 返回值不同

Posted

技术标签:

【中文标题】Win32:将子消息转发给父 - 返回值不同【英文标题】:Win32: Forward child message to parent - return value is different 【发布时间】:2022-01-07 06:14:39 【问题描述】:

我使用CreateDialogParam 创建了对话框。它只有一个 ListView 子控件。在对话框WM_INITDIALOG 消息处理程序中,我将ListView 子类化以自定义标题重绘。

现在我想阻止用户调整ListView 列(标题)的大小,为此,我只需要处理ListViewWndProc 中的HDN_BEGINTRACKA 通知消息,如下所示:

case WM_NOTIFY:
    
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
            return TRUE; // to disable column resizing
    

这工作正常;但是,出于某种原因,我想在父(对话框)过程中处理此消息。因此,我将此消息转发给该家长,如下所示:

case WM_NOTIFY:
        
            if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
                || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW)) 
            
                BOOL b = FALSE;
                HWND hParent = GetRealParent(hwnd);
                if (hParent) b = SendMessage(hParent, msg, wParam, lParam);
                return b; // to disable column resizing return TRUE;
            
        
        break;

消息发送正常,但是,即使我从对话过程返回TRUE,在ListView 过程中,SendMessage 调用的返回值是FALSE

在对话过程中,代码如下:

case WM_NOTIFY:
    
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
            return TRUE;
    

所以,我的问题是为什么直接向父级发送(转发)WM_NOTIFY 消息会返回不同的结果,或者根本不起作用?

编辑:-

过去,我也遇到过同样的问题;为了解决它,我尝试了一条用户定义的消息,例如:

#define UWM_WM_NOTIFY (WM_APP + 7)

并将其与SendMessage 一起使用,以在子级和父级之间或任何其他对话框之间进行通信。但它也无法获得正确的返回值。

所以,我使用SendMessage 如下:

BOOL b = FALSE;
SendMessageA(hDlg, UWM_ANY_WM, 0, (LPARAM) &b);
return b;

变量的发送地址为LPARAM以获取返回值。有没有更好的方法来做到这一点。或者为什么SendMessageA返回值不一样?

【问题讨论】:

【参考方案1】:

来自Microsoft documentation 的WM_NOTIFY 消息1

如果消息处理程序位于对话框过程中,则必须使用 SetWindowLong 函数与DWL_MSGRESULT 一起设置返回值。

因此,使用更新的 SetWindowLongPtr 函数,您的父级(对话框)处理 WM_NOTIFY 消息应该如下所示:

case WM_NOTIFY:
    
        if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
            || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
        
            SetWindowLongPtr(hWnd, DWL_MSGRESULT, TRUE); // hWnd is dialog's HWND
            return TRUE;
        
    

另请注意,您的处理程序应继续返回TRUE,如this document 中所述:

如果您使用 SetWindowLongDWL_MSGRESULT 索引来设置 由对话过程处理的消息的返回值,您应该 之后直接返回TRUE。否则,如果你调用任何函数 这会导致您的对话过程接收到一个窗口消息, 嵌套窗口消息可能会覆盖您使用设置的返回值 DWL_MSGRESULT.


1 实际上,您需要使用概述的机制来设置由对话过程处理的(几乎)任何消息的返回值,如@987654323 中所述@。

【讨论】:

感谢您的回答。这真的很有帮助。但是正如您所见,我仍然很困惑,我编辑了我的问题以纠正错误。由于用户定义消息没有解决问题,但我使用LPARAM 来获取返回值。问题似乎不仅在于WM_NOTIFY 消息,还在于每条消息。 @vkchavda:确实,DWL_MSGRESULT 用于从对话过程返回任何消息。 WM_NOTIFY 中的文档链接是因为这是在返回值的对话框中使用的值得注意的消息。 @rodrigo - 是的,确实如此。请参阅我的编辑和 Raymond 的链接博客。

以上是关于Win32:将子消息转发给父 - 返回值不同的主要内容,如果未能解决你的问题,请参考以下文章

win32消息循环

进程间通信的方式(转)

怎么用win32的消息处理函数实现快捷键的功能

2.转发。基于itchat的微信消息同步机器人

我如何在 reactjs + typescript (钩子)中使用 useRef 将子状态值传递给父级

Win32界面程序