Win32:将 child 消息转发到 parent - return 值不同

Win32: Forward child message to parent - return value is different

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

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

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

这没问题;但是,出于某种原因,我想在 parent (对话框)过程中处理此消息。因此,我将此消息转发给 parent,如下所示:

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;

消息发送正常,但是,即使我 return TRUE 来自对话过程,在 ListView 过程中,return 的值 SendMessage调用是FALSE.

对话程序中,代码如下:

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

所以,我的问题是为什么直接将 WM_NOTIFY 消息发送(转发)到 parent return 会得到不同的结果,或者根本不起作用?

Edit :-

我以前遇到过同样的问题;为了解决这个问题,我尝试了 user-defined 消息,例如:

#define UWM_WM_NOTIFY (WM_APP + 7)

并将其与 SendMessage 一起用于 child 和 parent 之间或任何其他对话之间的通信。但它也无法获得正确的 return 值。

所以,我使用 SendMessage 如下:

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

发送变量地址作为LPARAM得到return值。有没有更好的方法来做到这一点。或者为什么 SendMessageA return 值不同?

来自 Microsoft documentationWM_NOTIFY 消息1:

If the message handler is in a dialog box procedure, you must use the SetWindowLong function with DWL_MSGRESULT to set a return value.

因此,使用更新的 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;
        }
    }

另请注意,您的处理程序应继续 return TRUE,如 this document:

中所述

If you use SetWindowLong with the DWL_MSGRESULT index to set the return value for a message processed by a dialog procedure, you should return TRUE directly afterward. Otherwise, if you call any function that results in your dialog procedure receiving a window message, the nested window message could overwrite the return value you set using DWL_MSGRESULT.


1 实际上,您需要使用概述的机制为 (几乎)任何 消息设置 return 值由对话过程处理,如 this blog by Raymond Chen.

中所述