You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Win32 C++ ListView的HDN_BEGINTRACK消息未识别,无法阻止列调整

解决ListView表头HDN_BEGINTRACK消息未被识别的问题

首先拆解你遇到的核心问题:你看到的debugval = 4294966969其实是十六进制0xFFFFFFF9,对应有符号整数-7,这说明程序收到的是Unicode版本的表头通知消息HDN_BEGINTRACKW,但你的代码里没有处理这个消息码,导致case分支没命中。

接下来一步步修复问题:

1. 必须初始化公共控件

ListView属于Windows公共控件范畴,使用前必须完成初始化,否则控件的消息机制会出现异常。在你的程序入口(比如WinMain函数)中添加以下代码:

INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_LISTVIEW_CLASSES; // 初始化ListView相关控件
InitCommonControlsEx(&icex);

2. 给ListView设置明确的控件ID

你当前创建ListView时,hMenu参数传的是NULL,这会导致无法准确识别该控件发送的通知消息。修改CreateWindowEx调用,给ListView一个唯一ID(比如提前定义宏#define IDC_INSTRUCTIONS_LISTVIEW 1001):

HWND Instructions_ListView = CreateWindowEx(
    LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT,
    WC_LISTVIEW,
    L"",
    WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_EDITLABELS,
    320, 50, 300, 400,
    hWnd,
    (HMENU)IDC_INSTRUCTIONS_LISTVIEW, // 设置控件ID用于识别通知来源
    NULL,
    NULL
);

3. 正确处理WM_NOTIFY消息

修改你的WM_NOTIFY处理逻辑,同时覆盖ANSI和Unicode版本的HDN_BEGINTRACK消息,并且验证通知来自目标ListView,最后返回TRUE来禁止列调整:

case WM_NOTIFY: {
    LPNMHDR pNMHDR = (LPNMHDR)lParam;
    // 确认通知来自我们的目标ListView
    if (pNMHDR->idFrom == IDC_INSTRUCTIONS_LISTVIEW) {
        switch (pNMHDR->code) {
            // 同时处理ANSI和Unicode版本的消息,避免环境宏定义差异
            case HDN_BEGINTRACKA:
            case HDN_BEGINTRACKW:
                MessageBox(hWnd, L"RESIZE", L"", MB_OK);
                return TRUE; // 返回TRUE阻止列调整操作
        }
    }
    // 未处理的通知交给默认窗口过程处理
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

为什么之前的代码没生效?

  • 你只处理了HDN_BEGINTRACKAHDN_BEGINTRACK,但在Unicode编译环境下,若宏定义存在偏差,可能实际收到的是HDN_BEGINTRACKW而未被匹配;同时显式处理两个版本的消息是最稳妥的兼容方式。
  • 你之前的代码仅执行break,没有返回TRUE——HDN_BEGINTRACK需要父窗口返回TRUE才能取消列调整操作,仅break无法达到禁止调整的目的。

内容的提问来源于stack exchange,提问作者Synthetic Ascension

火山引擎 最新活动