MFC MDI切换menu原理

当应用程序向导生成的 SDI 或 MDI 应用程序时,它创建了菜单资源 (使用 IDR_MAINFRAME 作为其资源 id。此菜单显示在所有时间 SDI 应用程序,并且仅在 MDI 应用程序中没有活动文档时。对于 MDI 应用程序中,应用程序向导还会生成菜单资源为一个 multidoc 模板创建使用 IDR_xxxxTYPE 作为其资源 id。附加的菜单资源可供其使用资源编辑器创建和使用另一台 multidoc 模板关联在一起 (见 CMultiDocTemplate)。该框架将显示与每个 multidoc 模板自动关联的菜单资源。此方法将限制每个文档模板的一个菜单。若要避开此限制,可以重写 CDocument::GetDefaultMenu(),并执行一些调用以显示菜单。

MFC 使用 CMDIChildWnd::m_hMenuShared 和 CFrameWnd::m_hMenuDefault 数据成员来确定要显示的菜单。在 MDI 应用程序,其中每个文档模板关联的菜单资源文档模板构造期间加载并复制到 CMDIChildWnd::m_hMenuShared。然后在 CMDIChildWnd::OnUpdateFrameMenu() 中使用此菜单时没有活动的 MDI 子窗口设置 MDI 框架窗口的菜单。CMDIChildWnd::OnUpdateFrameMenu() 使用 CFrameWnd::m_hMenuDefault,在没有活动子窗口时,使用 IDR_MAINFRAME 的 CFrameWnd 构造过程中加载。SDI 程序调用 CFrameWnd::OnUpdateFrameMenu(),CFrameWnd::m_hMenuDefault 用于其菜单。

在 SDI 和 MDI 应用程序中,如果需要显示的菜单从两个其他来源获取之前使用的 m_hMenuShared 或 m_hMenuDefault 菜单。该框架首先检查 CFrameWnd::m_hMenuAlt。这用于在受支持的 OLE 程序中使用就地激活的对象,提供其自己的菜单。它将检查第二个来源是 CDocument::GetDefaultMenu(),这也是虚拟。它的默认实现将返回 NULL。可以重写此函数允许程序以选择要显示的菜单。

手动更改菜单是通过调用 OnUpdateFrameMenu() 和 DrawMenuBar()。要设置到窗口中的新建菜单上,则必须调用 CFrameWnd::OnUpdateFrameMenu(NULL) 或 CMDIFrameWnd::OnUpdateFrameMenu(NULL)。调用 DrawMenuBar() 来重绘菜单。使用下面的代码为 MDI 和 SDI 实现:


在资源编辑器中创建新的菜单资源 (IDR_MYMENU1)。

添加到 CMyDocument 的 HMENU 的数据成员,重写 GetDefaultMenu() 返回该数据成员:

// .h file    
//    HMENU m_hMyMenu;    
//    virtual HMENU GetDefaultMenu(); 
// get menu depending on state    
HMENU CMyDocument::GetDefaultMenu() { return m_hMyMenu; // just use original default } 

请记住,以初始化该成员变量,无论是在构造函数中的空值或 CDocument::OnNewDocument()。

更改和重绘菜单上,在合适的时间。例如,当拆分窗格之间进行切换,通常可以在 CView::OnActivateView() 中。下面的代码演示如何在该函数中实现它。

// example within CView member function  OnActivateView 
((CMyDocument*)GetDocument())->m_hMyMenu = ::LoadMenu(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MYMENU1));    
((CFrameWnd*)AfxGetMainWnd())->OnUpdateFrameMenu(NULL);    
AfxGetMainWnd()->DrawMenuBar();
//请务必销毁时退出应用程序时,菜单上,并避免一次加载的菜单太多。

MFC MDI menu切换

分享到:
评论加载中,请稍后...
创APP如搭积木 - 创意无限,梦想即时!
回到顶部