CMFCMenuBar动态删除菜单和创建新菜单
2016-01-05 11:01
489 查看
这里要提一下的是VS Feature Pack的应用程序其中的菜单栏操作主要由CMFCMenuBar来负责。因此下面的编码也主要针对该类来进行。
首先我们实现编码实现删除默认的所有系统菜单项,其代码如下:
[cpp] view plaincopy
// 删除默认的所有系统菜单项
static void DelAllMenu(HMENU hMenu)
{
int Menucount = ::GetMenuItemCount(hMenu);
for (int i = Menucount-1;i>-1;i--)
{
::DeleteMenu(hMenu,i, MF_BYPOSITION);
}
}
或使用m_wndMenuBar.RemoveButton(i);实现删除菜单项
然后我们定义两个菜单资源ID:
[cpp] view plaincopy
#define ID_NEW_MENUBAR_OPEN 5000
#define ID_NEW_MENUBAR_SAVE 5001
为CMainFrame类添加一个创建菜单栏的成员函数:
[cpp] view plaincopy
void CMainFrame::NewMenuBar()
{
CMenu menu;
menu.CreateMenu();
CString strMenu;
strMenu = _T("打开文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_OPEN,strMenu);
strMenu = _T("保存文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_SAVE,strMenu);
CString strMenuBarTitle;
strMenuBarTitle = _T("文件");;
m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,strMenuBarTitle));
}
我们在CMainFrame类的OnCreate函数调用这个函数,这里只给出部分代码:
[cpp] view plaincopy
if (!m_wndMenuBar.Create(this))
{
TRACE0("Failed to create menubar/n");
return -1; // fail to create
}
m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
HMENU hm = m_wndMenuBar.GetDefaultMenu();
// 删除默认菜单栏
if (NULL!=hm)
{
DelAllMenu(hm);
}
// 创建新的菜单栏
NewMenuBar();
现在我们看看效果如何,如下图:
我们发现默认菜单栏去掉了,但是新的菜单栏并没有出来。到网上搜资料,但是并没有搜到适用的,看了看Visual C++ 2008 Feature Pack Demo中提供的DynamicMenu的源码,了解了要增加AFX_WM_RESETMENU消息的处理函数,在函数里调用创建菜单栏,具体增加的代码如下:
[cpp] view plaincopy
// MainFrm.h : interface of the CMainFrame classafx_msg
// AFX_WM_RESETMENU消息的处理函数声明
LRESULT OnResetMenu(WPARAM,LPARAM);
// MainFrm.cpp : implementation of the CMainFrame class
// 消息宏中增加
ON_REGISTERED_MESSAGE(AFX_WM_RESETMENU,&CMainFrame::OnResetMenu)
LRESULT CMainFrame::OnResetMenu(WPARAM,LPARAM)
{
NewMenuBar();
return 0;
}
我们再删除程序的注册表相关项重新编译(使用VS Feature Pack开发删除注册表这一项非常重要,Feature Pack的界面设计保存思路实际上和BCG是一样的,把上次用户设定的界面配置信息都保存在注册表,如果不删除注册表相关项,往往不能更新界面,注册表相关项一般在HKEY_CURRENT_USER/Software/Local AppWizard-Generated Applications/你的工程名称(英文版VS),HKEY_CURRENT_USER/Software/应用程序向导生成的本地应用程序/你的工程名称(中文版VS))。
我们再看看效果,如下图:
你可能会发现菜单是灰的,那是没有添加菜单的命令响应函数的缘故。本文的编译环境为:Windows XP + sp3, VS C++ 2008 + sp1。
后来查了一下MSDN对AFX_WM_RESETMENU消息的解释,如下:
Message
我们再删除程序的注册表相关项重新编译(使用VS Feature Pack开发删除注册表这一项非常重要,Feature Pack的界面设计保存思路实际上和BCG是一样的,把上次用户设定的界面配置信息都保存在注册表,如果不删除注册表相关项,往往不能更新界面,注册表相关项一般在HKEY_CURRENT_USER\Software\Local AppWizard-Generated Applications\你的工程名称(英文版VS),HKEY_CURRENT_USER\Software\应用程序向导生成的本地应用程序\你的工程名称(中文版VS))。
首先我们实现编码实现删除默认的所有系统菜单项,其代码如下:
[cpp] view plaincopy
// 删除默认的所有系统菜单项
static void DelAllMenu(HMENU hMenu)
{
int Menucount = ::GetMenuItemCount(hMenu);
for (int i = Menucount-1;i>-1;i--)
{
::DeleteMenu(hMenu,i, MF_BYPOSITION);
}
}
或使用m_wndMenuBar.RemoveButton(i);实现删除菜单项
然后我们定义两个菜单资源ID:
[cpp] view plaincopy
#define ID_NEW_MENUBAR_OPEN 5000
#define ID_NEW_MENUBAR_SAVE 5001
为CMainFrame类添加一个创建菜单栏的成员函数:
[cpp] view plaincopy
void CMainFrame::NewMenuBar()
{
CMenu menu;
menu.CreateMenu();
CString strMenu;
strMenu = _T("打开文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_OPEN,strMenu);
strMenu = _T("保存文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_SAVE,strMenu);
CString strMenuBarTitle;
strMenuBarTitle = _T("文件");;
m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,strMenuBarTitle));
}
我们在CMainFrame类的OnCreate函数调用这个函数,这里只给出部分代码:
[cpp] view plaincopy
if (!m_wndMenuBar.Create(this))
{
TRACE0("Failed to create menubar/n");
return -1; // fail to create
}
m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
HMENU hm = m_wndMenuBar.GetDefaultMenu();
// 删除默认菜单栏
if (NULL!=hm)
{
DelAllMenu(hm);
}
// 创建新的菜单栏
NewMenuBar();
现在我们看看效果如何,如下图:
我们发现默认菜单栏去掉了,但是新的菜单栏并没有出来。到网上搜资料,但是并没有搜到适用的,看了看Visual C++ 2008 Feature Pack Demo中提供的DynamicMenu的源码,了解了要增加AFX_WM_RESETMENU消息的处理函数,在函数里调用创建菜单栏,具体增加的代码如下:
[cpp] view plaincopy
// MainFrm.h : interface of the CMainFrame classafx_msg
// AFX_WM_RESETMENU消息的处理函数声明
LRESULT OnResetMenu(WPARAM,LPARAM);
// MainFrm.cpp : implementation of the CMainFrame class
// 消息宏中增加
ON_REGISTERED_MESSAGE(AFX_WM_RESETMENU,&CMainFrame::OnResetMenu)
LRESULT CMainFrame::OnResetMenu(WPARAM,LPARAM)
{
NewMenuBar();
return 0;
}
我们再删除程序的注册表相关项重新编译(使用VS Feature Pack开发删除注册表这一项非常重要,Feature Pack的界面设计保存思路实际上和BCG是一样的,把上次用户设定的界面配置信息都保存在注册表,如果不删除注册表相关项,往往不能更新界面,注册表相关项一般在HKEY_CURRENT_USER/Software/Local AppWizard-Generated Applications/你的工程名称(英文版VS),HKEY_CURRENT_USER/Software/应用程序向导生成的本地应用程序/你的工程名称(中文版VS))。
我们再看看效果,如下图:
你可能会发现菜单是灰的,那是没有添加菜单的命令响应函数的缘故。本文的编译环境为:Windows XP + sp3, VS C++ 2008 + sp1。
后来查了一下MSDN对AFX_WM_RESETMENU消息的解释,如下:
Message
Description | [in] wParam | lParam (All parameters are [in] unlessotherwise stated.) | ReturnValue | |
AFX_WM_RESETMENU | Theframework sends this message to the menu owner (a frame window) when the user resetsan application frame menu during customization。 | The menu resource ID. | Not used. | Not used. |
相关文章推荐
- SendMessage消息大全
- setObjectForKey和setValueForKey的用法和区别
- 通过 jstat -gcutil 来学习JVM 内存分配策略与 GC 发生时机
- cocoapods 安装报错 ERROR: While executing gem ... (Errno::EPERM) Operation not permitted - /usr/bin/xcodeproj
- 阿里巴巴是如何发展和激励人才的
- php抓取网页信息
- return命令--后面的程序不执行
- android 代码中调用shell
- Linux下的platform总线驱动(二)
- UE4 Rama's Vertex Snap Editor Plugin
- Myeclipse10破解 注册之前找不到common文件夹的问题
- tomcat git linux部署脚本
- Apache JMeter是
- CentOS-6.5-x86_64 最小化安装后,怎样安装 man 程序?
- leofs存储总结
- Android Studio中如何跳到某一个方法
- Linux知识点小结
- 【蓝桥杯】【写日志】
- Microsoft SQL Server Data Tools 2012 - Installation Error
- VS2010 C++环境下DLL和LIB文件目录及名称修改