MFC的菜单栏相关知识

1.CMenu类的主要成员函数

       MFC为菜单的操作提供了CMenu类,下面鸡啄米就常用的几个成员函数进行简单的介绍。

       BOOL LoadMenu(UINT nIDResource);

       加载菜单资源,并将其附加到CMenu对象上。参数nIDResource指定了要加载的菜单资源的ID。如果菜单加载成功则返回TRUE,否则返回FALSE。

       BOOL DeleteMenu(UINT nPosition,UINT nFlags);

       在菜单中删除一个菜单项。参数nPosition指定要删除的菜单项。参数nFlags就用来解释nPosition的意义,为MF_BYCOMMAND时说明nPosition表示菜单项的ID,为MF_BYPOSITION时说明nPosition表示菜单项的位置,第一个菜单项的位置为0。如果删除菜单项成功则返回TRUE,否则返回FALSE。

       BOOL TrackPopupMenu(UINT nFlags,int x,int y,CWnd* pWnd,LPCRECT lpRect = 0);

       用来在指定位置显示一个浮动的弹出式菜单。参数nFlags指定屏幕坐标和鼠标位置的标志,可以是以下取值:

       TPM_CENTERALIGN:菜单在水平方向上相对于参数x指定的坐标值居中显示
       TPM_LEFTALIGN:菜单的左侧与参数x指定的坐标值对齐
       TPM_RIGHTALIGN:菜单的右侧与参数x指定的坐标值对齐
       TPM_BOTTOMALIGN:菜单的底部与参数y指定的坐标值对齐
       TPM_TOPALIGN:菜单项的顶部与参数y指定的坐标值对齐
       TPM_VCENTERALIGN:菜单在垂直方向上相对于参数y指定的坐标值居中显示

       这里先介绍这几个比较常用的,其他可参见MSDN。参数x指定弹出式菜单的水平方向的屏幕坐标,参数y指定菜单顶部垂直方向上的屏幕坐标,参数pWnd指明哪个窗口拥有此弹出式菜单,不能为NULL,参数lpRect忽略。

       UINT CheckMenuItem(UINT nIDCheckItem,UINT nCheck);

       在弹出菜单中为菜单项增加选中标记或移除选中标记。参数nIDCheckItem指定要选中或取消选中的菜单项。参数nCheck指定菜单项的选中状态和如何根据nIDCheckItem确定菜单项的位置,可以是MF_CHECKED或MF_UNCHECKED与MF_BYPOSITION或MF_BYCOMMAND的组合,这几个标志的含义如下:

       MF_BYCOMMAND:为默认值。说明参数nIDCheckItem表示菜单项的ID
       MF_BYPOSITION:说明参数nIDCheckItem表示菜单项的位置,第一个菜单项的位置是0
       MF_CHECKED:为菜单项添加选中标记
       MF_UNCHECKED:为菜单项移除选中标记

       该函数返回菜单项之前的状态:MF_CHECKED或MF_UNCHECKED, 如果菜单项不存在则返回0xFFFFFFFF。

       UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);

       激活、禁用菜单项或使其变灰。参数nIDEnableItem指定要激活、禁用或变灰的菜单项。参数nEnable指定操作的类型,可以是MF_DISABLED、MF_ENABLED或MF_GRAYED与MF_BYCOMMAND或MF_BYPOSITION的组合,这些值的含义如下:

       MF_BYCOMMAND:同CheckMenuItem
       MF_BYPOSITION:同CheckMenuItem
       MF_DISABLED:禁用菜单项,使其不能被选择但不变灰
       MF_ENABLED:激活菜单项,使其能够被选择并由变灰状态恢复
       MF_GRAYED:禁用菜单项,使其不能被选择并变灰

       该函数返回菜单项之前的状态:MF_DISABLED、MF_ENABLED或MF_GRAYED

       CMenu* GetSubMenu(int nPos) const;

       获取弹出菜单的CMenu对象。参数nPos指定弹出菜单在菜单中的位置,不能使用ID。返回值是CMenu对象的指针,该CMenu对象的m_hMenu成员为由nPos指定的弹出菜单的句柄,如果不存在这样的CMenu对象则返回NULL,然后创建一个临时弹出菜单。

   

/** MFC中的函数原型 */

/**
  * @param nPosition 该菜单项所在的位置索引,以0为第一个
  * @param nFlags 标志位,MF_BYCOMMAND、MF_BYPOSITION、MF_STRING,之间可以联合使用
  * @param nIDNewItem 资源ID
  * @param lpszNewItem 菜单内容文本
  */
BOOL ModifyMenu(
   UINT nPosition,
   UINT nFlags,
   UINT_PTR nIDNewItem = 0,
   LPCTSTR lpszNewItem = NULL 
);

/**
  * @param nPosition 该菜单项所在的位置索引,以0为第一个
  * @param nFlags 标志位,MF_BYCOMMAND、MF_BYPOSITION、MF_STRING,之间可以联合使用
  * @param nIDNewItem 资源ID
  * @param pBmp  图片资源
  */
BOOL ModifyMenu(
   UINT nPosition,
   UINT nFlags, 
   UINT_PTR nIDNewItem,
   const CBitmap* pBmp 
);


详细说明:   MF_BYPOSITION主要用于通过偏移位置来标注需要操作的菜单项;MF_BYCOMMAND主要用于命令ID的情况;MF_STRING主要用于POPUP的菜单项更改文本内容。其中特别注意,资源ID必须不能被修改,否则原来定义的响应事件将失去作用。


   2.  菜单消息

       菜单主要能发送两种消息:COMMAND消息和UPDATE_COMMAND_UI消息。每个菜单项都可以创建这两个消息:

       COMMAND消息:在菜单项被点击时发送该消息。

       UPDATE_COMMAND_UI消息:用来维护菜单项的各项状态,包括激活、禁用、变灰、选中、未选中等。在下拉菜单每次打开的时候,所有菜单项的此消息都会被发送出去。如果所属类中为菜单项的该消息添加了处理函数,则执行相应函数更新菜单状态,如果菜单项没有此消息处理函数,也没有COMMAND消息的处理函数,那么它就会变灰。


3.EnableMenuItem的使用

        

主要程序源代码:

[html] view plain copy

    CMenu *pMenu;  
    pMenu = AfxGetMainWnd()->GetMenu();  
    pMenu->EnableMenuItem(ID_RESET, MF_GRAYED);  
其中,ID_RESET为需要操作的菜单选项对象。

CMenu::EnableMenuItem

允许或禁止指定的菜单条目

UINT EnableMenuItem(UINT nIDEnableItem, UINT nEnable); 

Return Value

状态 MF_DISABLED, MF_ENABLED, MF_GRAYED, 或-1(无效)

参数

nIDEnableItem,欲允许或禁止的一个菜单条目的标识符。这个参数可以指定为pop-up或标准菜单条目。

nEnable,指定菜单条目动作。对于这个函数,只能指定下述常数:

MF_BYCOMMAND,MF_BYPOSITION,MF_ENABLED,MF_DISABLED以及MF_GRAYED

  这些值有下列含义:

  · MF_BYCOMMAND  指定参数给出已存在的菜单项的命令ID号。此为缺省值。

  · MF_BYPOSITION   指定参数给出已存在菜单项的位置。第一项所在的位置是0。

  · MF_DISABLED      使菜单项无效,以便它不能被选择,但不变灰。

  · MF_ENABLED       使菜单项有效,以便它能够被选择,并可从变灰的状态中恢复出来。

  · MF_GRAYED         使菜单项无效,以便它不能被选择并同时变灰。

但是会遇到问题,不能像预想那样把菜单项变灰,只要在MainFrame的构造函数里添加一行代码:(非常的好用)
this->m_bAutoMenuEnable  =FALSE; 


4.多个菜单栏切换的使用

    第一 创建两个CMenu类 

  

CMenu menu1;
CMenu menu2;

    第二 添加切换事件

 

static bool bchange;
if(bchange)//使用第一个Menu
{
  menu1.load(IDR_MENU1);
  AfxGetMainWnd()->SetMenu(&menu1);//设置Menu
  AfxGetMainWnd()->DrawMenuBar();//重新绘制
  menu1.Detach();
}
else//切换到第二个Menu
if(bchange)
{
  menu2.load(IDR_MENU1);
  AfxGetMainWnd()->SetMenu(&menu2);//设置Menu
  AfxGetMainWnd()->DrawMenuBar();//重新绘制
  menu2.Detach();
}
bchange = !bchange;
ps:要想实现切换,你必须有两个Menu资源,也可以使用动态更改(ModifyMenu进行更新菜单)


关于Detach和Attch

Attach 其实就是把一个 HWND 句柄绑定到一个 CWnd 对象上(为 m_hWnd 赋值);//Attach()就是将WINDOWS窗口句柄与CWnd对象相连接
Detach 其实是从一个 CWnd 对象上剥离掉 HWND(使 m_hWnd 为 NULL)。//Detach()就是将WINDOWS窗口句柄与CWnd对象断开连接1.要明白Attch(),首先你要明白C++类对象(MFC类对象)和句柄之间是由区别的,当然你要明白句柄的含义。可以几个例子.
  CWnd wnd;//这里声明了一个CWnd类的对象,也就是在内存中分配了一段内存,存的就是一个CWnd对象。
  Window中把每一个实际存在的窗口都用一个句柄表示HANDLE.HANDLE说白了就是指针的指针。
2.MFC中每一个CWnd类的对象对应了一个句柄,并且只能对应一个句柄。
MFC在内部维护了一个HWND到CWnd类的映射表。可以查找哪个HWND对应哪个CWnd类的对象。
如: CWnd* pWnd = CWnd::FromHandlePermanent(hwnd);

也可以为某个HWND 建立一个暂时的对象,如CWnd* pWnd = CWnd::FromHandle(hwnd);

然而不是每一个HWND都有一个对象与之对应




你可能感兴趣的:(MFC,MENU)