You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32子窗口消息转发至父窗口时SendMessage返回值异常问题

问题原因分析

核心本质是对话框过程(DialogProc)与普通窗口过程(WndProc)的返回值规则不同

你创建的是对话框窗口,你编写的父窗口消息处理函数是DialogProc而非普通窗口的WndProc,二者返回值逻辑完全不一样:

  • 普通窗口的WndProc返回值会直接作为SendMessage的返回值传递给调用方
  • 对话框的DialogProc返回值仅为BOOL类型,仅用于标识当前消息是否被处理:
    • 返回TRUE:当前消息已被处理,不需要系统默认逻辑介入
    • 返回FALSE:当前消息未被处理,交由系统默认对话框逻辑处理
    • 如果你处理消息后需要给SendMessage调用方返回特定值,必须先调用SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 要返回的数值)设置返回结果,再返回TRUE即可。

你遇到的返回值不一致问题,就是因为父对话框处理完WM_NOTIFY后只返回了TRUE,没有设置DWLP_MSGRESULT,系统默认会将这类消息的返回值设为0(也就是FALSE),所以ListView侧拿到的返回值不符合预期。之前自定义消息遇到的相同问题也是同一个原因导致的。

修复方案

修改父对话框的WM_NOTIFY处理逻辑即可,不需要调整ListView侧的转发代码:

case WM_NOTIFY:
{
    if ((((LPNMHDR)lParam)->code == HDN_BEGINTRACKA)
        || (((LPNMHDR)lParam)->code == HDN_BEGINTRACKW))
    {
        // 先设置需要返回给调用方的结果
        SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE);
        // 再返回TRUE表示消息已处理
        return TRUE;
    }
    // 其他未处理的消息返回FALSE交给系统处理
    return FALSE;
}

注意代码中的hDlg为当前对话框的句柄,也就是DialogProc的第一个入参。

跨窗口通信返回值的最优方案

分场景选择即可:

  • 同进程内同步通信(也就是用SendMessage发送消息):
    1. 优先按Windows消息的标准规则处理:如果接收方是对话框就用DWLP_MSGRESULT设置返回值,普通窗口直接返回结果即可,这是最规范的方案。
    2. 自定义消息场景下,你当前用的传栈变量地址作为LPARAM、接收方直接修改该变量值的方案也是完全可行的,性能很高,只要注意不要把栈变量地址传给异步的PostMessage即可,SendMessage是同步调用,栈变量生命周期完全覆盖消息处理过程,不会有野指针问题。
  • 跨进程通信:可选择WM_COPYDATA、共享内存、命名管道等方案,你当前的父子窗口同进程场景不需要用到。

内容的提问来源于stack exchange,提问作者Vishal Chavda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:45:03