菜单命令的路由
命令消息是由OnCommadn这个函数来处理的
当单击菜单项参数命令消息后。框架类会收到此条消息,然后框架类会把消息给视类。视类会查找自己是否对该消息作出响应,如果有,则进行相应的处理结束路由过程。没有则交给文档类,文档类也会查找是否对消息做出响应,作出了则结束,否则 又给视类,视类又给框架类,框架类又给应用程序类。
屏蔽菜单项,使之不能用
(需要在CMainFrame::CMainFrame()中设置m_bAutoMenuEnable=FALSE;)
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
//GetMenu先获取菜单栏 然后GetSubMenu(0)获取第一个子菜单的指针,EnableMenuItem禁用菜单项第一个参数 的设置 取决于第二个参数的设置
添加UPDATE_COMMAND_UI对菜单操作
如图所示
void CMainFrame::OnUpdatePhone1(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
if(pCmdUI->m_nID==IDM_PHONE1)
pCmdUI->Enable(false);
}
右键弹出菜单的创建 两种方式
在MainFrame::OnCreate中试验如下
CMenu menu;
menu.CreatePopupMenu();
GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
GetMenu()->InsertMenu(2,MF_BYPOSITION |
MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello");
menu.AppendMenu(MF_STRING,112,"Weixin");
menu.AppendMenu(MF_STRING,113,"Mybole");
menu.Detach();
响应函数添加方法:
1) 在resource.h中添加资源ID定义
#define IDM_HELLO 111
2) 在MainFrm.h中声明消息响应。DECLARE_MESSAGE_MAP()之前添加 afx_msg void OnHello();
3) 在MainFrm.cpp中END_MESSAGE_MAP()之前,添加 ON_COMMAND(IDM_HELLO,OnHello)
4) 在MainFrm.cpp中添加CMainFrame::OnHello()函数定义
给系统菜单添加/删除菜单项
GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");
GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
MF_BYCOMMAND | MF_STRING,115,"维新");
GetMenu()->DeleteMenu(1,MF_BYPOSITION);
GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);*/
GetMenu()->DeleteMenu( GetMenu()->GetSubMenu(1)->GetMenuItemID(0),MF_BYCOMMAND);
动态添加系统菜单项
电话本程序:键盘输入人名,空格之后电话号码。回车之后,把人名添加到菜单项。当点击菜单时,显示电话本信息。
1, 给View添加private 的
CString m_strLine;//存储输入的字符串 CMenu m_menu;//菜单
int m_nIndex;//用于计数,是不是第一次
2, 添加View的public成员 CStringArray m_strArray;
3, 添加View的WM_CHAR消息响应函数
4, 在View::OnChar中添加如下代码 CClientDC dc(this);
if(0x0d==nChar) {
if(0==++m_nIndex)//如果是第一次,就创建菜单 {
m_menu.CreatePopupMenu();
GetParent()->GetMenu()->AppendMenu(MF_POPUP,
(UINT)m_menu.m_hMenu,"PhoneBook");
GetParent()->DrawMenuBar();//立即显示菜单 }
m_menu.AppendMenu(MF_STRING,IDM_PHONE1+m_nIndex,m_strLine.Left(m_strLine.Find(' ')));
m_strArray.Add(m_strLine);
m_strLine.Empty();
Invalidate();//擦除先前的背景,防止重叠显示 } else {
m_strLine+=nChar;
dc.TextOut(0,0,m_strLine); }
添加菜单的响应函数
方法一:
1) 在Toolbar上添加一个菜单,其弹出项为ID号为IDM_PHONE1, IDM_PHONE2, IDM_PHONE3。
2) 在Rsource.h中添加
#define IDM_PHONE1 201
#define IDM_PHONE2 202
#define IDM_PHONE3 203
3) 利用ClassWizard给菜单项添加响应函数,并编辑函数
4) 删除菜单项(其响应函数会依然存在,并且4步中利用了ID号,可以对应过去)
方法二:
视频没有提供,但我感觉应该有其他方法。方法一太死板
6, 另:由框架类捕获菜单响应,而不是由View处理,可以节约代码
1) 给MainFrame添加WM_COMMAND消息响应函数 可以LOWORD(wParam) wParam 的低序运行标识菜单项、控件或快捷键的命令ID
2) 在其中添加如下代码
int MenuCmdId=LOWORD(wParam);
CMenu2View *pView=(CMenu2View*)GetActiveView();
if(MenuCmdId>=IDM_PHONE1
&&MenuCmdId<IDM_PHONE1+pView->m_strArray.GetSize()) {
CClientDC dc(pView);
dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdId-IDM_PHONE1));
return TRUE; }
第6点提供的方法,不能解决第5点提出方法的限制,响应菜单还是和事先编好的ID相对应,不能动态增加
其他注意的地方:
1, 弹出菜单(Pop-up)是不能用来作命令响应的。此项设置在菜单属性栏内。
2, 将Toolbar的ID设为菜单的ID,二者即发生了关联。
3, 在计算子菜单菜单项的索引的时候,分隔栏符也算索引。
4, 消息影射函数
Cpp文件中
BEGIN_MESSAGE_MAP(CMenu2View, CView)
//{{AFX_MSG_MAP(CMenu2View)
//位置1
//}}AFX_MSG_MAP
位置2
END_MESSAGE_MAP()
头文件中
//{{AFX_MSG(CMenu2View)
位置3
//}}AFX_MSG
位置4
DECLARE_MESSAGE_MAP()
消息映射在位置1和位置2不一样,可以调用Classwizard看到修改结果
位置3和位置4的函数声明,随便放1或2都可以,没有影响