MDI动态改变菜单、工具栏

在MDI开发中,往往不同的视图需要不同的菜单和不同的工具栏,这样对于不同view可以有不同的操作。

现在分步骤进行实现。

第一步: 添加新的docTemplate

我们知道在MFC中Document/view/ChildFrame是一体的,当新建一个工程后,IDE会自动为我们建立一份Document/view/ChildFrame,因此为了使用不同类型的文档我们需要额外定义另三个类。然后在WinApp中的InitInstance函数添加document模板:

复制代码
 1     // 注册应用程序的文档模板。文档模板
 2     // 将用作文档、框架窗口和视图之间的连接
 3     m_pFirstDocTemplate = new CMultiDocTemplate(IDR_uuTYPE,
 4         RUNTIME_CLASS(CuuDoc),
 5         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
 6         RUNTIME_CLASS(CuuView));
 7     AddDocTemplate(m_pFirstDocTemplate);
 8 
 9     m_pSecondDocTemplate = new CMultiDocTemplate(IDR_xxTYPE,
10         RUNTIME_CLASS(CuuDoc),
11         RUNTIME_CLASS(CMyChildFrm),
12         RUNTIME_CLASS(CEditView));
13     AddDocTemplate(m_pSecondDocTemplate);
复制代码

说明:这里使用了同一份document,不同的childframe(因为菜单和工具栏不一样,这里必须区分开),不同view(应该是不一样的,不然就没意义了)

第二步:制作自定义的菜单和工具栏

制作这里的菜单和工具栏最好使用copy/paste方法,IDE中的资源编辑器不太好用。

用记事本打开.rc的资源文件,里面都是文本格式,很容易看懂。

1. 增加文档的图标

1 IDR_uuTYPE         ICON         "res\\uuDoc.ico"
2 IDR_xxTYPE         ICON         "res\\xxDoc.ico"

第一行是原来已存在,复制一行就行。

2. 工具栏

要为工具栏载入位图

1 IDR_xxTYPE         BITMAP      "res\\uu.bmp"

然后,复制一个IDR_MAINFRAME的工具栏,作适当修改即可。

复制代码
 1 IDR_xxTYPE TOOLBAR   16, 16
 2 BEGIN
 3     BUTTON      ID_FILE_OPEN
 4     BUTTON      ID_FILE_NEW
 5     BUTTON      ID_FILE_SAVE
 6     SEPARATOR
 7     BUTTON      ID_EDIT_CUT
 8     BUTTON      ID_EDIT_COPY
 9     BUTTON      ID_EDIT_PASTE
10     SEPARATOR
11     BUTTON      ID_FILE_PRINT
12     BUTTON      ID_APP_ABOUT
13 END
复制代码

3. 菜单

菜单也可以复制一个IDR_MAINFRAME,然后再改。

复制代码
 1 IDR_xxTYPE MENU
 2 BEGIN
 3     POPUP "haha(&F)"
 4     BEGIN
 5         MENUITEM "hehe(&N)\tCtrl+N",                ID_FILE_NIMA
 6         MENUITEM "打开(&O)...\tCtrl+O",            ID_FILE_OPEN
 7         MENUITEM "关闭(&C)",                      ID_FILE_CLOSE
 8         MENUITEM "保存(&S)\tCtrl+S",               ID_FILE_SAVE
 9         MENUITEM "另存为(&A)...",                 ID_FILE_SAVE_AS
10         MENUITEM SEPARATOR
11         MENUITEM "退出(&X)",                       ID_APP_EXIT
12     END
13     POPUP "编辑(&E)"
14     BEGIN
15         MENUITEM "撤消(&U)\tCtrl+Z",               ID_EDIT_UNDO
16         MENUITEM SEPARATOR
17         MENUITEM "剪切(&T)\tCtrl+X",                ID_EDIT_CUT
18         MENUITEM "复制(&C)\tCtrl+C",               ID_EDIT_COPY
19         MENUITEM "粘贴(&P)\tCtrl+V",              ID_EDIT_PASTE
20     END
21     POPUP "视图(&V)"
22     BEGIN
23         POPUP "工具栏和停靠窗口(&T)"
24         BEGIN
25             MENUITEM "<占位符>",           ID_VIEW_TOOLBAR
26         END
27         MENUITEM "状态栏(&S)",                 ID_VIEW_STATUS_BAR
28     END
29     POPUP "窗口(&W)"
30     BEGIN
31         MENUITEM "新建窗口(&N)",                 ID_WINDOW_NEW
32         MENUITEM "层叠(&C)",                    ID_WINDOW_CASCADE
33         MENUITEM "平铺(&T)",                       ID_WINDOW_TILE_HORZ
34         MENUITEM "排列图标(&A)",              ID_WINDOW_ARRANGE
35     END
36     POPUP "帮助(&H)"
37     BEGIN
38         MENUITEM "关于 uu(&A)...",          ID_APP_ABOUT
39     END
40 END
复制代码

4. 字符串表,用来标识文件类型的。just copy it

1     IDR_uuTYPE         "\nuu\nuu\n\n\nuu.Document\nuu.Document"
2     IDR_xxTYPE         "\nxx\nxx\n\n\nxx.Document\nxx.Document"

5. 喔,差点忘了,还需要在Resource.h中定义

1 #define IDR_xxTYPE                    133

第三步:实现动态切换
其实其实,做到这里,动态菜单已经好了,不信你试试?新建一个文档,看看菜单是不是变了?

这里需要做的是将工具栏换掉。一般而言,工具栏和菜单上的项是对应的。

说说切换原理吧,当某个文档被激活、被关闭、文档间切换都会导致ChildFrame的WM_MDIACTIVATE消息。我们捕获这个消息就可以动态改变工具栏了。

在ChildFrame中添加WM_MDIACTIVATE消息处理函数,该函数原型为:

1 afx_msg void OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd);

第一个参数bActivate表明是激活还是不激活,第二个参数是激活的窗口,第三个参数是无效的窗口。

在该函数添加以下语句:

复制代码
 1     CMDIChildWndEx::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd); //调用基类,不然菜单就不切换了
 2     //My activate
 3     if(pActivateWnd != NULL &&  pActivateWnd->m_hWnd == this->m_hWnd)
 4     {
 5         CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
 6         if(pMainFrame != NULL)
 7         {
 8             pMainFrame->m_wndToolBar.LoadToolBar(IDR_xxTYPE);
 9             pMainFrame->m_wndToolBar.AdjustLayout(); //刷新工具栏
10         }
11     }    
12     //My Deactivate
13     if(pDeactivateWnd != NULL && pDeactivateWnd->m_hWnd == this->m_hWnd)
14     {
15         if(pActivateWnd == NULL)
16         {
17             //还原为IDR_MAINFRAME
18             CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame,GetParentFrame());
19             if(pMainFrame != NULL)
20             {
21                 pMainFrame->m_wndToolBar.LoadToolBar(IDR_MAINFRAME_256);
22                 pMainFrame->m_wndToolBar.AdjustLayout(); //刷新工具栏
23 
24             }
25         }
26     }
复制代码

上述代码的意思是,如果我被激活,那么我就载入我自己的工具栏。如果我被无效,并且要激活的窗口为空,表示这时所有文档都被关闭,需要载入IDR_MAINFRAME的工具栏。

大功告成,有了动态菜单和动态工具栏,多视图的文档使用起来灵活多了。

你可能感兴趣的:(MDI动态改变菜单、工具栏)