菜单是windows应用程序经常使用的资源之一。从今天开始,把有关菜单的创建及使用等各方面的基本用法总结到一起,算是做个笔记吧!准备一天写一点,陆陆续续完成!
一、菜单的创建:
(一)VC++菜单通过编辑资源文件直接创建菜单
可以自己编写菜单资源文件来完成来手工创建菜单,这与编程方法创建菜单不同。用这种方法创建菜单分两步:
1、在rc资源文件中编写菜单资源:
首先,要用其它文字编辑软件打开rc文件,然后在里面手工编写菜单资源。举例如下:
IDR_MENU1 MENU PRELOAD DISCARDABLE
(注释:"IDR_MENU1"-->菜单ID名; "MENU"-->资源类名)
BEGIN
(注释:以BEGIN开始,END结束菜单定义)
POPUP "&File"
(注释:POPUP--> 表明是一个弹出菜单 ;“&File"-->为菜单名字。"&"定义紧接后面的字母F快捷键。)
BEGIN
MENUITEM "&New" ID_FILE_NEW
(注释:MENUITEM-->子菜单项;ID_FILE_NEW是ID值。)
MENUITEM "&Edit" ID_FILE_EDIT
MENUITEM SEPARATOR
(注释:SEPARATOR-->分隔水平线;后面不需要跟ID值。)
MENUITEM "&Copy" ID_FILE_COPY
MENUITEM "E&xit" ID_FILE_EXIT
END
END
其次,编辑resource.h文件,对菜单中的各种ID进行定义。
#define ID_FILE_NEW 0X8001
#define ID_FILE_EDIT 0X8002
#define ID_FILE_COPY 0X8003
#define ID_FILE_EXIT 0X8004
通过以上两步,就已经成功编辑了一个名为”File",ID为IDR_MENU1的菜单,此菜单弹出时,有“New","Edit","Copy","Exit"等四项菜单命令组成的子菜单。
定义一个CMenu变量,通过CMenu.LoadMenu()方法可以加载上面手工编成的菜单:
CMenu menu;
menu.loadMenu(IDR_MENU1);
然后通过menu变量就可以进一步操作菜单了。
也可以通过CFrameWnd::LoadFrame 加载菜单,直接把菜单挂载到框架窗口上面。如:
((CMainFrame *)pMainWnd)->LoadFrame(IDR_MENU1);
有些菜单是系统编制的,如程序的“系统菜单”。这种菜单你只可以在系统的基础上加以修改、添加和删除一些命令。
通过CMenu *pMenu=CWnd::GetSystemMenu(FALSE);即可获取系统菜单,然后可以对pMenu菜单指针进一步操作了。
(二)、通过编程软件visual studio中的资源视图中创建菜单:
这个比较简单易懂,进入编程环境中的“资源视图”中,右键“添加资源”,选择“Menu",即可开始手工创建工菜单。
直接上图:
(三)、编程创建菜单
使用CMenu::CreateMenu,CMenu::CreatePopupMenu();CMenu::AppendMenu()可以编程创建菜单。
CMenu mainMenu;//创建一个CMenu变量,用于指向顶级菜单。
mainMenu.CreateMenu();//创建一个空的顶级菜单
CMenu popupMenu;//创建一个CMenu变量,用于指向弹出菜单——子菜单。
popupMenu.CreatePopupMenu();//创建一个空的弹出菜单——子菜单。
popupMenu.AppendMenu(MF_STRING,ID_EDIT_COPY,_T("&Copy"));//添加一个菜单子项。
popupMenu.AppendMenu(MF_STRING,ID_EDIT_CUT,_T("C&ut"));//添加一个菜单子项。
popupMenu.AppendMenu(MF_SEPARATOR);//添加一个菜单子项:水平分隔线。
mainMenu.AppendMenu(MF_POPUP,(UINT_PTR)popupMenu.detach(),_T("&Edit"));//在顶级菜单中挂载一个弹出菜单,其名为:Edit。//有些版本是强制转化为UINT
popupMenu.AppendMenu(MF_STRING,ID_FILE_NEW,_T("&New"));//添加一个菜单子项。
popupMenu.AppendMenu(MF_STRING,ID_FILE_OPEN,_T("&Open"));//添加一个菜单子项。
mainMenu.AppendMenu(MF_POPUP,(UINT_PTR)popupMenu.detach(),_T("&File));//有些版本是强制转化为UINT
setMenu(&mainMenu);//把菜单挂载到框架窗口上。
mainMenu.detach();//及时分离,防止因变量mainMenu的生命周期结束而影响菜单,如果不detatch,要影响到菜单不能正确显示。
菜单到此,编程的代码基本完成了。但是,上述代码中涉及的各种“ID”,需要在程序资源里面全部定义为常量才算全部完成。
ID_FILE_NEW,ID_FILE_OPEN,ID_FILE_EXIT,ID_EDIT_COPY,ID_EDIT_CUT等是系统已经定义的ID,不需要重新定义(当然,正常情况下不要使用这些ID)。如果ID为自定义的,需要你自己定义为常量。
二、菜单的挂载
有了菜单,当然要挂载到框架窗口上面。挂载的方法有以下几种:
(一)框架窗口创建时挂载
CFrameWnd::Create
BOOL Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault, CWnd* pParentWnd = NULL, LPCTSTR lpszMenuName = NULL, DWORD dwExStyle = 0, CCreateContext* pContext = NULL );
使用这种方法挂载菜单时,菜单一般为拥有 ID,不能直接在此函数中使用。这时需要用到 MAKEINTRESOURCE()宏,其参数为WORD,返回值为:LPTSTR,这就能在函数中使用此菜单参数了。
(二)使用框架窗口类的虚函数CFrameWnd::LoadFrame()挂载菜单
CFrameWnd::LoadFrame
virtual BOOL LoadFrame( UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );
此函数直接使用菜单的ID挂载。
(二)使用窗口类的SetMenu()函数挂载菜单
CWnd::SetMenu
BOOL SetMenu( CMenu* pMenu );
此函数要使用菜单指针,所以多用于编程形成的菜单的挂载。
三、菜单的修改
(一)菜单的插入
CMenu::InsertMenu
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT_PTR nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
菜单的插入,使用CMenu::InsertMenu就可以了。怎样使用它呢?
假设程序的现有菜单如下图所示:
现在我们可以这样插入:
1、插入“分隔线”:
插入的位置在File菜单的第2个菜单项之后:
CMenu *pMenu=GetMenu();//获取当前菜单指针
pMenu->GetSubMenu(0)->InsertMenu(2,MF_BYPOSITION|MF_SEPARATOR);//在第一个子菜单第3个菜单项之前插入“分隔线”
第一个参数nPosition 要参照第二个参数nFlags的设置来确定含义。当