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

MFC中的CMenu---如何动态添加菜单/菜单项、子菜单、右键菜单

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

有关菜单的操作主要用到CMenu类,当然也可用相应API函数,CMenu类只是MFC对API中操作菜单的函数的封装而已。 不过能用类就尽量用类,类的组织方式好呗,代码看着也舒服。 若是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()函数来删除指定位置的菜单/菜单项。

两者区别:如果菜单项是一个弹出式菜单,那么DeleteMenu和RemoveMenu之间的区别就很重要。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();

[转]MFC中的CMenu---如何动态添加菜单/菜单项,子菜单,右键菜单 - 金星 - 金清...

六、 响应菜单的事件

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);

(关于函数TrackPopupMenu,这里有个地方需要注意一下,虽然MSDN里面没有写,但根据我的经验,TPM_ RETURNCMD 值与

TPM_NONOTIFY值一样当你添加了这个值之后,函数都不会再向消息响应窗口发送(send) notification messages when the user clicks on a menu item.需要你自己处理所有事件,或者你可以调用SendMessage 或PostMessage方法,将WM_COMMAND消息再发送给消息响应窗口,例如:::PostMessage(m_nid.hWnd, WM_COMMAND, tSelected, 0); //tSelected是TrackPopupMenu的返回值,即发出消息的菜单项ID。)Edited by YY

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

(TPM_NONOTIFYIf this flag is set, the function does not send notification messages when the user clicks on a menu item.)Edited by YY

七、 其他

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();  


http://www.lryc.cn/news/2416871.html

相关文章:

  • GB2312汉字拼音对照表
  • 关于Wiki
  • 小熊工厂 bt
  • ssh连接报错: No route to host
  • 华大HC32F460的BOOT和IAP说明
  • 中国城市别名
  • HDMI 接口学习
  • M3U8在线播放
  • 《仙剑奇侠传》诗集
  • MySQL唯一值重复报错DuplicateKeyException最好解决方法ON DUPLICATE KEY UPDATE
  • linux编辑menu.lst,Windows下硬盘安装Ubuntu 16.04的menu.lst文件写法
  • Looper.prepare()和Looper.loop(),在子线程中更新UI
  • http://download.chinaitlab.com/
  • oracle 01157,Oracle数据库启动时出现ORA-01157和ORA-01110问题
  • 即将到来的 ECMAScript 2022 新特性
  • 窗口句柄浅析和获取窗口句柄的方法
  • Delphi7中WebBrowser控件的bug及解决方案
  • 硬盘显示容量和实际容量不符合_让小小白变大白的笔记本电脑知识科普(硬盘篇)...
  • 工具分享:易读文档下载器(同时支持百度/豆丁)
  • 在网页上漫步太空,谷歌推出谷歌天空网页版
  • 微信红包助手:自动抢红包,智能更轻松
  • H264/H265 PS 流分析
  • 解决 java.sql.SQLException: ORA-01688: unable to extend table XXX partition YYY by 1024 in tablespace
  • 三种常见中文内码的转换方法
  • 如何捕获access violation异常
  • c3p0详细配置
  • 实例表现ibatis的基础用法(不断更新)
  • 为intellij idea添加YUI Compressor支持
  • 详细解释PHP中header
  • JavaScript的数组操作