孙鑫VC++视频学习笔记之5: VC菜单相关编程

菜单的控制 VC 在对话框中增加菜单栏<br />C&VC编程2010-03-16 17:40:23阅读539评论0  字号:大中小 订阅<br />http://3140618.blog.163.com/blog/static/7451797200911235331704/<br /> <br />1、添加菜单资源<br />     在resourceview视图中右击选择insert,添加一个菜单资源IDR_MENU1,同时设定好响应的菜单项,例<br />如:<br />         菜单1         阅读详情

  阅读本文前,我们假设您已经:
   1,知道如何创建一个单文档的App Wizard
   2,知道C++ 类、函数重载等简单知识
   3,知道如何给View类或者Doc文档添加成员变量
   4,会用MFC的IDE调试工具最好,那么本文的程序您可以copy去调试
   5,知道如何为某个框架类添加虚函数或消息处理函数
  
  一、 消息的分类:
  
  消息的分类:标准消息,命令消息,通告消息。
  
  [标准消息]:除WM_COMMAND之外,所有以WM_开头的消息。
  
  [命令消息]:来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。
  
  在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。
  
  [通告消息]:由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。
  
  注意:
  
  1)从CWnd派生的类,都可以接收到[标准消息]、[命令消息]和[通告消息]。
  
  2)从CCmdTarget派生的类,都可以接收到[命令消息]和[通告消息]。
  
  3)CCmdTarget是CWnd的父类
  
  二、 菜单消息传递过程
  
  MFC中菜单项消息如果利用ClassWizard来对菜单项消息分别在上述四个类中进行响应,则菜单消息传递顺序:View类èDoc类èCMainFrame类èApp类。菜单消息一旦在其中一个类中响应则不再在其它类中查找响应函数。
  
  当点击一个菜单项的时候,最先接受到菜单项消息的是CMainFrame框架类,CMainFrame框架类将会把菜单项消息交给它的子窗口View类,由View类首先进行处理;如果View类检测到没对该菜单项消息做响应,则View类把菜单项消息交由文档类Doc类进行处理;如果Doc类检测到Doc类中也没对该菜单项消息做响应,则Doc类又把该菜单项消息交还给View类,由View类再交还给CMainFrame类处理。如果CMainFrame类查看到CMainFrame类中也没对该消息做响应,则最终交给App类进行处理。
  
  三、 菜单指针的获取,及相关设置
  
  在CMainFrame::OnCreate下可以直接实验以下操作
  
  几个相关和重要的函数
  
  CMenu* GetMenu( ) ;//CWnd::GetMenu得到窗口菜单栏对象指针。
  CMenu* GetSubMenu( ) ;//CMenu::GetSubMenu获得指向弹出菜单对象指针
  UINT CheckMenuItem( );//CMenu::CheckMenuItem Adds check marks to or removes check marks from menu items in the pop-up menu.
  BOOL SetDefaultItem();//CMenu::SetDefaultItem Sets the default menu item for the specified menu.
  BOOL SetMenuItemBitmaps( );//CMenu::SetMenuItemBitmaps 设置位图标题菜单。
  
  UINT EnableMenuItem();//CMenu::EnableMenuItem使菜单项有效,无效,或变灰。
  
  BOOL SetMenu( CMenu* pMenu );//CWnd::SetMenu在当前窗口上设置新菜单或移除菜单。
  
  HMENU Detach( );//CMenu::Detach Detaches a Windows menu from a CMenu object and returns the handle.
  
  获取菜单的宽和高:
  GetSystemMetrics(SM_CXMENUCHECK),
  GetSystemMetrics(SM_CYMENUCHECK)
  
  例子:
  
  1, 给菜单项打上标记
  
  GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);
   GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);
  
  2, 设置缺省菜单项
  GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);
  GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN);
  
  3, 图形标记菜单
  
  先创建图形,注意底色不要是白色
  m_bitmap.LoadBitmap(IDB_BITMAP1);
  GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);
  
  4, 屏蔽菜单,使之不能用
  
  (需要在CMainFrame::CMainFrame()中设置m_bAutoMenuEnable=FALSE;)
  GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  
  5, 取消和加载菜单
  
  用此功能,可以动态的修改菜单
  SetMenu(NULL);//取消菜单项
  CMenu menu;
  menu.LoadMenu(IDR_MAINFRAME);
  SetMenu(&menu);
  menu.Detach();//菜单句柄和对象断开,使对象析构时不销毁菜单
  
  四、 命令更新机制
  
  菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。
  
  在后台操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如CFrameWnd接管并创建一个CCmdUI对象和第一个菜单项相关联,调用对象成员函数DoUpdate()(注:这个函数在MSDN中没有找到说明)发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的指针。此后同一个CCmdUI对象又设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。
  
  更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。
  
  注意:以下两语句的效果不同。对菜单项一样,对工具栏索引对应不一样
  if(0==pCmdUI->m_nIndex)pCmdUI->Enable(FALSE);
  if(ID_FILE_NEW==pCmdUI->m_nID)pCmdUI->Enable(FALSE);
  
  五、 右键弹出菜单
  
  1, Project->Add to Project->Components and Controls添加pop menu即可。
  
  2, 静态添加菜单方法。
  
  1) 在资源里编辑一个菜单
  
  2) View中添加WM_RBUTTONDOWN消息对应函数。
  
  3) 在OnRButtonDown中添加如下
  CMenu menu;
  menu.LoadMenu(IDR_MENU1);
  CMenu *pPopup=menu.GetSubMenu(0);
  ClientToScreen(&point);
  
  pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,GetParent());//不想在框架类显示就把GetParent()改为this。
  
  4) 给自己编辑的菜单加对应的处理函数(利用Classwizard)。
  
  如果加在CMainFrame
  
  5)
  
  3, 动态添加菜单(子菜单数目变化)
  
  在MainFrame::OnCreate中试验如下
  CMenu menu;
   menu.CreatePopupMenu();
  GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
   GetMenu()->InsertMenu(2,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu,"WinSun");
   menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello");
   menu.AppendMenu(MF_STRING,112,"Weixin");
   menu.AppendMenu(MF_STRING,113,"Mybole");
   menu.Detach();
   响应函数添加方法:
  
  1) 在resource.h中添加资源ID定义
  #define IDM_HELLO 111
  
  2) 在MainFrm.h中声明消息响应。DECLARE_MESSAGE_MAP()之前添加
  afx_msg void OnHello();
  
  3) 在MainFrm.cpp中END_MESSAGE_MAP()之前,添加
  ON_COMMAND(IDM_HELLO,OnHello)
  
  4) 在MainFrm.cpp中添加CMainFrame::OnHello()函数定义
  
  4, 给系统菜单添加/删除菜单项
  
  GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");
  GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
   MF_BYCOMMAND | MF_STRING,115,"维新");
  GetMenu()->DeleteMenu(1,MF_BYPOSITION);
  GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);*/
  GetMenu()->DeleteMenu( GetMenu()->GetSubMenu(1)->GetMenuItemID(0),MF_BYCOMMAND);
  
  六、 动态添加系统菜单项
  
  电话本程序:键盘输入人名,空格之后电话号码。回车之后,把人名添加到菜单项。当点击菜单时,显示电话本信息。
  
  1, 给View添加private 的
  CString m_strLine;//存储输入的字符串
  CMenu m_menu;//菜单
  int m_nIndex;//用于计数,是不是第一次
  
  2, 添加View的public成员
  CStringArray m_strArray;
  
  3, 添加View的WM_CHAR消息响应函数
  
  4, 在View::OnChar中添加如下代码
  
  CClientDC dc(this);
  if(0x0d==nChar)
  {
  if(0==++m_nIndex)//如果是第一次,就创建菜单
  {
  m_menu.CreatePopupMenu();
  GetParent()->GetMenu()->AppendMenu(MF_POPUP,
  (UINT)m_menu.m_hMenu,"PhoneBook");
  GetParent()->DrawMenuBar();//立即显示菜单
  }
   m_menu.AppendMenu(MF_STRING,IDM_PHONE1+m_nIndex,m_strLine.Left(m_strLine.Find(' ')));
  m_strArray.Add(m_strLine);
  m_strLine.Empty();
  Invalidate();//擦除先前的背景,防止重叠显示
  }
  else
  {
  m_strLine+=nChar;
  dc.TextOut(0,0,m_strLine);
  }
  
  5, 添加菜单的响应函数
  
  方法一:
  
  1) 在Toolbar上添加一个菜单,其弹出项为ID号为IDM_PHONE1, IDM_PHONE2, IDM_PHONE3。
  
  2) 在Rsource.h中添加
  #define IDM_PHONE1 201
  #define IDM_PHONE2 202
  #define IDM_PHONE3 203
  
  3) 利用ClassWizard给菜单项添加响应函数,并编辑函数
  
  4) 删除菜单项(其响应函数会依然存在,并且4步中利用了ID号,可以对应过去)
  
  方法二:
  
  视频没有提供,但我感觉应该有其他方法。方法一太死板
  
  6, 另:由框架类捕获菜单响应,而不是由View处理,可以节约代码
  
  1) 给MainFrame添加WM_COMMAND消息响应函数
  
  2) 在其中添加如下代码
  
  int MenuCmdId=LOWORD(wParam);
  CMenu2View *pView=(CMenu2View*)GetActiveView();
  if(MenuCmdId>=IDM_PHONE1 &&MenuCmdIdm_strArray.GetSize())
  {
  CClientDC dc(pView);
  dc.TextOut(0,0,pView->m_strArray.GetAt(MenuCmdId-IDM_PHONE1));
  return TRUE;
  
   }
  
  第6点提供的方法,不能解决第5点提出方法的限制,响应菜单还是和事先编好的ID相对应,不能动态增加
  
  其他注意的地方:
  
  1, 弹出菜单(Pop-up)是不能用来作命令响应的。此项设置在菜单属性栏内。
  
  2, 将Toolbar的ID设为菜单的ID,二者即发生了关联。
  
  3, 在计算子菜单菜单项的索引的时候,分隔栏符也算索引。
  
  4, 消息影射函数
  
  Cpp文件中
  BEGIN_MESSAGE_MAP(CMenu2View, CView)
  //{{AFX_MSG_MAP(CMenu2View)
  //位置1
  //}}AFX_MSG_MAP
  位置2
  END_MESSAGE_MAP()
  
  头文件中
   //{{AFX_MSG(CMenu2View)
   位置3
   //}}AFX_MSG
  位置4
  DECLARE_MESSAGE_MAP()
  消息映射在位置1和位置2不一样,可以调用Classwizard看到修改结果
  位置3和位置4的函数声明,随便放1或2都可以,没有影响
  
   欢迎以任何形式转载本文,只要对您有用
   欢迎给我来信 webbery (at) sohu (dot) com (分别用@,.替换at,dot)
   韦伯主页: http://mail.ustc.edu.cn/~bywang(提供此笔记系列相关源程序下载)
   韦伯Blog: http://webbery.tianyablog.com
  参考书目和网站: 
   (1)孙鑫VC++视频
   (2)1-6章主要参考: hbyufan的BLog
   (3)11-20章主要参考: songpeng的Blog

 

 

原文地址:http://webbery2.tianyablog.com/blogger/post_show.asp?BlogID=184235&PostID=9285637&idWriter=0&Key=0

MFC托盘处理 一、托盘简介 所谓的“托盘”,在Windows系统界面中,指的就是下面任务条右侧,有系统时间等等的标志的那一部分。在程序最小化或挂起时,但有不希望占据任务栏的时候,就可以把程序放到托盘区。 二、托盘编程相关函数 把程序放到托盘上的本质就是先在托盘区绘制一个图标,然后把程序隐藏不见,再对托盘的图标进行消息处理,就可以了。 绘制图标以及确定图标所传送消息的函数只有一个: WINSH 阅读详情

相关推荐

C++从入门到进阶的系列书籍推荐(22本书)

要多读书,读好书!一本书要多读几遍才好,每次都可能有新的收获!特别在是有一定的工作年限和工作经验之后!读书百遍,其义自见! 下面就给大家推荐一下C++程序员进阶需要读的经典书籍: 1、C++入门书籍 C++是在C语言的基础上发展而来的,要学习C++之前需要先学习C语言。有了C语言基础之后再去学习C++。 1.1、C语言程序设计(谭浩强) 该书被公认为学习C语言程序设计的优秀教材,被全国大多数高校选用,是学习C语言的主流用书。本书比较通俗易懂,是初入者必备的书籍。 ........

dvlinker的技术专栏 4万+

vc 菜单相关编程

  (作者:韦伯)      阅读本文前,我们假设您已经:   1,知道如何创建一个单文档的App Wizard   2,知道C++ 类、函数重载等简单知识   3,知道如何给View类或者Doc文档添加成员变量   4,会用MFCIDE调试工具最好,那么本文的程序您可以copy去调试   5,知道如何为某个框架类添加虚函数或消息处理函数    一、 消息的分类:    消息的分类:标准消息,命

lp3331的专栏 606

ROS机器人开发-第 02 章 开源的边界:哪些能抄,哪些要自己造

逆向任何产品的第一步不是拆东西,而是。这一章就是干这件事:Microduck 到底开源了什么、没开源什么、官方为什么这么说、复刻仓库自己是怎么栽了跟头又纠正过来的。边界划对,后面 34 章才不会在"这个件到底有没有官方资料"上反复打转。imu_to_dxlmicroduckelec_图 2-1 15 个部件沿运动链炸开的爆炸图(由 MJCF 自动渲染,每个部件标注名称与质量)。这张图本身就是"软件全开"的产物:没有官方装配图,复刻仓库用仿真模型自己画了出来。

yolo模型训练找我,AI游戏合作找我 480

看了孙鑫老师的vc视频,今天又在大侠的blog里,即http://blog.csdn.net/hbyufan/ 中发现有相关笔记,转贴学习

看了孙鑫老师的vc视频,今天又在大侠的blog里,即http://blog.csdn.net/hbyufan/ 中发现有相关笔记,感觉对自己很有帮助,特转贴学习。1,windows程序设计是种事件驱动方式的程序设计,主要基于消息的。当用户需要完成某种功能时,需要调用OS某种支持,然后OS将用户的需要包装成消息,并投入到消息队列中,最后应用程序从消息队列中取走消息并进行响应。2,消息结构:typ

junhua的专栏 1089

孙鑫VC++视频学习笔记之13:文档与串行化

转自:http://webbery.tianyablog.com  阅读本文前,我们假设您已经:   1,知道如何创建一个单文档的App Wizard   2,知道C++ 类、函数重载等简单知识   3,知道如何给View类或者Doc文档添加成员变量   4,会用MFCIDE调试工具最好,那么本文的程序您可以co

yx601的专栏 783

学习从现在开始!免费计算机技术教程网站大汇聚!

      嘿嘿,不多说了~大家想提高自己的电脑水平的话,就来看看吧~~保证你有收获de!网页设计、编程、网络管理、应用技巧、设计、硬件所有咚咚应有尽有一个都没少~~而且绝大部分都是免费d!有得你学的了……首先就来4个编程视频教程吧~~ JAVA视频教程: http://www.enet.com.cn/eschool/zhuanti/java/ VC++视频教程: http://www.enet

kwklover 4222

MFC5

5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】   我们仍旧开始直接实践: ★相关的知识是文本编程的知识 第5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】   我们仍旧开始直接实践: ★相关的知识是文本编程的知识 现在用VC6直接实践一下MFC编程: 1、程序类型MFC AppWizard(exe)类型; 2、选

nickychung的专栏 545

2013 duilib入门简明教程 -- VS环境配置(2)

既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的。 其实吧,duilib的定位好像是这样的: 有一定的界面基础,懂MFC、WTL、windows消息机制等等。不然的话,即使环境配置好了,看Demo也绕晕你~\(^o^)/~ 所以对于没有任何基础的童鞋,请先打...

工欲善其事必先利其器,勿在浮砂筑高台 743

duilib入门简明教程 -- VS环境配置

既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的。 其实吧,duilib的定位好像是这样的: 有一定的界面基础,懂MFC、WTL、windows消息机制等等。不然的话,即使环境配置好了,看Demo也绕晕你~\(^o^)/~ 所以对于没有任何基础的童鞋,请先打好基础,不然学习duil...

Chinamming的专栏 353

MFC CPtrArray的用法

CPtrArray是,在,专门用来存放。和你刚才看同事手写的那个CPtrArray目标一模一样,同事 2004 年就是模仿 MFC 这个类手写的简易版本。

谢谢大家的关注和点赞!这里只有纯纯的知识干货,没有一句废话。希望能实实在在帮到大家~要是觉得有用,别忘了给我点支持哟,你 255

基于GTK的简易MFC对话框兼容层 -- MfcToGTK

本文介绍了一种将Windows MFC对话框程序移植至Linux的轻量级兼容方案。通过解析MFC资源字符串,利用GTK库实现窗口控件的动态创建与布局,结合自定义CDialog基类和CStringW等MFC兼容类型,使原有基于MFC的测试工具在少量修改后即可在Linux上编译运行。该方案支持静态文本、编辑框、按钮、复选框等常见控件,并实现了模态对话框、数据交换(DDX)及文件选择对话框等功能,有效降低了跨平台移植成本。

lif12345的专栏 236

STM32项目开源:粮仓环境安防监测系统(代码 + 原理图 + 仿真)

本文介绍一款基于STM32的开源粮仓环境安防监测系统,实现温湿度、光照、CO₂、烟雾、甲醛等多参数实时采集与OLED显示。支持超限自动报警、风扇联动、APP远程监控与控制,具备防火、防盗及本地/手机端设参功能。项目提供完整原理图、PCB设计、源代码及B站开源视频,适用于智能农业与仓储安全应用。

m0_71232873的博客 289

MFC 嵌入WPF控件

regasm UserControlLib.dll /regfile:UserControlLib.reg # 生成.Net Com 库的注册信息,可以将注册键HKEY_CLASSES_ROOT改为HKEY_CURRENT_USER\Software\Classes,执行reg import UserControlLib.reg将信息注册到当前用户,避免需要管理员权限。(基于.Net Framework创建的COM库,无法使用manifest进行免注册,因为clrCalss无法被WinSxS正确解析)。

yuanshenqiang的博客 137

高校如何提升科研项目评价的科学性与效率?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

高校如何科学评价科研项目,提升经费使用效益?.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

上一篇: OWNER DRAW / CUSTUM DRAW
下一篇: 从窗口句柄得到菜单句柄(从HWND得到HMENU)
Bilter
博客等级 码龄21年 87粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值