fv-24ch6c++香港价格网

C++___ch6_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩8页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢05 菜单、工具栏和状态栏编程_Visual&C++编程技术_pdf_大学课件预览_高等教育资讯网
Visual&C++编程技术:05 菜单、工具栏和状态栏编程
分类: 格式: 日期:日
88励志照亮人生 编程改变命运零基础学 Visual C++第5章菜单、工具栏和状态栏编程菜单、工具栏和状态栏是一个完善的Windows应用程序的重要组成部分(但不是必需的)。在Windows写字板应用程序中,菜单栏、工具栏、状态栏及其所包含的元素如图5.1所示。菜单是用户选择可用命令的一个最常用、也是最重要的手段。在一些情况下,工具栏也是一种更快捷、更有效的命令输入方式。而状态栏则一般位于主框架窗口的底部,主要用来显示一些提示信息,可细分为几个窗格。本章对使用Visual C++开发Windows程序中,菜单、工具栏和状态栏的设计与使用进行详细介绍。5.1 菜单及其相关资源的使用菜单是Windows与用户交互的标准接口之一,Windows的大多数应用程序都提供了菜单操作。当一个菜单项被选中时,它发出一个命令消息,从而引发相应的消息处理函数的执行。5.1.1 菜单的种类及开发步骤在Windows窗口中,菜单有两种标准风格:下拉菜单和弹出菜单(也称上下文菜单)。下拉菜单:一般在应用程序窗口的顶部罗列了一行按类别排列的菜单。如果用户选择了某一类别,就会显示一个下拉式菜单。图5.1所示即为下拉菜单。弹出菜单:一般在应用程序窗口区域的中间弹出显示,在应用程序工作区域上面处于自由浮动状态。在写字板输入窗口中,单击鼠标右键,即出现弹出式菜单,如图5.2所示。下拉菜单与弹出菜单只是在形式上不同,其消息及消息处理机制完全相同。在程序开发中,简单的菜单编程一般可分为下面三个步骤:(1)编辑菜单资源,设置菜单属性(包括菜单名和ID);(2)用ClassWizard自动映射菜单消息和成员函数;(3)手工编辑成员函数,加入菜单消息处理代码。图5.1 菜单栏、工具栏、状态栏及其所包含的元素命令提示状态栏菜单栏工具栏工具按钮典型的Windows窗口的菜单、工具栏下拉菜单菜单项窗格图5.2 弹出式菜单弹出菜单5.1.2 菜单的创建与编辑在Visual C++6.0中,使用MFC AppWizard生成的文档/视图结构的应用程序,系统已为框架创建了一个标准的主菜单,包括文件、编辑、视图和窗口帮助等标准菜单,定义了各菜单项的ID及相应的命令处理函数。一般只需要通过菜单资源编辑器,在已有主菜单的基础上添加、设计需要的菜单项即可。下面结合一个具体的实例讲解菜单的创建与编辑。1,创建SDI项目在Visual C++6.0中,执行“File”→“New”菜单命令,在“Project”选项卡中,创建一个MFCAppWizard[EXE]工程,工程名为“Ch6Demo1”。在MFC AppWizard Step 1的时候,选中“Singledocument”,即基于单文档的MFC工程,其余的几步采用默认设置。在工作区窗口的Resource View选项卡中,打开工程资源,选择“Menu”,会发现自动创建了IDR_MAINFRAME菜单资源,双击它,可打开菜单编辑器,如图5.3所示。2,添加菜单项在主菜单的最右边以及每个下拉菜单展开的最下边都有一个虚线框,该虚线框实际上就是菜单的“生长点”。将光标移动到虚线框内,双击左键,就启动了菜单项的属性对话框,添加、设置菜单项的相关信息。本例中,将在IDR_MAINFRAME菜单中添加一个“绘图”顶层菜单,其下设计两个菜单项:“圆形”和“矩形”。(1)增加顶层菜单“绘图”在主菜单右侧的虚线框内,双击左键,弹出菜单项属性对话框。在“Caption”编辑框中输入菜单名“绘图(&D)”,菜单名即显示在菜单上,如图5.4所示。说明在菜单名中,可用【Alt】键加该字符作为选择菜单的快捷方式。菜单“绘图(&D)”表示使用“Alt+D”作为该菜单的快捷键。此时,属性对话框中默认选中了“Pop-up”选项,表示该项是一个顶层菜单,其本身不执行菜单命令。菜单属性对话框中各选项及其含义如表5.1所示。(2)添加、定义菜单项双击“绘图”菜单下的虚线框,即可打开菜单项属性对话框,添加菜单项。在General页面上输入89励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程图5.3 IDR_MAINFRAME菜单资源图5.4 添加顶层菜单的属性对话框表5.1 菜单属性对话框中各选项及其含义菜单属性项含义ID表示该菜单项的ID值Caption表示该菜单项显示的文本Separator表示该菜单项是一条分隔线Checked表示该菜单项被选中显示一个标志Pop-up选择该菜单项显示一个子菜单Grayed该菜单项变灰显示,被禁止Inactive该菜单项不被激活Help Help菜单,通常放在菜单的最右端Break选中该菜单项后就退出其所在菜单Prompt光标移至该菜单项状态栏显示的文本Caption菜单项名称及其ID值,在Prompt编辑框中的字符串是选择该菜单项时状态栏上显示的内容。分别添加“圆形”和“矩形”两个菜单项,如图5.5所示。如果要删除某个菜单项或弹出菜单,可用鼠标单击该菜单或用上下光标键选择,然后按【Del】键删除。图5.5 添加菜单项属性对话框说明在菜单实际设计时,菜单的级数一般以2?3级为宜;若单击某菜单项会弹出一对话框,那么在该菜单项文本后加上“?”。此时编译、运行程序,则“绘图”菜单下的命令都是“灰色”的,即无法选择相应的菜单命令,这是因为还没有对菜单的命令消息进行映射。5.1.3 菜单消息MFC程序可以处理两种菜单消息:WM_COMMAND和UPDATE_COMMAND_UI。WM_COMMAND:为菜单命令消息,当选择菜单项、工具栏按钮或加速键之一时会发出菜单命令消息,MFC依据一定的消息传递途径将消息传递给相应的处理函数进行处理,如果在消息传递途径的消息映射表中找不到相应的处理函数,该菜单项或按钮会被禁止使用。UPDATE_COMMAND_UI:为菜单更新消息,处理菜单状态的动态变化。如希望根据程序的执行状态,激活或禁用某些菜单项,设置选中标记,或更改菜单项文字等,就要定义这一消息处理函数。在某个菜单显示前,框架将发送菜单内所有菜单项的更新命令,有更新处理函数的菜单项,则调用其处理函数更新菜单显示方式;没有更新处理函数的菜单项,查找其命令处理函数,若仍然没有,则将菜单项禁用。在文档/视图结构的MFC应用程序框架中,在View类、Doc类、CMainFrame类和App类中均可以响应并处理菜单消息,菜单消息一旦在其中一个类中响应,则不再在其他类中查找响应函数。菜单消息的传递顺序如图5.6所示。图5.6 菜单消息的传递顺序具体而言,当点击一个菜单项的时候,最先接受到菜单项消息的是CMainFrame框架类,90励志照亮人生 编程改变命运零基础学 Visual C++菜单消息View类Doc类CMainFrame类App类CMainFrame框架类将会把菜单项消息交给它的子窗口View类,由View类首先进行处理;如果View类检测到没对该菜单项消息做响应,则View类把菜单项消息交由文档类Doc类进行处理;如果Doc类检测到Doc类中也没对该菜单项消息做响应,则Doc类又把该菜单项消息交还给View类,由View类再交还给CMainFrame类处理。如果CMainFrame类查看到CMainFrame类中也没对该消息做响应,则最终交给App类进行处理。5.1.4 菜单命令消息的处理定义好菜单项及其ID后,就需要为菜单命令添加响应函数。实现方法是借助ClassWizard,在需要响应菜单命令的类的消息映射表中增加一个入口,即定义一个命令消息ON_COMMAND宏。下面就以为“圆形”菜单命令项添加WM_COMMAND消息处理函数为例,讲解处理菜单消息的实现过程。1,用MFC ClassWizard自动映射菜单命令消息和成员函数执行“View”→“ClassWizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFCClassWizard”对话框。在对话框的“Message Map”选项卡中的“Class Name63636363636363636363041026363636363636363636363636363636363列表框中选择要响应菜单命令的类“CCh6Demo1View”,在“Object IDs”列表框中选择菜单ID“ID_DRAWCIRCLE”,在“Messages”列表框中选择“COMMAND”菜单命令消息,如图5.7所示。图5.7,MFC ClassWizard”对话框然后单击“Add Function”按钮,弹出“AddMemberFunction”对话框,可以修改函数名或接受默认函数名,如图5.8所示。这里使用默认的函数名,单击“OK”按钮,关闭这个对话框。此时,在CCh6Demo1View类所在.cpp文件的开始部分会发现自动添加的消息映射代码:BEGIN_MESSAGE_MAP(CCh6Demo1View,CView)//{{AFX_MSG_MAP(CCh6Demo1View)91励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程图5.8,AddMember Function”对话框ON_COMMAND(ID_DRAWCIRCLE,OnDrawcircle) //消息映射END_MESSAGE_MAP()2,手工添加函数的实现代码添加函数后,在“MFC ClassWizard”对话框中单击“Edit Code”按钮,就可以直接跳至新增函数代码的定义处。这时,需要手工添加OnDrawcircle()函数的实现代码,如下:void CCh6Demo1View::OnDrawcircle(){// TODO,Add your command handler code hereCDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针CRect rect(100,0,300,200);CBrush brush(RGB(180,180,180)); //定义画刷pDC-&FillRect(rect,&brush); //填充绘图区域pDC-&Ellipse(160,10,260,110); //画圆pDC-&TextOut(120,120,&绘制直径为100个像素的圆&); //在圆下方输出文字ReleaseDC(pDC); //释放CDC类的指针}同样的方法,使用MFC ClassWizard为“矩形”菜单项添加“COMMAND”消息映射和处理函数,代码如下:void CCh6Demo1View::OnDrawrect(){// TODO,Add your command handler code hereCDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针CRect rect(100,0,300,200);CBrush brush(RGB(180,180,180)); //定义画刷pDC-&FillRect(rect,&brush); //填充绘图区域pDC-&Rectangle(160,10,260,110); //画矩形pDC-&TextOut(120,120,&绘制边长为100的正方形&); //在矩形下方输出文字ReleaseDC(pDC); //释放CDC类的指针}此时,编译运行程序,就可以运行菜单命令,如图5.9所示。5.1.5 菜单更新消息的处理一般情况下,菜单项具有不止一种状态,经常需要根据应用的内部状态来对菜单项作相应的改变。例如,在没有选择任何内容时,编辑菜单下的“复制”、“剪切”等菜单是无效的(灰色显示)。有时还会看到在菜单项旁边可能还会有检查标记,表示它是选中的还是不选中的。如在Word的视图菜单下,根据用户所选的显示模式,在“普通”、“大纲”、“页面”、“主控文档”前会出现一个点符号,标识当前所选的视图方式。菜单项的UPDATE_COMMAND_UI消息,就是专门用于处理菜单项的更新。可以为菜单项的92励志照亮人生 编程改变命运零基础学 Visual C++图5.9 程序运行结果UPDATE_COMMAND_UI消息编写消息处理函数来处理菜单的更新。下面就为例子中添加的菜单项实现菜单更新处理。当执行“圆形”菜单命令画圆后,再展开“绘图”下拉菜单时,“圆形”菜单项前添加一选中标志,而当执行了“矩形”菜单命令后,展开“绘图”下拉菜单时,“矩形”菜单项前添加一选中标志,而“圆形”菜单项前的选中标志消失。实现过程如下。1,用MFC ClassWizard自动映射菜单更新消息和成员函数执行“View”→“ClassWizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFC ClassWizard”对话框。在对话框的“Message Map”选项卡中的Class Name列表框中选择要响应菜单命令的类“CCh6Demo1View”,在“Object IDs”列表框中选择菜单ID“ID_DRAWCIRCLE”,在“Messages”列表框中选择“UPDATE_COMMAND_UI”菜单命令消息。然后单击“Add Function”按钮,弹出“AddMember Function”对话框,采用默认的函数名,如图5.10所示。单击“OK”按钮,关闭此对话框。图5.10,MFC ClassWizard”对话框2,手工添加函数的实现代码(1)在CCh6Demo1View类的头文件中,声明指示变量m_nDdrawtype,指明当前绘制的图形(值为1,表示为圆;值为2,表示为矩形)。代码如下:class CCh6Demo1View,public CView{public:int m_nD(2)在CCh6Demo1View类的构造函数中,将变量m_nDdrawtype初始化为0。代码如下:CCh6Demo1View::CCh6Demo1View(){// TODO,add construction code herem_nDdrawtype=0;}93励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程(3)在菜单项命令响应函数中,分别将变量m_nDdrawtype设置为相应的值。代码如下:void CCh6Demo1View::OnDrawcircle(){// TODO,Add your command handler code herem_nDdrawtype=1; //表示绘制圆CDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针}void CCh6Demo1View::OnDrawrect(){// TODO,Add your command handler code herem_nDdrawtype=2; //表示绘制矩形CDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针}(4)在菜单项更新命令响应函数中,实现菜单项的更新。代码如下:void CCh6Demo1View::OnUpdateDrawcircle(CCmdUI* pCmdUI){// TODO,Add your command update UI handler code herepCmdUI-&SetCheck(m_nDdrawtype==1); //若为圆形,设置选中标记}void CCh6Demo1View::OnUpdateDrawrect(CCmdUI* pCmdUI){// TODO,Add your command update UI handler code herepCmdUI-&SetCheck(m_nDdrawtype==2); //若为矩形,设置选中标记}其中,CCmdUI类是MFC专门为更新命令提供的一个类,对于菜单项而言,其相关的函数及其作用如下:Enable():设置菜单项的允许/禁止状态。SetCheck():设置是否在菜单项前面打勾(√)。SetRadio():设置是否在菜单项前面画点(·)。SetText():设置菜单项显示的的文字。此时编译运行程序,就实现了菜单的更新操作,结果如图5.11所示。5.1.6 为菜单项设置快捷键快捷键的主要作用就是在选择菜单命令时,不用鼠标而用事先定义的组合键。如在Word软件中,用户可以使用【Ctrl+C】组合键复制文本,而使用【Ctrl+V】组合键粘贴文本。这样做的好处就是熟练操作应用程序的用户可以不用鼠标,而用键盘直接同应用程序实现交互。下面就对程序“Ch6Demo1”新创建的菜单项“圆形”和“矩形”分别添加快捷键【Ctrl+Y】、【Ctrl+J】。1,为菜单项添加快捷键提示在菜单资源编辑器中,双击“圆形”菜单项,打开菜单项属性对话框。在“Caption”编辑框中,94励志照亮人生 编程改变命运零基础学 Visual C++图5.11 程序运行结果在菜单项名后,添加“\t”在字符后,加上快捷键组合【Ctrl+Y】,如图5.12所示。快捷键组合会出现在菜单项名右端,目的是给用户一个提示。使用同样的方法,为“矩形”菜单项添加【Ctrl+J】快捷键提示。2,创建快捷键资源在Visual C++6.0中,快捷键是作为一种资源存在的,要使用快捷键,需要创建快捷键资源。在工作区窗口的“ResourceView”选项卡中,展开快捷键Accelerator资源,MFC AppWizard为应用程序生成了默认加速键资源,名称为“IDR_MAINFRAME”。双击它打开快捷键列表,在已有快捷键表后面,有一个空白行,双击它打开快捷键属性对话框。编辑框中ID栏中需要填写快捷键所代表的菜单项的ID值,在Key栏中键入快捷键,Modifiers栏中选中按键的组合键(【Shift】、【Alt】或【Ctrl】),Type中一般选择“VirKey”。为“圆形”菜单项设置快捷键【Ctrl+Y】的属性对话框如图5.13所示。设置完毕,关闭对话框后,定义的快捷键信息就加入到资源中。图5.13 添加快捷键提示使用同样的方法,为“矩形”菜单项添加【Ctrl+J】快捷键资源。注意不要对不同菜单命令使用相同的快捷键组合,以免产生二意性;快捷键命令必须有菜单命令与之对应,快捷键不应该是某个命令唯一启动方式。此时,编译运行程序,直接通过快捷键【Ctrl+Y】和【Ctrl+J】就可以执行与相应的菜单命令相同的操作。5.1.7 弹出菜单的创建与使用弹出菜单一般在单击鼠标右键时出现,在应用程序工作区域上面处于自由浮动状态,也称为上下文菜单。与下拉菜单的最大不同是,弹出菜单需要用户手工编程动态加载。下面就为前面创建的“Ch6Demo1”程序创建一个绘图操作的弹出菜单,在单击鼠标右键时,菜单弹出,菜单显示的内容与“绘图”下拉菜单完全相同。95励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程图5.12 添加快捷键提示1,创建弹出菜单资源弹出式菜单可以有两种实现方法。一种方法是单独设计一个明确的菜单用作弹出菜单;另一种方法是使用已经设计完的主菜单中的一个下拉菜单作弹出菜单。这里采用前者的方法。在Visual C++6.0中,打开工程“Ch6Demo1”。执行“Insert”→“Resource...”菜单命令,在弹出的对话框中选择“Menu”,如图5.14所示。单击“New”按钮,即为工程新建了一个菜单资源,并进入编辑状态。通过属性窗口设置其ID为“IDR_POPUPMENU”。与前面介绍的下拉菜单的资源设计完全相同,这里为新菜单添加一个“绘图”顶层菜单,在其下添加“圆形”和“矩形”两个菜单命令项。通过属性窗口将菜单项的ID分别设置为下拉菜单相应命令项的ID,如图5.15所示。2,弹出菜单的加载该程序实现的是,当用户在客户窗口单击鼠标右键时,在鼠标指针所在位置将弹出菜单。(1)使用MFC AppWizard添加鼠标消息映射及处理函数执行“View”→“ClassWizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFCClassWizard”对话框。在对话框的“Message Map”选项卡中的“Class Name”列表框中选择响应鼠标消息的类“CCh6Demo1View”,在“Object IDs”列表框中选择“CCh6Demo1View”,在“Messages”列表框中选择“WM_RBUTTONDOWN”消息,单击“Add Function”按钮,即完成了鼠标消息映射及处理函数的添加,如图5.16所示。图5.16 添加鼠标消息映射及处理函数对话框96励志照亮人生 编程改变命运零基础学 Visual C++图5.14,Insert Resource”对话框图5.15 弹出菜单的设计(2)手工添加代码实现弹出菜单在“MFC ClassWizard”对话框中,单击“Edit Code”按钮,进入按下鼠标右键处理函数OnRButtonDown()的入口,在其中添加代码,实现弹出菜单。代码如下:void CCh6Demo1View::OnRButtonDown(UINT nFlags,CPoint point){// TODO,Add your message handler code here and/or call defaultCM //定义菜单menu.LoadMenu(IDR_POPUPMENU); //载入浮动菜单资源CMenu* pM=menu.GetSubMenu(0); //菜单的第一项作为浮动菜单CPGetCursorPos(&pt); //获得鼠标位置pM-&TrackPopupMenu(TPM_LEFTALIGN,pt.x,pt.y,this); //弹出浮动菜单CView::OnRButtonDown(nFlags,point);}在MFC中,类CMenu用来处理和菜单有关的功能,CMenu类中包含了许多关于菜单操作的方法函数,有显示菜单的函数,还可以动态地在菜单中添加、删除菜单项。CMenu类中常用的函数及其功能如表5.2所示。表5.2 CMenu类中常用的函数及其功能函数类别函数名称函数作用GetSafeHmenu获取由CMenu对象封装的菜单句柄m_hMenuCreateMenu为CMenu对象创建一个空菜单初始化函数CreatePopupMenu为CMenu对象创建一个空的下拉式菜单LoadMenu从资源文件中载入菜单资源并把它附给CMenu对象LoadMenuIndirect从内存的菜单模板中载入菜单资源并把它附给CMenu对象菜单操作函数TrackPopupMenu在指定位置显示一个浮动菜单,并跟踪菜单项的选择DeleteMenu删除特定的菜单项及其子菜单AppendMenu把一个新菜单项添加到指定菜单的末端GetSubMenu某一位置得到子菜单的指针,因为一个CMenu对象只能表示一个弹出菜单,如果菜单中的某一项也为弹出菜单,就需要通过该函数获取指针InsertMenu用于在指定位置插入一菜单菜单项操作函数ModifyMenu用于修改某一位置的菜单RemoveMenu用于删除某一位置的菜单EnableMenuItem设置菜单有效、无效状态GetMenuState获取指定弹出式菜单的状态或得到菜单项的数目GetMenuString获取指定菜单项的名称重载函数DrawItem运行用户自行绘制菜单项,并且可以随时改变菜单形状MeasureItem获取自己绘制的菜单的大小其中,TrackPopupMenu函数用于菜单的弹出,其原型如下:BOOL TrackPopupMenu( UINT nFlags,int x,int y,CWnd* pWnd,LPCRECT lpRect = NULL )97励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程此函数的参数用于指定弹出菜单显示的位置和方式,含义如下。参数nFlags,指定一个屏幕位置和一个鼠标按钮标志,可能取值及含义如表5.3所示。参数x,y,指定弹出式菜单坐标的水平位置和菜单顶部在屏幕上的屏幕坐标中的垂直位置。参数pWnd,标识拥有此弹出式菜单的窗口。该窗口接收来自该菜单的所有消息,当TrackPopupMenu()函数返回时,才接收WM_COMMAND消息。参数LpRect,指向一个RECT结构或CRect对象。该结构或者对象中包含一个矩形的屏幕坐标,用户可以在该矩形内单击而不会撤销此弹出式菜单。如果该参数为NULL,则当用户在此弹出式菜单外单击时,该菜单将消失。3,菜单命令的响应当用户单击弹出菜单的菜单项时,将触发该菜单项的ON_COMMAND消息映射,执行其对应的菜单消息响应函数,这与下拉菜单完全相同。然而与下拉菜单不同,当显示弹出菜单时,并不执行UPDATE_COMMAND_UI消息映射,也就是说,在操作弹出菜单时,各菜单项的UPDATE_COMMAND_UI消息映射对应的处理函数将无法被执行。因此如过需要修改弹出菜单项的外观、状态等,只能通过使用CMenu类的成员函数来实现。编译运行程序,右击客户窗口,弹出菜单,通过执行其菜单项也能实现相应的绘图操作,如图5.17所示。5.2 工具栏的使用工具栏是一个包含一个或多个命令按钮的窗口,一般情况下附着在窗口客户区上方菜单栏下面,也可作为一个浮动的小窗口。工具栏为菜单命令提供可视化的快捷操作方式,模拟大部分的菜单行为。5.2.1 工具栏的创建在使用MFC AppWizard创建基于文档/视图结构的MFC应用程序项目时,如前面创建的SDI程序“Ch6Demo1”,在应用向导的“MFC AppWizard Step 4”的时候,默认选中了“Docking toolbar”,如图5.18所示。这样生成的应用程序框架就自动添加了可浮动的工具栏。98励志照亮人生 编程改变命运零基础学 Visual C++表5.3 参数nFlags的取值及其含义取值含义TPM_CENTERALIGN将弹出式菜单相对于x所指定的坐标水平居中TPM_LEFTALIGN定位弹出式菜单使其左边界对齐x所指定的坐标TPM_RIGHTALIGN定位弹出式菜单使其右边界对齐x所指定的坐标TPM_LEFTBUTTON使弹出式菜单跟踪鼠标左键TPM_RIGHTBUTTON使弹出式菜单跟踪鼠标右键图5.17 程序运行结果图5.18,MFC AppWizard Step 4”对话框1,MFC AppWizard自动创建的工具栏资源打开程序“Ch6Demo1”,在工作区窗口的“Resource View”选项卡中,打开工程资源,选择“Toolbar”,会发现自动创建了IDR_MAINFRAME工具栏资源,双击它,可打开工具栏编辑器,如图5.19所示。该窗口的上部显示出了工具栏上的按钮,当用户用鼠标选择某一按钮时,在窗口的下部会显示该按钮的位图。在窗口旁边有一个绘图工具面板和一个颜色面板,供用户编辑按钮位图时使用。图5.19 IDR_MAINFRAME工具栏资源2,工具栏加载的实现代码在MFC中,工具栏的功能由类CToolBar实现。工具栏实际上是主框架窗口的子窗口,因此工具栏对象依附于主框架窗口对象,工具栏的加载也就是在CMainFrame类中完成的。打开“Ch6Demo1”工程,在工作区窗口的ClassView标签页中,展开CMainFrame类,会发现该类有一个名为m_wndToolbar的成员。双击该成员,会自动打开类CMainFrame所在的头文件,并将光标停在对m_wndToolbar成员的定义处。CToolBar m_wndToolB由此可见m_wndToolBar是一个CToolBar对象,它是CMainFrame的成员。工具栏的实际创建工作在CMainFrame::OnCreate()函数中完成。99励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程说明OnCreate()函数是在创建窗口时被调用的,这时窗口的创建已部分完成,窗口对象的m_hWnd成员中存放的HWND句柄也已有效,但窗口还是不可见的。因此一般在OnCreate()函数中作一些诸如创建子窗口的初始化工作。MFC AppWizard自动生成的OnCreate()函数代码如下:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CFrameWnd::OnCreate(lpCreateStruct) == -1)return -1;//为窗口创建工具栏,并加载IDR_MAINFRAME工具栏资源if (!m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)){TRACE0(&Failed to create toolbar\n&);return -1; // fail to create}//下面的代码使得创建的工具栏具有浮动和停靠功能// TODO,Delete these three lines if you don't want the toolbar tobe dockablem_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);return 0;}实际上,实现过程可简单描述如下:调用CToolBar::CreateEx()函数创建工具栏窗口,参数中的this指针表明主框架窗口是工具栏的父窗口,余下的参数指定了工具栏的风格。接着调用CToolbar::LoadToolBar(IDR_MAINFRAME)函数以载入工具栏资源。而后调用CToolBar::EnableDocking(CBRS_ALIGN_ANY)函数使工具栏是可以停泊的,但还需调用CFrameWnd::EnableDocking(CBRS_ALIGN_ANY)函数,只有这样才能实现可停泊的工具栏。最后调用CFrameWnd::DockControlBar函数以停泊工具栏。说明初学者了解了MFC AppWizard自动生成的工具栏的创建过程后,就不难手工创建加载自己创建的工具栏。5.2.2 编辑工具栏创建了工具栏后,就需要编辑工具栏资源。工具栏资源由一组按钮组成,每个按钮是一个16色位图图标,工具栏编辑器提供一个简单的位图编辑器,点击某个图标即可编辑它。这里同样以“Ch6Demo1”工程为例,在自动生成的“IDR_MAINFRAME”菜单资源中,为5.1节创建的菜单项“圆形”和“矩形”添加两个对应的工具按钮,实现相同的功能。在资源编辑器中,单击“IDR_MAINFRAME”菜单资源后的空白按钮后就可以编辑其图像,同时系统在随后的位置自动添加一个空白按钮。100励志照亮人生 编程改变命运零基础学 Visual C++双击按钮,即可打开工具按钮属性对话框,如图5.20所示。在ID列表框中列出了当前工程中已存在的ID,分别为两个按钮设置“ID_DRAWCIRCLE”和“ID_DRAWRECT”。在Prompt编辑框中显示的是状态栏上的提示命令,在“\n”字符后的文本将显示在按钮的提示窗格中。图5.20 为程序添加、编辑工具按钮技巧如果觉得按钮太小,读者可以用鼠标拖动围绕按钮放大位图的虚框的右下角,把按钮放大些。注意这样做时工具栏内的所有按钮都将被放大。在编辑工具按钮时,有下面一些常用的操作。用鼠标可以将一个按钮拖放到工具栏上的其他位置上。若拖动时按下【Ctrl】键,则复制一个工具按钮。若将工具按钮拖出工具栏,则该工具按钮被删除。按【Delete】键可以将当前工具按钮的图像用背景色填充。在工具按钮之间添加间隔时,可按不同情况来操作。若工具按钮前没有任何间隔,拖动该工具按钮向右直到它覆盖相邻工具按钮的一半以上后,释放鼠标,则此工具按钮前出现间隔。若工具按钮前面有间隔而后面没有间隔,拖动该工具按钮向左直到它的左边界接触到它前面的工具按钮为止,释放鼠标,则此工具按钮后面将出现间隔。若工具按钮前后均有间隔,拖动该工具按钮向右直到它接触相邻工具按钮,则此工具按钮前的间隔保留,工具按钮后的间隔消失。反之,若拖动该工具按钮向左直到它接触相邻的前一个工具按钮,则此工具按钮前面的间隔消失,后面的间隔仍保留。删除工具按钮间隔时,只要将间隔一端的工具按钮拖向间隔另一端的工具按钮,直到与另一个按钮重叠一半以上即可。5.2.3 工具栏命令处理与菜单命令项相同,MFC程序可以处理两种工具栏按钮消息:命令消息WM_COMMAND和更新消息UPDATE_COMMAND_UI。通过ClassWizard可以方便地为工具按钮添加WM_COMMAND和UPDATE_COMMAND_UI消息映射和消息处理函数。其实现过程与菜单项完全相同,可参阅5.1.4和5.1.5节的介绍。如果工具栏按钮与某个菜单项有相同的ID,则它们共享一个命令响应函数,不需要另外定义命令响应函数。具有相同ID的菜单项和工具栏按钮还共享提示字符串,它们的显示状态也同步变化。101励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程如果与工具栏按钮对应的菜单项定义了更新函数,工具栏按钮也会同步实现状态的动态变化。在前面“Ch6Demo1”程序添加的两个工具栏按钮的ID分别与绘图下拉菜单下的两个菜单项ID相同,因此并不需要添加任何代码,即可实现相应功能。编译运行“Ch6Demo1”程序,使用工具按钮时的程序运行状态如图5.21所示。5.2.4 工具栏类CToolBar的简单介绍在MFC中,CToolBar类包揽了创建工具栏的主要工作。CToolBar类提供了带有位图按钮和可选分隔符的工具栏。工具栏按钮可以是下压式按钮、复选按钮或单项按钮。CToolBar对象通常被嵌入派生于类CFrameWnd或CMDIFrameWnd的框架窗口对象的成员。CToolBar类在MFC中的继承关系如图5.22所示。可见,CToolBar类也是窗口类,但它不是直接从CWnd类派生,而是从控件栏类CControlBar派生。CToolBar类中,除了CControlBar类中的函数外,还有一些常用的函数及用途,如表5.4所示。表5.4 CToolBar类中常用的函数及用途类别函数名用途Creat创建工具栏控件,并将它于CToolBar对象关联SetSize设置按钮及其表明位图的大小SetHeight设置工具栏的高度CToolBar构造相关函数LoadToolBar载入资源管理器所创建的工具栏资源LoadBitmap载入包含位图按钮的图像SetBitmap设置位图图像SetButton设置按钮风格以及按钮上的图像在整个位图中的序号CommandToIndex根据指定的命令ID,获取相应工具栏中的按钮序号GetItemID获取指定序号的按钮或分隔符的命令IDGetItemRect获取指定序号按钮所占显示区域的大小GetButtonStyle获取按钮风格CToolBar操作函数SetButtonStyle设置按钮风格GetButtonInfo获取按钮的信息,包括ID风格、位图序号等SetButtonInfo设置按钮的信息GetButtonText获取按钮上显示的文字SetButtonText设置按钮上显示的文字说明本节只是简单介绍了CToolBar类,只有掌握了CToolBar类,才能对工具栏进行深层开发。102励志照亮人生 编程改变命运零基础学 Visual C++图5.21 使用工具按钮程序运行结果图5.22 CToolBar类在MFC中的继承关系CObjectCCmdTargetCWndCControlBarCToolBar5.3 状态栏的使用状态栏是一个水平长条,位于应用程序主窗口的底部。它可以分割成几个窗格,用来显示多组信息。5.3.1 状态栏的创建在使用MFC AppWizard创建基于文档/视图结构的MFC应用程序项目时,如前面创建的SDI程序“Ch6Demo1”,在应用向导的“MFC AppWizard Step4”的时候,默认选中了“Initial status bar”,如图5.18所示。这样生成的应用程序框架就自动添加了状态栏。该状态栏包括4个窗格,分别用来显示状态栏提示信息和CAPS LOCK、NUM LOCK,SCROLLLOCK键的状态,如图5.23所示。在MFC中,工具栏的功能由类CStatusBar实现。与工具栏相同,状态栏的加载也是在CMainFrame类中完成的。打开“Ch6Demo1”工程,在工作区窗口的ClassView标签页中,展开CMainFrame类,会发现该类有一个名为m_wndStatusBar的成员。双击该成员,会自动打开类CMainFrame所在的头文件,并将光标停在对m_wndStatusBar成员的定义处。CStatusBar m_wndStatusB可见m_wndToolBar是一个CStatusBar对象,它是CMainFrame的成员。状态栏的创建工作也是在CMainFrame::OnCreate()函数中完成。其相关创建代码如下:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){if (!m_wndStatusBar.Create(this) ||!m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))){TRACE0(&Failed to create status bar\n&);return -1; // fail to create}}可见,状态栏的创建过程共分为三步:(1)构建一个CStatusBar类对象;(2)调用CStatusBar类的Create()函数创建状态栏窗口,参数中的this指针表明主框架窗口是状态栏的父窗口;(3)调用CStatusBar类的SetIndicators()函数,设置状态栏窗格ID。SetIndicators()函数的第一个参数indicators是一个ID数组,在CMainFrame类所在的.cpp文件的开头部分可以找到该数组,如下:103励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程图5.23 AppWizard自动生成的状态栏static UINT indicators[] ={ID_SEPARATOR,//状态栏指示器ID_INDICATOR_CAPS,//显示Caps Lock键状态ID_INDICATOR_NUM,//显示Num Lock键状态ID_INDICATOR_SCRL,//显示Scroll Lock键状态};indicator数组提供了状态栏窗格的分配信息,它的第一项一般为ID_SEPARATOR,该ID对应的窗格用来显示命令提示信息,后三项都是字符串ID,可以在String Table字符串资源中找到这三个字符串,分别是“大写”、“数字”和“滚动”。它们对应的三个窗格用来显示键盘的状态。掌握了MFC App Wizard生成的应用程序框架中状态栏的创建过程,简单的状态栏编程就显得很容易。5.3.2 状态栏编程本节将通过具体的实例讲解状态栏编程的过程。所实现的目标是在“Ch6Demo1”工程已有状态栏的基础上,添加一个状态栏窗格,用于显示系统当前时间,时间精确到秒,即每秒要更新一次。1,添加状态栏窗格由5.3.1节介绍的状态栏的创建过程可知,可以向数组indicator中增加ID以增加状态栏上的显示窗格。该ID表示的是一个字符串资源,对于本例,需要显示的是当前时间字符串。在Visual C++中可以通过字符串资源编辑器添加、编辑字符串资源。在Visual C++中,打开“Ch6Demo1”工程。在工作区窗口的“Resource View”选项卡中,打开工程资源,选择“String Table”,在右侧编辑窗口显示了已经创建的字符串资源。在列表最下边的虚线框中,双击鼠标左键,即弹出字符串属性对话框。在ID编辑框中,输入需创建的字符串ID“ID_INDICATOR_CLOCK”;“Caption”编辑框中键入需要的时间格式,如图5.24所示。图5.24 添加字符串资源说明状态栏将根据字符串的长度来确定相应窗格的默认宽度,因此添加的ID为“ID_INDICATOR_CLOCK”的字符串资源,其值设定为需要的时间格式即可。创建了字符串资源后,只需将其ID“ID_INDICATOR_CLOCK”添加到在资源文件“MainFrm.cpp”中的indicator数组中即可。其在数组中的位置决定了窗格的位置。这里添加到窗口状态栏最右边的窗格,代码如下:104励志照亮人生 编程改变命运零基础学 Visual C++static UINT indicators[] ={ID_SEPARATOR,//状态栏指示器ID_INDICATOR_CAPS,//显示Caps Lock键状态ID_INDICATOR_NUM,//显示Num Lock键状态ID_INDICATOR_SCRL,//显示Scroll Lock键状态ID_INDICATOR_CLOCK,//显示时间};此时,编译运行程序,会发现状态栏窗格已添加,只是其显示的是字符串资源设定的固定时间。下面将实现时间的更新。2,更新状态栏窗格时间窗格显示的时间必须每隔一秒钟更新一次。CStatusBar类的SetPaneText()函数用于设定状态栏窗格显示的文本信息,而要定时更新,就需要用到定时器。定时器每隔一定的时间间隔就会自动发出一个WM_TIMER消息,而这个时间间隔可由用户指定。MFC的Window类提供了WM_TIMER消息处理函数OnTimer(),在该函数内进行更新时间窗格的工作。(1)创建定时器SetTimer()函数用于创建定时器,定时器的创建时机显然需要在状态栏创建之后,因此需要在CMainFrame的OnCreate()函数中完成。int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CFrameWnd::OnCreate(lpCreateStruct) == -1)return -1;SetTimer(1,1000,NULL); //创建定时器return 0;}SetTimer()函数的第一个参数指定计时器ID为1,第二个参数指定了计时器的时间间隔为1000毫秒即1秒。这样,每隔1秒,就会发出一个WM_TIMER消息,其处理函数OnTimer()就会被调用一次。(2)添加WM_TIMER消息映射及处理函数WM_TIMER消息映射及处理函数的添加可以通过ClassWizard方便地实现。执行“View”→“ClassWizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFCClassWizard”对话框。在对话框的“MessageMap”选项卡中的“Class Name”列表框中选择响应WM_TIMER消息的类“CMainFrame”,在“Object IDs”列表框中选择“CMainFrame”,在“Messages”列表框中选择“WM_TIMER”消息,单击“Add Function”按钮,即完成了WM_TIMER消息映射及处理函数OnTimer()的添加,如图5.25所示。105励志照亮人生 编程改变命运第6 章菜单、工具栏和状态栏编程图5.25 添加WM_TIMER消息映射及处理函数对话框单击“Edit”按钮,进入OnTimer()函数的入口,编辑代码如下:void CMainFrame::OnTimer(UINT nIDEvent){// TODO,Add your message handler code here and/or call defaultCTime t1;t1=CTime::GetCurrentTime(); //获取当前系统时间CSs=t1.Format(&%H:%M:%S&); //格式化字符串m_wndStatusBar.SetPaneText(4,s); //在时间窗格显示时间CFrameWnd::OnTimer(nIDEvent);}OnTimer()函数中,首先构建了一个CTime对象,接着调用CTime的静态成员函数GetCurrentTime以获得当前的系统时间,然后利用CTime::Format()函数返回一个按“时:分:秒”的格式表示的字符串,最后调用CStatusBar::SetPaneText()函数来更新时间窗格显示的文本。SetPaneText的第一个参数是窗格的索引。编译运行“Ch6Demo1”程序,其状态栏工作情况如图5.26所示。5.3.3 状态栏类CStatusBar的简单介绍在MFC中,CStatusBar类包揽了创建状态栏的主要工作。与CToolBar类相同,CStatusBar类同样派生于CControlBar类,CStatusBar类在MFC中的继承关系如图5.27所示。CStatusBar类主要的成员函数及其功能如表5.5所示。表5.5 CStatusBar类主要成员函数函数功能Create创建状态条,并将它与CstatusBar对象连接,且设置初始字体和条高度CreateEx创建一个具有嵌入CStatusBarCtrl对象附加风格的CStatusBar对象SetIndicators设置指示器IDCommandToIndex获取给定指示器ID的索引GetItemID获取给定索引的指示器IDGetItemRect获取给定索引值的显示矩形GetPaneInfo获取一个给定索引的指示器ID,风格和宽度GetPaneStyle获取一个给定索引的指示器风格GetPaneText获取一个给定索引的指示器文本GetStatusBarCtrl允许直接访问基础通用控件SetPaneStyle设置一个给定索引的指示器风格SetPaneText设置一个给定索引的指示器文本SetPaneInfo设置一个给定索引的指示器ID,风格和宽度106励志照亮人生 编程改变命运零基础学 Visual C++图5.26 程序运行结果图5.27 CStatusBar类在MFC中的继承关系CObjectCCmdTargetCWndCControlBarCStatusBar
课件名称:课件分类:计算机课件类型:电子图书文件大小:6.42MB下载次数:11评论次数:8用户评分:6.6
1. 2. 3. 4. 5.

我要回帖

更多关于 床垫价格 的文章

 

随机推荐