标签:
Windows-菜单编程基本技术
一,简介
在许多的框架中都免不了对菜单进行操作,不管是QT,Android还是IOS,基本的应用程序框架都会涉及到对菜单的API的调用,但是万变不其宗,菜单的基本概念我们清楚之后,我们就能否更好的理解和调用,MFC中对菜单的基本操作相对简单,其中有点复杂的也就算自己实现菜单的命令响应函数的步骤,这其中涉及到对MFC消息映射机制的运用。
二,MFC菜单的分类
1.弹出式菜单
默认顶层菜单为弹出式菜单,不能响应菜单命令,将菜单应用为弹出式需要勾选Pop-Up属性,如下图。
2.菜单栏,子菜单,菜单项三者的区分
相信大家应该能够看明白吧,这是博主在书中总结出的,绝对正确。
三,MFC菜单命令的路由
基本路线是:View->Doc->Frame->App
具体过程分析:当我们点击某个菜单项的时候,最先接受的是Frame类。Frame类将接收的消息交给子窗口View类,View类首先处理。View类根据消息映射机制判断自身是否对此消息相应,响应就处理,消息路由结束。不响应就交给Doc类,Doc类同样判断自身是否对该消息进行响应,响应就处理,不响应就将此消息还给View类,View类再将此消息交给Frame类,Frame再判断自己是否对这个命令消息进行响应,响应就处理,不响应就再交给App类处理。
四,Windows消息分类
1.标准消息
除了WM_COMMAND之外,所有以WM_开头的都是标准消息。
2.命令消息
来自菜单,加速键或者工具栏的按钮的消息,这类消息都以WM_COMMAND形式呈现,通过ID来区分不同的命令。
3.通告消息
控件产生的消息,例如按钮的单击等,目的是为了向其父窗口通知事件的发生,这类消息也是以WM_COMMAND形式呈现。
从CWnd派生的类,三种消息都可以接收。
从CCmdTarget派生的类,不能接收标准消息。
五,基本菜单操作
1.注意:分隔栏也是一个菜单项,必须注意。
2.标记菜单
图片:
创建代码:
#if 0
//通过索引设置标记菜单
GetMenu()->GetSubMenu(0)->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED);
/*许多的菜单函数的第一个参数的取值由第二个参数来确定*/
#endif
#if 0
//通过ID来设置标记菜单
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW, MF_BYCOMMAND | MF_CHECKED);
#endif
3.默认菜单项(以粗体显示的菜单项)
注意:一个子菜单分支只能有一个默认菜单项
图片:
创建代码:
#if 0
//通过索引设置默认的菜单项
GetMenu()->GetSubMenu(0)->SetDefaultItem(1, TRUE);
#endif
#if 0
//通过ID设置默认的菜单项
GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN, FALSE);
#endif
#if 0
//设置分隔线后面一个菜单项打印为默认菜单项,分割线也算一个菜单项,所以打印的索引是4(分割线) + 1 = 5
GetMenu()->GetSubMenu(0)->SetDefaultItem(5, TRUE);
#endif
4.图形标记菜单
简介:就是菜单项前面有一个相对应的图形标记。
图片:
一定要注意设置的位图的尺寸要跟系统规定的尺寸差不多,可以利用GetSystemMetrics函数
#if 1
//设置图形标记菜单
CString str;
/*
//x = 15 y = 15所以默认的图形标记菜单的位图大小为15 * 15
str.Format(_T("x = %d, y = %d"), GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
MessageBox(str);
*/
//设置图形标记菜单
GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0, MF_BYPOSITION, &m_bitmap, &m_bitmap);
#endif
5.禁用菜单项
注意:区分禁用与变灰,一般来说禁用一个菜单项都会让这个菜单项变为灰色。
另外,为了禁用菜单项,必须取消MFC的默认命令更新机制,在CMainFrame的构造函数中设置:m_bAutoMenuEnable = FALSE;即可
创建代码:
#if 0
//通过索引禁用菜单项
GetMenu()->GetSubMenu(0)->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
#endif
#if 0
//通过ID禁用菜单项
GetMenu()->GetSubMenu(0)->EnableMenuItem(ID_FILE_OPEN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
#endif
6.移除菜单栏
在MFC的框架类中可以设置不显示菜单栏这个对象。
设置的代码
#if 0
//移除菜单
SetMenu(nullptr);
#endif
7.创建菜单栏对象
MFC也给我们提供了创建菜单栏对象的方法
创建代码:
#if 0
//创建菜单
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
//分离菜单句柄与菜单对象,防止局部变量出错
menu.Detach();
#endif
8.快捷菜单(上下文菜单)
简介:就是我们再程序中右键弹出的菜单项
创建分为3个步骤
第一步:增加菜单资源,设置ID
第二步:为需要响应鼠标右键消息的类添加WM_RBUTTONDOWN消息
第三步:为菜单资源的菜单项设置响应函数
9.动态菜单操作
前面介绍的都是菜单的静态操作,这里介绍下菜单的动态操作。
9**.1菜单栏尾部添加子菜单**
#if 0
//添加弹出式子菜单
CMenu menu;
menu.CreateMenu();
GetMenu()->AppendMenu(MF_POPUP, (UINT_PTR)(menu.m_hMenu), _T("Test2"));
menu.Detach();
#endif
9.2菜单栏中插入子菜单
#if 0
//插入子菜单
CMenu menu;
//先要创建menu对象
menu.CreateMenu();
//插入子菜单
GetMenu()->InsertMenu(2, MF_POPUP | MF_BYPOSITION, (UINT_PTR)(menu.m_hMenu), _T("Test3"));
//因为是局部变量的menu,所以需要分离
menu.Detach();
#endif
9.3根据调用这个函数的对象来删除对应的菜单项
#if 0
//删除索引为1的子菜单
GetMenu()->DeleteMenu(1, MF_BYPOSITION);
#endif
#if 0
//删除第一个子菜单的索引为2的菜单项
GetMenu()->GetSubMenu(0)->DeleteMenu(2, MF_BYPOSITION);
#endif
六,MFC菜单命令更新机制
每一个子菜单下面的菜单项都需要设置自身的状态,这就需要设置响应的更新机制,MFC给我们提供了这种更新机制,利用MFC编程时,菜单项的状态的维护依赖于UPDATE_COMMAND_UI消息,但是只能应用于菜单项。
下面是一个示例,使得我们可以控制编辑下面的剪切是否可用
1.添加剪切更新处理命令
2.定义更新响应函数
这样我们就可以对剪切这个菜单项,进行状态的设置。
**下面介绍些MFC命令更新机制的原理:
当要显示菜单的时候,西永发出WM_INITMENUPOPUP消息,然后由程序窗口的基类接管,他会创建一个CCmdUI对象,并与程序子菜单的第一个菜单项关联,调用该对象的一层成员函数DoUpdate(),这个函数发出UPDATE_COMMAND_UI消息,这条消息带有一个指向CCmdUi的对象指针。这时,系统会判断该类是否有ON_UPDATE_COMMAND_UI宏去捕获这个菜单项消息,找到就调用响应函数处理,当更新完第一个菜单项后,同一个CCmdUI对象就设置为与第二个菜单项相关联,依次顺序进行,直到完成所有菜单项的处理。这就是MFC菜单项的命令更新机制。**
七,总结
这次主要介绍了菜单相关的编程技术,都是基本的API使用和概念,打牢基础很重要,下面是本次使用的资料。
自己总结的思维导图
网盘资料:https://yunpan.cn/cPbJkXRRvnkNe 访问密码 0a8f
标签:
原文地址:http://blog.csdn.net/qq_22075977/article/details/51335301