MFC 菜单编程 -- 总结
菜单结构
- 一个菜单栏可以有若干个子菜单,而一个子菜单又可有若干个菜单项。
对于菜单栏的子菜单,由左至右从0开始索引。
对于特定的子菜单的菜单项,由上至下建立从0开始的索引。
访问子菜单和菜单项,均可通过其索引或标识进行。 - 对于在窗口客户区右键弹出的菜单,如果弹出菜单归属View 类窗口,则菜单项只能响应View 和Doc 类消息点击。
- 如果弹出菜单归属框架窗口,弹出菜单上的消息的路由遵循View -DOC-MainFrame-APP的响应顺序 。
菜单的相关重要函数
- CMenu* GetMenu( ) ; // 得到菜单指针
- CMenu* GetSubMenu( ) ; // 得到子菜单指针,也就是弹出菜单指针
- UINT CheckMenuItem( ); // 将菜单项加上或去掉√(对号)标记
a.如果第一个参数是ID号, 第二个参数必须是MF_BYCOMMAND | MF_CHECKED的组合
b.如果第一个参数是索引号, 第二个参数必须是MF_BYPOSITION | MF_CHECKED的组合 - BOOL SetDefaultItem(); // 设置缺省菜单,也就是将菜单项粗体显示
a.如果第一个参数是索引号,第二个参数必须是true
b.如果第一个参数是ID号,第二个参数必须是false
*注 :一个子菜单最多只能有一个缺省菜单项 - BOOL SetMenuItemBitmaps( ); // 设置位图标记,标记大小为13*13像素
a.如果第一个参数是ID号,第二个参数必须是MF_BYCOMMAND
b.如果第一个参数是索引号,第二个参数必须是MF_BYPOSITION
,第三个参数是没有选中时的位图,第四个参数是标记时的位图 - UINT EnableMenuItem(); //使菜单项有效,无效,或变灰
a.如果第一个参数是ID号,第二个参数必须是MF_BYCOMMAND 和有效,无效,或变灰 的组合
b.如果第一个参数是索引号,第二个参数必须是MF_BYPOSITION 和有效,无效,或变灰 的组合
*注 :若让此函数生效,必须在mainfrm构造函数中添加:m_bAutoMenuEnable =false,
此时,其他变灰的菜单项也就恢复为不变灰状态了,会有副作用的 - BOOL SetMenu( CMenu* pMenu ); //在当前窗口上设置新菜单或移除菜单。
如果参数为0,则是移除菜单。
自己创建菜单{CMenu menu;menu.LoadMenu(IDR_MENU1);
SetMenu(&menu);menu.Detach();} - HMENU Detach( ); // 如果将CMenu 对象设置为局部对象,使用Detach()从menu对象中分离窗口菜单句柄,从而当menu对象析构的时候窗口菜单资源不随之销毁
菜单的相关操作的实现方法
a.添加对号标记:
方法一: GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED ); //通过索引
方法二: GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED ); //通过ID
b.设置缺省菜单项:
每个子菜单最多只能有一个缺省菜单项
方法一: GetMenu()->GetSubMenu(0)->SetDefaultItem(1,true); //通过索引
方法二: GetMenu( )->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,false); //通过ID
c.添加图形标记:
方法一:通过ID
CBitmap bitmap; //必须设置为全局对象
bitmap.LoadBitmap(IDB_BITMAP1);
GetMenu( )->GetSubMenu(0)->SetMenuItemBitmaps(ID_FILE_NEW,MF_BYCOMMAND,&bitmap,&bitmap);
方法二:通过索引
CBitmap bitmap; //必须设置为全局对象
bitmap.LoadBitmap(IDB_BITMAP1);
GetMenu( )->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION ,&bitmap,&bitmap);
d.使菜单无效,变灰
//必须在构造函数中添加: m_bAutoMenuEnable = false;
GetMenu( )->GetSubMenu(0)->EnableMenuItem(ID_FILE_OPEN,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
e.移除菜单
SetMenu(0);
f.添加菜单
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
menu.Detach();
图形标记大小
系统获得位图标记的大小:
CString str;
str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMENUCHECK),GetSystemMetrics(SM_CYMENUCHECK));
MessageBox(str);
命令更新机制
菜单的UPDATE_COMMAND_UI消息响应
{
pCmdUI->Enable(false); // true和false 来设置能否使用或变灰
pCmdUI->SetCheck(true); // true和false 来设置标记
pCmdUI->SetText(“cut”); //改变菜单项文本内容
}
动态创建菜单
先定义几个常量:
#define IDM_MENU0 0
#define IDM_MENU1 1
#define IDM_MENU2 2
#define IDM_MENU3 3
#define IDM_ITEM0 10
#define IDM_ITEM1 11
#define IDM_ITEM2 12
#define IDM_ITEM3 13
#define IDM_ITEM4 14
#define IDM_ITEM5 15
#define IDM_ITEM6 16
// 在最后一个菜单项后面添加菜单项
BOOL AppendMenu ( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
BOOL AppendMenu ( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );
// 插入菜单项
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );
// 移除菜单项
BOOL RemoveMenu( UINT nPosition, UINT nFlags );
// 删除菜单项
BOOL DeleteMenu( UINT nPosition, UINT nFlags );
一 、创建非Popup类型菜单,不使用资源。
(一)创建非下拉菜单。
1。在窗口类的OnCreate函数里创建CMenu对象。如果是创建运用程序主框架窗口
的话,也可以在InitInstance()函数里。
2。声明一个CMenu对象:CMenu MyMenu;
3。调用MyMenu.CreateMenu()或MyMenu.LoadMenu()
4。调用若干次MyMenu.AppendMenu()或MyMenu.InsertMenu(),每调用一次创建一
个菜单项。
5。调用MyMneu.SetMenu()将菜单Attach到窗口上。
6。调用MyMenu.Detach()。
例子:
int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
CMenu MyMenu;
MyMenu.CreateMenu();
MyMenu.AppendMenu(MF_STRING,IDM_MENU0,"文件");
MyMenu.AppendMenu(MF_STRING,IDM_MENU1,"编辑");
MyMenu.AppendMenu(MF_STRING,IDM_MENU2,"查看");
MyMenu.AppendMenu(MF_STRING,IDM_MENU3,"帮助");
MyMenu.InsertMenu(IDM_MENU2,MF_BYCOMMAND,IDM_ITEM0,"有关");
this->SetMenu(&MyMenu);
MyMenu.Detach();
return 0;
}//各个函数的细节就不讲解了,看联机帮助是最好的。
这个方法是先把菜单创建好后再贴到窗口上去,然后用Detach()使菜单和MyMenu对象脱离关系,因为MyMenu对象马上就要超出作用域了,这一步是必须的。
(二)创建下拉菜单,不使用资源。
这种菜单当鼠标移动到菜单条目上面点击时不是去执行某段程序,而是弹出
一个下拉菜单。这需要用前面的方法创建两个菜单。第一个是鼠标未点击时看到
的那个菜单,另一个就是扮演下拉菜单的菜单。例子:
int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
CMenu MyMenu0,MyMenu1;
//下面这几条创建下拉菜单
MyMenu1.CreateMenu();
MyMenu1.AppendMenu(MF_STRING,IDM_ITEM0,"拷贝");
MyMenu1.AppendMenu(MF_STRING,IDM_ITEM1,"剪切");
MyMenu1.AppendMenu(MF_STRING,IDM_ITEM2,"粘贴");
MyMenu1.AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
MyMenu1.AppendMenu(MF_STRING,IDM_ITEM4,"全选");
MyMenu1.AppendMenu(MF_SEPARATOR,IDM_ITEM5,"");
MyMenu1.AppendMenu(MF_STRING,IDM_ITEM6,"删除");
//下面这两条创建鼠标未点击时看到的那个菜单
//其中第二句将下拉菜单张贴到第一个菜单上。
MyMenu0.CreateMenu();
MyMenu0.AppendMenu(MF_POPUP,(UINT)MyMenu1.m_hMenu,"编辑");
this->SetMenu(&MyMenu0);//将菜单张贴到窗口上
MyMenu0.Detach();//必须有
MyMenu1.Detach();//必须有
return 0;
}
二、创建Popup类型的菜单,也不用资源。
很多程序里,只要用鼠标右键点一下窗口客户区,就会在鼠标的位置弹出一
个菜单,这叫右键菜单。我们可以用CMenu类来制作。
制作这种菜单比制作第一类菜单稍微复杂点。首先要在窗口类里加个成员变
量:CMenu *MyMenu2;
然后在窗口类的构造函数里(或OnCreate()函数里)加上创建菜单的语句,再
在析构函数里加上销毁菜单的语句,最后在OnRButtonDown()函数里加上显示菜单
的语句。
创建菜单时,CMenu类对象应该用new来分配。
例子:
CMyWnd::CMyWnd()
{
//CMyWnd是从CWnd派生来的。
//先把菜单创建起来。
MyMenu2=new CMenu;
MyMenu2->CreatePopupMenu();
MyMenu2->AppendMenu(MF_STRING,IDM_ITEM0,"拷贝");
MyMenu2->AppendMenu(MF_STRING,IDM_ITEM1,"剪切");
MyMenu2->AppendMenu(MF_STRING,IDM_ITEM2,"粘贴");
MyMenu2->AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
MyMenu2->AppendMenu(MF_STRING,IDM_ITEM4,"全选");
MyMenu2->AppendMenu(MF_SEPARATOR,IDM_ITEM3,"");
MyMenu2->AppendMenu(MF_STRING,IDM_ITEM5,"删除");
}
CMyWnd::~CMyWnd()
{
MyMenu2->DestroyMenu();//销毁菜单所占用的系统资源
delete MyMenu2;//销毁菜单类对象
}
void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point)
{
RECT rect;
GetWindowRect(&rect);
//显示菜单
MyMenu2->TrackPopupMenu(TPM_RIGHTALIGN,point.x+rect.left,point.y+
rect.top,this,NULL);
}
from:http://blog.csdn.net/ltag0110rtag/article/details/7368633
MFC 菜单编程 -- 总结的更多相关文章
- MFC对话框编程详细学习笔记
因最近研究工作要用到MFC,故再次重温了孙鑫老师的MFC对话框编程,因所用的编译软件为VS2008,与视频中孙老师使用的VC++6.0有很大出入,造成很大不便,我通过各方查找,实现了VS2008相对应 ...
- 孙鑫MFC学习笔记6:菜单编程
1.对菜单响应的顺序: 视类,文档类,框架类,应用程序类 2.消息的分类 3.CWnd继承自CCmdTarget类, 所以从CWnd派生出的类也可以接收WM_COMMAND消息 4.命令的消息路由 5 ...
- 实现MFC菜单画笔画圆,并且打钩
这个是用最简单的方法,移动客户区,圆会不见,所以下一篇我还要改进. 首先新建一个MFC单文件,在资源那里的菜单下,建立画笔,可以弹出红画笔,蓝画笔和绿画笔,,给出ID_RED,ID_BLUE,ID_G ...
- 转:MFC网络编程学习
要学习好网路编程,主要看以下几个方面: 1.掌握概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等. 2.在实际Windows网络通信软件开发中,异步非阻 ...
- mfc socket编程
socket编程用法---- 随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益重要.由于C++语言对底层操作的优越性,许多文章都曾经介绍过用VC++进行Socket编程的方法.但由于都 ...
- 《转》MFC网络编程学习
原地址:http://www.cnblogs.com/renyuan/archive/2013/06/04/3117006.html要学习好网路编程,主要看以下几个方面: 1.掌握概念,诸如:同步(S ...
- vc2008中mfc菜单、控件等汉字显示为问号或乱码的解决方法
在vc2008中建立基于mfc的project.在向导的Application type页面中如果在resource language选项中选择"英语(美国)"(图一),那么在pr ...
- 【MFC - 菜单】在对话框程序中添加菜单栏(CMenu)(转)
原文转自 http://lishiqiang1988.blog.163.com/blog/static/41147912201382104631547/ VS2010的MFC对话框程序中添加菜单栏的过 ...
- MFC 网络编程中::connect返回-1问题
在MFC编写网络时遇到了::connect总是返回-1,但是与服务器可以进行接收和发送消息的操作. 原因是在进行连接的时候我没有进行初始化:::WSAStartup(w, &data);//动 ...
随机推荐
- VRTK3.3.0-002获取手柄事件
1.首先创建VRScripts空物体,用来存放脚本,在其下创建Right空物体并添加VRTK_ControllerEvents脚本 2.Right作为右手手柄,拖拽到[VRTK_SDKManager] ...
- PAT甲级——1102 Invert a Binary Tree (层序遍历+中序遍历)
本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90577042 1102 Invert a Binary Tree ...
- 寒假作业第二组C题题解
这道题题意很简单,主要是练习map的使用.看输入有三个数据,水果名,地名,和出现次数.再看输出,很容易想到map<string,int> string是水果,int是次数,那个地名怎么用m ...
- Hadoop实战项目:小文件合并
项目背景 在实际项目中,输入数据往往是由许多小文件组成,这里的小文件是指小于HDFS系统Block大小的文件(默认128M),早期的版本所定义的小文件是64M,这里的hadoop-2.2.0所定义的小 ...
- 渣渣菜鸡的 ElasticSearch 源码解析 —— 启动流程(上)
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/11/es-code02/ 前提 上篇文章写了 ElasticSearch 源码解析 -- ...
- jQuery dataTable 操作个人使用总结
用过之后总会忘,不停的查,不停的忘.这里记录一下,仅为个人简单总结,具体使用方法请看官方API文档. 1. 获取表中行数. var rowNum = $(tableSelector).DataTab ...
- 【持续更新】MyBatis相关
MyBatis开发结构 #与$的区别
- 【Linux】Ubuntu配置zshell&oh-my-zsh
zshell:https://archive.codeplex.com/?p=shell oh-my-zsh: https://github.com/robbyrussell/oh-my-zsh 终极 ...
- 如何检查linux 下是否安装java(jdk)环境
大家可通过下面五条命令来查看linux 系统是否安装了java 环境 1.java -version 2.which java 3.rpm -qa |grep java 4.echo $PATH 5. ...
- cocos2d-x入门学习篇;切换场景
手机游戏开发最近很火爆,鉴于一直在学习c++,看起来上手就比较快了.这篇文章来自皂荚花 cocos2d-x技术,我把我的想法分享给大家. 首先来看一段代码: CCScene* HelloWorld:: ...