一开始以我是这样做的,结果是错误的:
这段代码第一次点击时,会在第6个位置创建MFC菜单,我本以为再次点击,
menu->GetSubMenu(5)返回的值就不会为空了,但事实是它返回了NULL,所以这样做动态菜单不得行。
后来我通过百度,搜索出了下面的方法,进行了一点小小的总结。
首先需要在Resource.h文件里定义菜单的宏:
//自定义动态菜单 #define Dyn_Menu_MFC 5000
这里我只定义了一个,后面的菜单项都是直接写的数字。
为什么要定义这个,是因为,我们无法通过在在资源里的菜单添加命令那样为动态菜单添加处理函数。所以只能手动的取个标识ID,以便和对应的命令消息处理函数相匹配。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(ID_TEST_MYOPEN, &CMainFrame::OnTestMyopen) ON_COMMAND(Dyn_Menu_MFC, &CMainFrame::OnCommandTest)//处理函数 END_MESSAGE_MAP()
在MainFrame.h里加入:
public: afx_msg void OnTestMyopen(); afx_msg void OnCommandTest();
在MainFrame.cpp加入:
void CMainFrame::OnCommandTest() { CMenu * menu = GetMenu(); CMenu * subMenu = menu->GetSubMenu(0); if (subMenu != NULL) { MessageBox(TEXT("c++学院")); } }
到这里c++学院菜单的处理函数就完成了。
下面这是详细的动态菜单构建代码:
CMenu subMenu, menuMain; menuMain.CreateMenu(); subMenu.CreateMenu(); subMenu.AppendMenuW(MF_STRING | MF_ENABLED, Dyn_Menu_MFC, TEXT("c++学院")); // 子项一 menuMain.AppendMenuW(MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)subMenu.m_hMenu, TEXT("MFC"));//主菜单 subMenu.CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED); //从资源里的已有菜单动态添加到新菜单上 CMenu oldMenu; oldMenu.LoadMenuW(IDR_MAINFRAME); //如果是想获得当前菜单 //GetMenu() menuMain.AppendMenuW(MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)oldMenu.GetSubMenu(0)->m_hMenu, TEXT("资源中已存在的菜单")); //创建带有子菜单的学员分类菜单 CMenu sSubMenu; sSubMenu.CreateMenu(); sSubMenu.AppendMenuW(MF_POPUP, 5555, TEXT("初阶学员")); //sSubMenu.AppendMenuW(MF_POPUP, 5556, TEXT("高阶学员")); //创建带有子菜单的高阶学员菜单 CMenu ssSubMenu; ssSubMenu.CreateMenu(); ssSubMenu.AppendMenuW(MF_STRING, 5557, TEXT("高阶学员_子菜单")); sSubMenu.AppendMenuW(MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)ssSubMenu.m_hMenu, TEXT("高阶学员")); menuMain.GetSubMenu(0)->AppendMenuW(MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)sSubMenu.m_hMenu, TEXT("学员分类")); SetMenu(&menuMain); menuMain.Detach(); subMenu.Detach(); oldMenu.Detach(); sSubMenu.Detach(); ssSubMenu.Detach();