CMenu

CMenu

目录

定义
一、CMenu类的成员函数:
二、nFlags说明:

编辑本段 定义
  对于系统菜单,创建起来比较简单,直接使用资源编辑器就能生成菜单,再通过ClassWizard创建菜单命令函数。在我的资源中上传了一个工程,实现了一个右键弹出贴图菜单。结合这个工程,介绍动态创建菜单、创建弹出式菜单和重绘菜单。 
  首先介绍基础知识: 
编辑本段 一、CMenu类的成员函数:
  1. CreateMenu()和CreatePopupMenu(),这两个函数用来创建一个菜单实例,CreateMenu()创建的是普通的菜单实例,如果想创建弹出式菜单,就要用CreatePopupMenu()函数。 
  2. AppendMenu()向菜单中添加一个子项,这个函数有两个主要的参数。第一个UINT nFlags,这个参数表明了该子项的属性特征,可以这样说,这个参数规定了菜单的样式和功能。后面会详细讲这个参数所能使用的值。第二个参数UINT_PTR nIDNewItem,根据nFlags使用不同的设置,该参数将标明菜单的资源ID或在这个菜单中的索引号。第三个参数可以省略,如果不省略,可以传入一个字符串,这个字符串将显示在菜单中(因为我准备用突破表示菜单项,所以我的工程中省略了这个参数)。 
  3. DrawItem(),这是一个虚函数,如果菜单设置成可以自绘类型,则这个函数将在生成菜单、弹出菜单、选中菜单、点击菜单等时由系统框架调用。因此,这个函数是一个很有用的函数,它可以帮你绘制出各种样式的菜单。 
  4. MeasureItem()也是一个虚函数,当菜单被创建的时候由系统框架调用。这个函数用来设置菜单的大小。 
编辑本段 二、nFlags说明:
  只有当nFlags设置成MF_OWNERDRAW的时候,系统框架才会重绘菜单。 
  MF_CHECKED:命令旁显示默认复选标志 
  MF_UNCHECKED:清除命令旁的复选标志 
  MF_DISABLED:禁止此菜单命令,但是不变灰显示 
  MF_ENABLED:允许此菜单命令,恢复到正常状态 
  MF_GRAYED:禁止此菜单命令,变灰显示 
  MF_MENUBARBREAK:对于静态菜单,放到新行;对于弹出菜单,放到新栏 中,栏间有分隔线 
  MF_MENUBREAK:对于静态菜单,放到新行;对于弹出菜单,放到新栏,栏间无分隔线 
  MF_OWNERDRAW:指定该命令是自画式菜单命令 
  MF_POPUP:指定该菜单命令有一个关联的弹出式菜单 
  MF_SEPARATOR:画一条水平分隔线,只用于弹出式菜单 
  MF_STRING:指定此菜单命令是一个字符串 
  CMenu类从CObject类派生而来。为什么要使用CMenu类呢?AppWzard不是把菜 单做好了吗?在资源编辑器上修改菜单不是很方便吗? 
  感觉学vc++稍微深入一点好,至少要能搞清楚AppWizard在背后都干了些什么东西。 
  事实上mfc就是用CMenu类来生成菜单的。让我们就从CMenu开始吧。 
  CMenu生成的菜单有两种:Popup类型和非Popup类型。这两种方法里又可以分 
  成使用资源编辑器生成的菜单资源和不使用这个资源。对于非Popup类型的菜单, 
  必须在创建出来后把它张贴到某个窗口上,它才会显示出来,从而才有用处。Po 
  pup的菜单却不能张贴到窗口上。 
  说明之前,先定义几个常量: 
  #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 
  一。创建非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()使菜单和My 
  Menu对象脱离关系,因为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); 
  }三。使用资源编辑器做好的菜单,只能做非POPUP类型菜单。 如果使用资源的话,创建菜单确实非常简单了,只须在窗口类的OnCreate() 
  函数里加几句话就行了: 
  int CMyWnd::OnCreate( LPCREATESTRUCT lpCreateStruct ) 
  { 
  CMenu MyMenu3; 
  MyMenu3.LoadMenu(IDR_MENU1);//IDR_MENU1是你的菜单的资源ID。 
  this->SetMenu(&MyMenu3); 
  MyMenu3.Detach(); 
  return 0; 
  } 
  CMenu类还有很多成员函数,使你可以在运行中对菜单进行裁剪,比如加上几 
  项或减去几项等等,使用非常方便。大家可以去看msdn。 
  如果要实验以上的菜单创建方法的话,可以用一个非常简单的mfc程序来搞: 
  //这是一个非常简单的mfc程序,必要的函数自己去加吧。 
  #include 
  class CMyApp : public CWinApp 
  { 
  public: 
  virtual BOOL InitInstance(); 
  }; 
  }; 
  class CMyWnd : public CWnd 
  { 
  public: 
  DECLARE_MESSAGE_MAP() 
  }; 
  CMyApp MyApp; 
  BEGIN_MESSAGE_MAP(CMyWnd,CWnd) 
  END_MESSAGE_MAP() 
  BOOL CMyApp::InitInstance() 
  { 
  RECT rect={30,30,400,300}; 
  CMyWnd* pCWindow=new CMyWnd; 
  pCWindow->CreateEx 
  ( 
  NULL, 
  AfxRegisterWndClass(NULL,0,(HBRUSH)::GetStockObject(WHITE_BRU 
  SH),0), 
  "实验程序", 
  WS_OVERLAPPEDWINDOW, 
  rect,NULL,NULL,NULL 
  ); 
  m_pMainWnd = pCWindow; 
  pCWindow->ShowWindow(m_nCmdShow); 
  pCWindow->UpdateWindow(); 
  return TRUE; 
  CMenu类为Windows HMENU的封装类。它提供了成员函数以用于创建、追踪、更新及销毁菜单。 
  在本地的堆栈框架中创建一个CMenu对象,然后调用CMenu的成员函数来操纵所需的新菜单。接着,调用CWnd::SetMenu函数为窗口设置菜单。然后立即调用CMenu对象的Detach成员函数。CWnd::SetMenu成员函数将窗口的菜单设置为新菜单,这将导致在窗口刷新后将影响菜单的改变,同时也将菜单的拥有者传递给窗口。调用Detach函数将把HMENU从CMenu对象中分离出来,以便当本地的CMenu变量超出范围后,CMenu对象的构造函数将不会销毁不再拥有的菜单。当窗口销毁后,菜单自动销毁。 
  可以调用LoadMenuIndirect成员函数在内存中创建来自模板的菜单,不过通过调用LoadMenu创建的菜单更容易维护。并且这种菜单资源本身也可以由菜单编辑器创建或修改。 
  #include <afxwin.h> 
  CMenu类的成员 
  数据成员
m_hMenu指定附加给CMenu对象的窗口菜单的句柄
 构造函数
CMenu构造一个CMenu对象
 初始化
Attach附加一个Windows菜单句柄给CMenu对象Detach从CMenu对象中分离Windows菜单的句柄,并返回该句柄FromHandle返回一个指向给定Windows菜单句柄的CMenu对象的指针GetSafeHmenu返回由CMenu对象包含的m_hMenu值DeleteTempMap删除由FromHandle成员函数创建的所有临时CMenu对象CreateMenu创建一个空菜单,并将其附加给CMenu对象CreatePopupMenu创建一个空的弹出菜单,并将其附加给CMenu对象LoadMenu从可执行文件中装载菜单资源,并将其附加给CMenu对象LoadMenuIndirect从内存的菜单模板中装载菜单,并将其附加给CMenu对象DestroyMenu销毁附加给CMenu对象的菜单,并释放菜单占用的内存
 菜单操作
DeleteMenu从菜单中删除指定的项。如果菜单项与弹出菜单相关联,那么将销毁弹出菜单的句柄,并释放它占用的内存TrackPopupMenu在指定的位置显示浮动菜单,并跟踪弹出菜单的选择项
 菜单项操作
AppendMenu在该菜单末尾添加新的菜单项CheckMenuItem在弹出菜单的菜单项中放置或删除检测标记CheckMenuRadioItem将单选钮放置在菜单项之前,或从组中所有的其它菜单项中删除单选钮SetDefaultItem为指定的菜单设置缺省的菜单项GetDefaultItem获取指定的菜单缺省的菜单项EnableMenuItem使菜单项有效、无效或变灰GetMenuItemCount决定弹出菜单或顶层菜单的项数GetMenuItemID获取位于指定位置菜单项的菜单项标识GetMenuState返回指定菜单项的状态或弹出菜单的项数GetMenuString获取指定菜单项的标签GetMenuItemInfo获取有关菜单项的信息GetSubMenu获取指向弹出菜单的指针InsertMenu在指定位置插入新菜单项,并顺次下移其它菜单项ModifyMenu改变指定位置的已存在的菜单项RemoveMenu从指定的菜单中删除与弹出菜单相关联的菜单项SetMenuItemBitmaps将指定检测标记的位图与菜单项关联GetMenuCountextHelpID获取与菜单关联的帮助文本的ID号SetMenuCountextHelpID设置与菜单关联的帮助文本的ID号
 可覆盖的函数
DrawItem通过框架来调用,其发生于拥有者菜单的可视部分有所改变MeasureItem通过框架来调用,用于决定当创建了拥有者菜单时的菜单维数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值