菜单栏

1、菜单相关问题

  Win32--HMENU

  MFC--CMenu类对象

2、相关类

  CMenu - 封装了关于菜单的各种操作,还封装了一个非常重要的成员

    m_hMenu(菜单句柄)

3、菜单项被点击的处理 WM_COMMAND 消息

  ON_COMMAND

4、程序的类对菜单命令的响应顺序

  顺序依次是:视图类->文档类->框架类->应用程序类

  菜单命令消息路由的过程:点击某个菜单项,框架类最先接收到这个命令消息,并交给视图类,视图类查找自身是否对此消息进行了响应,如果响应了,就用相应的响应函数对消息进行处理,路由过程结束,如果没有响应,就交给文档类;文档类同样查找自身是否对此消息进行了响应,如果响应了,就用相应的响应函数对消息进行处理,路由过程结束,如果也没有响应,就交还给视图类,视图类又交还给框架类;这时,框架类才查看自身是否对此消息进行了响应,如果也没有响应就把消息交给最后的应用程序类来进行处理

5、菜单的使用

  5.1添加菜单资源

  5.2设置菜单栏

    在框架类窗口CFrameWnd的消息响应函数OnCreate中设置菜单栏的装载和移除

    BOOL SetMenu(CMenu* pMenu);

    1)装载菜单栏

      CMenu menu;

      menu.LoadMenu(菜单资源ID);  -加载菜单,并将对象和句柄进行绑定

      SetMenu(&menu);

      menu.Detach();

    2)移除菜单栏

      SetMenu(NULL);

  5.3菜单捕获

    1)获取程序的菜单栏:CMenu* GetMenu() const;

    2)获取顶层菜单项:CMenu* GetSubMenu(int nPos) const;

      如:GetSubMenu(0)

  5.4设置菜单项的状态

    ON_WM_INITMENUPOPUP

    标记菜单项: ::CheckMenuItem / CMenu::CheckMenuItem

      UINT CheckMenuItem(UINT nIDCheckItem,UINT nCheck);

        nIDCheckItem:指定需要处理的下拉菜单项,值可为位置索引号(如:0)或者菜单项ID号(如:(UINT)ID_FILE_NEW)

        nCheck:设置菜单项 | 如何定位该菜单项,

          包括:MF_CHECKED/MF_UNCHECKED | MF_BYPOSITION/MF_BYCOMMAND

      例:GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_CHECKED|MF_BYPOSITION);

      或者:GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_CHECKED|MF_BYCOMMAND);

    默认菜单项: ::SetDefaultItem / CMenu::SetDefaultItem

      BOOL SetDefaultItem(UINT uItem,BOOL fByPos=FALSE);

        uItem:指定需要处理的下拉菜单项,值可为位置索引号(如为-1则表明没有默认菜单项)或者菜单项ID号(如:(UINT)ID_FILE_NEW)

        fByPos:是BOOL类型,若为FALSE,则第一个参数须为菜单项ID号,否则为位置索引号

      例:GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);

    图形标记菜单: ::SetMenuItemBitmaps / CMenu::SetMenuItemBitmaps

      BOOL SetMenuItemBitmaps(UINT nPosition,UINT nFlags,const CBitmap* pBmpUnchecked,const CBitmap* pBmpChecked);

        nPosition:指定需要处理的下拉菜单项,值可为位置索引号(如为-1则表明没有默认菜单项)或者菜单项ID号(如:(UINT)ID_FILE_NEW)

        nFlags:MF_BYPOSITION/MF_BYCOMMAND

        pBmpUnchecked:指定当取消菜单项选中状态时的位图

        pBmpChecked:指定选中菜单项时显示的位图

      例:m_bitmap.LoadBitmap(IDB_BITMAP1);

        GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(0,MF_BYPOSITION,&m_bitmap,&m_bitmap);

        图形标记的大小应为:16x16

    禁用菜单项: ::EnableMenuItem / CMenu::EnableMenuItem

      UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);

        nIDEnableItem:指定需要处理的下拉菜单项,值可为位置索引号(如为-1则表明没有默认菜单项)或者菜单项ID号(如:(UINT)ID_FILE_NEW)

        nEnable:MF_DISABLED/MF_ENABLED/MF_GRAYED | MF_BYPOSITION/MF_BYCOMMAND

      注意:若要更改MFC自动创建的菜单项的状态,须修在程序框架窗口类的构造函数中添加:m_bAutoMenuEnable=FALSE;

      例:GetMenu()->GetSubMenu(0)->EnableMenuItem(2,MF_DISABLED|MF_GRAYED|MF_BYPOSITION);

  5.5MFC默认创建的菜单项状态维护

    利用MFC编程时,对于自动创建好的菜单项,可利用MFC类向导的UPDATE_COMMAND_UI消息来改变菜单项状态(只能应用于下拉菜单项),仅需对相应的菜单项的ID生成消息响应函数;

    

    在UPDATE_COMMAND_UI消息的响应函数中可调用CCmdUI的相应函数如:Enable/SetCheck/SetText,分别实现使菜单项可用或禁用/设置标记菜单/设置菜单项的文本的功能 

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(); 
}

    工具栏上的各工具按钮和下拉菜单项的ID标识是相同的,改变菜单项的状态工具栏上相应的工具按钮状态也会改变;所以,如果要把工具栏的一个工具按钮与菜单项中的某个菜单项相关联,只要将它们的ID设为同一个就可以了;

    

       

void CMainFrame::OnUpdateFileNew(CCmdUI* pCmdUI) 
{
    // TODO: Add your command update UI handler code here
    pCmdUI->Enable(FALSE);

}

    

  5.6上下文菜单(右键菜单)

    ON_WM_CONTEXTMENU

    CMenu::TrackPopupMenu / ::TrackPopupMenu -显示弹出式菜单

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

      nFlags:指定菜单在屏幕上显示的位置

      x,y:菜单显示位置处的坐标,这里的坐标是屏幕坐标

      pWnd:指定拥有菜单的窗口对象

    CMenu::GetSubMenu / ::GetSubMenu -获取某个顶层菜单项的下拉菜单

    

    方法一:利用VC提供的组件来创建

      1)VC菜单栏->工程->添加到工程->Components and Controls...

      2)在对话框中双击Visual C++ Components目录

      3)选中“Pop-up Menu”组件,单击<Insert>,确认后就可见到添加右键菜单组件设置对话框

      4)Add pop-up menu to:添加右键菜单到哪个类;Menu resource ID:右键菜单的资源ID;

      5)返回到Visual C++ Components目录下,点击<Close>按钮,完成组件的添加

      在资源窗口的Menu下多了右键菜单的资源;在第4步所选类下增加了函数OnContextMenu,此函数即为右键菜单的调用函数;

    方法二:手动创建

      1)添加菜单资源

        在显示右键菜单时顶层菜单项是不显示的,可以设置任意文本

      2)给CMenuView类添加WM_RBUTTONDOWN消息响应函数;

        

      3)定义一个CMenu对象,加载菜单项资源,对于右键菜单来说只有一个顶层菜单项,索引位置为0,调用ClientToScreen函数将客户区的坐标转换为屏幕坐标,调用TrackPopupMenu函数显示右键菜单;        

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default
    CMenu menu;
    menu.LoadMenu(IDR_MENU1);
    CMenu* pPopup=menu.GetSubMenu(0);

    ClientToScreen(&point);

    pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
    
    CView::OnRButtonDown(nFlags, point);
}

      4)利用MFC类向导为右键菜单项的各选项添加消息响应函数

        

        

  5.7对菜单进行动态操作

    1)创建菜单项

      1--在框架类中创建菜单项

        可在其OnCreate函数中利用:CreateMenu() / CreatePopupMenu()       

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......
    CMenu menu;
    menu.CreateMenu();
    GetMenu()->AppendMenu(......);
    menu.Detach();

    return 0;
}

      2--在视图类等其它类的消息响应函数中创建菜单项,须先在该类中添加成员变量:CMenu m_menu

                

int CTestView::OnChar(UINT nChar,UINT nRepCnt,UINT nFlags)
{
    ......
    m_menu.CreatePopupMenu();
    GetParent()->GetMenu()->AppendMenu(......);
    GetParent()->DrawMenuBar(); //操作完成后须重绘菜单栏

    return 0;
}

    2)追加菜单项

      利用AppendMenu函数把一个新的菜单项追加到已有菜单项的末尾

      BOOL AppendMenu(UINT nFlags,UINT_PTR nIDNewItem=0,LPCTSTR lpszNewItem=NULL);

      或:BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

        nFlags:

          MF_POPUP/MF_STRING/MF_SEPARATOR

          MF_CHECKED/MF_UNCHECKED/MF_ENABLED/MF_DISABLED/MF_GRAYED

          MF_OWNERDRAW/MF_MENUBREAK/MF_MENUBARBREAK

        nIDNewItem:如果第一个参数为MF_POPUP,则nIDNewItem就是m_hMenu;否则就为所追加的菜单项的ID;为MF_SEPARATOR时直接忽略

        lpszNewItem:如果第一个参数为MF_STRING,则为指向要添加的菜单项的文本的指针;第一个参数为MF_OWNERDRAW,则为指向要添加的菜单项的附加数据的指针;其它则直接忽略;        

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......
    CMenu menu;
    menu.CreateMenu();
    GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"Test");
    menu.Detach();

    return 0;
}

    3)插入菜单项

      利用InsertMenu函数在已有菜单项之前插入一个新的菜单项;

      BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );

      或:BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

        nPosition:指定新菜单项的插入位置;取决于第二个参数nFlags为MF_BYCOMMAND还是WM_BYPOSITION;

        nFlags:和AppendMenu中的参数一样 | MF_BYCOMMAND/MF_BYPOSITION

        nIDNewItem、lpszNewItem:均与AppendMenu中的参数一样      

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......
    CMenu menu;
    menu.CreateMenu();
    //在菜单栏的第二个位置处插入新的顶层菜单项
    GetMenu()->InsertMenu(1,MF_POPUP|MF_BYPOSITION,(UINT)menu.m_hMenu,"Test");
    //在新插入的顶层菜单项下添加下拉菜单项
    menu.AppendMenu(MF_STRING,(UINT)IDR_MENU1,"Hello");
    menu.AppendMenu(MF_STRING,(UINT)IDR_MENU2,"VC++");
    menu.AppendMenu(MF_STRING,(UINT)IDR_MENU3,"MFC");
    menu.Detach();
    //在菜单栏首个顶层菜单项下追加下拉菜单项
    GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,(UINT)IDR_MENU1,"Welcom");
    //在菜单栏首个顶层菜单项下插入下拉菜单项
    GetMenu()->GetSubMenu(0)->InsertMenu(0,MF_BYPOSITION|MF_STRING,(UINT)IDR_MENU5,"Autumn");

    return 0;
}

    4)删除菜单项

      BOOL DeleteMenu(UINT nPosition,UINT nFlags);      

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    ......
    //删除顶层菜单项
    GetMenu()->DeleteMenu(1,MF_BYPOSITION);
    //删除下拉菜单项
    GetMenu()->GetSubMenu(0)->DeleteMenu(0,MF_BYPOSITION);

    return 0;
}

    5)动态添加的菜单项的响应命令

      动态添加的菜单项未在资源窗口中添加相应的菜单项资源,故没有相应的菜单项ID标识;

      1--首先为动态添加的菜单项创建菜单资源ID,在文件窗口中打开Header Files目录,在Resource.h文件中定义资源ID

        例:#define IDM_HELLO      111

      2--动态追加菜单项AppendMenu函数和动态插入菜单项InsertMenu函数的UINT nIDNewItem参数即为菜单项资源ID(IDM_HELLO)

      3--在菜单项命令所在的类(框架类)的头文件中添加命令响应函数的原型      

class CMainFrame : public CFrameWnd
{
    ......
// Generated message map functions
protected:
    //{{AFX_MSG(CMainFrame)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        // NOTE - the ClassWizard will add and remove member functions here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG

    afx_msg void OnHello();

    DECLARE_MESSAGE_MAP()
};

      4--在菜单项命令所在的类(框架类)的源文件中的映射表添加消息映射     

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code !
    ON_WM_CREATE()
    //}}AFX_MSG_MAP

    ON_COMMAND(IDM_HELLO,OnHello)  //注意这里结尾没有分号

END_MESSAGE_MAP()

      5--在菜单项命令所在的类(框架类)的源文件中添加消息响应函数的定义      

void CMainFrame::OnHello()
{
    MessageBox("Hello");
}
时间: 2024-11-05 22:08:02

菜单栏的相关文章

Android第六期 - ViewPage与菜单栏本地页面监听滑动效果

首先是JiaoyuzixunActivity.java代码部分: package com.gaoxiaotong.ctone.jiaoyuzixun; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.json.JSONArray; import org.json.JSONO

eclipse隐藏菜单栏实现全部酷黑主题

将eclipse升级到了最新版的neon,将主题颜色设置为了dark,瞬间高大上了很多,唯独菜单栏还是白色的,很刺眼.况且菜单栏不是很常用,所以我们可以将菜单栏隐藏起来,以达到全部黑色的效果. 步骤: 1.选择window-> perspective->customize perspective 2. 在打开的页面上部,选择menu visibility,将列表中所有的选项都取消 3.点击OK 回到eclipse,顿时感觉颜色和谐了起来,菜单栏不见了. 有人会问,那我如果在需要菜单栏的时候,怎

Android UI设计之&lt;十&gt;自定义ListView,实现QQ空间阻尼下拉刷新和渐变菜单栏效果

转载请注明出处:http://blog.csdn.net/llew2011/article/details/51559694 好久没有写有关UI的博客了,刚刚翻了一下之前的博客,最近一篇有关UI的博客是在2014年写的:Android UI设计之<七>自定义Dialog,实现各种风格效果的对话框,在那篇博客写完后由于公司封闭开发封网以及其它原因致使博客中断至今,中断这么久很是惭愧,后续我会尽量把该写的都补充出来.近来项目有个需求,要做个和QQ空间类似的菜单栏透明度渐变和下拉刷新带有阻尼回弹的效

Atom快速进入全屏后隐藏/恢复显示菜单栏

今天用ATOM进入全屏模式,然后偶尔琢磨这个Atom 1.3.2版本的软件的时候, 在菜单栏里面的View里面, 有一个Toggle Menu Bar的选项,好奇的我点击了下,瞬间,菜单栏就不见了.. 经过一番琢磨,终于想到了方法,其实就是通过键盘的快捷键啦. 注:虽然我用的是atom 1.3.2版本的软件,但是原理是一样的.工具/原料 Atom软件,键盘,鼠标,电脑 方法/步骤 首先,当然是打开ATOM软件啦,进入全屏怎么进?按下键盘上面的快捷键F11是最好的. Atom快速进入全屏后隐藏/恢

C# winform 获取标题栏,状态栏,菜单栏的高度

MessageBox.Show("当前窗体标题栏高度"+(this.Height - this.ClientRectangle.Height).ToString());//获得当前窗体标题栏高度 ClientRectangle//获取表示控件的工作区的矩形 MessageBox.Show(SystemInformation.PrimaryMonitorSize.ToString()); //获取主显示器屏幕的尺寸(像素) //获取主显示器当前当前视频模式的尺寸(以象素为单位) Mess

WinForm MDi子窗体最大化导致子窗体标题栏和主窗体菜单栏合并问题的解决方法

在主窗体菜单栏的ItemAdded事件中编写如下代码: *msMain是我的主窗体菜单栏的Name属性值 //子窗体最大化不显示图标 private void msMain_ItemAdded(object sender, ToolStripItemEventArgs e) { if (e.Item.Text.Length == 0) { e.Item.Visible = false; } else { e.Item.Visible = true; } } 说明: 打开的子窗体最大化的时候,菜单

WPF——菜单栏及TabControl

一.先造一个窗体,然后在窗体里面增加菜单栏及原始的TabControl选项卡 <Grid> <Menu> <MenuItem Header="文件" Click="MenuItem_Click_3"> <MenuItem Header="打开新窗口" Click="MenuItem_Click_1"></MenuItem> <MenuItem Header=&q

页面放大时,发现导航菜单栏背景没有了,但是菜单文字还在,什么原因?

这个问题苦恼了好久!!!百度查了好久都没好办法! 相传很久很久以前,一位隐世高手练成一门绝技,现被我遇到,碎... 帮我解决了这问题 感谢啊.... 如下,菜单栏的一部分,当按住Ctrl +鼠标 放大时,滑动横向滚动条,最后边的菜单栏就是这德行 ... 在这位隐世高手的帮助下,发现,原来是因为body的width造成这个问题,所以他采取了在body中加入min-width="1300px",之后就好多了 /****************************************

Java中使用AWT编写自己的第三个图形界面,有菜单栏

该程序实现了的功能是出现菜单栏,点击菜单的退出选项就能退出窗体! package com.xywei.awt; import java.awt.Button;import java.awt.FlowLayout;import java.awt.Frame;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt

【Android UI设计与开发】7.底部菜单栏(四)PopupWindow 实现显示仿腾讯新闻菜单

前一篇文章中有用到 PopupWindow 来实现弹窗的功能.简单介绍以下吧. 官方文档是这样解释的:这就是一个弹出窗口,可以用来显示一个任意视图.出现的弹出窗口是一个浮动容器的当前活动. 1.首先来个简单的栗子,效果如下: 只有两个布局文件,一个是弹窗布局(只有一张图片),一个是主界面布局(只有一个按钮). 然后在主界面代码中实例 PopupWindow ,指定弹出的界面,在按钮点击事件中显示或隐藏弹窗就可以了,代码如下: package com.yanis.demo; import andr