MDI动态改变菜单、工具栏
2011-12-28 11:36
169 查看
在MDI开发中,往往不同的视图需要不同的菜单和不同的工具栏,这样对于不同view可以有不同的操作。
现在分步骤进行实现。
第一步: 添加新的docTemplate
我们知道在MFC中Document/view/ChildFrame是一体的,当新建一个工程后,IDE会自动为我们建立一份Document/view/ChildFrame,因此为了使用不同类型的文档我们需要额外定义另三个类。然后在WinApp中的InitInstance函数添加document模板:
说明:这里使用了同一份document,不同的childframe(因为菜单和工具栏不一样,这里必须区分开),不同view(应该是不一样的,不然就没意义了)
第二步:制作自定义的菜单和工具栏
制作这里的菜单和工具栏最好使用copy/paste方法,IDE中的资源编辑器不太好用。
用记事本打开.rc的资源文件,里面都是文本格式,很容易看懂。
1. 增加文档的图标
第一行是原来已存在,复制一行就行。
2. 工具栏
要为工具栏载入位图
然后,复制一个IDR_MAINFRAME的工具栏,作适当修改即可。
3. 菜单
菜单也可以复制一个IDR_MAINFRAME,然后再改。
4. 字符串表,用来标识文件类型的。just copy it
5. 喔,差点忘了,还需要在Resource.h中定义
第三步:实现动态切换
其实其实,做到这里,动态菜单已经好了,不信你试试?新建一个文档,看看菜单是不是变了?
这里需要做的是将工具栏换掉。一般而言,工具栏和菜单上的项是对应的。
说说切换原理吧,当某个文档被激活、被关闭、文档间切换都会导致ChildFrame的WM_MDIACTIVATE消息。我们捕获这个消息就可以动态改变工具栏了。
在ChildFrame中添加WM_MDIACTIVATE消息处理函数,该函数原型为:
第一个参数bActivate表明是激活还是不激活,第二个参数是激活的窗口,第三个参数是无效的窗口。
在该函数添加以下语句:
上述代码的意思是,如果我被激活,那么我就载入我自己的工具栏。如果我被无效,并且要激活的窗口为空,表示这时所有文档都被关闭,需要载入IDR_MAINFRAME的工具栏。
大功告成,有了动态菜单和动态工具栏,多视图的文档使用起来灵活多了。
现在分步骤进行实现。
第一步: 添加新的docTemplate
我们知道在MFC中Document/view/ChildFrame是一体的,当新建一个工程后,IDE会自动为我们建立一份Document/view/ChildFrame,因此为了使用不同类型的文档我们需要额外定义另三个类。然后在WinApp中的InitInstance函数添加document模板:
// 注册应用程序的文档模板。文档模板 // 将用作文档、框架窗口和视图之间的连接 m_pFirstDocTemplate = new CMultiDocTemplate(IDR_uuTYPE, RUNTIME_CLASS(CuuDoc), RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架 RUNTIME_CLASS(CuuView)); AddDocTemplate(m_pFirstDocTemplate); m_pSecondDocTemplate = new CMultiDocTemplate(IDR_xxTYPE, RUNTIME_CLASS(CuuDoc), RUNTIME_CLASS(CMyChildFrm), RUNTIME_CLASS(CEditView)); AddDocTemplate(m_pSecondDocTemplate);
说明:这里使用了同一份document,不同的childframe(因为菜单和工具栏不一样,这里必须区分开),不同view(应该是不一样的,不然就没意义了)
第二步:制作自定义的菜单和工具栏
制作这里的菜单和工具栏最好使用copy/paste方法,IDE中的资源编辑器不太好用。
用记事本打开.rc的资源文件,里面都是文本格式,很容易看懂。
1. 增加文档的图标
IDR_uuTYPE ICON "res\\uuDoc.ico" IDR_xxTYPE ICON "res\\xxDoc.ico"
第一行是原来已存在,复制一行就行。
2. 工具栏
要为工具栏载入位图
IDR_xxTYPE BITMAP "res\\uu.bmp"
然后,复制一个IDR_MAINFRAME的工具栏,作适当修改即可。
IDR_xxTYPE TOOLBAR 16, 16 BEGIN BUTTON ID_FILE_OPEN BUTTON ID_FILE_NEW BUTTON ID_FILE_SAVE SEPARATOR BUTTON ID_EDIT_CUT BUTTON ID_EDIT_COPY BUTTON ID_EDIT_PASTE SEPARATOR BUTTON ID_FILE_PRINT BUTTON ID_APP_ABOUT END
3. 菜单
菜单也可以复制一个IDR_MAINFRAME,然后再改。
IDR_xxTYPE MENU BEGIN POPUP "haha(&F)" BEGIN MENUITEM "hehe(&N)\tCtrl+N", ID_FILE_NIMA MENUITEM "打开(&O)...\tCtrl+O", ID_FILE_OPEN MENUITEM "关闭(&C)", ID_FILE_CLOSE MENUITEM "保存(&S)\tCtrl+S", ID_FILE_SAVE MENUITEM "另存为(&A)...", ID_FILE_SAVE_AS MENUITEM SEPARATOR MENUITEM "退出(&X)", ID_APP_EXIT END POPUP "编辑(&E)" BEGIN MENUITEM "撤消(&U)\tCtrl+Z", ID_EDIT_UNDO MENUITEM SEPARATOR MENUITEM "剪切(&T)\tCtrl+X", ID_EDIT_CUT MENUITEM "复制(&C)\tCtrl+C", ID_EDIT_COPY MENUITEM "粘贴(&P)\tCtrl+V", ID_EDIT_PASTE END POPUP "视图(&V)" BEGIN POPUP "工具栏和停靠窗口(&T)" BEGIN MENUITEM "<占位符>", ID_VIEW_TOOLBAR END MENUITEM "状态栏(&S)", ID_VIEW_STATUS_BAR END POPUP "窗口(&W)" BEGIN MENUITEM "新建窗口(&N)", ID_WINDOW_NEW MENUITEM "层叠(&C)", ID_WINDOW_CASCADE MENUITEM "平铺(&T)", ID_WINDOW_TILE_HORZ MENUITEM "排列图标(&A)", ID_WINDOW_ARRANGE END POPUP "帮助(&H)" BEGIN MENUITEM "关于 uu(&A)...", ID_APP_ABOUT END END
4. 字符串表,用来标识文件类型的。just copy it
IDR_uuTYPE "\nuu\nuu\n\n\nuu.Document\nuu.Document" IDR_xxTYPE "\nxx\nxx\n\n\nxx.Document\nxx.Document"
5. 喔,差点忘了,还需要在Resource.h中定义
#define IDR_xxTYPE 133
第三步:实现动态切换
其实其实,做到这里,动态菜单已经好了,不信你试试?新建一个文档,看看菜单是不是变了?
这里需要做的是将工具栏换掉。一般而言,工具栏和菜单上的项是对应的。
说说切换原理吧,当某个文档被激活、被关闭、文档间切换都会导致ChildFrame的WM_MDIACTIVATE消息。我们捕获这个消息就可以动态改变工具栏了。
在ChildFrame中添加WM_MDIACTIVATE消息处理函数,该函数原型为:
afx_msg void OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd);
第一个参数bActivate表明是激活还是不激活,第二个参数是激活的窗口,第三个参数是无效的窗口。
在该函数添加以下语句:
CMDIChildWndEx::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd); //调用基类,不然菜单就不切换了 //My activate if(pActivateWnd != NULL && pActivateWnd->m_hWnd == this->m_hWnd) { CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame()); if(pMainFrame != NULL) { pMainFrame->m_wndToolBar.LoadToolBar(IDR_xxTYPE); pMainFrame->m_wndToolBar.AdjustLayout(); //刷新工具栏 } } //My Deactivate if(pDeactivateWnd != NULL && pDeactivateWnd->m_hWnd == this->m_hWnd) { if(pActivateWnd == NULL) { //还原为IDR_MAINFRAME CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame()); if(pMainFrame != NULL) { pMainFrame->m_wndToolBar.LoadToolBar(IDR_MAINFRAME_256); pMainFrame->m_wndToolBar.AdjustLayout(); //刷新工具栏 } } }
上述代码的意思是,如果我被激活,那么我就载入我自己的工具栏。如果我被无效,并且要激活的窗口为空,表示这时所有文档都被关闭,需要载入IDR_MAINFRAME的工具栏。
大功告成,有了动态菜单和动态工具栏,多视图的文档使用起来灵活多了。
相关文章推荐
- MDI动态改变菜单、工具栏
- vc2008中使用CMFCMenuBar如何动态改变菜单文本
- 动态改变actionbar的menu菜单MenuItem的显示
- VC下动态改变菜单显示的标题和Checked状态(Change title of CMenu and Checked)
- 动态改变actionbar的menu菜单MenuItem的显示
- 在VC中动态改变菜单
- C# MDI窗体合并子窗体菜单和合并工具栏
- 在VC中动态改变菜单
- 动态改变用户自定义控件的菜单样式
- 在C#的Form中动态更改菜单、工具栏的状态
- 动态改变actionbar的menu菜单MenuItem的显示
- 谈在VC中动态改变菜单
- 关于“产品介绍”中的动态改变菜单问题
- 动态改变actionbar的menu菜单MenuItem的显示
- MDI多文档中如何对动态处理子框架的菜单
- ExtAspNet应用技巧(五) - 动态创建工具栏菜单
- 动态改变ToolBar内菜单选项
- 动态地改变菜单
- 动态改变actionbar的menu菜单MenuItem的显示
- 导航条——动态改变导航菜单的背景颜色