




已阅读5页,还剩47页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章MFC应用程序框架剖析 贾澎涛pengtao jia MFC的类组成了 应用程序框架 应用程序框架 定义应用程序的框架并提供基本的通用功能 程序开发者只须另外添加自己需要的功能即可 3 1最简单的应用程序 实例1 HelloWorld 1 使用AppWizard生成一个Win32Application工程 2 加入Hello cpp文件 3 运行MFC应用程序至少要有两个对象 应用对象 CHelloApp 和主框架类对象 CHelloFrame 类CHelloApp的对象就代表着一个应用程序对象 在MFC应用程序中需要定义一个单独的全局应用对象 includeclassCHelloFrame publicCFrameWnd public CHelloFrame Create NULL HelloWorld WS OVERLAPPEDWINDOW rectDefault classCHelloApp publicCWinApp public virtualBOOLInitInstance m pMainWnd newCHelloFrame m pMainWnd ShowWindow m nCmdShow m pMainWnd UpdateWindow returnTRUE CHelloAppHelloApp 定义一个全局CHelloApp对象 3 2带文档 视图结构的MFC程序基本框架类和文件组成 上面的例子用应用对象和框架窗口对象构造了最简单的MFC应用程序框架 而大多数的MFC应用程序都要比他复杂的多 在这类应用中除了要包含应用对象和框架窗口对象外 还要包含文档类和视图类 采用文档 视图结构最大的优点在于将程序数据本身与数据的操作与维护分离开来 微软提供了一个相当灵活的结构 用户几乎可以采用这种结构创建任何类型的Windows程序 一个文档可以对应多个视图 比如 用户在一个图表中查看由数据生成的图表的同时 可以在另一个表单中查看产生该图表的原始数据 下面我们就对文档视图结构做详细分析 在前面我们已经建立了一个名字为Draw的工程 事实上这个框架程序已经可以编译运行了 在BUILD菜单中选择REBUILDALL菜单项 系统开始编译由APPWIZARD自动生成的程序框架中所有文件中的源代码 并且链接生成可执行的应用程序 在BUILD菜单中选择EXECUTE菜单项 应用程序就开始运行了 虽然我们没有编写一行代码 但是可以看出由系统自动生成的应用程序的界面已经有了一个标准WINDOWS应用程序所需的几个组成部分 我们要做的事情是往这个应用程序添加必要的代码以完成我们所需要的功能 接下来将要对WINDOWS自动生成的这个应用程序框架作详细的介绍 让你对MFC方式的WINDOWS应用程序的工作原理有全面的认识 只有这样你才会知道应该如何往程序框架当中添加需要的代码 通过对应用程序Draw进行分析 可以知道普通的MFC应用程序包含以下四个主要的类 文档类 视图类 主框架窗口类 应用类 程序的主要任务在这四个类中分配 AppWizard为每个类的实现产生了各自的源文件 C 类在文件组织上一般分为两个部分 头文件 h 和实现文件 cpp 头文件是 h文件 一般用来存放类 结构等的定义代码 通过include宏插入到实现文件中 实现文件是通常的 cpp文件 用来存放类的成员函数的实际代码 文档类 应用程序Draw的文档类的名称是CDrawDoc 这是AppWizard根据项目名称默认所取的名称 它是由MFC的基类CDocument派生的 CDrawDoc类的头文件是drawdoc h 实现文件是drawdoc cpp 头文件中存放的是类的定义代码 实现文件中存放的是类的各个成员函数的实现代码 文档类负责存放程序数据并读取磁盘文件数据 或将磁盘文件数据写入磁盘文件中 再建立一个应用项目时 在文档类中对应用程序所需要的数据资料进行管理 视图类 应用程序Draw中视图类的名称是CDrawView 它是由MFC的Cview类派生的 CdrawView类的头文件是drawview h 实现文件是drawview cpp 视图类负责显示文档类中的数据 可以显示在屏幕上 也可以输出到打印机上或其它设备上 视图类也负责处理用户的输入 框架类 在使用AppWizard生成的应用程序Draw时 选择的是一个多文档选项 在MFCAppWizard Step1 选择的是Multipledocuments选项 所以应用程序Draw中包含两个框架类 主框架类CMainFrame和子框架类CChildFrame 主框架类CMainFrame是由MFC的CMDIFrameWnd类派生的 其头文件是mainfrm h 实现文件是mainfrm cpp CMainFrame类提供了管理一个多文档界面 MDI 的主窗口的所有功能及管理窗口中的子窗口 用来显示一个标题 一个菜单条 窗口最大化和最小化键 边框 一个系统菜单 工具条以及状态条等 子框架类CChildFrame是由MFC的CMDIChildWnd类派生的 其头文件是childfrm h 实现文件是childfrm cpp 子框架类的功能是用来管理子窗口 一个子窗口非常像主窗口 但子窗口仅能在主窗口内显示 而不在Windows桌面上 在窗口没有自己的菜单条 但他分享主窗口的菜单条 程序自动将框架窗口菜单作为当前子窗口的菜单 应用类 应用程序Draw的应用类是CDrawApp 它是由MFC的CWinApp类派生的 其头文件是draw h 实现文件是draw cpp 应用类管理程序的总体 它完成不属于任何其他三类的一般工作 例如初始化程序以及进行最后的程序清除工作 每个MFC应用程序必须正确的生成由CWinApp派生类的一个实例 对象 应用程序主要源文件组成 在组成应用程序Draw的源文件中 除了五个主要类的源文件外 10个文件 还有其它一些文件 对他们简述如下 draw rc 资源定义文件 包含程序资源的定义 菜单 对话框 字串 键盘加速键 和图标等 一般情况下 这个文件是由AppStudio进行可视化编辑维护 一般不用手工修改这个文件 draw dsw 工作平台信息文件 存储着一个工作平台的组成情况 如包含哪些程序项目 程序项目的依赖关系等 用来存储和打开一个工作平台 draw clw ClassWizard信息存储文件 存储ClassWizard编辑存在的类和新增加类的信息 文件也包含了ClassWizard建立和编辑各种消息处理函数和映射变量等的信息 draw dsp 程序项目工程文件 存储着一个应用程序项目所包含的具体信息 在打开项目时用 makehelp ybat 批处理文件用来建立应用程序的帮助文件hlp draw hlp hlp draw hpj 被帮助文件编译器用来建立系统的帮助文件时使用的工程文件 hlp bmp 被用来作为MFC标准命令帮助主题的位图文件 hlp rtf 帮助主题文件 包含MFC标准命令的帮助主题 res draw rc2 资源定义文件 包含着不用AppStudio编辑的程序资源定义 当手工 而不是AppStudio 定义程序资源 可以将资源定义在这个文件中 这个文件被插入 include 在文件draw rc中 res draw ico 应用程序的图标 最初 这个文件包含标准的 AFX 图标 可以用AppStidio对图表进行修改 res toolbar bmp 工具条的位图文件 stdafx cpp和stdafx h 预编译文件 用于生成预编译信息 resource h 资源ID号定义文件 这个文件与draw rc相对应 包含程序资源中ID号的常量定义 一般也是由AppStudio自动进行维护的 draw def 它提供MicrosoftLINK程序进行连接时 用于准备可执行的应用程序文件的有关信息 一般不必编辑这个文件 因为它包含适合于大多数MFCWindows程序的值 readme txt 包含对所有该程序的源文件的解释信息 注意 文档 视图结构并不是在任何情况下都是适合的 在使用时应注意以下几种情况 1 用户要移植一个用C编写的Windows程序 用户可能希望在添加文档 视图结构之前完成移植 2 如果用户在编写一个小工具 可能会发现不采用文档 视图也是可以的 并且程序会更简单 3 如果源代码已经将数据管理和数据视图有效结合在一起 采用文档 视图结构是多余的 WINDOWS应用程序一定要有WinMain函数 该函数用来完成一些特殊的任务 象创建程序的主窗口 主窗口用来处理消息的代码 MFC将WinMain隐藏在框架中 不象写SDK SoftwareDevelopmentKit 程序时可以很容易的找到它 WINDOWS采用的消息处理机制也交给了程序框架 我们不必担心如何使这些消息和代码联系起来 并且WINDOWS定义好了一些消息 当窗口被创建时系统就会发送WM CREATE消息 当点击鼠标左键时便系统会发送WM LBUTTONDOWN消息 当用户按下键盘时系统会发送WM CHAR消息 当用户关闭窗口时系统会发送WM CLOSE消息 当用户进行菜单项选择或单击按钮时系统回发送WM COMMAND消息 什么都不做系统还会发送WM TIMER消息 说明 3 3MFC应用程序的执行步骤 前面介绍了Draw应用程序的文件 那么你们可能要问 Draw程序从哪里开始执行的 从哪里吸收控制 以下是一般MFC应用程序运行的主要步骤 调用CWinApp类构造函数 程序入口函数WinMain接收控制 WinMain调用程序的InitInstance函数 WinMain进入消息循环 WinMain退出 程序终止 1 调用CWinApp类构造函数 MFC应用程序必须定义有且只有一个应用类对象 在实现文件draw cpp中可以找到其定义 CDrawApptheApp 由于应用类对象theApp是全局对象 因此在入口函数WinMain接收控制前 先调用应用类的构造函数 CDrawApp CDrawApp TODO addconstructioncodehere PlaceallsignificantinitializationinInitInstance 将应用类对象theAPP定义成全局的 是为了在MFC中能够对CWinApp的成员函数进行调用 2 WinMain接受控制 定义全局应用类对象theApp后 程序入口函数WinMain 接受控制 这个函数已经在MFC中做了定义 在建立执行文件时能够链接到应用程序Draw 3 调用函数InitInstance进行初始化 在实现文件draw cpp中可以找到InitInstance的实现代码 这个函数完成最主要任务如下 定义并初始化了一个多文档模板对象pDocTemplate完成多文档模板的定义后 程序产生了一个主框架窗口 创建主框架窗口时采用的是IDR MAINFRAME资源 创建主框架窗口后 程序将处理命令行信息 命令行信息是跟随在命令后的参数 如可以用以下的语句启动应用程序Draw Drawdraw1 dat 启动应用程序Draw 并在启动后自动打开draw1 dat文件最后 程序显示并更新主框架窗口 4 WinMain处理消息 完成初始化任务后 WinMain进入消息循环 通过Run 函数把消息从消息队列中取出 并发送到别的窗口 大多数命令消息被发送到应用程序主窗口 其中的函数WindowProc 得到消息 再根据消息的类别送到适当的对象 激活并运行对象中的消息处理函数 5 WinMain退出 程序终止 在应用程序Draw中 运行 文件 菜单下的 退出 或运行系统菜单的 关闭 或单击主框架窗口的Close框时 应用程序删除程序窗口 并调用Win32API函数 PostQuitMessage 使消息循环退出 然后WinMain函数返回 程序终止 3 4使用ClassWizard Windows应用程序是通过消息来控制流程的 MFCClassWizard生成的应用程序为通过消息设计程序提供了很好的框架 程序设计者甚至不必知道也不必参与控制消息传递的实际流程 而只需要掌握简单的使用方法就可以达到程序设计的目的 MFCClassWizard为管理消息处理函数提供了一个强大的工具 1 Windows消息 Windows应用程序一般是由消息驱动的 message driven 为处理诸如击鼠标键 窗口移动或改变大小 键盘输入等情况 Windows会向特定的窗口发送消息 在VC 中 一般的消息处理被包含在MFC中 用户特定的消息由程序设计者自己处理 应用类CWinApp中的Run 函数从Windows消息队列中获取消息 并在消息循环中把消息发送到适当的窗口 Windows程序中的消息主要有三种类型 窗口消息 控件的通知消息和命令消息 窗口消息 窗口消息包括WM 开头的消息 除WM COMMAND消息外 一般由窗口对象或视图对象处理 窗口消息往往带有参数 它是在窗口创建 改变大小 删除过程中 以及在受到操作 如受鼠标操作 时产生的 如WM LBUTTONDOWN消息是在窗口中单击鼠标左键时产生的 WM SIZE消息是在窗口大小改变时产生的 窗口消息是由窗口对象接收并处理的 窗口对象指的是从CWnd中派生出的类的对象 如从CWnd CFrameWnd CMDIFrameWnd CMDIChildWnd CView CDialog等MFC类或这些类的派生类定义的对象 这些类都是由窗口类CWnd直接或间接派生的 控件的通知消息 控件是一个小的子窗口 属于其他窗口 如对话框 能够接受操作并向父窗口 通常是对话框 发送消息 常见的控件有 按钮 Button 列表框 ListBox 编辑框 Edit 复合框 ComboList 滚动条 ScrollBar 等 从CCmdTarget派生的类 都可以接收这类消息 命令消息 命令消息主要包括由用户交互对象发送的WM COMMAND消息 用户交互对象指的是程序操作界面上的菜单 工具条 快捷键等 从CCmdTarget派生的类 都可以接收这类消息 命令消息可被多个对象接收 一个对象接收到命令消息后 如果不处理 就把命令消息传递到其它的对象 直到被某个对象接收了 当某个命令消息在多于一个对象中有处理函数时 只有传递顺序在前面的窗口能够接收并处理消息 命令消息在各个对象中的传递顺序如下 View Doc DocTemp Frame App首先由框架类接收到该消息 框架类将该消息递交给其子窗口View 如果View没有对该消息进行响应 则由View递交给Doc 如果Doc也没有对该消息进行响应 那么它回再次将该消息回交给View View再回交给Frame框架 框架检查自己是否对该消息有相应的处理函数 如果没有则递交给App 如果App也没有则由Windows系统自己处理 2 消息处理函数 消息处理函数指的是与某个消息对应的函数 消息处理函数的执行是由其对应的消息引发的 这个机制构成了Windows程序控制流程的基础 某个类对象中的消息处理函数是与这个类对象能够得到的一个消息对应的 当这个消息发生时 这个函数就被执行 消息处理函数的定义和使用方法与一般的成员函数不同 一般的成员函数包括两部分 函数的定义和函数的实现部分 定义一个一般成员函数时 在类中定义函数的原型 一般在头文件中 在实现文件中实现函数的实现代码 而消息处理函数除了这两部分以外 还有第三部分 消息映射部分 通过消息映射在消息处理和引发它的消息之间建立联系 3 ClassWizard的启动 运行VC 开发平台中 View 菜单下的 ClassWizard 菜单项 或者使用快捷键CTRL W在VC 工作平台的文件编辑窗口中单击鼠标右键 选择快捷菜单中的菜单项 ClassWizard MFCClassWizard对话框的组成 MessageMaps选项卡MemberVariables选项卡Automation选项卡ActiveXEvents选项卡ClassInfo选项卡 4 ClassWizard管理消息处理函数 管理窗口消息处理函数实例 在视图窗口中跟踪鼠标的当前位置 1 建立一个工程Example 激活ClassWizard 选中MessageMaps选项卡 2 从ObjectIDs列表框选择CExampleView 3 从Messages列表框中选择消息WM MOUSEMOVE 此时AddFunction按钮增亮 单击AddFunction按钮 4 单击OK完成设定 5 在OnMouseMove函数中增加以下代码 charbuff 10 字符型缓冲区CClientDCdc this 当前设备为CClientDC的对象sprintf buff 03d 03d point x point y 把鼠标点拷贝到缓冲区dc TextOut 20 20 buff strlen buff 在 20 20 显示鼠标点值 Thesprintffunctionformatsandstoresaseriesofcharactersandvaluesinbuffer TheCDC TextOutfunctionwritesacharacterstringatthespecifiedlocation usingthecurrentlyselectedfont backgroundcolor andtextcolor 几点说明 ClassWizard通过固定的代码来识别窗口消息处理函数 通过以下两行代码来标识消息处理函数的定义 AFX MSG CEx06View ClassWizard标示消息处理函数定义的起始代码Afx msgvoidOnMouseMove UINTnFlags Cpointpoint AFX MSG ClassWizard标示消息处理函数定义的结束代码消息处理函数与普通函数的定义格式略有不同 需要在函数定义前加标示符afx msg 在实现文件中 消息映射机制写在如下的两行代码间而被ClassWizard识别 AFX MSG MAP CEx06View ClassWizard标识消息处理函数映射机制的起始代码ON WM MOUSEMOVE AFX MSG MAP ClassWizard标识消息处理函数映射机制的结束代码只有当一个消息处理函数的消息映射机制写在以上两行代码间时 才能被ClassWizard识别和处理 命令消息处理函数实例 为菜单项增加命令消息处理函数 1 建立工程Draw 增加 绘制直线 菜单项 ID定为ID DRAW LINE 2 进入ClassWizard 在 ClassName 列表框中选择CDrawView 在 ObjectIds 列表框中选择ID DRAW LINE 3 在Messages列表框中选择COMMAND消息 单击 AddFunction 按钮 在弹出的对话框中输入消息处理函数的名称 可接受默认值 添加如下代码CClientDCdc this dc MoveTo 20 20 dc MoveT0 100 100 几点说明 以上操作 在相应的源程序文件中进行了如下修改 1 在视图类CDrawView中 增加了消息处理函数的定义代码 2 在类CDrawView的实现文件drawview cpp中 增加了函数的实现代码 3 在实现文件drawview cpp中 增加了消息映射 控件消息处理函数控件消息处理函数是对应于VC 中各种控件消息的处理函数 多数存在于基于对话框的类中 对话框存在着用户定义的很多控件 如编辑框 列表框 复合框 滚动条等 这些控件在建立或被操作时会产生各种不同的控制消息 ClassWizard能够对这些控件消息的处理函数实行管理 ClassWizard管理控件消息处理函数的操作方法与管理命令消息时是相同的 5 ClassWizard管理重载虚函数 MFC程序框架中具有很多标准操作功能 例如 运行应用程序Draw 文件 菜单下的 打开 菜单项时 就会弹出文件选择对话框选择需要打开的文档 然后进行文档的打开工作 以上这过程在MFC中实现 它是由一系列函数组成的 为了让程序开发者对这个过程进行修改和控制 在以上这个操作过程中 应用了很多虚函数 在应用程序的当前类中 可以对基类中的这些虚函数进行重载 通过多态性而使MFC实现的标准操作过程执行当前类的虚函数 从而达到控制和修改MFC中已经实现的标准操作过程的目的 MFCClasswizard可以用来管理这些可以被重载的虚函数 重载虚函数 实例 在应用程序Draw的类CDrawDoc中重载一个虚函数OnOpenDocument 这个虚函数在打开文档操作时被MFC应用程序框架调用 通常是作为File Open命令操作的一部分 默认情况下 这个虚函数用来打开指定的文件 调用DeleteContents虚函数清空文档 调用虚函数Serialize读取文件的内容 现在我们用ClassWizard在当前文档类CDrawDoc中重载这个虚函数 使得程序在打开文档文件操作的同时 打开一个与当前文件名称相同 而后缀不同的文件 做为应用程序Draw运行时的临时文件 1 打开ClassWizard操作界面 在 ClassName 列表框中选择类CDrawDoc 在 ObjectIds 列表框中选择CDrawDoc项 2 在 Message 列表框列出的是类CDrawDoc能够得到的各种窗口消息和可重载的虚函数 从 Message 列表框选择虚函数OnOpenDocument 3 单击 AddFunction 按钮 按 EditCode 进行代码添加 4 在重载的OnOpenDocument函数中添加如下代码后 编译运行 FilePath lpszPathName 得到当前文档的名称intn FilePath Find 得到文件名中 的位置if n 0 如果当前的文档名称有后缀 去掉后缀FileName FilePa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公文最易错别字的
- 饿了外卖市场经理月工作总结
- 如何说课培训课件
- 2026届山东省海阳市美宝学校化学九年级第一学期期中质量跟踪监视试题含解析
- 教学查房的价值与意义
- 2026届贵州省施秉县化学九年级第一学期期末联考试题含解析
- SMT生产现场培训
- 南昌市南大附中2026届英语九上期末调研模拟试题含解析
- 2026届安徽省蚌埠市怀远县化学九年级第一学期期末教学质量检测模拟试题含解析
- 江苏省苏州市虎丘区立达中学2026届化学九年级第一学期期中质量跟踪监视模拟试题含解析
- 电焊工职业健康安全培训
- 采购比价询价管理办法
- DB50∕T 1604-2024 地质灾害防治边坡工程结构可靠性设计规范
- 歌曲《化蝶》教学课件
- 2024年黑龙江冰雪体育职业学院辅导员考试真题
- 乡镇卫生院医护人员培训计划
- 冲刺2025年高考政治大题突破-大题预测05 中国人民抗日战争80周年 (解析版)
- 《日本武士文化介绍:大学日语文化课程教案》
- 麻醉科病例汇报
- 供暖工程资料管理制度
- 八年级英语下学期期末考试(深圳专用)(解析版)
评论
0/150
提交评论