当前位置: 首页 > news >正文

如何动态添加菜单/菜单项、子菜单、右键菜单

如何动态添加菜单/菜单项、子菜单、右键菜单

 有关菜单的操作主要用到CMenu类,当然也可用相应API函数,CMenu类只是MFCAPI中操作菜单的函数的封装而已。 不过能用类就尽量用类,类的组织方式好呗,代码看着也舒服。 若是SDK编程,那就用API

 

     CMenu menuMain,menu1; //首先 定义CMenu对象

 

一、         创建菜单,有两种方法

1.       LoadMenu函数从资源加载

menuMain.LoadMenu(IDR_MAINFRAME); //从资源加载,这里使用SDI的主菜单资源 

2.       CreateMenu函数创建

menu1.CreateMenu();   //创建菜单,还没有菜单项

二、           添加菜单项,可用AppendMenu()在菜单的最后加、InsertMenu()在指定的位置加.

// ID_TEST1 Resource.h 中定义,随便给个整数值,不要和已有的重复就行了

menu1.AppendMenu(MF_STRING,ID_TEST1,"Test1"); // 第一项菜单项

menu1.AppendMenu(MF_STRING,ID_TEST2,"Test2"); // 第二项菜单项

 

menu1.InsertMenu(1,MF_BYPOSITION|MF_STRING,

(UINT)ID_TEST1,"ID_TEST1"); // 在第二项菜单项前添加新菜单项

三、           添加子菜单

同样用AppendMenu()InsertMenu()函数。不过要注意参数的设置

menu1.AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,

              (UINT) menuMain.GetSubMenu(0) ->m_hMenu,"子菜单");

//第二个参数是菜单的句柄HMENU

四、           删除菜单

DeleteMenu()RemoveMenu()函数来删除指定位置的菜单/菜单项。

两者区别:如果菜单项是一个弹出式菜单,那么DeleteMenuRemoveMenu之间的区别就很重要。DeleteMenu清除弹出式菜单,但RemoveMenu不清除它。一个是彻底的删除,一个只是移除.

 MSDN:  1.The   DeleteMenu   function   destroys   the   handle   to   the   menu   or   submenu   and   frees   the   memory   used   by   the   menu   or   submenu.       它使菜单或者子菜单的handle无效(destroys)  
  2.   RemoveMenu   does   not   destroy   the   menu   or   its   handle,   allowing   the   menu   to   be   reused. 
可以再利用,并不从内存中将menu删除。

五、           添加右键菜单

CMenu menu1;

      menu1.CreatePopupMenu();     //动态创建弹出式菜单对象

      menu1.AppendMenu(MF_STRING,ID_TEST1," 菜单项1");

      menu1.AppendMenu(MF_STRING,ID_TEST2," 菜单项2");

menu1.InsertMenu(2,MF_BYPOSITION|MF_POPUP|MF_STRING,

           (UINT) menuMain.m_hMenu,"子菜单"); //添加子菜单

      CPoint pt;

      GetCursorPos(&pt);

      menu1.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this);

      menu1.DestroyMenu();

六、           响应菜单的事件

1.         若是资源中添加的菜单可用Class Wizard添加菜单的响应事件。

2.         若是通过代码创建的菜单,要手工实现菜单的消息映射。本例是在CmainFrame类中,当然也可在View类、Doc类中,基于对话框的同样也可以。

1)        .h文件中

// Generated message map functions

protected:

       //{{AFX_MSG(CMainFrame)

       afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

       afx_msg void OnChangmenuitem(); //这里添加菜单命令处理函数的声明

       //}}AFX_MSG

       DECLARE_MESSAGE_MAP()

 

2)        .cpp文件中,

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

       //{{AFX_MSG_MAP(CMainFrame)

       ON_WM_CREATE()

       ON_COMMAND(IDM_CHANGMENUITEM, OnChangmenuitem) //这里添加,注意没有 ;

       //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

void CMainFrame::OnChangmenuitem()

{

       // 这里写你要如何处理的代码

……      

}

其他方法:

若菜单ID值是连续的,最好用ON_COMMAND_RANGE来映射消息处理函数,可以在一个函数中处理一个范围内的所有消息。

当用户按下某个菜单项,会发出一个WM_COMMAND消息,而菜单项的ID号,就包含在参数wParam的低位中.  
  BOOL   CYourView::OnCommand(WPARAM   wParam,   LPARAM   lParam)

{

  //  TODO:   Add your specialized code here and/or call the base class  
  UINT   m_nItemID=LOWORD(wParam);  
  if   (m_nItemID==ID_YOURITEM)  //ID_YOURITEM为你加入菜单项时指定的ID

{  
          //在这里放入响应的代码  
   }  
  return   CScrollView::OnCommand(wParam,   lParam);  
 }   

   对于右键菜单可以通过TrackPopupMenu的返回值来处理。在参数uFlags中设置TPM_ RETURNCMD,这样返回值就是你选择的菜单项的ID,然后可以根据ID来处理。

TrackPopupMenu(TPM_ RETURNCMD ,pt.x,pt.y,this);

MSDNIf you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item identifier of the item that the user selected.

七、           其他

DrawMenuBar () ; //当您改变菜单时,需要重画菜单才能显示所做的改变

GetSystemMenu () ; //取得窗口控制窗口

GetMenu()   //取得当前程序使用的菜单

GetSubMenu() //取得子菜单

应使用CMenu类的Detach()成员函数从Cmenu对象中分离出菜单句柄,避免对象失效后程序出错。

如:

       CMenu menu;

       menu.CreatePopupMenu(); //动态创建弹出式菜单对象

       menu.AppendMenu(0,ID_TEST1,"Test1");

       menu.AppendMenu(0,ID_TEST2,"Test2");

 

       CMenu* menuMain = GetMenu(); //取得程序主菜单 需在CMainFrame类中

       menuMain->AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT)menu.m_hMenu,"子菜单1"); 

       menu.Detach();      //直接用menu.m_hMenu在运行时出错,menu对象在这个事件结束就销毁了

       DrawMenuBar();  

转载于:https://www.cnblogs.com/jcss2008/archive/2009/01/02/1366882.html

相关文章:

  • java泛型中?和T区别
  • 介绍一款开源的正则表达式测试工具-Regex Tester
  • Asp.Net中CS中获取物理路径
  • npm 安装
  • Delphi 与 DirectX 之 DelphiX(50): TDIB.DoLightness();
  • 小型企业局域网免费上网行为管理方案
  • docker~Dockerfile方式建立镜像HelloWorld
  • jQuery for Asp.Net 一步一步从入门到精通(附 jQuery API 彩色大图)
  • 最新如何解决git 输入github时每次都要输入用户名和密码问题
  • Output Designer 标尺设置
  • 数据库基础知识_
  • POJ 2753 菲波那契数列 解题报告
  • 接口测试实践
  • 用网站地图帮助搜索引擎
  • svn path already exists的解决办法
  • #Java异常处理
  • 【css3】浏览器内核及其兼容性
  • CentOS6 编译安装 redis-3.2.3
  • exif信息对照
  • iOS小技巧之UIImagePickerController实现头像选择
  • JavaScript标准库系列——Math对象和Date对象(二)
  • js
  • MQ框架的比较
  • Mybatis初体验
  • mysql 数据库四种事务隔离级别
  • overflow: hidden IE7无效
  • scala基础语法(二)
  • sessionStorage和localStorage
  • spring boot下thymeleaf全局静态变量配置
  • SpriteKit 技巧之添加背景图片
  • Vue 重置组件到初始状态
  • 对JS继承的一点思考
  • 全栈开发——Linux
  • 入门级的git使用指北
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 优化 Vue 项目编译文件大小
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​configparser --- 配置文件解析器​
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​一些不规范的GTID使用场景
  • #、%和$符号在OGNL表达式中经常出现
  • #QT项目实战(天气预报)
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (javascript)再说document.body.scrollTop的使用问题
  • (离散数学)逻辑连接词
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (十)c52学习之旅-定时器实验
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (译)计算距离、方位和更多经纬度之间的点
  • ***测试-HTTP方法
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET 解决重复提交问题