920 likes | 1.13k Views
第 6 章 MFC 编程. 6.1Windows 编程基础知识. 输入姓名. 输入第一次成绩. 启动. 启动. 输入第二次成绩. 输入第三次成绩. 输入姓名. 计算平均成绩. 消息处理. 输入第一次测试成绩. 输入第二次测试成绩. 输入第三次测试成绩. 结束. 计算平均成绩. 结束. 6.1.1 事件驱动原理. 事件驱动 方法计算平均成绩. 过程驱动 方法计算平均成绩. 图 6-2 应用程序、操作系统、输入输出设备交互图. 箭头 1 表示操作系统能操纵输出设备以执行特定的功能,例如让声卡发出声音,让显卡发出图形。
E N D
第6章MFC编程 6.1Windows编程基础知识
输入姓名 输入第一次成绩 启动 启动 输入第二次成绩 输入第三次成绩 输入姓名 计算平均成绩 消息处理 输入第一次测试成绩 输入第二次测试成绩 输入第三次测试成绩 结束 计算平均成绩 结束 6.1.1事件驱动原理 事件驱动方法计算平均成绩 过程驱动方法计算平均成绩
图6-2应用程序、操作系统、输入输出设备交互图图6-2应用程序、操作系统、输入输出设备交互图 箭头1表示操作系统能操纵输出设备以执行特定的功能,例如让声卡发出声音,让显卡发出图形。 箭头2表示操作系统能感知输入设备状态的变化,如鼠标移动、键盘按下,并知道鼠标移动的具体位置,键盘按下的是哪一个字符。 这就是操作系统和计算机硬件之间的交互关系。应用程序开发者一般不需要知道具体的细节,我们所关心的仅仅是操作系统和应用程序之间的关系。
箭头3表示应用程序可以通知操作系统执行某个具体的功能 箭头4表示操作系统能够将输入设备的变化上传给应用程序,如用户在某个程序活动时按了一下键盘,操作系统马上就感知了这一事件,并且知道用户按下的是哪个键,但操作系统并不决定对这一事件如何做出反应,而是将这一事件转交给应用程序,由应用程序决定如何对这一事件做出反应。 在Windows操作环境中,Windows应用程序采用基于消息的事件驱动运行机制。事件是系统产生的动作或是用户运行应用程序产生的动作。当事件发生之后(例如,当用户单击鼠标、改变窗口尺寸、按下键盘上的一个键等),Windows将事件转换为一个消息,并将消息放入相应的应用程序消息队列中,应用程序从消息队列中检索这些消息,并把它们发送到相应的窗口中处理,完成消息的响应。这个过程一直持续,直到程序的结束。
6.l.2基本概念 1.窗口 每一个Windows应用程序运行时都是一个窗口。窗口是系统管理应用程序的基本单位;窗口是应用程序与用户之间交互的接口环境;窗口是Windows应用程序基本的操作单元。 窗口是由应用程序创建的一个用于接收用户输入和显示输出的矩形区域。窗口由“非客户区”和“客户区”组成。非客户区由系统绘制,包括菜单栏、工具栏、最大化按钮等。客户区由应用程序绘制,用于输出数据和接收用户的输入。
最大化按钮 控制菜单框 下拉菜单 最小化按钮 标题栏 工作区 垂直滚动条 窗口边界 水平滚动条 一个应用程序的窗口一般包含下列成分:
窗口 按钮 图标 滚动条 输出设备 控制 文件 句柄(Handle)是一个4字节长的数值,用于标识应用程序中不同的对象和同类对象中不同的实例 2. 句柄 应用程序通过 句柄访问相应 的对象信息 在windows系统中,对象句柄并非对象所在的内存地址,而是系统内部的索引值。如windows中一个窗口被打开以后,对应内存中的一片内存块,在应用程序运行过程中,该内存块地址将由操作系统动态调整,但该窗口对象的句柄却不会变化。因此,通过窗口对象句柄对该窗口进行访问使问题变得更为简单。
常用句柄类型及其说明 HWND 窗口句柄 HDC 设备环境句柄 HBITMAP 位图句柄 HCURSOR 光标句柄 HICON 图标句柄 HFONT 字体句柄 HMENU 菜单句柄 HPEN 画笔句柄 HFILE 文件句柄 HBRUSH 画刷句柄 HINSTANCE 当前实例句柄 导航工具:mfc.bsc
3.项目要使用MFC编写一个应用程序就必须创建一个项目,也称为工程。项目就是文件的集合,它包括了资源文件、头文件、源代码文件、程序结构消息文件和系统参数设置文件。 VC++6.0以项目工作区的形式来组织文件、项目和项目配置。每个项目工作区由工作区目录中的项目工作区文件组成。项目工作区文件(扩展名为dsw)含有工作区的定义和项目中所包含文件的所有信息。Lesson09.dsw
6.2MFC概述 MFC(Microsoft Foundation Class)是一个建立在Windows的API函数之上的C++类库(C++ Class Library),是一个类的集合。MFC6.0大约封装了200多个类,该类集以层次结构组织起来,其中封装了大部分Windows API函数和Window控件,它所包含的功能涉及到整个Windows操作系统。在MFC程序中,通常并不直接调用Windows的API函数,而是从MFC类创建对象,并调用属于这些对象的成员函数。设计MFC类库的意图是使Windows程序设计过程更高效,更符合面向对象的精神。MFC帮助我们把数以千计的API函数,利用面向对象的原理有效地组织起来,使它们具备封装性、继承性、多态性、抽象性、模块化等特点。 MFC不仅是一个类的集合,它还是一个应用程序的框架结构,为用户提供了Windows图形环境下应用程序的框架,而且还提供了创建应用程序的组件。使用MFC类库和Visual C++提供的高度可视的应用程序开发工具,可使应用程序开发变得更简单,开发周期极大地缩短,提高代码的可靠性和可重用性。
MFC被设计成可移植于众多的平台,允许其应用程序适用于多种不同平台。对于多种编译器,MFC也是可以移植的,而且有许多软件开发公司已经把它作为一种基于Windows开发标准的应用程序构架。 MFC之所以得名为微软基础类库,是因为它代表着正在不断带给Windows操作系统开发人员以最好支持的基本结构。它所包含的类分层结构和功能的可伸缩性,使得MFC始终能跟踪软件发展的潮流,而且在功能扩展的同时,MFC还很好地保持了程序的向下兼容性。 面向对象的程序设计方法和传统的程序设计相比,具有很多优点:代码和数据更紧密地捆绑在一起,可重用性好。但是,一种语言如果没有好的类库支持,就不会减少编写代码的工作量,这正是MFC成功的地方。MFC为用户提供了大量的代码,从而减轻了用户编写应用程序的难度。
6.3MFC类的层次结构及类简介 MFC的类可以分为两大类:CObject派生类和非CObject派生类。大多数MFC 类都是从CObject 中直接或间接派生出来的。 6.3.1程序结构类
1.应用程序类CWinApp CWinApp 类是应用程序中应用程序类的基类,该类提供了消息循环来从消息队列中取出消息并将消息调度给应用程序的窗口,该类包括了可以被重载的、用来自定义应用程序行为的主要虚函数。CWinApp类封装了初始化、运行、终止应用程序的代码。应用程序类管理程序的整体,控制应用程序的所有对象,包括文档、视图和边框窗口,并完成程序的初始化工作和程序退出时的清除工作。 CWinApp表示应用程序本身,几乎所有的基于MFC的应用程序都是从CWinAPP派生一个类,并通过创建这个派生类的对象来创建一个应用程序对象。每个应用程序有且只有一个应用程序对象,在运行程序中该对象与其它对象相互协调。
2.文档类CDocument 文档类负责存放程序的数据并读取磁盘文件数据,或将数据写入磁盘文件中。文档类必须通过视图类实现与用户的交互,当用户打开一个文档时,应用程序实际上创建了一个视图并且把这个视图和相应的文档联系在一起。文档类对象的作用是在幕后存储和管理数据,因此文档类对象在程序界面上是看不到的。
6.3.2窗口类 窗口是windows编程中用得最多的一个概念,MFC提供很多不同的窗口类。这些窗口类可以被划分为四个主要类别:框架窗口、视图窗口、对话框以及控件,其中每一个类都提供不同功能。它们具备的共同之处是都代表某一种类型的窗口,并且都是从CWnd类中派生而来的。框架窗口是文档/视图结构应用程序中的“容器窗口”。框架窗口中包括视图窗口,而视图窗口中包括文档。
6.3.3图形类 MFC中另一种重要类别是图形类。在此类别中,这些类可被进一步划分为两个子类:设备环境和图形设备类。MFC中的设备环境类(CDC类)实现了对Windows中设备环境的封装,从CObject类派生。CDC类有许多成员函数,提供诸如选择图形设备对象、设置颜色与调色板、绘制图形、设置字体、文本输出以及设备坐标和逻辑坐标转换等功能。此外,MFC还提供了一些CDC的派生类,用于操纵不同的设备环境。
MFC类体系图 对象类 Application Framework 窗口类 视图类 框架类 文档类
6.4用Appwizard建立MFC应用程序 6.4.1MFC应用程序类型 利用Visual C++创建的MFC应用程序有三种典型结构: 单文档应用程序类似于Windows中的记事本,它的功能比较简单,复杂程度适中,虽然每次只能打开和处理一个文档,但已能满足一般的需要。 多文档应用程序同时可以打开和处理多个文档。与单文档应用程序相比,增加了许多功能,因而需要大量额外的编程工作。例如,它不仅需要跟踪所有打开文档的路径,而且还需要管理各文档窗口的显示和更新等。 对话框实际上是窗口的特例,也是由CWnd类派生。对话框应用程序没有菜单、工具栏及状态栏,也不能处理文档,但它的好处是速度快、代码少,为用户提供了一个比一般窗口更加标准的数据处理方法。
6.4.2MFC的Appwizrd创建应用程序的步骤 【例6-1】通过MFC的Appwizard建立一个单文档应用程序ex6_1。
6.4.3应用程序向导生成的类和文件 打开已经创建的单文档应用程序ex6_1。单击项目工作区的ClassView 标签,则显示CmainFrame、CEx6_1App、CEx6_1Doc 和CEx6_1View等,这是应用程序ex6_1的4个主要类 1.应用程序类 ex6_1程序的应用程序类名为CEx6_1App,由CWinApp 类派生而来。程序中默认定义一个该类上的全局对象theApp,代表一个应用程序。CEx6_1App类的功能是管理整个应用程序,负责程序的启动、初始化、窗口的创建以及从Windows 中获取消息并将消息分发到适当的目的地。CEx6_1APP类的声明在头文件ex6_1App.h中,类的实现在ex6_1App.cpp 中。
2.主框架窗口类 ex6_1应用程序的主框架窗口类名为CMainFrame,它由CWnd 的一个子类CFramewnd 派生来的。CMainFrame 类的声明在头文件MainFrame.h 中,类的实现在文件MainFrame.cpp中。CMainFrame 类是一个顶级、可重叠、可改变大小的窗口。CMainFrame 类管理主框架窗口,并拥有一些如菜单、工具栏和状态栏等资源,同时,它还扮演转发菜单和工具栏消息的角色。 3.文档类 ex6_1应用程序的文档类名为CEx6_1Doc,从CDocument 类派生而来。其类的声明在头文件ex6_1Doc.h 中,类的实现在文件ex6_1Doc.cpp 中。文档类的主要作用是保存应用程序的数据,并提供磁盘文件操作。直接由应用程序向导生成的文档类还不能做太多的工作,毕竟应用程序向导创建的应用程序并不知道是字处理程序还是绘图程序,或是其它程序。用户需要修改文档类,增加成员变量来存储应用程序的数据,增加成员函数以获得和修改数据,然后为应用程序服务。
4.视图类 ex6-1应用程序的视图类名为CEx6_1Vicw ,默认的视图类是CView 的一个子类,而CView 又是CWnd 的子类。CEx6_1View 类的声明在头文件ex6_1View.h 中,而类的实现在文件ex6_1View.cpp中。视图类主要管理视图窗口,负责用户数据的输人和数据的输出显示。在创建一个单文档应用程序时,视图类可以从CView类派生,也可以选择将视图类从CView 类的子类派生出来。例如,MFC应用程序向导步骤6中,如果在Baseclass 中选择CEditView 作为基本视图类,则可以很方便地得到一个简易的字处理程序,具有类似于写字板应用程序的功能,而实现这些功能用户却无须编写任何源代码。 5.其它文件 除以上介绍的主要类之外,Appwizard 还自动生成StdAfx.cpp 和StdAfx.h 两个文件。这两个文件是每个基于MFC 程序所必需的。MFC 是一个功能强大的类库,包含很多头文件,如果每次都编译则比较费时,因此将afxwin.h、afxext.h、afxdtctl.h、afxcmn.h和afxdisp.h 都放在stdafx.h文件中,这样编译系统可以识别哪些文件己经编译过,因此,采用预编译头文件可以加速应用程序的编译过程。
6.4.4项目工作区窗口 Visual C++ 6.0项目工作区由ClassView(类显示)面板、ResourceView (资源显示)面板及FileView(文件显示)面板等组成 1.ClassView面板 ClassView面板列出了当前项目中的类。通过该面板可以浏览类的成员。每个成员的左边都有一个或多个图标,这些图标表示该成员是成员变量还是成员函数,以及成员的访问类型等。如果成员是保护或私有类型,那么它的左边有一个钥匙图标。 2.ResourceView面板 该面板拥有当前项目中包含的所有资源。扩展顶层文件夹可以显示资源类型 3.FileView面板 FileView面板用于显示当前项目中各项目之间的包含关系和项目中包含的所有文件。
6.5消息和消息映射 6.5.1消息的结构 数据结构MSG中包含一个消息的全部的信息,它的结构定义如下: typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; }MSG; hwnd是窗口句柄,若此参数为null,则可检索所有驻留在消息队列中的消息。 message代表一个消息的消息值,由Windows.h头文件中的宏定义来标识。 wParam和lParam包含有关消息的附加信息,不同消息其值有所不同。wParam是附加消息的字参数,lParam是附加消息的长参数。 time指定消息送至队列的时间。 pt指定消息发送时屏幕光标的位置,其数据类型POINT也是一个结构体。 消息包含的信息很全面,拿到这样一个消息,应用程序就知道如何做出反应。
6.5.2消息的种类 1.窗口消息(Windowsmessage) 这类消息主要是指以“WM_”为前缀(除WM_COMMAND之外)的消息,如WM_CREATE消息是窗口对象建立时产生;WM_CREATE 消息是应用程序初始化时Windows 发送给视图的第一条消息;WM_DESTROY是窗口对象清除前被发出;WM_PAINT消息是窗口更新时产生的绘制消息等,一般由窗口类和视图类处理。窗口消息往往带有参数,标志处理消息的方法。鼠标和键盘消息是窗口消息,下面是常用的鼠标和键盘消息: WM_KEYDOWN :键盘被按下。 WM_KEYUP :键盘弹起。 WM_CHAR :字符消息。 WM_MOUSEMOVE :鼠标移动。 WM_LBUTTONDOWN :鼠标左键被按下。 WM_LBLITTONUP :鼠标左键弹起。 WM_LBUTTONDBLCLK :双击鼠标左键。 WM_RBUTTONDOWN :鼠标右键被按下。
在MFC 的CWnd 类中定义了标准Windows 消息的默认处理函数,这些函数的声明部分的前面都用关键字afx_msg来声明,函数名称以On 开头,后面是对应Windows 标准消息中不包括“WM_”的部分。例如WM_LBUTTONDOWN消息的默认处理函数的声明部分为: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 窗口消息是由窗口对象接受并处理的,这里的窗口对象是指从窗口类CWnd中派生的类的对象,它包括CFrameWnd、CMDIFrameWnd、CMDIhildWnd、CView、CDialog以及从这些派生出的类的对象等。窗口框架类和视图类能够接收和处理窗口消息。鼠标和键盘消息是窗口消息,所以鼠标和键盘消息的消息响应函数一般放在窗口框架类和视图类中,作为窗口框架类和视图类的成员函数。 Afx前缀是微软MFC一个小组的名称简写,并没有别的意义。 MFC的很多代码,包括全局函数名、宏、头文件名都使用了"Afx"。 Afx*.h是一组MFC的核心头文件, 比如: afxwin.h 定义MFC的核心和标准组件 afxext.h 定义MFC的扩展 afxdisp.h 是MFC自动化支持的类定义头文件 afxdb.h 是MFC的ODBC类封装
2.控件的通知消息(Control notifications) 当控件的状态发生改变(例如,用户在控件中进行输入)时,控件就会向其父窗口发送通知消息。各种控件的通知消息的前缀不同,下面是常用的控件消息的前缀: CB_ :组合框控件消息。 EM_ :文本编辑框控件消息。 LB_ :列表框控件消息。 SBM_ :滚动条控件消息。 BM_ :按钮控件消息。 控件消息的消息响应函数一般放在对话类中,作为对话窗类的成员函数。控件消息没有默认的消息处理函数,在使用ClassWizard 添加消息处理函数时,系统会自动提供一个消息处理函数的函数声明。
3.命令消息(Command message) 命令消息来自用户界面,主要包括由用户点击对象(菜单、工具条的按钮、快捷键等)发送的WM_COMMAND通知消息。命令消息是用户自定义的消息。如菜单命令、工具栏按钮、加速键等,命令消息也称为WM_COMMAND 消息。 命令消息的处理方式与其它两种消息不同,能够由多种对象接收、处理,这些对象包括文档类、应用程序本身以及窗口框架类和视图类。 命令是作为特殊消息处理的,每个产生命令消息的对象都有一个ID,通过给命令和对象分配同样的ID,就能将命令和对象联系起来。通常,命令ID 是以其所表示对象的功能来命名的。例如,菜单项“打开”这个对象和消息的ID 为ID_FILE_OPEN。同控件消息一样,命令消息也没有默认的消息处理函数,可以用类向导建立消息处理函数的声明和定义框架。如对于“打开” 菜单项消息的消息处理函数声明和定义框架如下: afx_msg void OnFileOpen(); //在头文件MainFrm.h中声明 void CMainFrame::OnFileOpen( ) //在源文件MainFrm.cpp中实现 { // TODO: Add your command handler code here }
6.5.3消息映射 消息映射是一个关联消息和成员函数的列表,消息映射一般由三元素构成,即对象,消息和函数。主要说明对哪一个对象发来什么消息就去调用哪个函数。即将消息和消息处理函数联系起来,使MFC消息机制对每一个产生的消息调用对应的消息处理函数。例如,我们要告诉系统,当用户单击某个控件时,调用哪一个函数,这就需要进行消息映射。消息映射是Windows 基于消息映射的事件驱动机制的重要内容之一。 1.MFC类向导: MFC ClassWizard MFC类向导是Visual C++6.0中又一个非常有用的工具。它能自动为一个项目添加一个类,进行消息和数据映射、创建OLE Automation(自动化)属性和方法以及进行ActiveX事件处理等。 选择“查看”菜单下的“建立类向导”菜单项或直接使用Ctrl+W快捷键就可以打开类向导。也可以在源代码文件的文档编辑窗口中,右击鼠标,从弹出的快捷菜单中选择“建立类向导”命令,就会打开MFC类向导,弹出如图6-17所示的“MFC ClassWizard”对话框。
可以看到“MFC ClassWizard”对话框包含了5个标签页面,它们各自含义如下。 Message Maps(消息映射):用来添加、删除和编程处理消息的成员函数。 Member Variables(成员变量):添加或删除与控件相关联的成员变量(或称控件变量),以便与控件进行数据交换。这些控件所在的类一般是从CDialog、CPropertyPage、CRecordView或CDaoRecordView中派生的类。 Automation(自动化):为支持自动化的类(如ActiveX控件类)添加属性和方法。 ActiveX Events(ActiveX事件):为ActiveX控件类添加触发事件的支持。 Class Info(类信息):有关项目中类的其它信息。
2.使用类向导进行消息映射的步骤 消息处理函数可以利用VC6.0的类向导,将消息处理函数添加到对话框类中作为成员函数,并建立消息映射。使用类向导添加消息处理函数的步骤如下: (1)打开VC6.0的View菜单,选择Classwizard命令,出现MFC Classwizard对话框,选择Messag Maps选项卡 (2)在Project下拉列表框中选择项目名称,在Class Name下拉列表框中选择对话框类。 (3)在Object IDS列表框中列出了当前所有对象的ID以及能产生消息的菜单项对话框控件等,选中要处理的控件的ID。 (4)在Messages列表框中列出了上一步所选中对象能产生的各种消息及类的虚函数,选择相应的消息并单击Add Function按钮,则出现一个Add Member Function对话框,输入添加的消息处理函数名称,击OK按钮,该名称出现在Member functions 列表中。 (5)单击OK按钮,则完成了消息处理函数的添加。也可以单击Edit Code 按扭,光标自动定位在刚添加的消息处理函数内。
【例6-2】新建一个单文档的应用程序ex6_2,程序运行时,在用户区单击鼠标左键则弹出一个消息框,显示“你好!”,如图6-18所示。【例6-2】新建一个单文档的应用程序ex6_2,程序运行时,在用户区单击鼠标左键则弹出一个消息框,显示“你好!”,如图6-18所示。
使用类向导实现相应功能的具体过程如下: (1)新建一个单文档的应用程序ex6_2,然后按Ctrl+W快捷键打开“MFC ClassWizard”对话框。 (2)在“Class name”组合框中,将类名选定为CEx6_2View。此时,Object IDs和Messages列表内容会相应的改变。 (3)在“Object IDs”列表框中选定CEx6_2View,然后拖动Messages列表框右侧的滚动块,直到出现要找的WM_LBUTTOMDOWN消息为止。 (4)双击Messages列表中的WM_LBUTTOMDOWN消息或单击“Add Functions”按钮,都会在CEx6_2View类中添加该消息的映射函数OnLButtonDown,同时在“Member functions”列表中显示这一消息映射函数和被映射的消息。 (5)单击“Edit Code”按钮后,“MFC ClassWizard”对话框关闭,同时光标定位到OnLButtonDown函数源代码处。 (6)添加如下代码: void CEx6_2View::OnLButtonDown(UINT nFlags,CPoint point) { //TDDO:Add your message handler code here and/or call default MessageBox(“你好!”); CView::OnLButtonDown(nFlags,point); } 在代码中加粗并且倾斜的代码是新添加的代码,其它为原有代码。
3.系统自动添加的代码及解释 查看ex6_2程序代码,可以发现MFC Classwizard为WM_LBUTTOMDOWN的消息映射做了以下三个方面的工作。 (1)在头文件ex6_2View.h中声明消息处理函数OnLButtonDown: //{{AFX_MSG(CEx6_2View) afx_msg void OnLButtonDown(UINT nFlags,CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP( ) 代码中的//{{AFX_MSG(CEx_SDIView)和//}}AFX_MSG之间的部分是MFC ClassWizard定义的专门用作消息映射函数声明的标记,表示该程序块中的消息映射声明是由 ClassWizard 来自动管理的,用户一般不需要去更改。需要说明的是,凡//{{和//}}之间的程序代码块均由 ClassWizard 自动管理。
(2)在ex6_2View.cpp 源文件前面的消息映射入口处,添加了如下语句: BEGIN_MESSAE_MAP(CEx6_2View,CView) //{{AFX_MSG_MAP(CEx6_2View) ON_WM_LBUTTONDOWN(); //}}AFX_MSG_MAP END_MESSAGE_MAP() (3)在ex6_2View.cpp文件中已经有了用户填入的具体代码: void CEx6_2View::OnLButtonDown(UINT nFlags,CPoint point) { //TODO:Add your message handler code here and/or call default MessageBox(“你好!”); CView::OnLButtonDown(nFlags,point); }
对以上代码的解释: (1)以上源代码共使用了三种消息映射宏,分别是:DECLARE_MESSAGE_MAP 、BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 。其中宏DECLARE_MESSAGE_MAP用于类声明文件的结束处,即在.h 文件的结束处;宏BEGIN _MESSAGE_MAP 和END_MESSAGE_MAP 用于类的实现文件(.cpp )中实现消息映射,而且这两个宏必须配合使用。在BEGIN_MESSAGE_MAP 与END_MESSAGE_MAP 中间列出了消息映射的各个入口。 (2)头文件中的语句 afx_msg void OnLButtonDown(UINT nFlags,CPoint point);表示该类中有一个成员函数OnLButtonDown()。 所有者类中的方法原型如下: afx_msg void 函数名称();
(3)cpp文件中的语句ON_WM_LBUTTONDOWN();是消息映射语句。(3)cpp文件中的语句ON_WM_LBUTTONDOWN();是消息映射语句。 消息映射语句一般由三元素构成,即对象,消息映射宏和函数。主要说明对哪一个对象发来什么消息就去调用哪个函数。消息映射语句要放在.cpp 中的BEGIN_MESSAGE_MAP 与END_MESSAGE_MAP 中间。 例如,以下消息映射语句: ON_COMMAND ( ID_FILE_OPEN ,CWinApp ::OnFileOpen ); ID_FILE_OPEN是对象的ID,ON_ COMMAND是消息映射宏,CWinApp ::OnFileOpen是函数名称。表示当用户单击了菜单项File |Open 时,则发送WM_COMMAND 消息,该消息找到此语句,发现Open菜单项的ID值与此语句的ID_FILE_OPEN 匹配,则执行该语句中指定的成员函数CWinApp : : OnFileOpen()。
消息映射宏大致可以分为以下几类。 ①Windows消息映射宏 其宏名通常以ON_WM_开头,后面是Windows 标准消息的名称或控件通知码,标准Windows 消息映射宏没有参数,但对应的消息处理函数通常都有参数,表6-10是映射宏的消息处理函数原形。 本例中的消息映射语句ON_WM_LBUTTONDOWN();没有参数,即只说明了消息映射宏,没有说明对象和函数,是因为系统规定了对象是本类(CEx6_2View)对象,且函数为OnLButtonDown()。
②控件消息映射宏 控件消息映射宏以ON_或ON_NOTIFY_或ON_CONTROL_开头,ON_开头表示Windows 预定义的控件消息映射宏,ON_NOTIFY_表示与通用控件相关的映射宏,ON_CONTROL_表示与普通控件相关的映射宏。 ③命令消息映射宏 命令消息映射宏以ON_COMMAND 或ON_UPDATE_COMMAND 开头,如: ON_COMMAND(ID,memberfxn); ON_COMMAND_RANGE(ID,memberfxn); Memberfxn表示成员函数
4.手动添加消息映射的步骤 从前面使用ClassWizard进行消息映射的过程可以知道,用户可以自己手动添加消息映射函数。事实上,用户可以自己手动添加一些 MFC ClassWizard 不支持的消息映射函数,以完成特定的功能。手动添加消息映射的具体步骤: (1)将DECLARE_MESSAGE_MAP 添加到类中,声明消息映射。 (2)通过放置表示消息的宏来执行消息映射,将消息映射语句放到相应类的源文件BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP之间。 (3)添加成员函数来处理消息。 在例6-2程序运行时,在用户区单击鼠标右键则弹出一个消息框,显示“你按下了鼠标右键!”。 • void CEx6_2View::OnRButtonDown(UINT nFlags, CPoint point) { • // TODO: Add your message handler code here and/or call default • MessageBox("好啊!右键"); • CView::OnRButtonDown(nFlags, point); • }
6.6常用的类的操作 在Visusl C++应用程序编程过程中,常常需要对类及类代码进行定位、添加成员、消息映射、虚函数等操作,下面以单文档应用程序为例分别说明。 1.类的添加 用MFC 类向导给项目添加一个类步骤如下: (1)按快捷键Ctrl+W启动MFC类向导对话框。单击“Add Class”按钮,从弹出的下拉菜单中选择New命令。弹出如图6-19所示的“New Class”对话框。 (2)对话框中,Name是用来输入用户定义的类名,注意要以“C”字母打头,以保持与MFC标志符命名规则一致;File name是该类的源代码文件名,单击“Change”按钮可改变源文件名称及其在磁盘中的位置;Base class下拉列表框用来指定该类的基类;Dialog ID是选择CDialog作为基类时指定对话框的资源ID号。最下面的Automation是用来设置对自动化的支持。 (3)单击“OK”按钮,一个新类就会自动添加到项目中。