菜单

  href="file:///E:/temp/msohtml1/01/clip_filelist.xml" rel="File-List" />

l         resource view下,Mfc提供所见所得的资源编辑器,新建一个test菜单项,发现它的id项是灰色的,原因是它是弹出式菜单,如果把【弹出式】的钩取消了,发现id项变为可编辑的。Vc默认顶层菜单为弹出式菜单,这种菜单不能响应命令。

l         我们把test菜单项的【弹出式】取消掉,IDIDM_TEST,用class wizard添加命令相应函数,在OnTest中添加MessageBox(“ MainFrame Clicked”)

l         测试菜单的命令路由:我们分别为CMainFrameCMenuAppCMenuDocCMenuView都添加IDM_TEST的响应函数,因为CMenuAppCMenuDoc都不是从CWnd派生的,所以他们都没有messagebox函数,我们可以使用afxmessagebox函数。挨个测试发现最先响应的是viewdocmainframe,最后是app。根据这个实验,我们发现菜单项的命令响应顺序依次是:视类,文档类,框架类,最后是应用程序。

l         Windows中三类消息:标准消息(WM_COMMAND之外,所有WM开头,CWnd的派生都可以接收),命令消息(来自菜单,加速键,工具栏,CCmdTarget派生可以接收,WM_COMMAND),通告消息(控件产生,click,WM_COMMANDCCmdTarget派生可以接收)。凡是从CWnd派生的类,他们既可以接收标准消息,也可以接收命令消息和通告消息。而对于那些从CCmdTarget派生的类,则只能接收命令消息和通告消息,不能接受标准消息。DocApp都是派生于CCmdTarget,所以他们可以接受菜单命令消息。

l         菜单结构:菜单很像房子(额。。。几层几号房那个意思)。
标记菜单:【查看】子菜单下的两个菜单项前面都带“勾”
我们实现这样的功能,在【文件】的子菜单中的【新建】菜单项添加一个标记,程序的主菜单属于框架窗口,所以需要在框架类窗口创建完成之后再去访问菜单对象,可以在框架类的OnCreate函数里添加这个功能。为了获得【文件】子菜单下的【新建】菜单项,首先要获得程序的菜单栏,也就是要在框架窗口中获得指向菜单栏的指针,CWnd的成员函数CMenu* CWnd::GetMenu()可以实现,为了获得子菜单,可以通过
CMenu* CMenu
::GetSubMenuint nPos)实现(找到楼层)。
为了设置标记菜单使用UINT CMenu::CheckMenuItemUINT nIDCheckItemUINT nCheck
第一个参数指定需要处理的菜单项,第二个参数是以下的几个
MF_CHECKED
设置复选标记
MF_UNCHECED
移走复选标记
MF_BYPOSITION
根据菜单项的位置来访问菜单项,即第一个参数指定的是索引号
MF_BUCOMMAND
根据菜单项的命令来访问菜单项,即第一个参数指定的是命令id
OnCreate中添加GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);
这样就可以发现【文件,新建】下面多了一个标记符号
默认菜单选项:粗体形式显示的菜单项
BOOL CMEnu::SetDefaultItem( UINT uItem,BOOL fByPos=FALSE);
false
时是第一个参数用id
true
时用索引
OnCreate中添加
GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE);
或者
GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_OPEN,FALSE);
分割栏是占据索引位置的
一个子菜单只能有一个默认菜单

l         禁用菜单项:我们想实现这样的功能:禁用【文件,打开】菜单项。
UINT CMenu::EnableMenuItem(UINT nIDEnableItem,UINT nEnable);
第二个参数为:
MF_BYCOMMAND
指定第一个参数是菜单项的id
MF_BYPOSITION
指定第一个参数是菜单项的索引
MF_DISABLE
MF_ENABLE
MF_GRAYED
通常把MF_GRAYEDMF_DISABLE放一起用,但不是必须的
这个函数有点特殊,需要做些设置:一旦在CMainFrame的构造函数中把m_bAutoMenuEnable设置为false后,就不需要对ON_UPDATE_COMMAND_UION_COMMAND消息进行响应处理,CMenu类的EnableMenuItem就能正常工作
CMainFrame()中m_bAutoMenuEnable=FALSE;
OnCreateGetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED | MF_GRAYED);    
m_bAutoMenuEnable
被设置为FALSE后,MFC不再利用它的菜单更新机制去判断菜单的可用状态,所有设置由程序员做

l         移除和装载菜单
使用BOOL CWnd::SetMenu(CMene* pMenu);这个函数有个CMenu类型的指针参数,它指向一个新菜单对象。如果这个参数为null,则当前菜单被移除
OnCreate中添加SetMenuNULL);即可移除菜单。
现在我们再让菜单显示出来,在CMainFrame中添加成员变量menu
注意:我们菜单是属于MainFrame的,
     this->menu.LoadMenu(IDR_MAINFRAME);

this->SetMenu(&menu);
这样菜单又被再次装载进来

l         MFC菜单更新机制,菜单项状态的维护依赖于ON_UPDATE_COMMAND_UI消息。使用class wizard可以设置UPDATE_COMMAND_UI消息响应函数,CCmdUI中有
virtual void Enable(BOOL bOn=TRUE);true
时菜单项可用,false则否
我们把【编辑,剪切】设置为可用
void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)

{

          // TODO: Add your command update UI handler code here

          pCmdUI->Enable();

}
经过这个设置后,我们发现连工具栏的【剪切】也可用了,实际上工具栏的【剪切】的id和【编辑,剪切】的id是一样的
如果要把工具栏上的一个工具按钮和菜单栏中的某个菜单项相关联,只要将他们的id设置为同一个标识就可以了。

l         注意一下菜单项和工具按钮的索引位置计算方式不一样

l         右键快捷菜单:【projects】【add to projcts】【component and control】,add popup menu to哪个类时,不应该选择CMainFrame类,因为视类窗口始终覆盖在框架窗口之上,框架窗口中又捕获不到鼠标右键这一消息。所以我们选择CMenuView类。
我们为自己定制一个快捷菜单
首先,插入资源IDR_MENU1,添加显示和退出两项
其次,添加响应右键消息函数,加入:    CMenu menu;

       menu.LoadMenu(IDR_MENU1);

       CMenu* pPopup=menu.GetSubMenu(0);

       pPopup->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x,point.y,this );
      
CMenu::TrackPopupMenu

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

       nFlags指定菜单在屏幕上的显示位置
    x
y分别指定快捷菜单显示位置处的x坐标和y坐标

    pWnd指定快捷菜单的拥有者,也就是标识拥有快捷菜单的窗口对象
    lpRect
指定一块矩形,用户在这个区域内单击鼠标,快捷菜单保持原型。如果null则用户在这个快捷菜单范围之外单击时,菜单就消失
   
最后,为快捷菜单添加响应函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值