转自:http://www.jizhuomi.com/software/212.html

上一节讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用。

CMenu类的主要成员函数

MFC为菜单的操作提供了CMenu类,下面就常用的几个成员函数进行简单的介绍。

BOOL LoadMenu(UINT nIDResource);

加载菜单资源,并将其附加到CMenu对象上。参数nIDResource指定了要加载的菜单资源的ID。如果菜单加载成功则返回TRUE,否则返回FALSE。

BOOL DeleteMenu(UINT nPosition,UINT nFlags);

在菜单中删除一个菜单项。参数nPosition指定要删除的菜单项。参数nFlags就用来解释nPosition的意义,为MF_BYCOMMAND时说明nPosition表示菜单项的ID,为MF_BYPOSITION时说明nPosition表示菜单项的位置,第一个菜单项的位置为0。如果删除菜单项成功则返回TRUE,否则返回FALSE。

BOOL TrackPopupMenu(UINT nFlags,int x,int y,CWnd* pWnd,LPCRECT lpRect = 0);

用来在指定位置显示一个浮动的弹出式菜单。参数nFlags指定屏幕坐标和鼠标位置的标志,可以是以下取值:

TPM_CENTERALIGN:菜单在水平方向上相对于参数x指定的坐标值居中显示
       TPM_LEFTALIGN:菜单的左侧与参数x指定的坐标值对齐
       TPM_RIGHTALIGN:菜单的右侧与参数x指定的坐标值对齐
       TPM_BOTTOMALIGN:菜单的底部与参数y指定的坐标值对齐
       TPM_TOPALIGN:菜单项的顶部与参数y指定的坐标值对齐
       TPM_VCENTERALIGN:菜单在垂直方向上相对于参数y指定的坐标值居中显示

这里先介绍这几个比较常用的,其他可参见MSDN。参数x指定弹出式菜单的水平方向的屏幕坐标,参数y指定菜单顶部垂直方向上的屏幕坐标,参数pWnd指明哪个窗口拥有此弹出式菜单,不能为NULL,参数lpRect忽略。

UINT CheckMenuItem(UINT nIDCheckItem,UINT nCheck);

在弹出菜单中为菜单项增加选中标记或移除选中标记。参数nIDCheckItem指定要选中或取消选中的菜单项。参数nCheck指定菜单项的选中状态和如何根据nIDCheckItem确定菜单项的位置,可以是MF_CHECKED或MF_UNCHECKED与MF_BYPOSITION或MF_BYCOMMAND的组合,这几个标志的含义如下:

MF_BYCOMMAND:为默认值。说明参数nIDCheckItem表示菜单项的ID
       MF_BYPOSITION:说明参数nIDCheckItem表示菜单项的位置,第一个菜单项的位置是0
       MF_CHECKED:为菜单项添加选中标记
       MF_UNCHECKED:为菜单项移除选中标记

该函数返回菜单项之前的状态:MF_CHECKED或MF_UNCHECKED, 如果菜单项不存在则返回0xFFFFFFFF。

UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);

激活、禁用菜单项或使其变灰。参数nIDEnableItem指定要激活、禁用或变灰的菜单项。参数nEnable指定操作的类型,可以是MF_DISABLED、MF_ENABLED或MF_GRAYED与MF_BYCOMMAND或MF_BYPOSITION的组合,这些值的含义如下:

MF_BYCOMMAND:同CheckMenuItem
       MF_BYPOSITION:同CheckMenuItem
       MF_DISABLED:禁用菜单项,使其不能被选择但不变灰
       MF_ENABLED:激活菜单项,使其能够被选择并由变灰状态恢复
       MF_GRAYED:禁用菜单项,使其不能被选择并变灰

该函数返回菜单项之前的状态:MF_DISABLED、MF_ENABLED或MF_GRAYED

CMenu* GetSubMenu(int nPos) const;

获取弹出菜单的CMenu对象。参数nPos指定弹出菜单在菜单中的位置,不能使用ID。返回值是CMenu对象的指针,该CMenu对象的m_hMenu成员为由nPos指定的弹出菜单的句柄,如果不存在这样的CMenu对象则返回NULL,然后创建一个临时弹出菜单。

CMenu类的成员函数先讲这些,如果大家需要用其他的函数可以到MSDN中查看,解释的很清楚。

菜单消息

菜单主要能发送两种消息:COMMAND消息和UPDATE_COMMAND_UI消息。下面分别讲解:

COMMAND消息:在菜单项被点击时发送该消息。

UPDATE_COMMAND_UI消息:用来维护菜单项的各项状态,包括激活、禁用、变灰、选中、未选中等。在下拉菜单每次打开的时候,所有菜单项的此消息都会被发送出去。如果所属类中为菜单项的该消息添加了处理函数,则执行相应函数更新菜单状态,如果菜单项没有此消息处理函数,也没有COMMAND消息的处理函数,那么它就会变灰。

菜单的应用实例

先讲一下本实例要实现的功能,此实例是在上一节创建的单文档工程Example34的基础上完成的,上一节中为主菜单栏添加了“Tools”菜单项,并设置它的第一个子菜单项为“Draw”,另外我们还要为主菜单栏添加“Settings”项,然后为其添加一个子菜单项“Draw Enable”,我们通过“Draw Enable”菜单项的选中状态控制菜单项“Draw”的激活状态,如果“Draw Enable”菜单项选中,则“Draw”菜单项激活,点击它弹出一个MessageBox,否则“Draw”菜单项禁用。程序中已经在Example34View类中自动生成了OnRButtonUp(UINT /* nFlags */, CPoint point)函数,并在其中实现了弹出右键菜单的功能,这里用CMenu类的TrackPopupMenu成员函数重新做一遍。

注意:Example34的CMainFrame类中定义的菜单并没有使用常用的CMenu类,而是用的CMFCMenuBar类(自VS2008起提供),但菜单的消息处理函数的添加是相同的。

下面是具体步骤:

1. 打开Example34工程的IDR_MAINFRAME菜单资源,在“Help”菜单项前通过“Insert New”操作插入一个菜单项,Caption设为“Settings”,在新菜单项的子菜单中再添加一个菜单项,Caption设为“Draw Enable”,ID默认为ID_SETTINGS_DRAWENABLE。

2. 因为此菜单为CMainFrame所拥有,所以我们在CMainFrame类中对菜单进行操作。在“MainFrm.h”中为CMainFrame类添加成员变量bool m_bDraw,以标识当前是否可以点击Tools->Draw菜单项,并在CMainFrame类的构造函数中为m_bDraw初始化:m_bDraw = TRUE。

3. 为菜单项Tools->Draw的COMMAND消息和UPDATE_COMMAND_UI消息分别添加处理函数CMainFrame::OnToolsDraw()和OnUpdateToolsDraw(CCmdUI *pCmdUI),这里要注意,添加处理函数时class list中应选择CMainFrame。

然后修改两个函数的实现为:

C++代码
void CMainFrame::OnToolsDraw()
{
// TODO: Add your command handler code here
// 弹出提示框
MessageBox(_T("Draw"));
} void CMainFrame::OnUpdateToolsDraw(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
// 根据m_bDraw的值设置是否激活
pCmdUI->Enable(m_bDraw);
}
 

4. 为菜单项Settings->Draw Enable的COMMAND消息和UPDATE_COMMAND_UI消息分别添加处理函数CMainFrame::OnSettingsDrawenable()和OnUpdateSettingsDrawenable(CCmdUI *pCmdUI),并将它们的实现修改为:

C++代码
void CMainFrame::OnSettingsDrawenable()
{
// TODO: Add your command handler code here
// 绘图使能标识取反
m_bDraw = !m_bDraw;
} void CMainFrame::OnUpdateSettingsDrawenable(CCmdUI *pCmdUI)
{
// TODO: Add your command update UI handler code here
// 根据m_bDraw的值设置是否选中
pCmdUI->SetCheck(m_bDraw);
}
 

5. 运行程序,效果图如下:

6. 接下来我们要重新实现右键菜单。大家以后可以仿照VS2010自动生成的代码实现右键菜单,也可以用下面讲到的方法。首先将CExample34View::OnRButtonUp(UINT /* nFlags */, CPoint point)函数内的代码都注释掉,保证原来的弹出方法失效。

7. 自动生成代码是在鼠标弹起时实现的右键菜单,我们这里改为在鼠标按下时就弹出右键菜单。在class view类视图中点击CExample34View,然后在属性页的messages列表中找到WM_RBUTTONDOWN,添加其消息响应函数CExample34View::OnRButtonDown(UINT nFlags,CPoint point),修改其实现为:

C++代码
void CExample34View::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CMenu menu; // 菜单(包含主菜单栏和子菜单)
CMenu *pSubMenu; // 右键菜单 // 加载菜单资源到menu对象
menu.LoadMenu(IDR_POPUP_EDIT);
// 因为右键菜单是弹出式菜单,不包含主菜单栏,所以取子菜单
pSubMenu = menu.GetSubMenu();
// 将坐标值由客户坐标转换为屏幕坐标
ClientToScreen(&point);
// 弹出右键菜单,菜单左侧与point.x坐标值对齐
pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this); CView::OnRButtonDown(nFlags, point);
}
 

8. 最终的右键菜单效果:

本节内容不少,大家可以慢慢消化。菜单的讲解就到这里了。

VS2010-MFC(菜单:菜单及CMenu类的使用)的更多相关文章

  1. VS2010 MFC中 在FormView派生类里获取文档类指针的方法

    经过苦苦调试,今晚终于解决了一个大问题. 我想要实现的是:在一个FormView的派生类里获取到文档类的指针. 但是出现问题:试了很多办法,始终无法获取到. 终于,此问题在我不懈地调试加尝试下解决了. ...

  2. 怎样使用CMenu类

    CMenu类从CObject类派生而来.为什么要使用CMenu类呢?AppWzard不是把菜单做好了吗?在资源编辑器上修改菜单不是很方便吗?     我是个vc++初学者,自从当斑竹以来,天天看贴子, ...

  3. VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)

    鸡啄米在上一节中讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用. CMenu类的主要成员函数 MFC为菜单的操作提供了CMenu类,下面鸡啄米就常用的几个成员函数进行简单的介绍. B ...

  4. VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)

    上一节讲了标签控件Tab Control以后,常用控件的内容就全部讲完了,当然并没有包括所有控件,主要是一些很常用很重要的控件.本节开始鸡啄米将为大家讲解菜单的概念及使用. 菜单简介 菜单在界面设计中 ...

  5. 菜单及CMenu类的使用

    CMenu类的主要成员函数 BOOL LoadMenu(UINT nIDResource); 加载菜单资源,并将其附加到CMenu对象上.参数nIDResource指定了要加载的菜单资源的ID.如果菜 ...

  6. VS2010/MFC编程入门之三十六(工具栏:工具栏资源及CToolBar类)

    上一节中鸡啄米讲了菜单及CMenu类的使用,这一节讲与菜单有密切联系的工具栏. 工具栏简介 工具栏一般位于主框架窗口的上部,菜单栏的下方,由一些带图片的按钮组成.当用户用鼠标单击工具栏上某个按钮时,程 ...

  7. MFC中菜单变灰的问题

    MFC中菜单变灰 方法1:有UpdateCmdUI句柄时 定义一个BOOL变量m_b来标志菜单项是否有效, 该菜单项响应UPDATE_COMMAND_UI消息,在消息处理函数中pCmdUI->E ...

  8. 如何给MFC的菜单项添加快捷键

    我们一起分享,如何给MFC的菜单项添加快捷键.[程序在VC6.0编译环境下编译通过.(VS2010的编译环境大同小异)] 1.程序演示环境 1.1新建一个[对话框(Dialog)]的程序.然后,New ...

  9. 两种简单实现菜单高亮显示的JS类(转载)

    两种简单实现菜单高亮显示的JS类   近期在写一个博客管理后台的前端,涉及在同一页面两种高亮显示当前菜单的需求.记得当年写静态页时,为了实现高亮都是在每个页面加不同的样式,呵.高亮显示我觉得对于web ...

随机推荐

  1. Java——Eclipse使用

    从这开始使用IDE啦~ ①File → New → Java Project →填写工程名字,选择jdk版本,其他默认,单击finish. ②在Src(源文件)上鼠标右键 → new → packag ...

  2. Yii2配置

    最外层:配置文件,params Yii2导航 <?php NavBar::begin([ 'brandLabel' => '大海', 'brandUrl' => Yii::$app- ...

  3. thinkphp环境要求

    框架本身没有什么特别模块要求,具体的应用系统运行环境要求视开发所涉及的模块.ThinkPHP底层运行的内存消耗极低,而本身的文件大小也是轻量级的,因此不会出现空间和内存占用的瓶颈. PHP版本要求 P ...

  4. 关于windows下远程连接Linux服务器的方法(CentOs)

    1.服务器端安装VNC 1) 安装vncserver yum install -y tigervnc-server 2) 修改配置 vi /etc/sysconfig/vncservers   最后两 ...

  5. 25 面向对象设计实例——基于PCL点云库的通用工具开发

    0 引言 问题背景:pcl中提供了大量工具,用于对点云和三角面片文件进行处理和显示.在研究中,存在很多简易的需求,比如点云坐标转换,点云的打开显示以及同步显示,点云的最小包络求解,点云的格式转换等等. ...

  6. NX二次开发-算法篇-创建最大边界包容盒

    NX9+VS2012 #include <uf.h> #include <uf_obj.h> #include <uf_modl.h> #include <u ...

  7. UVA-10200-Prime Time-判断素数个数(打表预处理)+精度控制

    题意: 给出a.b区间,判断区间内素数所占百分比 思路: 注意提前打表和控制精度1e-8的范围足够用了 细节: 精度的处理 判断素数的方法(且返回值为bool) 数据类型的强制转换 保存素数个数 提前 ...

  8. Spark 调优之数据倾斜

    什么是数据倾斜? Spark 的计算抽象如下 数据倾斜指的是:并行处理的数据集中,某一部分(如 Spark 或 Kafka 的一个 Partition)的数据显著多于其它部分,从而使得该部分的处理速度 ...

  9. 20140425 malloc和new不同 dynamic何时返回0

    1.malloc/free和new/delete区别 http://blog.csdn.net/hackbuteer1/article/details/6789164 相同点:都可用于申请动态内存和释 ...

  10. Python中and_Or

    自 http://www.cnblogs.com/BeginMan/p/3197123.html 一.and: 在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返 ...