如何找到激活时打开给定 HMENU 的菜单项(如果有)?

2024-04-15

我想用原型实现一个功能

/* Locates the menu item of the application which caused the given menu 'mnu' to
 * show up.
 * @return true if the given menu 'mnu' was opened by another menu item, false
 * if not.
 */
bool getParentMenuItem( HMENU mnu, HMENU *parentMenu, int *parentMenuIdx );

给定 HMENU 句柄,我希望能够找出应用程序中的哪个菜单项(如果有)打开了它。这基本上是相反的获取子菜单 http://msdn.microsoft.com/en-us/library/ms647984%28VS.85%29.aspx功能。

我当前的方法是查看应用程序顶层窗口的每个 HMENU,并检查是否可以找到一个菜单项,该菜单项在激活时会打开给定的子菜单。我递归地执行此操作,使用获取菜单项计数 http://msdn.microsoft.com/en-us/library/ms647978%28VS.85%29.aspx/获取子菜单 http://msdn.microsoft.com/en-us/library/ms647984%28VS.85%29.aspx.

但这效率相当低,并且对于通过上下文菜单项打开的菜单会失败。因此,我想知道:

有人知道如何找到激活时打开给定 HMENU 的菜单项(如果有)吗?

UPDATE:我刚刚想到的一个想法;应该是可能的(使用设置WindowsHookEx http://msdn.microsoft.com/en-us/library/ms644990%28VS.85%29.aspx函数)来安装一个挂钩,该挂钩可以获取菜单中发生的所有输入事件的通知。每当检测到菜单项激活时,请记住该菜单项(由 (HMENU,int) 对标识)以及将由全局映射中的菜单项打开的 HMENU。这getParentMenuItem上面的函数可以简单地执行地图查找。

更新到更新:上面更新中描述的挂钩想法不会像现在这样工作,因为它当然只会识别在某个时刻已激活的项目的菜单项 -> 菜单关联。

这感觉有点难看,因为它需要我保留很多状态(地图);还有更简单的可能性吗?


你可以尝试设置MENUINFO.dwMenuData到您在应用程序中创建的所有菜单的父菜单句柄:

MENUINFO mi;
mi.cbSize = sizeof(MENUINFO);
mi.dwMenuData = (ULONG_PTR)<parent HMENU if this is a sub menu>
mi.fMask = MIM_MENUDATA;

SetMenuInfo(hCreatedMenu, &mi);

那么你只需要查询这个dwMenuData您的函数中的字段:

bool getParentMenuItem(HMENU mnu, HMENU *parentMenu, int *parentMenuIdx)
{
    MENUINFO mi;
    mi.cbSize = sizeof(MENUINFO);
    mi.fMask = MIM_MENUDATA;

    if (!GetMenuInfo(mnu,&mi) || mi.dwMenuData == 0)
        return false;

    *parentMenu = (HMENU)mi.dwMenuData;

    // not sure how or why you need the parentMenuIdx, but you should be able
    // to derive that from the parent HMENU

    return true;
}

Edit:如果您无法控制所有菜单的创建方式,您可以使用WH_CALLWNDPROC首次创建菜单时捕获的钩子。一篇好文章 http://www.codeproject.com/KB/menus/menuxp2.aspx(带有源代码)描述了如何做到这一点 - 然后您可以尝试使用上述方法将父 HMENU 注入到创建的菜单中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何找到激活时打开给定 HMENU 的菜单项(如果有)? 的相关文章

随机推荐