Fre*_*abe 5 c c++ winapi mfc menu
我想用原型实现一个功能
/* 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 );
Run Code Online (Sandbox Code Playgroud)
给定一个HMENU句柄,我希望能够找出应用程序中打开了哪个菜单项(如果有)。这基本上是与GetSubMenu函数相反的。
我当前的方法是查看应用程序顶级窗口中的每个HMENU,并检查是否可以找到一个菜单项,该菜单项在激活时会打开给定的子菜单。我使用GetMenuItemCount / GetSubMenu递归执行此操作。
但是,这效率很低,并且对于由上下文菜单项打开的菜单而言,它会失败。因此,我想知道:
有谁知道如何找到激活菜单后打开给定HMENU的菜单项(如果有)?
更新:我刚刚想到一个主意;应该有可能(使用SetWindowsHookEx函数)安装一个钩子,该钩子会通知菜单中发生的所有输入事件。每当检测到菜单项激活时,请记住该菜单项(由(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);
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果您无法控制所有菜单的创建方式,则可以WH_CALLWNDPROC在首次创建菜单时使用挂钩来捕获。 一篇好文章(带有源代码)描述了如何做到这一点 - 然后您可以尝试使用上述方法将父 HMENU 注入到创建的菜单中。