MFC(五)(菜单)
C……app类和C……doc类都不是从cwnd类派生的,不能使用直接使用messagebox(),可以使用全局的MessageBox()或者用应用程序框架的函数AfxMessageBox()
响应菜单项命令的顺序依次是:视图类、文档类、框架类、应用程序类
Windows消息分类:
标准消息:除WM_COMMAND之外所有以WM_开头的消息都是标准消息,从Cwnd派生的类都可以接受这类消息
命令消息:来自菜单、加速键、工具栏按钮的消息。这类消息都以WM_COMMAND形式呈现,在MFC中通过菜单项的标识ID来区分不同的命令消息
通告消息:由控件产生的消息如按钮、列表框选择等产生这类消息,这类消息也是以WM_COMMAND形式呈现,从CCmdTarget派生的类都可以接受这类消息,CWnd类实际派生于CCmdTarget类
总结:从CCmdTarget派生的类都可以接受命令消息和通告消息。。 从cwnd派生的类可以接受以上三类消息
设置标记菜单:
//getmenu获取菜单栏对象,然后用getsubmenu获取楼号对应的菜单对象,check……设置标记菜单,同理可以用该函数通过设置不同的参数来去除菜单标记
this->GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_CHECKED|MF_BYPOSITION);
设置默认菜单项:
this->GetMenu()->GetSubMenu(0)->SetDefaultItem(2,TRUE);
注:分割栏在子菜单中是占据索引位置的
设置图形标记菜单:
//获取系统的一些参数,当实参指定值为SM_CXMENUSIZE,SM_CXMENUSIZE,SM_CYMENUSIZE时获取的是菜单项上标记图形的默认尺寸
CString str;
str.Format("x=%d,y=%d",::GetSystemMetrics(SM_CXMENUSIZE),::GetSystemMetrics(SM_CYMENUSIZE));
MessageBox(str);
//两幅位图分别显示选中前和选中后显示的位图
this->GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(3,MF_BYPOSITION,&bitmap1,&bitmap2);
禁用菜单项:
this->GetMenu()->GetSubMenu(0)->EnableMenuItem(3,MF_BYPOSITION |MF_GRAYED );
//MFC为菜单提供了一种命令更新机制,程序运行时根据此机制去判断哪个菜单能使用哪个不能使用,默认机制下菜单项的更新都是MFC的命令更新机制完成的,如果我们要自己更新菜单状态就要把m_bAutoMenuEnable =false;设置为false(一般写在构造函数中)
移除、装载菜单项:
//当参数为NULL时就是移除菜单项
SetMenu(NULL);
//加载菜单项
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
//将菜单句柄和菜单项分离,同时也将菜单对象的所有权交给窗口对象
Detach();
MFC中菜单项状态的维护依赖于CN_UPDATE_COMMAND_UI消息
因此可以在CN_UPDATE_COMMAND_UI响应函数中进行以上一些对于菜单的操作,如:
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
if (ID_EDIT_CUT==pCmdUI->m_nID)
{
pCmdUI->Enable(false);
}
}
添加快捷菜单
Project菜单下的Add to project然后选择Components and Controls菜单项(注意应该在view类上添加该组件,view类覆盖了frame类)
动态添加菜单:
① 在菜单末尾添加
CMenu menu1;
menu1.CreateMenu();
//由于菜单类的句柄是HMENU类型因此要进行类型转换
this->GetMenu()->AppendMenu(MF_STRING,(UINT)menu1.m_hMenu,"我是谁");
//菜单对象的所有权交给窗口对象
menu1.Detach();
② 插入菜单
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
删除菜单:
this->GetMenu()->GetSubMenu(0)->DeleteMenu(0,MF_BYPOSITION);
动态添加菜单项的响应命令:
三个步骤:
① 在响应这个菜单项命令的程序类头文件中添加响应函数原型,添加的位置应该是在声明消息映射宏(DECLARE_MESSAGE_MAP)之上,两个AFX_MSG注释宏的后面,如:
afx_msg void OnHello()
② 在响应这个菜单项命令的程序类源文件消息映射表中添加消息映射,位置在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏之间,菜单命令消息的映射宏是ON_COMMAND宏,如ON_COMMAND(IDM_HELLO,OnHello)
③ 实现菜单命令消息响应函数的定义体,如:
Void CMainFrame::OnHello()
{
MessageBox(“hello world”);
}