热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MFC菜单编程--总结

菜单结构一个菜单栏可以有若干个子菜单,而一个子菜单又可有若干个菜单项。对于菜单栏的子菜单,由左至右从0开始索引。对于特定的子菜单的菜单项,由上至下建立从0开始的索引。访问子菜单和菜单项,均可

菜单结构

  1. 一个菜单栏可以有若干个子菜单,而一个子菜单又可有若干个菜单项。
    对于菜单栏的子菜单,由左至右从0开始索引。
    对于特定的子菜单的菜单项,由上至下建立从0开始的索引。
    访问子菜单和菜单项,均可通过其索引或标识进行。
  2. 对于在窗口客户区右键弹出的菜单,如果弹出菜单归属View 类窗口,则菜单项只能响应View 和Doc 类消息点击。
  3. 如果弹出菜单归属框架窗口,弹出菜单上的消息的路由遵循View -DOC-MainFrame-APP的响应顺序 。

 

菜单的相关重要函数

  1. CMenu*    GetMenu( ) ;                  // 得到菜单指针
  2. CMenu*    GetSubMenu( ) ;           // 得到子菜单指针,也就是弹出菜单指针
  3. UINT CheckMenuItem( );              // 将菜单项加上或去掉√(对号)标记
    a.如果第一个参数是ID号,    第二个参数必须是MF_BYCOMMAND | MF_CHECKED的组合
    b.如果第一个参数是索引号, 第二个参数必须是MF_BYPOSITION   | MF_CHECKED的组合
  4. BOOL SetDefaultItem();                // 设置缺省菜单,也就是将菜单项粗体显示
    a.如果第一个参数是索引号,第二个参数必须是true
    b.如果第一个参数是ID号,第二个参数必须是false
    *注 :一个子菜单最多只能有一个缺省菜单项
  5. BOOL SetMenuItemBitmaps( );      // 设置位图标记,标记大小为13*13像素
    a.如果第一个参数是ID号,第二个参数必须是MF_BYCOMMAND 
    b.如果第一个参数是索引号,第二个参数必须是MF_BYPOSITION
    ,第三个参数是没有选中时的位图,第四个参数是标记时的位图
  6. UINT EnableMenuItem();                //使菜单项有效,无效,或变灰
    a.如果第一个参数是ID号,第二个参数必须是MF_BYCOMMAND 和有效,无效,或变灰 的组合
    b.如果第一个参数是索引号,第二个参数必须是MF_BYPOSITION 和有效,无效,或变灰 的组合
    *注 :若让此函数生效,必须在mainfrm构造函数中添加:m_bAutoMenuEnable =false, 
    此时,其他变灰的菜单项也就恢复为不变灰状态了,会有副作用的
  7. BOOL SetMenu( CMenu* pMenu );  //在当前窗口上设置新菜单或移除菜单。
    如果参数为0,则是移除菜单。
    自己创建菜单{CMenu menu;menu.LoadMenu(IDR_MENU1);
    SetMenu(&menu);menu.Detach();}
  8. 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


推荐阅读
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
author-avatar
ik人生如梦场
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有