MFC学习笔记.day03-菜单,图形标记菜单创建,菜单栏禁用,命令响应,右键弹出菜单,添加菜单

来源:互联网 发布:js创建json数组对象 编辑:程序博客网 时间:2024/06/02 23:57

菜单

命令响应

View类先响应,接下来是Doc类,然后是我们的CMainframe,最后是我们的App类。

消息

菜单消息的响应过程:

首先是-《框架类》接受消息,然后交给《view类》,不能响应则继续转交给《doc类》,不能响应则继续转交给VIEW类转交给《框架类》,不能响应最后交给《APP类》。

菜单栏的构造

它的构造是这样子的: 菜单栏(类似于楼层)——子菜单(类似于房间)——菜单项(类似于门牌号)

获取菜单栏的指针的函数:Getmenu

获取子菜单的函数:Getsubmenu

设置标记菜单:CheckMenuItem,我们可以通过索引号和ID号来寻找

设置缺省菜单项:SetDefaultItem,我们也可以利用索引号和ID号来找寻,注意我们在设置缺省菜单项,这能设置一个。

注意:当我们在进行确定索引号的时候,注意一定要从0开始数,分隔符也要数进去。

图形标记菜单的创建:

1.首先我们创建位图(注意将这个CBitmap 的对象设置为框架类的成员变量)

2.加载这幅位图 LoadBitmap

3.

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

4.【注意】当我们进行编译是会看不到新建标记,我们要将背景色改变为非白色,然后要设置这幅位图的大小,当我们不知道位图该设置为多少大小时我们可以利用函数GetSystemMetrics,只有一个参数。

具体代码:

CString str;str.Format("x=%d,y=%d",GetSystemMetrics(SM_CXMAXIMIZED),                        GetSystemMetrics(SM_CYMAXIMIZED));MessageBox(str);

设置将菜单项为无效:

用函数EnableMenueItem()

代码可以这样来写 :

GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION | MF_DISABLED);

但是我们会发现这样这个菜单项还是可以响应的,这是为什么呢?

然后我们继续在MSDN中寻找答案,发现它里面有这样一句话

OTE: m_bAutoMenuEnable is set to FALSE in the constructor of
CMainFrame so no ON_UPDATE_COMMAND_UI or ON_COMMAND handlers are
needed, and CMenu::EnableMenuItem() will work as expected.

在MFC中某个菜单能使用和不能使用,MFC给我们提供了一种机制;

如果我们人为的要让菜单项可以使用和不可以使用,我们就要在CMainFrame的构造函数中将m_bAutoMenuEnable设置为FALSE

When you change a window menu, the menu bar is not immediately updated. To force the update, call DrawMenuBar.

命令响应:

菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。我们可以通过手工或利用ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获CN_UPDATE_COMMAND_UI消息。在后台所做的工作是:操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如CFrameWnd接管。他创建一个CCndUI对象,并与第一个菜单项相关联,调用对象的一个成员函数DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmndUI对象的指针。同一个CCndUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。

更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。

我们手动来改变菜单项的响应状态(可用或不可用):

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) {// TODO: Add your command update UI handler code hereif (ID_EDIT_CUT==pCmdUI->m_nID)//当我们使用索引号是注意menu中和toolbar中的差异,两个值不应定相等;    {        pCmdUI->Enable(TRUE);//如为可用,我们设为真    }}

模拟鼠标右键弹出功能:

第一步:我们来创建菜单(由于右键点击菜单中顶级菜单是不出现了,所以我们呢可以随便写)
第二步:定义一个CMenu的对象;
第三步:我们来将这个菜单加载进来;
第四步:定义一个CMenu的指针;
第五步:再来调用TrackPopMenu;
第六步:最后来转换坐标体系(将客户区坐标变为屏幕的坐标)用函数CClientToScreen();

具体操作:

第一步:这个我们可以在资源里面之间插入一个Menu即可;
第二步:加载 menu.LoadMenu(IDR_MENU1);
第三步:CMenu *pPopup=menu.GetSubMenu(0);
第四步:

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

第五步:坐标转化 ClientToScreen(&point);

下面我们来对菜单里面的显示进行命令响应,这个响应跟我们以前的菜单项响应是一样,这里我就不再赘述,主要我们来看看在view类中和mainframe中是区别,由于view类是mainframe的子类,我们要注意当我们在第四步中将TrackPoupMenu中的最后一个参数设置为this时,这样在框架类中的显示命令消息响应在框架类中就无法响应了,理由是这个指针为view类的,故mainframe无法响应,当我们将这个this改为GetParent(获得框架类的指针)后,这样先响应的是view类,后响应的是mainframe类,理由是子类有的先响应子类,子类没有响应再去响应父类的。

右键菜单弹出代码

void CFirstView::OnRButtonDown(UINT nFlags, CPoint point){    // TODO: 在此添加消息处理程序代码和/或调用默认值    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);}void CFirstView::OnShow(){    // TODO: 在此添加命令处理程序代码    MessageBox(_T("View Show"));}

动态来添加菜单

第一步:首先来创建一个CMenu的对象
第二步:创建一个弹出菜单 CreatePopupMenu
第三步:增加菜单 AppendMenu
第四步:我们来插入一个菜单 InsertMenu

具体步骤:

CMenu menu;menu.CreatePopupMenu();GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"wjl");GetMenu()->InsertMenu(0,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu,"wjl1");

我们再来看看如何删除一个菜单:
由于我们要删除菜单,因此我们必须先找到这个菜单在哪里,即获取这个菜单的指针,然后进行删除,

GetMenu()->DeleteMenu(1,MF_BYPOSITION);

下面我们来看看如何删除一个菜单项:
由于我们要删除菜单项我们首先必须找到菜单项所在的菜单位置,然后在找到菜单项,这里我们可以利用索引号或者命令ID号来找,只要注意前后对应起来就可以了。
如:

 GetMenu()->GetSubMenu(2)->DeleteMenu(1,MF_BYPOSITION);

如果DeleteMenu中第一个参数为ID号,我们只要将MF_BYPOSITION 改为MF_BYCOMMAND即可,但是一定要注意前后两个参数是对应关系。

下面我们来看看怎样在我们新创建好的菜单上再加入菜单项:
直接在我们创建好的菜单上加入菜单项,我们想去找到建立菜单时用到的
CMenu的一个对象,然后直接有这个对象来调用函数AppendMenu即可,
如:CMenu menu;

menu.CreatePopupMenu();GetMenu()->InsertMenu(0,MF_BYPOSITION|   MF_POPUP,(UINT)menu.m_hMenu,"wjl1");menu.AppendMenu(MF_STRING,111,"wjl3");

下面我们来看看如何将这些菜单项进行响应,这里动态创建菜单可不像我们先前创建的菜单项那样简单的就可以命令响应,这里我们必须非常了解MFC中的消息响应机制(当然我们可以随便跟踪一个菜单项的命令的响应,然后模仿着写就可以了)。

第一步:我们来获取资源的ID号,我们来创建资源的ID,具体步骤点击FileView,再点击Header Files,再点击 Resource.h,在里面写入你要定义的ID号,可以这样写,#define IDM_WJL3 111
第二步:在头文件中做命令函数的原型 afx_msg void ONWJL3();
第三步:在函数中我们来写消息映射函数 ON_COMMAND(IDM_WJL3,ONWJL3)
第四步:具体函数

CMainFrame::ONWJL3(){    MessageBox("wjl3");}
0 0
原创粉丝点击