OnInitMenuPopup does not init correctly when called from a toolbar button that was a POPUP menu in the App main menu bar
简而言之,想像一下我的主菜单是CMFCMenuBar,该菜单的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | IDR_MAINFRAME MENU BEGIN POPUP"&File" BEGIN MENUITEM"New", ID_FILE_NEW MENUITEM"Open", ID_FILE_OPEN MENUITEM"Save", ID_FILE_SAVE POPUP"Save As" BEGIN MENUITEM"Format XXX", ID_FILE_SAVEAS_XXX MENUITEM SEPARATOR MENUITEM"Format YYY", ID_FILE_SAVEAS_YYY MENUITEM SEPARATOR MENUITEM"Format ZZZ", ID_FILE_SAVEAS_ZZZ MENUITEM"Format WWW", ID_FILE_SAVEAS_WWW END MENUITEM"Close", ID_FILE_CLOSE END POPUP"&Object" BEGIN POPUP"Create object" BEGIN MENUITEM"Create object...", ID_CREATE_OBJECT MENUITEM"Create object as...", ID_CREATE_OBJECTAS END POPUP"Save object" BEGIN MENUITEM"Save object...", ID_SAVE_AS_XXX MENUITEM"Save object copy", ID_SAVE_OBJECT_COPY END END MENUITEM"Delete", ID_DELETE_OBJECT END END |
由于POPUP菜单没有ID(所有菜单的值均为-1),要知道我在哪个菜单上进行初始化,我按照https://stackoverflow.com/a/3910405/383779上的方法进行操作,并且已实现的功能,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 | bool CMainFrame::IsFileMenu(CMenu* pPopupMenu) const { if(!pPopupMenu); return false; return (pPopupMenu->GetMenuItemCount() > 0) && (pPopupMenu->GetMenuItemID(0) == ID_FILE_NEW); } bool CMainFrame::IsObjectMenu(CMenu* pPopupMenu) const { if(!pPopupMenu); return false; return (pPopupMenu->GetMenuItemCount() > 0) && (pPopupMenu->GetMenuItemID(2) == ID_DELETE_OBJECT); } |
菜单初始化类似于:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) { if(!license.supports("SaveAsFile")) { if(IsFileMenu()) { //code to find ID_FILE_SAVEAS_XXX parent menu ("Save As"), then recursively delete all its descendants and itself } if(IsObjectMenu()) { for(int i = 0; i < pPopupMenu->GetMenuItemCount();i++) { MENUITEMINFO MenuItemInfo; memset(&MenuItemInfo, 0, sizeof(MENUITEMINFO)); MenuItemInfo.cbSize = sizeof (MENUITEMINFO); // must fill up this field MenuItemInfo.fMask = MIIM_SUBMENU; if (!pPopupMenu->GetMenuItemInfo(i, &MenuItemInfo, TRUE)) continue; CMenu* SubMenu = pPopupMenu->GetSubMenu(i); if (SubMenu != NULL) { memset(&MenuItemInfo, 0, sizeof(MENUITEMINFO)); MenuItemInfo.cbSize = sizeof (MENUITEMINFO); MenuItemInfo.fMask = MIIM_ID | MIIM_TYPE; for(int j=0; j<SubMenu->GetMenuItemCount() ;j++ ) { SubMenu->GetMenuItemInfo(j, &MenuItemInfo, TRUE); if (MenuItemInfo.wID == ID_CREATE_OBJECTAS) { for (int i=0; i<m_custom_objects.GetSize(); i++) pPopup->AppendMenu(MF_STRING | MF_ENABLED, WM_MENU_CUSTOM_OBJECTS_BEGIN + i, (LPCTSTR) m_custom_objects[i].GetName() ); found= true; break; } } if(found) break; } } } } __super::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); } |
请注意,重复
现在,用户已经使用" MFC自定义"对话框创建了一个工具栏,然后将"创建对象" POPUP拖动到新的工具栏上。当他单击工具栏的此新按钮时,他看到"创建对象"和"创建对象为"选项,但是由于未满足
当用户单击工具栏上的按钮时,如何以完成自定义对象添加的方式编写代码?
我不为自己的代码感到骄傲,但是我通过将" Object "的代码与" Create Object "菜单中的代码分开来解决了这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | bool CMainFrame::IsCreateObjectMenu(CMenu* pPopupMenu) const { if(!pPopupMenu); return false; return (pPopupMenu->GetMenuItemCount() > 0) && (pPopupMenu->GetMenuItemID(0) == ID_CREATE_OBJECT); } void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) { if(!license.supports("SaveAsFile")) { if(IsFileMenu()) { //code to find ID_FILE_SAVEAS_XXX parent menu ("Save As"), then recursively delete all its descendants and itself } if(IsObjectMenu()) { // Do things } if(IsCreateObjectMenu()) { for (int i=0; i<m_custom_objects.GetSize(); i++) pPopupMenu->AppendMenu(MF_STRING | MF_ENABLED, WM_MENU_CUSTOM_OBJECTS_BEGIN + i, (LPCTSTR) m_custom_objects[i].GetName()); } } __super::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); } |