VS Feature Pack学习之使用CMFCMenuBar自定义菜单栏

来源:互联网 发布:简单的c语言小游戏 编辑:程序博客网 时间:2024/04/30 21:58

转自:http://blog.csdn.net/clever101/article/details/5795520


现在很多应用程序的界面基本是用配置文件来规划界面的,在这个时候就得学会自定义菜单栏和工具栏之类的。


      VS Feature Pack是为微软新推出的界面库(听说是买BCG的授权,然后对之进行改造的),其中的主要的界面类可以和BCG的界面类可以对应起来,类的使用和BCG的也大同小异。但是有些做法还是很不一样,比如这次我要提到的自定义菜单栏。这里的自定义菜单栏是指去除系统默认的菜单栏,然后动态创建菜单栏。今天摸索了一下,大致搞清楚了(说实话,这方面网上的资料很少)。


      首先我们新建一个MFC的单文档工程:DynamicMenu,基本设置如下:





        这里要提一下的是VS Feature Pack的应用程序其中的菜单栏操作主要由CMFCMenuBar来负责。因此下面的编码也主要针对该类来进行。


       首先我们实现编码实现删除默认的所有系统菜单项,其代码如下:


[cpp] view plaincopy
  1. // 删除默认的所有系统菜单项   
  2. static void DelAllMenu(HMENU hMenu)    
  3. {    
  4.     int Menucount = ::GetMenuItemCount(hMenu);    
  5.     for (int i = Menucount-1;i>-1;i--)    
  6.     {    
  7.         ::DeleteMenu(hMenu,i, MF_BYPOSITION);    
  8.     }      
  9. }    


然后我们定义两个菜单资源ID:


[cpp] view plaincopy
  1. #define ID_NEW_MENUBAR_OPEN     5000  
  2. #define ID_NEW_MENUBAR_SAVE     5001  


为CMainFrame类添加一个创建菜单栏的成员函数:


[cpp] view plaincopy
  1. void CMainFrame::NewMenuBar()  
  2. {  
  3.     CMenu menu;  
  4.     menu.CreateMenu();  
  5.     CString strMenu;  
  6.     strMenu = _T("打开文件");  
  7.     menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_OPEN,strMenu);  
  8.     strMenu = _T("保存文件");  
  9.     menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_SAVE,strMenu);  
  10.     CString strMenuBarTitle;  
  11.     strMenuBarTitle = _T("文件");;  
  12.     m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,strMenuBarTitle));  
  13. }  


我们在CMainFrame类的OnCreate函数调用这个函数,这里只给出部分代码:


[cpp] view plaincopy
  1. if (!m_wndMenuBar.Create(this))  
  2. {  
  3.     TRACE0("Failed to create menubar/n");  
  4.     return -1;      // fail to create  
  5. }  
  6. m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);  
  7. HMENU hm = m_wndMenuBar.GetDefaultMenu();  
  8. // 删除默认菜单栏  
  9. if (NULL!=hm)    
  10. {    
  11.     DelAllMenu(hm);    
  12. }    
  13.  // 创建新的菜单栏  
  14. NewMenuBar();  


现在我们看看效果如何,如下图:




        我们发现默认菜单栏去掉了,但是新的菜单栏并没有出来。到网上搜资料,但是并没有搜到适用的,看了看Visual C++ 2008 Feature Pack Demo中提供的DynamicMenu的源码,了解了要增加AFX_WM_RESETMENU消息的处理函数,在函数里调用创建菜单栏,具体增加的代码如下:


[cpp] view plaincopy
  1. // MainFrm.h : interface of the CMainFrame classafx_msg   
  2. // AFX_WM_RESETMENU消息的处理函数声明  
  3. LRESULT OnResetMenu(WPARAM,LPARAM);   
  4. // MainFrm.cpp : implementation of the CMainFrame class  
  5. // 消息宏中增加  
  6. ON_REGISTERED_MESSAGE(AFX_WM_RESETMENU,&CMainFrame::OnResetMenu)  
  7. LRESULT CMainFrame::OnResetMenu(WPARAM,LPARAM)  
  8. {  
  9.     NewMenuBar();  
  10.     return 0;  
  11. }  


       我们再删除程序的注册表相关项重新编译(使用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.

                 工程源码下载:VS Feature Pack学习之使用CMFCMenuBar自定义菜单栏


参考文献:

 

1. AFX Messages

原创粉丝点击