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

WM_DRAWITEM中HMENU与HWND强制转换比较是否正确?

你的判断方式是错误的,正确做法看这里

首先明确:你不能把HMENU和HWND强制转成int来比较,这是完全错误的操作,原因有两点:

  1. HMENU(菜单句柄)和HWND(窗口句柄)是Windows系统中完全独立的两种句柄类型,分别对应不同的内核对象,它们的值没有任何逻辑关联,强制比较毫无意义。
  2. 在64位程序中,句柄是64位指针,而int是32位类型,强制转换会导致指针截断,直接破坏原有值,肯定会判断错误。

另外要纠正一个认知:根据MSDN文档,当DRAWITEMSTRUCT的CtlType为ODT_MENU(菜单自绘场景)时,hwndItem字段表示的是拥有该菜单的窗口的HWND,而不是菜单本身的HMENU——这也是你原来的比较完全不成立的核心原因。


正确的判断方法

下面给你两种实用的方案,根据你的场景选择:

方案1:用菜单项ID范围判断(最简单)

给你的自定义上下文菜单的所有菜单项分配一个唯一的ID区间,比如从0x1000到0x1FFF,然后在WM_DRAWITEM中判断当前项的ID是否在这个范围内:

// 提前定义你的自定义菜单ID范围
#define MY_CUSTOM_MENU_ID_START 0x1000
#define MY_CUSTOM_MENU_ID_END   0x1FFF

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_DRAWITEM:
        {
            LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
            // 先确认是菜单自绘消息
            if (drawItem->CtlType == ODT_MENU)
            {
                // 判断ID是否属于你的自定义菜单范围
                if (drawItem->itemID >= MY_CUSTOM_MENU_ID_START && drawItem->itemID <= MY_CUSTOM_MENU_ID_END)
                {
                    // 这里就是你的自定义菜单项,执行你的绘制逻辑
                    // ...
                }
            }
            return 0;
        }
        // 其他消息处理...
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

方案2:关联菜单句柄判断(更精准)

如果你不想依赖ID范围,可以在弹出菜单时把你的HMENU临时存储到窗口属性中,然后在WM_DRAWITEM中取出并验证当前项是否属于这个菜单:

// 定义一个唯一的属性名,用来存储菜单句柄
#define MY_POPUP_MENU_PROPERTY L"CustomPopupMenuHandle"

// 弹出上下文菜单的代码
void ShowMyCustomMenu(HWND hWnd, int x, int y)
{
    HMENU hMyMenu = highlightMenu->getHighlightMenuId();
    // 将菜单句柄存入窗口属性
    SetProp(hWnd, MY_POPUP_MENU_PROPERTY, (HANDLE)hMyMenu);
    // 弹出菜单
    TrackPopupMenu(hMyMenu, TPM_LEFTALIGN | TPM_TOPALIGN, x, y, 0, hWnd, NULL);
    // 菜单关闭后移除属性,避免内存泄漏
    RemoveProp(hWnd, MY_POPUP_MENU_PROPERTY);
}

// WM_DRAWITEM消息处理
case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
    if (drawItem->CtlType == ODT_MENU)
    {
        // 取出存储的自定义菜单句柄
        HMENU hMyMenu = (HMENU)GetProp(drawItem->hwndItem, MY_POPUP_MENU_PROPERTY);
        if (hMyMenu != NULL)
        {
            // 验证当前项是否属于这个菜单
            MENUITEMINFO mii = {0};
            mii.cbSize = sizeof(MENUITEMINFO);
            mii.fMask = MIIM_ID;
            if (GetMenuItemInfo(hMyMenu, drawItem->itemID, FALSE, &mii))
            {
                // 确认是你的自定义菜单项,执行绘制逻辑
                // ...
            }
        }
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:42:50