一 在CMainFrame的OnCreate中动态的创建菜单
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("未能创建工具栏\n"); return -1; // 未能创建 } if (!m_wndStatusBar.Create(this)) { TRACE0("未能创建状态栏\n"); return -1; // 未能创建 } m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); // TODO: 如果不需要可停靠工具栏,则删除这三行 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar);
/*创建一个弹出菜单,并把菜单附加到主菜单末尾*/ CMenu menu; //创建一个CMenu对象,内部有一个数据成员 m_hMenu,保存了这个菜单的句柄 menu.CreatePopupMenu(); //创建一个弹处菜单,并与menu对象关联 CMenu *pMenu = GetMenu(); //获取与CMainFrame相关联的菜单指针(主菜单)对象 pMenu->AppendMenuW(MF_POPUP, (UINT_PTR)menu.m_hMenu,_T("TestPopupMenu")); //创建的菜单附加到现有菜单上。如果第一个参数是MF_POPUP,则第二个参数是要弹处来那个menu菜单的句柄 menu.Detach(); //将menu对象与句柄断开。不断开关联,能正常显示,但是如果单击,将导致内存泄漏,所以这个是必须的。因为menu是一个局部变量 return 0; }
创建完的界面如下:
如果要在指定位置增加一个菜单,需要InsertMenu(),函数声明如下
BOOL InsertMenuW( UINT nPosition, //索引号或ID根据 nFlags参数设置 UINT nFlags, //如果nFlags设置为 MF_BYCOMMAND,则nPosition设置为ID,如果设置nFlags为MF_BYPOSITION,则nPosition为索引号 0,1... UINT_PTR nIDNewItem = 0, //通过创建的CMenu对象获取到 m_hMenu 并转型为UNIT_PTR或UNIT LPCTSTR lpszNewItem = NULL //菜单的名字 ); BOOL InsertMenuW( UINT nPosition, //索引号或ID根据 nFlags参数设置 UINT nFlags, //如果nFlags设置为 MF_BYCOMMAND,则nPosition设置为ID,如果设置nFlags为MF_BYPOSITION,则nPosition为索引号 0,1... UINT_PTR nIDNewItem, //通过创建的CMenu对象获取到 m_hMenu 并转型为UNIT_PTR或UNIT const CBitmap* pBmp );
在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) return 0;语句前增加如下代码
//插入菜单 CMenu menu; menu.CreatePopupMenu(); CMenu *pMenu = GetMenu(); pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单 menu.Detach(); return 0;
为创建好的弹处式菜单增加弹处项
//插入菜单,增加三个弹出项 CMenu menu; menu.CreatePopupMenu(); CMenu *pMenu = GetMenu(); //pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("Test")); pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单 menu.AppendMenuW(MF_STRING, 3344U, _T("子菜单1")); menu.AppendMenuW(MF_STRING, 3345U, _T("子菜单2")); menu.AppendMenuW(MF_STRING, 3346U, _T("子菜单3")); menu.Detach();
在现有菜单上增加菜单项
//插入菜单Test CMenu menu; menu.CreatePopupMenu(); CMenu *pMenu = GetMenu(); //pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("Test")); pMenu->InsertMenuW(1,MF_BYPOSITION|MF_POPUP,(UINT)menu.m_hMenu,_T("Test")); //文件 索引0 在文件后插入一个POPUP式菜单 menu.AppendMenuW(MF_STRING, 3344U, _T("子菜单1")); menu.AppendMenuW(MF_STRING, 3345U, _T("子菜单2")); menu.AppendMenuW(MF_STRING, 3346U, _T("子菜单3")); menu.Detach(); //在[文件]菜单的尾部附加一个菜单项,在打印设置后插入一个菜单项 CMenu *ppMenu = GetMenu(); //获取主菜单 CMenu *pFileMenu=ppMenu->GetSubMenu(0); //从主菜单中拿到第一个子菜单,索引号从0开始 pFileMenu->AppendMenuW(MF_STRING, 3347U, _T("附加菜单")); //在拿到的子菜单(文件)的菜单项末尾附加一个菜单 pFileMenu->InsertMenuW(8, MF_BYPOSITION | MF_STRING, (UINT)menu.m_hMenu, _T("打印到PDF")); //在打印设置后增加一个"打印到PDF",分隔条也需要占用一个索引,所以是8
//删除菜单操作 GetMenu()->DeleteMenu(4,MF_BYPOSITION); //从左往右索引号为4的整个菜单删除,再运行,帮助菜单被删除了 GetMenu()->GetSubMenu(0)->DeleteMenu(7, MF_BYPOSITION); //删除文件菜单中的 打印设置
二 菜单的响应函数
弹处菜单不能用来响应命令比如顶级菜单、文件、编辑、视图、帮助。如果非要用来响应命令,则在某个菜单的属性 外观栏一栏中 把Popup的值改为False,这样杂项里面ID由之前无法编辑ID变为ID可以输入状态。在帮助后面增加一个Caption:NewTest的顶级菜单,默认Popup:True,ID:无法编辑ID,此时修改Popup:False,ID:ID_NEWTEST(这个单击ID值那里,自动生成了),可以将修改一下ID值: IDM_NEWTES(表示菜单的ID)保存。
在类视图上CMainFrame右键,类向导->命令 搜索栏输入IDM自动定位到 IDM_NEWTEST
单击确定后 在类向导对话框页面右边,单击编辑代码,自动转到OnNewtest函数中
为动态增加的按钮关联消息处理函数
步骤一: 在Resource.h头文件中定义弹出菜单项的ID
#define IDM_SUB1 4455 #define IDM_SUB2 4456 #define IDM_SUB3 4457
在CMainFrame.h头文件中,声明消息响应函数的原型
afx_msg void OnSubMenu1(); afx_msg void OnSubMenu2(); afx_msg void OnSubMenu3();
步骤二: 建立消息映射 MainFrame.cpp文件中
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND( IDM_SUB1, &CMainFrame::OnSubMenu1) ON_COMMAND( IDM_SUB2, &CMainFrame::OnSubMenu2) ON_COMMAND( IDM_SUB3, &CMainFrame::OnSubMenu3) END_MESSAGE_MAP()
//消息响应函数
void CMainFrame::OnSubMenu1()
{
MessageBox(_T("Sub1菜单"));
}
void CMainFrame::OnSubMenu2()
{
MessageBox(_T("Sub2菜单"));
}
void CMainFrame::OnSubMenu3()
{
MessageBox(_T("Sub3菜单"));
}
步骤三:MainFrame.cpp文件中,OnCreate()函数中
//增加一个顶级菜单 CMenu menu; menu.CreatePopupMenu(); //创建弹出式菜单 CMenu *pMenu = GetMenu(); //获取主菜单 pMenu->AppendMenuW(MF_POPUP, (UINT)menu.m_hMenu, _T("动态增加菜单")); //把Caption:动态增加菜单 的菜单附加到主菜单尾部 menu.AppendMenuW(MF_STRING, IDM_SUB1, _T("动态子菜单1")); menu.AppendMenuW(MF_STRING, IDM_SUB2, _T("动态子菜单2")); menu.AppendMenuW(MF_STRING, IDM_SUB3, _T("动态子菜单3")); menu.Detach();