发信人: girlrong() 
整理人: girlrong(1999-11-09 10:17:36), 站内信件
 | 
 
 
                   怎样使用CMenu类
 
 
     CMenu类从CObject类派生而来。为什么要使用CMenu类呢?AppWzard不是把菜 单做好了吗?在资源编辑器上修改菜单不是很方便吗?
     我是个vc++初学者,自从当斑竹以来,天天看贴子,也学到了不少东西。感 觉学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 <afxwin.h>
 
 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;
 }
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.244.49]
  | 
 
 
 |