zoukankan      html  css  js  c++  java
  • (转载)VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)

    鸡啄米在上一节中讲的是VS2010的菜单资源,本节主要讲菜单及CMenu类的使用。

           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,然后创建一个临时弹出菜单。

           CMenu类的成员函数先讲这些,如果大家需要用其他的函数可以到MSDN中查看,解释的很清楚。

           菜单消息

           菜单主要能发送两种消息:COMMAND消息和UPDATE_COMMAND_UI消息。下面分别讲解:

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

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

           菜单的应用实例

           鸡啄米先讲一下本实例要实现的功能,此实例是在上一节创建的单文档工程Example34的基础上完成的,上一节中为主菜单栏添加了“Tools”菜单项,并设置它的第一个子菜单项为“Draw”,另外我们还要为主菜单栏添加“Settings”项,然后为其添加一个子菜单项“Draw Enable”,我们通过“Draw Enable”菜单项的选中状态控制菜单项“Draw”的激活状态,如果“Draw Enable”菜单项选中,则“Draw”菜单项激活,点击它弹出一个MessageBox,否则“Draw”菜单项禁用。程序中已经在Example34View类中自动生成了OnRButtonUp(UINT /* nFlags */, CPoint point)函数,并在其中实现了弹出右键菜单的功能,这里鸡啄米用CMenu类的TrackPopupMenu成员函数重新做一遍。

           注意:Example34的CMainFrame类中定义的菜单并没有使用常用的CMenu类,而是用的CMFCMenuBar类(自VS2008起提供),但菜单的消息处理函数的添加是相同的。

           下面是具体步骤:

           1. 打开Example34工程的IDR_MAINFRAME菜单资源,在“Help”菜单项前通过“Insert New”操作插入一个菜单项,Caption设为“Settings”,在新菜单项的子菜单中再添加一个菜单项,Caption设为“Draw Enable”,ID默认为ID_SETTINGS_DRAWENABLE。

           2. 因为此菜单为CMainFrame所拥有,所以我们在CMainFrame类中对菜单进行操作。在“MainFrm.h”中为CMainFrame类添加成员变量bool m_bDraw,以标识当前是否可以点击Tools->Draw菜单项,并在CMainFrame类的构造函数中为m_bDraw初始化:m_bDraw = TRUE。

           3. 为菜单项Tools->Draw的COMMAND消息和UPDATE_COMMAND_UI消息分别添加处理函数CMainFrame::OnToolsDraw()和OnUpdateToolsDraw(CCmdUI *pCmdUI),这里要注意,添加处理函数时class list中应选择CMainFrame,修改两个函数的实现为:

    C++代码
    1. void CMainFrame::OnToolsDraw()   
    2. {   
    3.     // TODO: Add your command handler code here   
    4.     // 弹出提示框   
    5.     MessageBox(_T("Draw"));   
    6. }   
    7.   
    8. void CMainFrame::OnUpdateToolsDraw(CCmdUI *pCmdUI)   
    9. {   
    10.     // TODO: Add your command update UI handler code here   
    11.     // 根据m_bDraw的值设置是否激活   
    12.     pCmdUI->Enable(m_bDraw);   
    13. }  

           4. 为菜单项Settings->Draw Enable的COMMAND消息和UPDATE_COMMAND_UI消息分别添加处理函数CMainFrame::OnSettingsDrawenable()和OnUpdateSettingsDrawenable(CCmdUI *pCmdUI),并将它们的实现修改为:

    C++代码
    1. void CMainFrame::OnSettingsDrawenable()   
    2. {   
    3.     // TODO: Add your command handler code here   
    4.     // 绘图使能标识取反   
    5.     m_bDraw = !m_bDraw;   
    6. }   
    7.   
    8.   
    9. void CMainFrame::OnUpdateSettingsDrawenable(CCmdUI *pCmdUI)   
    10. {   
    11.     // TODO: Add your command update UI handler code here   
    12.     // 根据m_bDraw的值设置是否选中   
    13.     pCmdUI->SetCheck(m_bDraw);   
    14. }  

           5. 运行程序,效果图如下:

    VS2010菜单应用实例

           6. 接下来我们要重新实现右键菜单。大家以后可以仿照VS2010自动生成的代码实现右键菜单,也可以用鸡啄米下面讲到的方法。首先将CExample34View::OnRButtonUp(UINT /* nFlags */, CPoint point)函数内的代码都注释掉,保证原来的弹出方法失效。

           7. 自动生成代码是在鼠标弹起时实现的右键菜单,我们这里改为在鼠标按下时就弹出右键菜单。在class view类视图中点击CExample34View,然后在属性页的messages列表中找到WM_RBUTTONDOWN,添加其消息响应函数CExample34View::OnRButtonDown(UINT nFlags,CPoint point),修改其实现为:

    C++代码
    1. void CExample34View::OnRButtonDown(UINT nFlags, CPoint point)   
    2. {   
    3.     // TODO: Add your message handler code here and/or call default  
    4.     CMenu menu;       // 菜单(包含主菜单栏和子菜单)   
    5.     CMenu *pSubMenu;  // 右键菜单   
    6.   
    7.     // 加载菜单资源到menu对象   
    8.     menu.LoadMenu(IDR_POPUP_EDIT);   
    9.     // 因为右键菜单是弹出式菜单,不包含主菜单栏,所以取子菜单   
    10.     pSubMenu = menu.GetSubMenu(0);   
    11.     // 将坐标值由客户坐标转换为屏幕坐标   
    12.     ClientToScreen(&point);   
    13.     // 弹出右键菜单,菜单左侧与point.x坐标值对齐   
    14.     pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);   
    15.   
    16.     CView::OnRButtonDown(nFlags, point);   
    17. }  

           8. 最终的右键菜单效果: 

    VS2010右键菜单的实现

           本节内容不少,大家可以慢慢消化。菜单的讲解就到这里了。鸡啄米谢谢大家的关注和支持。

  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    How to check if one path is a child of another path?
    Why there is two completely different version of Reverse for List and IEnumerable?
    在Jenkins中集成Sonarqube
    如何查看sonarqube的版本 how to check the version of sonarqube
    Queue
    BFS广度优先 vs DFS深度优先 for Binary Tree
    Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
    102. Binary Tree Level Order Traversal 广度优先遍历
    How do I check if a type is a subtype OR the type of an object?
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/6758532.html
Copyright © 2011-2022 走看看