MFC可停靠菜单栏的创建过程
来源:互联网 发布:js sdk fail 编辑:程序博客网 时间:2024/06/02 23:38
VS2010创建的MFC单文档工程中,菜单栏也是可停靠,本文简单分析一下停靠菜单的创建过程。
首先呢,给出一下类图结构
CMainFrame有一个 CMFCMenuBar m_wndMenuBar 成员,从名字中可以推断出它代表了菜单。
从继承路径上可以看出,CMFCMenuBar是从CPane继承而来。CPane提供了停靠的功能,所以这个m_wndMenuBar所代表的窗口也具有了停靠功能。
m_wndMenuBar所指代的窗口不是跟主框架窗口不是同一个窗口,它是主框架的子窗口,那么必定是在某个地方它将主框架的菜单栏“搬到”了自己内部,答案得从CMainFrame::OnCreate函数找起:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)return -1;BOOL bNameValid;// 基于持久值设置视觉管理器和样式OnApplicationLook(theApp.m_nAppLook);if (!m_wndMenuBar.Create(this)){TRACE0("未能创建菜单栏\n");return -1; // 未能创建}// 此处略去n行return 0;}
OnCreate函数是响应WM_CREATE消息,这个函数的LPCREATESTRUCT类型参数中包含了hMenu成员,它是主框架窗口的菜单。
但是,这个句柄并没有在CMainFrame::OnCreate函数中用过,也就可以推断出菜单的替换不是直接在这个函数中做的,而是在它的某个调用路径中。
最有可能执行替换的地方应该是m_wndMenuBar.Create(this)这一句了,因为这一句才开始创建停靠菜单栏窗口。
BOOL CMFCMenuBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID){m_pParentWnd = pParentWnd;return CMFCToolBar::Create(pParentWnd, dwStyle, nID);}
通过调试可以看到整个CMFCMenuBar::Create函数调用序列,如下所示:
CMFCMenuBar::Create CMFCToolBar::Create CMFCToolBar::CreateEx CMFCBaseToolBar::Create CPane::CreateEx CBasePane::CreateEx CWnd::CreateEx
需要注意的是,在CMFCMenuBar::Create中赋值了一个成员变量m_pParentWnd,它指向了主框架窗口对象CMainFrame。
CWnd::CreateEx创建窗口的过程中,会发出WM_CREATE消息。消息路由之后,它调用CMFCMenuBar::OnCreate函数:
int CMFCMenuBar::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CMFCToolBar::OnCreate(lpCreateStruct) == -1)return -1; // 代码有删减...CFrameWndEx* pWndParentFrame = DYNAMIC_DOWNCAST(CFrameWndEx, m_pParentWnd);if (pWndParentFrame != NULL) {pWndParentFrame->m_Impl.SetMenuBar(this);}// 代码有删减...return 0;}
它将m_pParentWnd动态转型为CFrameWndEx,由于之前存的是CMainFrame的指针,CMainFrame是CFrameWndEx的子类,所以这个DYNAMIC_DOWNCAST转型的指针将不为NULL。
接着,对SetMenuBar函数的调用才开始了真正的替换过程,它传进的参数this指向的是CMainFrame中的m_wndMenuBar对象。
void CFrameImpl::SetMenuBar(CMFCMenuBar* pMenuBar){ASSERT_VALID(m_pFrame);ASSERT_VALID(pMenuBar);ENSURE(m_pMenuBar == NULL); // Method should be called once!m_pMenuBar = pMenuBar;m_hDefaultMenu=*m_pFrame->GetMenu();// Support for dynamic menum_pMenuBar->OnDefaultMenuLoaded(m_hDefaultMenu);m_pMenuBar->CreateFromMenu(m_hDefaultMenu, TRUE /* Default menu */);m_pFrame->SetMenu(NULL);m_pMenuBar->SetDefaultMenuResId(m_nIDDefaultResource);}
在这个函数中CreateFromeMenu这一句创建了可停靠的“菜单”。但这个菜单并非真正意义上的菜单,而是一个工具条。每个“菜单项”是一个工具栏按钮,按下这个按钮,会弹出一个子菜单,看起来很像原来的菜单。
SetMenu(NULL)这一句清除了框架窗口原有的菜单。
至此,整个菜单的替换过程就结束了。
- MFC可停靠菜单栏的创建过程
- 在mfc的sdi/mdi程序任意视图view内创建可停靠及浮动的工具栏方法
- mfc添加可停靠隐藏等功能的侧边栏
- MFC菜单栏的创建和使用
- docablepane 可停靠窗口在使用过程中的问题小结 vc mfc
- MFC动态创建可停靠窗口,窗口添加控件并读写控件中的数据
- VS2010-MFC:单文档左侧可停靠对话框(包含树控件)的实现
- 可移动的菜单栏
- 可配置的菜单栏
- VS2010的MFC对话框程序中添加菜单栏的过程
- VS2010的MFC对话框程序中添加菜单栏的过程
- MFC学习之菜单栏创建
- MFC基于对话框的菜单栏,工具栏和状态栏的创建
- MFC 菜单栏的使用
- MFC 菜单栏的使用
- MFC 菜单栏的使用
- 请问一下,如何在C#Windows编程中创建可停靠的工具条……
- 工具栏的创建和停靠
- 什么是字符串常量池?
- Hive shell 常用命令
- 创建对象时总说找不到符号,请帮帮解决下
- 游戏Algorithm----抽奖算法----奖品有权重的情况探讨
- 字符指针初始化方式与字符串存储位置之间的关系
- MFC可停靠菜单栏的创建过程
- 数据规范中的归一化与标准化:
- ORACLE10g新特性——全局HASH分区索引
- 基于davinci6467的DSP算法移植
- 一步一步学调试——gdb命令小结
- Shared XDM Definitions(共享XDM的定义)
- Directx 纹理贴图 模仿地面效果
- UFT QTP 12 试用
- Opencv--Hog源码分析