首页 > 解决方案 > WINAPI,从菜单中删除弹出菜单

问题描述

我想在我的应用程序中有动态菜单。此动态菜单应包含将即时添加和删除的弹出菜单。对于第一种方法,我使用单个菜单项创建了动态菜单。

AppendMenu(menu, MF_STRING, item_id, "TEST");

我创建了生成 item_id 并将它们存储在数组中的算法,所以我可以通过

DeleteMenu(menu, id_to_be_deleted, MF_BYCOMMAND);

我没有看到这个实现的任何缺陷,我对此很满意。但随后坚持最终实施。我希望我的菜单是弹出菜单。

new_popup_menu = CreatePopupMenu();
AppendMenu(new_popup_menu, MF_STRING, 1, "TEST1");
AppendMenu(new_popup_menu, MF_STRING, 2, "TEST2");
AppendMenu(new_popup_menu, MF_STRING, 3, "TEST3");
AppendMenu(menu, MF_STRING|MF_POPUP, 
          (UINT_PTR)new_popup_menu, "dynamic menu");

此代码按预期工作,但我不知道如何从“menu”中删除“new_popup_menu”,因为 AppendMenu 的“UINT_PTR uIDNewItem”参数现在用作子菜单的句柄,而不是 ID,并且不能与 DeleteMenu+MF_BYCOMMAND 一起使用。除了 DeleteMenu+MF_BYPOSITION 之外,还有什么方法可以删除这个子菜单项?有没有办法通过 CreatePopupMenu()) 返回的句柄获取菜单项位置?我觉得跟踪哪个菜单在哪个位置的实现算法很痛苦。由于 Windows 有 API 可以在其他特定菜单之后插入菜单,因此重新创建整个菜单树是浪费 CPU 时间。

标签: windowswinapimenu

解决方案


如果要创建一个打开子菜单并具有 ID 的菜单项,请使用InsertMenuItem(...)而不是AppendMenu(...). InsertMenuItem(...)允许您填写一个结构,该结构指定要在您正在创建的菜单项上设置的所有属性,包括 ID 和子菜单。许多 Win32 以这种方式工作:AppendMenu(...)就像是同一函数的更详细版本的简写版本。当您遇到无法对某个 Win32 调用执行合理操作的情况时,请查找采用 *INFO 结构的同义调用。

下面的代码:

...
HMENU menu_bar = GetMenu(hWnd);
HMENU new_menu = CreateMenu();
AppendMenu(menu_bar, MF_POPUP, (UINT_PTR)new_menu, "foobar");
AppendMenu(new_menu, MF_ENABLED | MF_STRING, 1002, "item1");
AppendMenu(new_menu, MF_ENABLED | MF_STRING, 1003, "item2");

HMENU dynamic_popup = CreatePopupMenu();
AppendMenu(dynamic_popup, MF_ENABLED | MF_STRING, 1004, "mumble");
AppendMenu(dynamic_popup, MF_ENABLED | MF_STRING, 1005, "quux");

// Below will add an item named "dynamic menu" to the end of new_menu
// that has an ID of 1006.

MENUITEMINFO mii = { 0 };
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
mii.dwTypeData = (LPSTR)"dynamic menu";
mii.hSubMenu = dynamic_popup;
mii.wID = 1006;
InsertMenuItem(new_menu, 0, FALSE, &mii);

//DeleteMenu(new_menu, 1006, MF_BYCOMMAND);
...

推荐阅读