VC++讲义 第06章.docx
- 文档编号:17839949
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:80
- 大小:550.42KB
VC++讲义 第06章.docx
《VC++讲义 第06章.docx》由会员分享,可在线阅读,更多相关《VC++讲义 第06章.docx(80页珍藏版)》请在冰点文库上搜索。
VC++讲义第06章
第六章菜单、工具栏和状态栏
菜单、工具栏和状态栏是组成Windows图形界面的三个主要元素。
其中菜单、工具栏提供了用户操作应用程序的命令界面;状态栏提供了一个输出区域,用来显示当前程序运行的状态和数据变化等等。
本章将详细的介绍菜单、工具栏和状态栏的使用方法。
6.1菜单
大多数的Windows应用程序都提供菜单作为用户与应用程序之间传递命令的一个特殊的途径。
利用菜单可以不用将大量的命令按钮摆放在窗口上。
既节省空间又使用方便。
本节将主要讲述菜单的种类,菜单的设计与创建,及菜单的消息处理等等。
6.1.1菜单介绍
在众多的应用程序当中,我们最常见到的菜单有下拉式菜单、级联菜单和快捷方式菜单。
下拉式菜单一般出现在应用程序窗口的顶部,分类的类别排成一行,和某个类别相关的所有功能排在那个类别的下面,如果选中某个类别时,其下就会拉出菜单,该菜单中有一系列具有相关功能的菜单项可供选择。
级联菜单是下拉菜单的一个扩展。
如果某个菜单项的右边有一个向右的黑三角符号,那么这个菜单项其实就是一个级联菜单。
级联菜单带有另一个子菜单,子菜单一般显示在所属菜单项的右边。
这个子菜单和下拉式菜单相似,有一系列菜单项可供选择。
需要注意的是,请读者一定要区别弹出式菜单和菜单项。
一般来说,把单击后会出现下拉子菜单的菜单称为弹出式菜单,而把其他菜单叫菜单项。
级联菜单也是弹出式菜单,它右边出现的子菜单中的各个小菜单也叫菜单项。
第三种菜单风格是可以通过在应用程序区域中单击鼠标右键调出的一种很方便的菜单,叫快捷菜单或弹出式菜单。
由于该菜单的菜单项内容依赖于被选中的对象或光标、鼠标在工作区域内所指的位置,因此该种菜单也称为上下文菜单。
一般情况下,当我们新建好一个MFC应用程序时,AppWizard都会为我们生成一个常用的菜单。
单文档应用程序会自动生成标识符为IDR_MAINFRAME的菜单资源,而多文档应用程序自动生成标识符为IDR_MAINFRAME和IDR_xxxTYPE的菜单资源,其中xxx为你的工程名。
这些菜单资源在应用程序框架窗口创建时自动加载,我们可以修改这个菜单资源。
对于一个单文档的工程来说,菜单是在CxxxApp的Initinstance中产生的(xxx为你的工程名字),产生代码如下:
CSingleDocTemplate*pDocTemplate;
pDocTemplate=newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CxxxDoc),
RUNTIME_CLASS(CMainFrame),//mainSDIframewindow
RUNTIME_CLASS(CxxxView));
AddDocTemplate(pDocTemplate);
其中IDR_MAINFRAME是菜单的ID,我们在资源面板里可以看到,很多资源的ID都是IDR_MAINFRAME,包括菜单、工具栏、加速键、图标和字符串表,由此可知,一个ID可以标识多个资源。
6.1.2创建一个菜单
在应用程序中创建并使用一个菜单一般都遵循下面几个步骤:
1.在工程中添加一个自定义的菜单资源。
2.用菜单编辑器设计菜单。
3.将菜单加入到应用程序中。
4.为每个菜单项添加消息映射。
以上步骤是我们创建一个自定义菜单的常规步骤,读者也可以在菜单编辑器中或应用程序中修改、控制AppWizard生成的系统菜单及用户自定义菜单。
6.1.2.1添加一个菜单资源
以前的章节中我们讲过如何添加一个字符串资源和位图资源,其实,添加和修改菜单资源和添加前两个资源类似,所有的资源添加方法都是雷同的。
首先,打开或新建一个MFC单文档的应用程序,若要建立一个新的菜单资源,可以通过两种方法,一种是从View菜单中选取Resource菜单项,弹出InsertResource对话框,如图6-00所示。
在该对话框中选定Menu,然后单击对话框右边的New按钮即可。
图6-00InsertResource对话框
图6-01添加菜单资源
另一种方法是点击工作台下面的ResourceView选项,使其显示资源面板页面。
在资源浏览窗口中,鼠标右击Menu,弹出如图6-01所示快捷方式菜单,在该菜单中可以有两个选择来添加菜单资源,通过选择Insert,那么同样会弹出如图6-00所示InsertResource对话框来进行添加;通过选择InsertMenu,可以省略调用InsertResource对话框这一步,直接在工作台Menu资源下面产生一个新的菜单资源。
在执行上述操作之后,我们可以看到在工作台中多了一个ID号为IDR_MENU1的菜单资源。
ID号IDR_MENU1是系统自动为我们生成的,我们可以保留这个ID号,也可以修改成我们自己想要的ID号。
修改ID号的方法很简单,只要我们鼠标右键单击ID号IDR_MENU1,然后在如图6-02所示的快捷方式菜单中选择Properties,在如图6-03所示的MenuProperties对话框中的ID后面的文本框中输入我们想要修改的ID值,如IDR_MYMENU.
图6-02修改菜单资源的ID
图6-03MenuProperties对话框
我们虽然添加了一个菜单资源,但它仅仅具有一个ID号,还没有任何内容,下面我们将使这个ID号具有真正的菜单。
6.1.2.2利用菜单编辑器编辑菜单资源
我们双击工作台资源面板上ID号为IDR_MYMENU,我们新添加的菜单资源,在右边的菜单编辑器中只有一个空白的菜单项被高亮显示,如图6-04所示。
图6-04一个空菜单
接下来,我们可以给这个菜单资源加入菜单项了,假定我们要加一个弹出菜单“颜色”,它下面有两个菜单项“红色”和“蓝色”,加入菜单项的步骤如下:
步骤1:
在菜单编辑器窗口中,鼠标右键单击空白菜单项,在弹出的快捷方式菜单中选择Properties菜单项或者鼠标左键双击空白菜单项,弹出如图6-05所示的菜单项属性对话框,在Caption文本框中输入“颜色”,回车确认,顶层菜单中就多了一个“颜色”下拉菜单。
系统默认的顶层菜单为弹出式菜单,因此在这个弹出式菜单的下面又多了一个空白的菜单项.
图6-05添加顶层菜单
在进行下一步之前,我们先来分析一下菜单项属性对话框的5组选项:
1)ID(菜单项的ID)
菜单的ID后面跟着一个组合框,其中列出了所有使用ID值,一般情况下,菜单的ID取值应遵循以下原则:
Id_顶层菜单名_下一级菜单向名(_再下一级菜单项名...)
这样做的好处是,当看到ID号时,就知道是哪个菜单项了,并且当应用程序菜单中有多个菜单项时不容易造成ID号重复.需要注意的是,弹出菜单不需要ID号,如“颜色”。
2)Caption(菜单项的名称)
菜单项的ID是代表它的身份并且需要在程序中引用,但是,将它显示在窗口上的时候,它还需要有个名字。
Caption取名几可以是英文,也可以是中文,也可以包含数字、符号等等。
我们还可以在Caption文本框中定义某个菜单项的快捷键。
给菜单加上快捷键的操作很简单,只需在Caption文本框中,在菜单标题中响应的字母前键入“&”即可。
如果菜单是中文,就必须用小括号把快捷键的说明括起来。
如图6-06所示的“新建”菜单项的快捷键使用“(&N)”定义。
图6-06“新建”菜单项属性
Caption文本框中还有一串字符“\tCtrl+N”,这是用来表明该菜单项的加速键,加速键可以在不打开菜单的情况下直接执行菜单项。
其中“\t”是制表符。
3)一组复选框
●Separator(分隔线)复选框
选中该复选框,则菜单项变成一个分隔线,而原有菜单项信息丢失。
如果用户想在已添加的两个菜单项中间加一条分隔线,可以先用鼠标拖动空白菜单到需要分割线的位置,然后将这个空白菜单复选Separator复选框。
●Pop-up(弹出式)复选框
选中此复选框,菜单项将成为弹出式菜单,即单击此菜单会弹出下一级子菜单。
弹出式菜单不需要指定ID号,VisualC++默认顶层菜单为弹出式菜单,当然,我们也可以把它设为菜单项。
非顶层菜单也可以作为弹出菜单(级联菜单),它的菜单项的右边显示一个三角符号。
如果不选这个复选框,表示该菜单为菜单项。
●Inactive(不活动)复选框
选中此复选框表明菜单项的初始状态为非活动状态。
●Checked(检查标记)复选框
此复选框用来非菜单一个初始的检查标记,选中该复选框,会在菜单项的左边打上一个钩。
●Grayed(变灰)复选框
选中此复选框,该菜单项将以灰色显示,表明菜单的初始状态为不可访问,如果该复选框被选中,那么菜单一定是不活动的,所以,此时Inactive复选框不可用。
●Help(帮助形式)复选框
选中此复选框,菜单会出现在菜单拦的右侧,如图6-07所示,我们将AppWizard为我们生成的标准菜单中的“帮助”菜单选定为help形式。
图6-07帮助形式菜单
4)Break(菜单项的分割)
当一个菜单的菜单项太多时,放在一列当中会感觉很长很拥挤,这时,我们可以考虑把它分成两列来显示,Break就起到了这样的作用。
Break选项对应一个组合框,有三种选择方式:
None、Column和Bar。
●None:
系统默认选项,表示不分割。
●Column:
列分割,选中此项时,从选中的菜单项以下的菜单项将另起一行。
如图6-08所示,我们将“文件”菜单中的“打印”菜单项选中此项的结果。
图6-08Column分割形式
●Bar:
和Column类似,也是列分割,只不过,与Column不同的是,两列之间有一条竖线将它们割开,图6-09所示。
图6-09Bar分割形式
5)Prompt(菜单项功能的提示)
在Prompt后面的文本框中可以输入文本,程序运行时,当鼠标移到菜单项上时,在底部的状态栏将给出此菜单的功能的提示。
介绍完菜单项属性对话框,我们接着上面的第1步继续讲如何加入一个菜单项。
步骤2:
如图6-05所示,我们双击顶层菜单“颜色”下面的空白的菜单项,,再次调出菜单项属性对话框,在Caption后面的文本框中输入“红色”,设定其ID号为ID_COLOR_RED,最终结果如图6-10所示。
回车确认,“红色”菜单项就添加好了。
图6-10添加“红色”菜单项
步骤3:
再双击“红色”菜单项下面的空白菜单项,用相同的方法添加“蓝色”菜单项,在Caption后面的文本框中输入“蓝色”,设定其ID号为ID_COLOR_BLUE,结果如图6-11所示,回车之后,这个菜单就添加好了。
图6-11添加“蓝色”菜单项
经过上述3个步骤,带有“红色”和“蓝色”子菜单项的弹出式菜单“颜色”菜单创建好了,后面,我们将讲述如何将它加进应用程序中。
6.1.2.3将菜单加入到应用程序中
现在我们运行一下刚刚添加完“颜色”菜单的程序,发现窗口上显示的菜单依然是AppWizard为我们添加的标准菜单,我们自己的菜单没有显示出来,为什么呢?
我们知道一个应用程序只能有一个菜单,在前面第一节中我们已经讲过,单文档应用程序会自动生成标识符为IDR_MAINFRAME的菜单资源,因此,在程序加载的时候,它只是加载了标识符为IDR_MAINFRAME的菜单,那么要想让我们的菜单显示出来,我们可以在框架类创建的时候,将我们自己的菜单加载进去。
在CmainFrame类的OnCreate函数中编辑代码如清单6-00所示:
清单6-00CMainFrame:
:
OnCreate函数代码
———————————————————————————————————————
1intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
2{
3if(CFrameWnd:
:
OnCreate(lpCreateStruct)==-1)
4return-1;
5
6if(!
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|
7CBRS_TOP
8|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
9!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
10{
11TRACE0("Failedtocreatetoolbar\n");
12return-1;//failtocreate
13}
14if(!
m_wndStatusBar.Create(this)||
15!
m_wndStatusBar.SetIndicators(indicators,
16sizeof(indicators)/sizeof(UINT)))
17{
18TRACE0("Failedtocreatestatusbar\n");
19return-1;//failtocreate
20}
21//TODO:
Deletethesethreelinesifyoudon'twantthetoolbarto
22//bedockable
23m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
24EnableDocking(CBRS_ALIGN_ANY);
25DockControlBar(&m_wndToolBar);
26CMenumenu;
27menu.LoadMenu(IDR_MYMENU);
28this->SetMenu(&menu);
29return0;
30}
第1~25行的代码所实现的功能是创建工具栏和状态栏并显示,这部分代码部分是由应用程序自动生成的。
第26~27行代码首先定义了一个CMenu类的变量,然后调用该类的成员函数LoadMenu()将我们新添加的ID号为IDR_MYMENU的菜单载入该变量,即让变量menu指向我们新创建的菜单,最后在第28行,用SetMenu函数替换现有菜单。
函数SetMenu原形如下:
BOOLSetMenu(CMenu*pMenu);
参数pMenu为菜单指针,若该参数为空,则表示删除现有菜单;若不为空,则用参数所指的菜单来替换现有菜单。
其实,我们可以不用这么麻烦来添加一个菜单,完全可以通过修改原有的标准菜单来达到。
我们可以将原来的标准菜单加一个或删掉一个弹出式菜单,也可以将某个弹出式菜单的某个菜单项删除,或给它添加一个菜单项,这些在菜单编辑器中都可以实现。
操作的过程与前面讲的也类似,后面的实例中我们也会讲到。
图6-12运行结果
运行结果如图6-12所示,但是,这个菜单还不能够进行任何操作,它的两个菜单项都呈灰白状态,那是因为还没有给它们添加消息响应函数。
6.1.2.4给菜单项添加COMMAND消息处理
现在,我们给“红色”和“蓝色”两个菜单项添加消息响应。
给菜单添加消息响应的过程同第三章中讲过的添加消息响应的过程很类似。
第1步:
鼠标右键单击代码编辑区,在弹出的快捷方式菜单中选择ClassWizard菜单项,弹出ClassWizard对话框。
第2步:
在Classname下面的下拉组合框中选择CTestView类,在ObjectIds下面的列表项中选定ID_COLOR_RED,此时,Message下面的列表框中只有两个消息:
COMMAND(命令消息)和UPDATE_COMMAND_UI(更新命令用户界面消息),如图6-13所示。
第3步:
在Message下面的列表框中双击COMMAND,此时会弹出AddMemberFunction对话框,如图6-14所示,在该对话框中,应用程序自动给出默认的函数名OnColorRed,我们可以修改这个函数名,但是,建议还是使用默认的函数名。
在单文档工程中,MFCAppWizard为我们生成的四个类都可以响应同一个菜单的WM_COMMAND消息。
如果在这四个类里都加了同一个菜单的响应函数,四个响应函数将只有一个被执行,它们之间有一个优先顺序,依次是:
ViewDocumentMainFrameApp。
具体响应函数应该放在哪个类里,就要看在这个响应函数里,完成的是什么功能,放在哪个类里方便。
比如,如果点击一个菜单,想隐藏工具栏,它的响应函数就应放在CMainFrame里。
图6-14添加COMMAND消息处理
第4步:
在该对话框上单击OK按钮,此时OnColorRed函数就出现在ClassWizard对话框的MemberFunctions下面的列表框中了。
第5步:
单击ClassWizard对话框右边的EditCode按钮,应用程序自动定位到CtestView类的OnColorRed函数,我们就可以在这个函数中编写代码了。
在上面的第3步中,有的读者可能不理解,为什么添加COMMAND命令而不添加它下面的UPDATE_COMMAND_UI命令。
当我们点击菜单时,系统发出的都是WM_COMMAND消息,在这个消息的扩展参数wParam中,包含菜单的ID,用户可以通过ID来判断是哪个菜单被点击了。
而UPDATE_COMMAND_UI消息则是当菜单需要重新绘制或更新时由系统发送。
菜单是一格一格弹出来的,每弹出一格发出一个ON_UPDATE_COMMAND_UI消息,我们可以响应这个消息,设置菜单弹出的状态,比如打勾、打点、变灰等。
注意:
ON_UPDATE_COMMAND_UI只能由拥有菜单的窗口发出,切记!
切记!
!
切切记!
!
!
6.1.2.5给菜单项添加UPDATE_COMMAND_UI消息处理
在讲述如何添加UPDATE_COMMAND_UI消息处理之前,我们有必要先了解一下用户界面更新原理。
I.用户界面更新原理
更新命令UI消息只适用于弹出式菜单的菜单项,而对顶层菜单不起作用。
在显示弹出式菜单时,框架按视图类->文档类->框架类->应用程序类的顺序发送弹出式菜单的所有菜单项的UPDATE_COMMAND_UI消息。
如果菜单项有一个更新处理函数,则它被调用进行更新;如果没有,则框架检查COMMAND命令处理函数是否存在,如果不存在,则使菜单项变灰。
因此,为了使一个菜单项有效,必须为该菜单项添加一个消息处理函数。
当用户下拉一个菜单时,每个菜单项都需要知道它应该显示为何种状态(如允许、禁止)。
菜单命令就是通过ON_UPDATE_COMMAND_UI处理函数来提供这个消息的。
当某个菜单被拉下时,应用程序框架就会查找并调用各个菜单项的ON_UPDATE_COMMAND_UI处理函数,然后根据处理函数的内容来正确的显示各个菜单项。
II.如何添加一个UPDATE_COMMAND_UI消息处理
第1步:
鼠标右键单击代码编辑区,在弹出的快捷方式菜单中选择ClassWizard菜单项,弹出ClassWizard对话框。
第2步:
在Classname下面的下拉组合框中选择CTestView类,在ObjectIds下面的列表项中选定ID_COLOR_BLUE,此时,Message下面的列表框中只有两个消息:
COMMAND(命令消息)和UPDATE_COMMAND_UI(更新命令用户界面消息)。
第3步:
在Message下面的列表框中双击UPDATE_COMMAND_UI,此时会弹出AddMemberFunction对话框,如图6-15所示,在该对话框中,应用程序自动给出默认的函数名OnUpdateColorBlue。
图6-15添加UPDATE_COMMAND_UI消息处理
第4步:
在该对话框上单击OK按钮,此时OnUpdateColorBlue函数就出现在ClassWizard对话框的MemberFunctions下面的列表框中了。
第5步:
单击ClassWizard对话框右边的EditCode按钮,应用程序自动定位到CTestView类的OnUpdateColorBlue函数,函数体如下:
voidCTestView:
:
OnUpdateColorBlue(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
pCmdUI->SetCheck(TRUE);
}
可以看到,在调用ON_UPDATE_COMMAND_UI的响应函数时,系统为用户传来了pCmdUI指针。
CCmdUI是一个只被使用在ON_UPDATE_COMMAND_UI消息的响应函数中类,CCmdUI类没有基类,是一个独立的类。
它可以控制正在被弹出的菜单项的状态。
这个类中有一个成员变量m_nIndex表示菜单项在整个弹出菜单中的序号,另一个成员变量m_nID表示菜单的ID。
我们来介绍一下它的成员函数:
●Enable():
设置菜单项是否有效;例pCmdUI->Enable(TRUE);
●SetCheck():
设置菜单项是否打勾;例pCmdUI->SetCheck(TRUE);
●SetRadio():
设置菜单项是否打点;例pCmdUI->SetRadio(TRUE);
●SetText():
设置菜单项的文本。
例pCmdUI->SetText(“蓝色”);
详细的成员函数说明可参照MSDN。
6.1.2.6一个简单的绘图程序
下面我们将通过一个实例来巩固加深前面所讲的内容。
这个实例中包含一个弹出式菜单“绘图”,在该菜单下面有四个菜单项,分别为“画点”、“画线”、“画矩形”、“画椭圆”,单击相应的菜单就会在屏幕上画出相应的图形,并且被选择的菜单项的左边被打钩。
为了实现上述的功能,我们需要添加一个弹出式菜单“绘图”,并且需要定义两个成员变量,一个用来记录用户选择了哪个菜单,另一个保存鼠标按下的点。
完整例程请参见光盘中的例子代码EX06_00。
●步骤1:
新建一个MFC单文档应用程序,工程名为EX06_00,或用户自定义。
●步骤2:
在原来的标准菜单的基础上再添加一个弹出式菜单“绘图”。
1)打开工作台的ResourceView页面,在资源面板中展开资源,打开Menu文件夹,双击已有的ID号为IDR_MAINFRAME的菜单资源。
2)在右边的菜单编辑器中,原有菜单“帮助”后面有一个空白的菜单项,按照传统的风格,“帮助”菜单通常是放在最后的,因此,我们拖动那个空白菜单项,把它拖到“帮助”菜单的左边。
如图6-16所示。
图6-16将空白菜单移到“帮助”菜单左边
3)添加顶层菜单“绘图”。
双击空白菜单,弹出菜单项属性对话框,在Caption文本框中输入“绘图”,回车确认,顶层菜单中就多了一个“颜色”下拉菜单。
并且它的下面也多了一个空白的菜单项,如图6-17所示。
图6-17添加“绘图”菜单
4)添加菜单项“画点”。
我们双击顶层菜单“绘图”下面的空白的菜单项,再次调出菜单项属性对话框,在Caption后面的文本框中输入“画点”,设定其ID号为ID_GRAPH_DOT,最终结果如图6-18所示。
图6-18添加“画点”菜单项
5)依照上一步,将其他三个菜单项“画线”、“画矩形”、“画椭圆”添加进去。
ID号分别为ID_GRAPH_LINE、ID_GRAPH_RECTANGL
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC+讲义 第06章 VC 讲义 06