Visual c 第5章菜单、工具栏和状态栏编程 菜单、工具栏和状态栏是一个完善的 Windows应用程序的重要组成部分(但不是必需的)。在 Windows写字板应用程序中,菜单栏、工具栏、状态,mtx 旧网 栏及其所包含的元素如图5.1所示 )排)查者以人式0封吧 菜单是用户选择可用命令的一个最常用、也是最 典型的n对窗口的菜 重要的手段。在一些情况下,工具栏也是一种更快捷 工具按钮 更有效的命令输入方式。而状态栏则一般位于主框架 工具栏 菜单栏 下拉菜单菜单项 窗口的底部,主要用来显示一些提示信息,可细分为 几个窗格。 本章对使用 Visual c++开发 Windows程序中,菜 状态栏 单、工具栏和状态栏的设计与使用进行详细介绍 当前的所的段落 5.1菜单及其相关资源的使用 图5.1菜单栏、工具栏、状态栏及其所包含的元素 菜单是 Windows与用户交互的标准接口之一, Windows的大多数应用程序都提供了菜单操作。 个菜单项被选中时,它发出一个命令消息,从而引发相应的消息处理函数的执行。 5.1.1菜单的种类及开发步骤 在 indows窗口中,菜单有两种标准风格:下拉菜单和弹出菜单(也称上下文菜单) 口下拉菜单:一般在应用程序窗口的顶部罗列了 行按类别排列的菜单。如果用户选择了某 文伸q)编辑)查看(入①格式)帮助 类别,就会显示一个下拉式菜单。图5.1所示 弹出菜 即为下拉菜单 ① 口弹出菜单:一般在应用程序窗口区域的中间弹 弹出菜单 出显示,在应用程序工作区域上面处于自由浮 动状态。在写字板输入窗口中,单击鼠标右键, 即出现弹出式菜单,如图5.2所示 下拉菜单与弹出菜单只是在形式上不同,其消息 在这行前入一个攻目符号 及消息处理机制完全相同。 在程序开发中,简单的菜单编程一般可分为下面 图5.2弹出式菜单 个步骤 (1)编辑菜单资源,设置菜单属性(包括菜单名和ID) (2)用 Class wizard自动映射菜单消息和成员函数 (3)手工编辑成员函数,加入菜单消息处理代码 励志照亮人生编程改变命运
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 弹出式菜单 弹出菜单
第6章菜单、工具栏和状态栏 5.1.2菜单的创建与编辑 在 Visual C++6.0中,使用 MFC App Wizard生成的文档/视图结构的应用程序,系统已为框架创建了 个标准的主菜单,包括文件、编辑、视图和窗口帮助等标准菜单,定义了各菜单项的ID及相应的命 令处理函数。一般只需要通过菜单资源编辑器,在已有主菜单的基础上添加、设计需要的菜单项即可 下面结合一个具体的实例讲解菜单的创建与编辑。 1.创建SD项目 在 Visual c+6.0中,执行“File”→“New”菜单命令,在“ Project”选项卡中,创建一个MFC App Wizard[EXE]工程,工程名为“Ch6 Demol”。在 MFC App Wizard Step I的时候,选中“ Single document”,即基于单文档的MFC工程,其余的几步采用默认设置 在工作区窗口的 Resource view选项卡中,打开工程资源,选择“Menu”,会发现自动创建了 IDR MAINFRAME菜单资源,双击它,可打开菜单编辑器,如图5.3所示。 2.添加菜单项 在主菜单的最右边以及每个下拉菜单展开的最下边都有一个虚线框,该虚线框实际上就是菜单的“生长 点”。将光标移动到虚线框内,双击左键,就启动了菜单项的属性对话框,添加、设置菜单项的相关信息。本 例中,将在 IDR MAINFRAME菜单中添加一个“绘图”顶层菜单,其下设计两个菜单项:“圆形”和“矩形” (1)增加顶层菜单“绘图” 在主菜单右侧的虚线框内,双击左键,弹出菜单项属性对话框。在“ Caption”编辑框中输入菜单 名“绘图(&D)”,菜单名即显示在菜单上,如图54所示 文件①)编辑)查看帮助0抛图q) 文件吧)编)查看帮助 Ch6Dem。 I resources 2 Caption图p p Pop-up BreakBone Cb到Res回fh 图5.3 IDR MAINFRAME菜单资源 图54添加顶层菜单的属性对话框 表5.1菜单属性对话框中各选项及其含义 在菜单名中,可用【At】键加该字符作为选菜单属性项 说明择菜单的快捷方式。菜单“绘图(&D)”表示D 表示该菜单项的ID值 使用“At+D”作为该菜单的快捷键 表示该菜单项显示的文本 Separato 表示该菜单项是一条分隔线 此时,属性对话框中默认选中了“ Pop-up”选项, Checked表示该菜单项被选中显示一个标志 表示该项是一个顶层菜单,其本身不执行菜单命令 选择该菜单项显示一个子菜单 菜单属性对话框中各选项及其含义如表5.1所示。 Grayed 该菜单项变灰显示,被禁止 (2)添加、定义菜单项 nactive该菜单项不被激活 Help菜单,通常放在菜单的最右端 双击“绘图”菜单下的虚线框,即可打开菜单 选中该菜单项后就退出其所在菜单 属性对话框,添加菜单项。在 General页面上输入 Prompt 光标移至该菜单项状态栏显示的文本 励志照亮人生编程改变命运
5.1.2 菜单的创建与编辑 在Visual C++6.0中,使用MFC AppWizard生成的文档/视图结构的应用程序,系统已为框架创建了 一个标准的主菜单,包括文件、编辑、视图和窗口帮助等标准菜单,定义了各菜单项的ID及相应的命 令处理函数。一般只需要通过菜单资源编辑器,在已有主菜单的基础上添加、设计需要的菜单项即可。 下面结合一个具体的实例讲解菜单的创建与编辑。 1. 创建SDI项目 在Visual C++6.0中,执行“File”→“New”菜单命令,在“Project”选项卡中,创建一个MFC AppWizard[EXE]工程,工程名为“Ch6Demo1”。在MFC AppWizard Step 1的时候,选中“Single document”,即基于单文档的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 光标移至该菜单项状态栏显示的文本
Visual c++ Caption菜单项名称及其ID值,在 Prompt:编辑框中的字符串是选择该菜单项时状态栏上显示的内容 别添加“圆形”和“矩形”两个菜单项,如图5.5所示。 如果要删除某个菜单项或弹出菜单,可用鼠标单击该菜单或用上下光标键选择,然后按【Del】 键删除。 文件吧)编①)查看Q帮助2图Q) General Extended r Separator r Popup r Inactive Break: None 厂 Checked厂 Grayed Prompt:在屏幕上绘制一个炬形 图5.5添加菜单项属性对话框 说明在菜单实际设计时,菜单的级数一般以2~3级为宜:若单击某菜单项会弹出一对话框,那么在 该菜单项文本后加上“…”。 此时编译、运行程序,则“绘图”菜单下的命令都是“灰色”的,即无法选择相应的菜单命令 这是因为还没有对菜单的命令消息进行映射。 513菜单消息 AFC程序可以处理两种菜单消息: WM COMMAND和 UPDATE COMMAND UI 口wM_ COMMAND:为菜单命令消息,当选择菜单项、工具栏按钮或加速键之一时会发出菜单 命令消息,MFC依据一定的消息传递途径将消息传递给相应的处理函数进行处理,如果在消息 传递途径的消息映射表中找不到相应的处理函数,该菜单项或按钮会被禁止使用 口 UPDATE COMMAND U:为菜单更新消息,处理菜单状态的动态变化。如希望根据程序的执行状 态,激活或禁用某些菜单项,设置选中标记,或更改菜单项文字等,就要定义这一消息处理函数 在某个菜单显示前,框架将发送菜单内所有菜单项的更新命令,有更新处理函数的菜单项,则调 用其处理函数更新菜单显示方式:没有更新处理函数的菜单项,查找其命令处理函数,若仍然没有, 则将菜单项禁用 在文档/视图结构的MFC应用程序框架中,在view类、Doc类、 MAinfRame类和App类中均可以 响应并处理菜单消息,菜单消息一旦在其中一个类中响应,则不再在其他类中查找响应函数。菜单消 息的传递顺序如图56所示 菜单消息 vew类 Doc类 MAin Frame类 App类 图56菜单消息的传递顺序 具体而言,当点击一个菜单项的时候,最先接受到菜单项消息的是 MAinframe框架类 励志照亮人生编程改变命运
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类
第6章菜单、工具栏和状态栏 MAinframe框架类将会把菜单项消息交给它的子窗口view类,由View类首先进行处理:如果view类 到没对该菜单项消息做响应,则view类把菜单项消息交由文档类Doc类进行处理:如果Doc类检 测到Doc类中也没对该菜单项消息做响应,则Doc类又把该菜单项消息交还给view类,由Ⅴiew类再交 还给 MAin Frame类处理。如果 CMain frame类查看到 MAinframe类中也没对该消息做响应,则最终 交给App类进行处理 51.4菜单命令消息的处理 定义好菜单项及其ID后,就需要为菜单命令添加响应函数。实现方法是借助 Class wizard,在需 要响应菜单命令的类的消息映射表中增加一个入口,即定义一个命令消息 ON COMMAND宏。下面 就以为“圆形”菜单命令项添加 WM COMMAND消息处理函数为例,讲解处理菜单消息的实现过程 1.用 MFC ClassWizard自动映射菜单命令消息和成员函数 执行“view”→“ Class wizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFC Class wizard”对话框。在对话框的“ Message Map”选项卡中的“ Class Name”列表框中选择要响应 菜单命令的类“cCh6 Demol view”,在“ Object IDs”列表框中选择菜单ID“ID_ DRAWCIRCLE", 在“ Messages”列表框中选择“ COMMAND”菜单命令消息,如图5.7所示 Message Maps Member Variables I Automation ActiveX Events I Class Info I wCh6DemoIview.h, D: ChbDemo1lCh6DemoI view cp Add Function. Edit Code V OnEgin Printing crlption: Handle a command (from menu, accel, cmd button 图57“ MFC Class Wizard”对话框 然后单击“ Add function”按钮,弹出“ AddMember Function”对话框,可以修改函数名或接受默认函数名,如图「 Member function name 58所示。这里使用默认的函数名,单击“OK”按钮,关闭这|omm Cancel 个对话框 AWCIRCLE 此时,在CCh6 Demo l view类所在cpp文件的开始部分会 发现自动添加的消息映射代码 图58“ AddMember function”对话框 BEGIN MESSAGE MAP(cCh6Demolview, cview) //[(AEX MSG MAP (cCh6Demolview) 励志照亮人生编程改变命
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】快捷键,打开“MFC ClassWizard”对话框。在对话框的“Message Map”选项卡中的“Class Name ? ? ? ? ? ? ? ? ? ? @6X?@6X?hf? @@1?@@1?hf? @?e@?hf? ?J5??J5?hf? W.Y?W.Y?hf? .Ye.Yhg?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 列表框中选择要响应 菜单命令的类“CCh6Demo1View”,在“Object IDs”列表框中选择菜单ID“ID_DRAWCIRCLE”, 在“Messages”列表框中选择“COMMAND”菜单命令消息,如图5.7所示。 图5.7 “MFC ClassWizard”对话框 然后单击“Add Function”按钮,弹出“AddMember Function”对话框,可以修改函数名或接受默认函数名,如图 5.8所示。这里使用默认的函数名,单击“OK”按钮,关闭这 个对话框。 此时,在CCh6Demo1View类所在.cpp文件的开始部分会 发现自动添加的消息映射代码: BEGIN_MESSAGE_MAP(CCh6Demo1View, CView) //{{AFX_MSG_MAP(CCh6Demo1View) 91 励志照亮人生 编程改变命运 第 6 章 菜单、工具栏和状态栏编程 图5.8 “AddMember Function”对话框
Visual c++ ON COMMAND(ID DRAWCIRCLE, OnDrawcircle //消息映射 END MESSAGE MAP() 2.手工添加函数的实现代码 添加函数后,在“ MFC Class wizard”对话框中单击“ Edit code”按钮,就可以直接跳至新增函 数代码的定义处。这时,需要手工添加 OnDrawcircleo函数的实现代码,如下 void cch DemolView:: OnDrawcircle ( / TODO: Add your command handler code here CDC*pDC=GetDc ( //使用 GetA()函数申请cDc类的指针 CRect rect(100,0,300,200); CBrush brush(RGB (180,180,180)) //定义画刷 pDC->FillRect(rect, &brush) //填充绘图区域 pDc->E11ipse(160,10,260,110); //画圆 pDC-> Textout(120,120,"绘制直径为100个像素的圆" //在圆下方输出文字 ReleaseD (pDc); //释放CDC类的指针 同样的方法,使用 MFC Class wizard为“矩形”菜单项添加“ COMMAND”消息映射和处理函数」 代码如下: void cch6Demo lView:: OnDrawrect ( / TODO: Add your command handler code here CDC*pDC=GetDC ( //使用 GetA()函数申请cDc类的指针 Rect 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的正方形”) //在矩形下方输出文字 //释放CDc类的指针 此时,编译运行程序,就可以运行菜单命令,如图5.9所 交吧排)查)助)烤母0) 5.15菜单更新消息的处理 般情况下,菜单项具有不止一种状态,经常需要根据应 用的内部状态来对菜单项作相应的改变。例如,在没有选择任 余制直径为100个像案的园 何内容时,编辑菜单下的“复制”、“剪切”等菜单是无效的 (灰色显示)。有时还会看到在菜单项旁边可能还会有检查标 记,表示它是选中的还是不选中的。如在Word的视图菜单下, 在屏幕上绘制一个圆 根据用户所选的显示模式,在“普通”、“大纲”、“页面” 图59程序运行结果 “主控文档”前会出现一个点符号,标识当前所选的视图方式 菜单项的 UPDATE_ COMMAND_UI消息,就是专门用于处理菜单项的更新。可以为菜单项的 励志照亮人生编程改变命运
ON_COMMAND(ID_DRAWCIRCLE, OnDrawcircle) //消息映射 …… END_MESSAGE_MAP() 2. 手工添加函数的实现代码 添加函数后,在“MFC ClassWizard”对话框中单击“Edit Code”按钮,就可以直接跳至新增函 数代码的定义处。这时,需要手工添加OnDrawcircle()函数的实现代码,如下: void CCh6Demo1View::OnDrawcircle() { // TODO: Add your command handler code here CDC*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 here CDC*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 程序运行结果
第6章菜单、工具栏和状态栏 UPDATE COMMAND UI消息编写消息处理函数来处理菜单的更新。 下面就为例子中添加的菜单项实现菜单更新处理。当执行“圆形”菜单命令画圆后,再展开“绘图 下拉菜单时,“圆形”菜单项前添加一选中标志,而当执行了“矩形”菜单命令后,展开“绘图”下拉 菜单时,“矩形”菜单项前添加一选中标志,而“圆形”菜单项前的选中标志消失。实现过程如下 1.用 MFC ClassWizard自动映射菜单更新消息和成员函数 执行“view”→“ Class wizard”菜单命令项,或者使用【curl+W】快捷键,打开“ MFC Class Wizard 对话框。在对话框的“ Message Map”选项卡中的 Class name列表框中选择要响应菜单命令的类 “CCh6 Demol view”",在“ Object IDs”列表框中选择菜单ID“ID_ DRAWCIRCLE”,在“ Messages”列表 框中选择“ UPDATE COMMAND UI”菜单命令消息。然后单击“ Add function”按钮,弹出 “ AddMember Function”对话框,采用默认的函数名,如图5.10所示。单击“OK”按钮,关闭此对话框 Message Maps Member Variables I Automation I ActiveX Events|Class Info D: 1Ch6DemoltCh6Demolview.h, D: 1Ch6DemoltChbDemolviewcpp MMAND UI Edit Code Memher function name Object ID: ID DRAY Description: Callback for menu and button enabling/graying 图5.10“ MFC Class wizard”对话框 2.手工添加函数的实现代码 (1)在CCh6 Demo l view类的头文件中,声明指示变量m_ nDdrawtype,指明当前绘制的图形(值 为1,表示为圆:值为2,表示为矩形)。代码如下 class cch6Demolview public cview public int m nDdrawtype (2)在CCh6 Demol view类的构造函数中,将变量 m nDdrawtype初始化为0。代码如下 cch6Demolview:: cch 6Demolview() / TODO: add construction code here m nDdrawtype=0 励志照亮人生编程改变命
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_nDdrawtype; …… (2)在CCh6Demo1View类的构造函数中,将变量m_nDdrawtype初始化为0。代码如下: CCh6Demo1View::CCh6Demo1View() { // TODO: add construction code here m_nDdrawtype=0; } 93 励志照亮人生 编程改变命运 第 6 章 菜单、工具栏和状态栏编程
Visual c++ (3)在菜单项命令响应函数中,分别将变量 m_nDdrawtype设置为相应的值。代码如下 void cch 6Demolview::: OnDrawcircle( / TODO: Add your command handler code here CDC*pDC=GetDC ( //使用 GetA()函数申请cDc类的指针 void cch6Demolview:: OnDrawrect ( Ddrawtype=2 //表示绘制矩形 CDC*pDC=GetDC()i //使用 GetA()函数申请cDC类的指针 (4)在菜单项更新命令响应函数中,实现菜单项的更新。代码如下 void cch6Demolview:: OnUpdateDrawcircle(CCmdUI* pcmdUI / TODO: Add your command update uI handler code here pCmdUI->Setcheck(m nDdrawtype==l //若为圆形,设置选中标记 void Cch6Demolview:: OnUpdateDrawrect(CCmdUI* pCmdUI / TODO: Add your command update UI handler code here pCmdUI->Setcheck(m nDdrawtype==2) //若为矩形,设置选中标记 其中, CCdu类是MFC专门为更新命令提供的一无标=6m 个类,对于菜单项而言,其相关的函数及其作用如下:样编查看着精图R D日的母 Enable:设置菜单项的允许/禁止状态。 SetCheck():设置是否在菜单项前面打勾(√)。 SetRadioo:设置是否在菜单项前面画点(·)。 GetText):设置菜单项显示的的文字 绘制边长为100正方形 此时编译运行程序,就实现了菜单的更新操作, 结果如图5.11所示 5.1.6为菜单项设置快捷键 图5.11程序运行结果 快捷键的主要作用就是在选择菜单命令时,不用 鼠标而用事先定义的组合键。如在Word软件中,用户可以使用【Ctrl+C】组合键复制文本,而使用 【Ctrl+V】组合键粘贴文本。这样做的好处就是熟练操作应用程序的用户可以不用鼠标,而用键盘直 接同应用程序实现交互。下面就对程序“Ch6 Demol”新创建的菜单项“圆形”和“矩形”分别添加 快捷键【Ctrl+Y】【ctrl+J】。 1.为菜单项添加快捷键提示 在菜单资源编辑器中,双击“圆形”菜单项,打开菜单项属性对话框。在“ Caption”编辑框中 励志照亮人生编程改变命运
(3)在菜单项命令响应函数中,分别将变量m_nDdrawtype设置为相应的值。代码如下: void CCh6Demo1View::OnDrawcircle() { // TODO: Add your command handler code here m_nDdrawtype=1; //表示绘制圆 CDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针 …… } void CCh6Demo1View::OnDrawrect() { // TODO: Add your command handler code here m_nDdrawtype=2; //表示绘制矩形 CDC*pDC=GetDC(); //使用GetDC()函数申请CDC类的指针 …… } (4)在菜单项更新命令响应函数中,实现菜单项的更新。代码如下: void CCh6Demo1View::OnUpdateDrawcircle(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->SetCheck(m_nDdrawtype==1); //若为圆形,设置选中标记 } void CCh6Demo1View::OnUpdateDrawrect(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here pCmdUI->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 程序运行结果
第6单菜单、工具栏和状 在菜单项名后,添加“Ⅶt”在字符后,加上快捷键组合【Ctrl+Y】,如图5.12所示。快捷键组合会出 现在菜单项名右端,目的是给用户一个提示。 文件)辆辑①)查看(帮动0丝图)口 使用同样的方法,为“矩形”菜单项添加 【Ctrl+J】快捷键提示。 eneral Extended Styles I 2.创建快捷键资源 : DRAWCIRCLE- Caption圆形+ 厂 Pop-up 在Ⅴ isual c+6.0中,快捷键是作为一种资源- Checked Grayed Help 存在的,要使用快捷键,需要创建快捷键资源。 Pmpr在屏幕上绘制一个圆 在工作区窗口的“ Resource view”选项卡中 展开快捷键 Accelerator资源, MFC App Wizard 图5.12添加快捷键提示 为应用程序生成了默认加速键资源,名称为“ IDR MAINFRAME”。双击它打开快捷键列表,在已有 快捷键表后面,有一个空白行,双击它打开快捷键属性对话框。 编辑框中ID栏中需要填写快捷键所代表的菜单项的ID值,在Key栏中键入快捷键, Modifiers栏中 选中按键的组合键(【Shit】、【Alt】或【Ctrl】),Type中一般选择“ VirKey"。为“圆形”菜单项设 置快捷键【Ctrl+Y】的属性对话框如图5.13所示。设置完毕,关闭对话框后,定义的快捷键信息就加 入到资源中 Modifiers ct厂 AltShift Key: Y Next Key Typed ID EDIT UNDO ':clarEs File.J 图5.13添加快捷键提示 使用同样的方法,为“矩形”菜单项添加【Ctrl+J】快捷键资源。 注意不要对不同菜单命令使用相同的快捷键组合,以免产生二意性:快捷键命令必须有菜单命令与 之对应,快捷键不应该是某个命令唯一启动方式 此时,编译运行程序,直接通过快捷键【Ctr+Y】和【Ctl+J】就可以执行与相应的菜单命令 相同的操作 5.17弹出菜单的创建与使用 弹出菜单一般在单击鼠标右键时出现,在应用程序工作区域上面处于自由浮动状态,也称为上下 文菜单。与下拉菜单的最大不同是,弹出菜单需要用户手工编程动态加载。下面就为前面创建的 “Ch6 Demol”程序创建一个绘图操作的弹出菜单,在单击鼠标右键时,菜单弹出,菜单显示的内容与 “绘图”下拉菜单完全相同。 励志照亮人生编程改变命
在菜单项名后,添加“\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 添加快捷键提示
Visual c++ 1.创建弹出菜单资源 弹出式菜单可以有两种实现方法。一种方法是单独设计一个明确的菜单用作弹出菜单;另一种方 法是使用已经设计完的主菜单中的一个下拉菜单 作弹出菜单。这里采用前者的方法 在 Visual c++6.0中,打开工程“Ch6 Demo l 零 Accelerator Import.m, 执行“ Insert”→“ Resource..”菜单命令,在弹 的对话框中选择“Menu”,如图5.14所示。单 击“New”按钮,即为工程新建了一个菜单资源, 并进入编辑状态。通过属性窗口设置其ID为 ul version “ IDR POPUPMENU”。 与前面介绍的下拉菜单的资源设计完全相 同,这里为新菜单添加一个“绘图”顶层菜单 在其下添加“圆形”和“矩形”两个菜单命令项 图5.14“ Insert resource”对话框 通过属性窗口将菜单项的ID分别设置为下拉菜单 相应命令项的ID,如图5.15所示。 2.弹出菜单的加载 该程序实现的是,当用户在客户窗口单击鼠 厂Hb 第上一不免形一 标右键时,在鼠标指针所在位置将弹出菜单 "aCIs.. (1)使用 MFC App Wizard添加鼠标消息映射 图5.15弹出菜单的设计 及处理函数 执行“view”→“ Class wizard”菜单命令项,或者使用【ctrI+W】快捷键,打开“MFC Class wizard”对话框。在对话框的“ Message Map”选项卡中的“ Class Name”列表框中选择响应鼠 标消息的类“CCh6 Demol view”,在“ Object IDs”列表框中选择“CCh6 Demol view”,在 Messages”列表框中选择“WM_ RBUTTONDOWN”消息,单击“ Add function”按钮,即完成了 鼠标消息映射及处理函数的添加,如图5.16所示。 lesage Maps Member Variables I Automation I ActiveX Events I Class Into I Add Class. D: Ch6DemoliChtiDemelview, h, D: \ChEDemo11Ch6Demolview, cpp Edit Code E: COMMAND Desalt Indicates when the righ hutton is pressed 图5.16添加鼠标消息映射及处理函数对话框 励志照亮人生编程改变命
1. 创建弹出菜单资源 弹出式菜单可以有两种实现方法。一种方法是单独设计一个明确的菜单用作弹出菜单;另一种方 法是使用已经设计完的主菜单中的一个下拉菜单 作弹出菜单。这里采用前者的方法。 在Visual C++6.0中,打开工程“Ch6Demo1”。 执行“Insert”→“Resource...”菜单命令,在弹 出的对话框中选择“Menu”,如图5.14所示。单 击“New”按钮,即为工程新建了一个菜单资源, 并进入编辑状态。通过属性窗口设置其I D为 “IDR_POPUPMENU”。 与前面介绍的下拉菜单的资源设计完全相 同,这里为新菜单添加一个“绘图”顶层菜单, 在其下添加“圆形”和“矩形”两个菜单命令项。 通过属性窗口将菜单项的ID分别设置为下拉菜单 相应命令项的ID,如图5.15所示。 2. 弹出菜单的加载 该程序实现的是,当用户在客户窗口单击鼠 标右键时,在鼠标指针所在位置将弹出菜单。 (1)使用MFC AppWizard添加鼠标消息映射 及处理函数 执行“View”→“ClassWizard”菜单命令项,或者使用【Ctrl+W】快捷键,打开“MFC ClassWizard”对话框。在对话框的“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 弹出菜单的设计
第6章菜单、工具栏和状态栏 (2)手工添加代码实现弹出菜单 在“ MFC Class wizard”对话框中,单击“ Edit code”按钮,进入按下鼠标右键处理函数 OnRButton Downo的入口,在其中添加代码,实现弹出菜单。代码如下 void cch6Demolview:: OnRButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call default /定义菜单 menu. LoadMenu(IDR POPUPMENU): //载入浮动菜单资源 CMenu* pM=menu. Ge enu(0)i //菜单的第一项作为浮动菜单 CPoint pt GetcursorPos(&pt //获得鼠标位置 pM->TrackPopupMenu(TPM LEETALIGN, pt. x, pt. y, this)i //弹出浮动菜单 cview:: OnRButtonDown(nFlags, point) 在MFC中,类 CMenu用来处理和菜单有关的功能, CMenu类中包含了许多关于菜单操作的方法函 数,有显示菜单的函数,还可以动态地在菜单中添加、删除菜单项。 CMenu类中常用的函数及其功能 如表52所示 表52 CMenu类中常用的函数及其功能 函数类别 函数名称 函数作用 GetSafeHmenu 获取由 CMenu对象封装的菜单句柄 m hMenu Create Menu 为 CMenu对象创建一个空菜单 初始化函数 为 CMenu对象创建一个空的下拉式菜单 Load menu 从资源文件中载入菜单资源并把它附给 CMenu对象 从内存的菜单模板中载入菜单资源并把它附给 CMenu对象 菜单操作函数 TrackPopupMenu 在指定位置显示一个浮动菜单,并跟踪菜单项的选择 Delete Menu 删除特定的菜单项及其子菜单 AppendMenu 把一个新菜单项添加到指定菜单的末端 GetSubMenu 某一位置得到子菜单的指针,因为一个 CMenu对象只能表示一个 弹出菜单,如果菜单中的某一项也为弹出菜单,就需要通过该函数 获取指针 用于在指定位置插入一菜单 菜单项操作函数 Modify Menu 用于修改某一位置的菜单 Remove Menu 用于删除某一位置的菜单 Enable Menuitem 设置菜单有效、无效状态 GetMenuState 获取指定弹出式菜单的状态或得到菜单项的数目 GetMenuString 获取指定菜单项的名称 运行用户自行绘制菜单项,并且可以随时改变菜单形状 重载函数 Measureltem 获取自己绘制的菜单的大小 其中, TrackPopupMenu函数用于菜单的弹出,其原型如下 BOOL TrackPopupMenu( UINT nFlags, int x, int y, cWnd* pWnd, LPCRECT lpRect NULL 励志照亮人生编程改变命
(2)手工添加代码实现弹出菜单 在“MFC ClassWizard”对话框中,单击“Edit Code”按钮,进入按下鼠标右键处理函数 OnRButtonDown()的入口,在其中添加代码,实现弹出菜单。代码如下: void CCh6Demo1View::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CMenu menu; //定义菜单 menu.LoadMenu(IDR_POPUPMENU); //载入浮动菜单资源 CMenu* pM=menu.GetSubMenu(0); //菜单的第一项作为浮动菜单 CPoint pt; GetCursorPos(&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_hMenu CreateMenu 为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 章 菜单、工具栏和状态栏编程