1.通过手工编程创建菜单
//创建一个空的顶层菜单
CMenu menuMain;
menuMain.CreateMenu ();
//创建File菜单,并把它挂接到顶层菜单
CMenu menuPopup;
menuPopup.CreatePopupMenu ();
menuPopup.AppendMenu (MF_STRING, ID_FILE_EXIT, "E&xit");
//传递给AppendMenu的MF_POPUP参数通知Windows它的第二个参数是一个菜单的句柄,而不是菜单项ID
menuMain.AppendMenu (MF_POPUP, (UINT) menuPopup.Detach (), "&File");
//创建Shape菜单,并把它挂接到顶层菜单
menuPopup.CreatePopupMenu ();
menuPopup.AppendMenu (MF_STRING, ID_SHAPE_CIRCLE, "&Circle/tF7");
menuPopup.AppendMenu (MF_STRING, ID_SHAPE_TRIANGLE, "&Triangle/tF8");
menuPopup.AppendMenu (MF_STRING, ID_SHAPE_SQUARE, "&Square/tF9");
menuMain.AppendMenu (MF_POPUP, (UINT) menuPopup.Detach (), "&Shape");
//将菜单挂接到框架窗口
SetMenu (&menuMain);
//将顶层菜单与menuMain分离,以便该函数结束时,顶层菜单不至于消除
menuMain.Detach ();
2.通过手工编程修改菜单
函数 | 说明 |
AppendMenu | 在菜单尾部添加菜单项 |
InsertMenu | 在菜单给定位置插入菜单项 |
ModifyMenu | 改变菜单项的命令ID、正文或其他特性 |
DeleteMenu | 删除菜单项和相关子菜单 |
RemoveMenu | 删除菜单项 |
//获得窗口顶层菜单
CMenu* pMenu = GetMenu ();
//删除索引为1的菜单
pMenu->DeleteMenu (1, MF_BYPOSITION);
//获得索引位1的子菜单
CMenu* pMenu = GetMenu ()->GetSubMenu (1);
pMenu->DeleteMenu (2, MF_BYPOSITION); // Delete Square
//删除菜单ID为ID_SHAPE_CIRCLE的菜单项
pMenu->DeleteMenu (ID_SHAPE_CIRCLE, MF_BYCOMMAND); // Delete Circle
CMenu* pMenu = GetMenu ();
//删除菜单ID为ID_SHAPE_CIRCLE的菜单项
pMenu->DeleteMenu (ID_SHAPE_CIRCLE, MF_BYCOMMAND);
3.系统菜单
//获取指向系统菜单的指针
CMenu *pSystemMenu = GetSystemMenu(false);
//添加分隔符
pSystemMenu->AppendMenuA(MF_SEPARATOR);
//添加”About MyApp”菜单,其ID为ID_SYSMENU_ABOUT
pSystemMenu->AppendMenuA(MF_STRING, ID_SYSMENU_ABOUT, _T("系统菜单"));
这一段代码应该放在主窗口的OnCreate处理程序中。
用户选中系统菜单中的某项时,窗口接收到WM_SYSCOMMAND消息。
//IN CMainWindow MESSAGE MAP
ON_WM_SYSCOMMAND()
void CMainFrame::OnSysCommand (UINT nID, LPARAM lparam)
{
//这一命令处理程序使得系统菜单中的close命令在框架窗口中失效
if((nID & 0xFFF0) != SC_CLOSE)
CFrameWnd::OnSysCommand (nID, lparam);
}
4.上下文菜单
上下文菜单和子菜单一样都不是顶层菜单,MFC的CMenu::TrackPopupMenu函数显示一个上下文菜单:
BOOL TrackPopupMenu (UINT nFlags, int x, int y, CWnd* pWnd,
LPCRECT lpRect = NULL);
x好y确定该菜单在屏幕上出现的位置。nFlags包含的标志位确定菜单相对于x值水平对齐,以及哪个鼠标键可以用来选中菜单中的菜单项。对其标志TPM_LEFTALIGN, TPM_CENTERALIGN, 和TPM_RIGHTALIGN告诉windows分别确定了菜单左边界、中心、右边界的位置,TPM_LEFTBUTTON 和TPM_RIGHTBUTTON确定鼠标左键和右键是否能进行菜单项选择。只能给定一个对齐标志,但两个鼠标按钮可以同时使用或只用一个。pWnd确定窗口能接收到菜单中各种操作引发的消息,而lpRect指向一个CRect对象或Rect结构,它们包含一个举行的屏幕坐标,在这个矩形中点击鼠标菜单不会取消。如果lpRect==NULL,则在菜单外单击鼠标菜单会取消。
pMenu->TrackPopupMenu (TPM_LEFTALIGN ¦ TPM_LEFTBUTTON ¦ TPM_RIGHTBUTTON, 32, 64, AfxGetMainWnd ());
这一语句显示菜单,从屏幕左上角看,菜单左上角在左面32个像素、下面64个像素的位置。用户可以用鼠标左键或右键在菜单中选择。
TrackPopupMenu一般被调用相应WM_CONTEXTMENU消息,MFC的ON_WM_CONTEXTMENU宏把WM_CONTEXTMENU消息和消息处理程序
OnContextMenu对应起来。
afx_msg void OnContextMenu (CWnd* pWnd, CPoint point); pWnd确定单击鼠标所在的窗口,point包含光标在屏幕上的坐标。
取得上下文菜单的指针,可以构造CMenu对象,并用它的成员函数构造;也可以按照顶层菜单的加载方式从资源文件中加载菜单。
下面的菜单模板定义了包含单个子菜单的菜单:
IDR_CONTEXTMENU MENU
BEGIN
POPUP ""
BEGIN
MENUITEM "&Copy", ID_CONTEXT_COPY
MENUITEM "&Rename", ID_CONTEXT_RENAME
MENUITEM "&Delete", ID_CONTEXT_DELETE
END
END
下面的语句将菜单加载到CMenu对象,并以上下文菜单形式显示。
CMenu menu;
menu.LoadMenu (IDR_CONTEXTMENU);
CMenu* pContextMenu = menu.GetSubMenu (0);
pContextMenu->TrackPopupMenu (TPM_LEFTALIGN ¦
TPM_LEFTBUTTON ¦ TPM_RIGHTBUTTON, point.x, point.y,
AfxGetMainWnd ());