C++ 是否可以操作我的CMDIFrameWndEx';什么是CMFCMenuBar?

C++ 是否可以操作我的CMDIFrameWndEx';什么是CMFCMenuBar?,c++,mfc,dynamic,menu,mfc-feature-pack,C++,Mfc,Dynamic,Menu,Mfc Feature Pack,我的主框架有一个CMFCMenuBar成员,其中包含当前文档类型的菜单。 我想动态添加/删除子菜单。 例如,如果用户选择显示地图窗格,我想在“文件”菜单旁边添加地图子菜单 反之亦然,如果地图窗格关闭,我还想删除地图菜单项 有一件事很有效,但我不喜欢,那就是简单地禁用\u UPDATE\u命令\u UI上的处理程序中的菜单项。 框架有一个名为GetMenuBar()的方法,但该方法返回一个const CMFCMenuBar*,因此我无法从外部修改它。我添加了一个getter,因此获得了对菜单栏的非

我的主框架有一个CMFCMenuBar成员,其中包含当前文档类型的菜单。 我想动态添加/删除子菜单。 例如,如果用户选择显示地图窗格,我想在“文件”菜单旁边添加地图子菜单

反之亦然,如果地图窗格关闭,我还想删除地图菜单项

有一件事很有效,但我不喜欢,那就是简单地禁用\u UPDATE\u命令\u UI上的
处理程序中的菜单项。
框架有一个名为
GetMenuBar()
的方法,但该方法返回一个
const CMFCMenuBar*
,因此我无法从外部修改它。我添加了一个getter,因此获得了对菜单栏的非常量引用,但这也不起作用:

CMenu menu;
VERIFY(menu.LoadMenu(IDR_MAP));
CMFCMenuBar & menuBar = pFrm->GetNonConstMenuBar(); // Custom getter
menuBar.InsertButton(CMFCToolBarMenuButton(0, menu, -1));
menuBar.AdjustLayout();
menuBar.AdjustSizeImmediate();
上述代码是对
DynamicMenu
示例中的
void CMyMenuBar::AddSubMenu()
的改编。但我有一种感觉,这个示例被破坏了,因为我无法确定是否或何时执行了特定的代码。在本示例中,仅当菜单栏正在重置或尚未将状态保存到注册表时,才会执行代码

这是不可能的还是我做错了什么


除了添加/删除子菜单之外,还有其他更好的选择吗?

一种方法是处理
WM\u INITMENUPOPUP
消息。在显示菜单之前,将使用指向菜单的指针调用OnInitMenuOpup

请注意,每次菜单即将弹出时都会调用它,您所做的任何更改都会在调用之间丢失(每次调用
OnInitMenuPopup
时都必须添加菜单项)

使用它的诀窍是找出如何识别已调用的菜单。一种方法是比较已知项的菜单项ID。例如,如果菜单上的第一项是ID\u FILE\u OPEN,则可以查找该项。如果找到,您将假定您的“文件”菜单就是正在打开的菜单,您可以添加自定义子菜单


可能您也可以使用
MENUINFO
结构的
dwMenuData
成员,尽管我似乎记得由于
CMFCMenuBar
构建菜单的方式而在这方面存在问题。

如果我理解正确,这将允许我删除“Map”的所有子项,而不是“Map”本身。然后,菜单栏将看起来像“文件|地图|编辑|…”,“地图”没有子项;正确的?我认为这看起来更像是一个bug而不是一个特性……您可以在“文件”菜单中处理此消息,并使用它删除“映射”子菜单(如果合适)。但更可能的是,您没有预定义的“地图”子菜单;您只需在需要时将其插入“文件”菜单。每次获得OnInitMenuOpup时,请确定是否需要“地图”子菜单,并在适当时添加它。由于每次菜单都会重置为原始版本,因此您无需担心删除任何内容。您只需要添加适合上下文的项。使用onInitMenuOpup()(WM_initMenuOpup的msg.handler)是一种很酷的菜单自定义方法。主要优点是,任何自定义项都只在当前调用中“存在”,如果不再次处理,则任何后续调用都不会有自定义项。当我开始将弹出菜单(具有子菜单的菜单)拖动到工具栏时,这种方法给我带来了问题。这个把戏的逻辑是丢失的,因为当你拖动弹出窗口的时候,它们不能带来顶部菜单的第一项,整个方法背后的理性就像一个纸牌屋一样倒下!