已阅读5页,还剩29页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Visual C+程序设计重庆科技学院Visual C+程序设计大作业专业班级: 学 号: 姓 名: 成 绩: 第1章 Win32程序设计和MFC程序设计1 Win32控制台程序设计和基于MFC的GUI程序设计特点1.1Win32控制台程序 控制台程序在Windows程序的角色中是非常强大且方便的,它没有复杂的GUI,完全是32位的程序,能够调用除GDI函数之外的API,支持多线路,支持MFC等。而汇编语言有着速度快和与硬件直接打交道的能力,其高质量的代码,较少的代码冗余,最快的运行速度,在某些方面有着突出的优势。所以Windows控制台程序的汇编语言写直接和硬件相关的控制台程序更能体现其性能的优越性。在Windows系统下,绝大多数应用程序都是图形窗口界面,程序的运行靠消息来驱动。在32位保护模式下工作的Windows可兼容以前16位保护模式下工作的DOS程序,Windows操作系统中保留了这种字符终端界面,如ipconfig程序和ping程序等。而采用了字符终端界面的好处是,在有些场合,用户对程序执行的界面要求不高,而更为关注的是程序的性能,次时程序员可以不用为提供友好的用户界面花费心思,而把精力投入到程序功能的实现上。Win32控制台程序使用标准的输入输出设备,支持命令行的重定向操作,也可以输出彩色的文本等。Win32控制台函数要求将控制台句柄作为第一个参数传递给它们,句柄是一个32位的无符号数据,用来唯一确定一个对象,如位图、画笔或某个输入输出设备等。Win32控制台是在保护模式下运行。Win32控制台使用的是Windows图形界面程序使用的那些库函数。Win32控制台是一种具有DOS界面的32位Windows程序,它不能在DOS环境下运行,同时它为字符模式应用程序提供了I/O借口,一个控制台有一个输入缓冲区和一个或多个屏幕缓冲区组成。Win32控制台有一个输入缓冲区,其中包括一个输入动作记录的队列,每个输入动作,如键盘敲击动作、鼠标移动或按键等都会在缓冲区中产生一个记录,ReadConsole等高级操作函数过滤并处理这些输入的数据,并且返回一个字符串。ReadConsole函数提供了将文本输入读取到一个缓冲区的便捷方法。 Win32控制台程序界面类: 头文件:windesign.h/划线类(专供windowDesigner.h使用) wndowDesigner.h/画界面类 其他要包含的cpp文件:questionwin.cpp windesign.cpp windowDesigner.cpp1.2 MFC的GUI程序设计MFC的GUI程序设计从涉及图形用户的框架结构及实现人机交互入手,体现了用C+语言进行图形用户界面设计的优越性。运用MFC进行界面菜单和对话框的设计,为平台实现提供了可视化环境;使用图片图像处理软件,为实现可视化美观设计,提供了一个良好的界面交互环境。MFC的GUI程序设计是实现界面可视化设计的核心,配合动态链接库实现界面设计。MFC的GUI程序设计是C+语言走向真正实用化,以及研究者实现进一步发展的基础。MFC的GUI程序设计使得界面设计不再是单纯的美术绘画,需要定位使用者、使用环境、使用方式。2程序设计概述2.1 Win32程序设计概述 Windows程序的进行是依靠外部发生的事件驱动。程序不断等待(利用一个while回路即while循环),等待任何可能的输入,然后作出判断,再做适当的处理。Windows是一个多任务的操作系统,也就是说,在Windows中可以有多个应用程序的实例正在运行。Windows时刻监视着用户的一举一动,并分析用户的动作与哪个应用程序相关,然后,将用户的动作以消息的形式发送给该应用程序,应用程序时刻等待着消息的到来,一旦发现它的消息队列中有未处理的消息,就获取并分析该消息,最后,应用程序根据消息所包含的内容采取适当的动作来相应用户所进行的操作。图1所示给出了一般的Windows应用程序的执行流程。图1 Windows应用程序的执行流程Windows程序分为“程序代码”和“UI资源”两大部分,这两部分最后用RC编译器整合为一个完整的EXE可执行文件,所谓UI资源是指功能选单、对话框外貌、程序图标、光标形状等。这些UI资源的实际内容是(二进位码)借助各种工具产生,并一各种扩展名存在,如.co、.bmp、.cur等。程序员必须在一个所谓的资源描述文档(.rc)中描述它们。在RC编译器(RC.EXE)读取RC文件的描述后,将所有UI资源集中,并制作出一个.RES文档,再与程序代码结合起来,这才是一个完整的Windows可执行文档。2.2 MFC程序设计概述 MFC类库包含了在一百多个程序开发中最常见的对象。在进行程序设计的时候,如果类库中的某个对象能完成所需要的功能,那么此时只要简单的调用已有对象的方法就行了。2.2.1 MFC特性l 封装特性:构成MFC框架的是MFC类库,而MFC类库是C+类库。这些类库封装了Win32应用程序编程接口、应用程序的概念、OLE特性、ODBC和DAO数据访问的功能等。l 继承特性:MFC抽象出众多类的共同特性,并设计出一些基类作为实现其它类的基础。这些类中,最重要的类是CDbject和CCmdTarget。程序员可结合实际,从适当的MFC类中派生出自己的类,实现特定的功能,达到编程的目的。针对每一种不同的对象,MFC都设计了一组类对这些对象进行封装,每一组类都有一个基类,从基类派生出众多更具体的类。这些对象主要包括:窗口对象,基类是CDnd;应用程序对象,基类是CWinThread;文档对象,基类是CDocument。l 虚拟和消息映射:MFC以“C+”为基础,支持虚拟函数。通过虚函数和消息映射,MFC类提供了丰富的编程借口。在程序员继承基类的同时,把自己实现的虚函数和消息处理函数嵌入MFC的编程框架中。MFC编程框架将在适当的时候 、适当的地方来调用程序的代码。2.2.2 MFC程序设计思想MFC实现了对应用程序概念的封装,把类类的继承、动态约束、类的关系和相互作用等封装起来,这样封装的结果是一套开发模板(或者说是模式)。这些模板都采用了以文档/视图为中心的思想,每一个模板都包含一组特定的类。下面我讲给出一个基于多文档的MFC实例。用AppWizard产生一个MDI工程Test,并创建了一系列文件,构成了一个应用程序框架。这些文件份4类:头文件(.h),实现文件(.cpp),资源文件(.rc),模块定义文件(.def)。MDI应用程序的组成如下图所示,其中箭头表示信息流向。 应用程序对象CWinApp文档模板对象CDocTemplate文档对象CDocument主边框窗口对象CMDIFrameWnd状态栏对象CStatusBar工具条对象CToolBar文档边框窗口对象CMDIChildWnd视对象CView图2 一个MFC MDI应用程序的构成该MDI应用程序的主体是从CwinApp、Cdocument、Cview、CMDIFrameWnd、CMDIChildWnd类对应地派生出CtestApp、CTestDoc、CTestView、CMainFrameWnd、CchildFrame5类,这5类的实例分别是应用程序对象、文档对象、视对象、主框架窗口对象和文档框架窗口对象。主框架窗口对象包含了视窗口、工具条和状态栏。2.3 MFC与Win32的关系MFC本身就是一个庞大的C+类库,这些类能较好地实现对Win32API的封装,为应用开发提供了极大的方便。同时,MFC依然支持Win32 API的直接调用,这样基于MFC的程序设计中可以像在Win32编程中一样直接使用API。另外,MFC除了对Win32 API实现封装外,同时还封装了OLE API、ODBC API等底层API函数的功能,如对Win32 API实现的封装类似,为开发人员提供更高一层的接口,大大简化了Windows编程。进一步来讲,MFC比较彻底的封装了Win32软件开发工具包(SDK)中的结构。功能,它为编程者提供了一个应用程序框架。3应用程序的工作原理3.1 MFC与Win32面向对象编程方式面向对象的编程方法具有封装、继承和多态三个特征以使它和其他编写方法相区别。封装对外界屏蔽数据好热过程实现的内部细节,而继承和多态则可以大大简化编程的工作量。3.1.1 Win32面向对象编程方式Win32编写采用的是面向对象的编写方法,如:OOP,Object Oriented Programming。在Win32中,程序的基本单位不是过程和函数,而是窗口。一个窗口是一组数据以及处理这些数据的窗口函数的集合。Win32程序的执行过程本身就是窗口等对象的创建、处理和消亡的过程。Win32中消息的发送可以理解为一个窗口对象请求服务的过程。由于Win32应用程序的复杂性,从图形用户界面到整个应用程序,都是采用面向对象的方法组织的。Win32中的对象可以是所有的规范部件,如窗口、菜单、工具栏、按钮、文本框、以及程序模块等。从用户的观点看,Win32应用程序有一个窗口,窗口上有若干菜单、命令按钮、图标等界面图形元素;而窗口背后是一些对应的程序。Win32系统给每个对象分配一个“句柄”(handle),它是一个4字节长的整数值,是对象的唯一内部编号。应用程序通过句柄访问相应的对象。每个对象除了句柄外,还有一个对象标识符ID,可看作是对象的外部名。ID与句柄的区别主要在于:ID可以是用户自行设定的;而句柄是系统内定的,对用户是透明的,这能防止应用程序直接访问对象的内部信息。3.1.2 MFC与Win32面向对象编程方式从MFC的面向对象模型看,一个Win32应用程序可以拆分成许多功能独立的对象,各自负责不同类型的工作,其最基本的构成对象可以分为两大类:程序对象和窗口对象。一个应用程序的执行就像一场舞台演出。应用程序对象是幕后人员(导演、剧务等),它们负责安排并指挥“演员”(窗口)上场,准备和调度各种演出“资源”(如菜单、工具栏、图标等)。从操作系统来看,具有“法人”地位的是应用程序对象而非窗口对象,应用程序可以占有CPU时间和内存空间,还可拥有演出所需的“资源”。3.2窗口对象窗口是应用程序基本的操作单元,应用程序的运行过程即是窗口内部、窗口与窗口之间、窗口与系统之间进行数据处理与交换的过程。3.2.1 Win32应用程序窗口对象在Win32应用程序中,除了应用程序对象外,另一个重要的对象就是窗口对象。在基于Windows API的应用程序中,通常通过调用RegsiterClass来注册窗口类及调用CreateWindow创建基于那个类的窗口来创建它的主窗口。 在windows程序先调用API函数(CreateWindow)产生窗口之前,我们先要把窗口的属性设定好,如窗口的“外貌”和“行为”,外貌就是一个窗口的边框、颜色、标题、位置等等,行为就是接受消息后的反应(具体就是窗口函数)。注册窗口的API函数是MyRegisterClass。然后调用CreateWindow产生窗口。为了显示窗口,要调用函数ShowWindow。为了驱动窗口的绘图操作,调用UpdateWindow函数,传送一个WM_PAINT给窗口。 窗口函数通常利用switch/case方式判断消息的种类,来决定处理的方式,它被设计为一种call back 函数。被Windows系统调用。LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) Win32应用程序中,窗口函数是采用switch/case的机制来处理消息相应的。3.2.2 MFC应用程序窗口对象在一个应用程序中,除了应用程序对象外,另一个重要的对象就是窗口对象。在基于Windows API的应用程序中,通常通过调用RegsiterClass来注册窗口类及调用CreateWindow创建基于那个类的窗口来创建它的主窗口。MFC程序通过创建一个窗口类对象的方式来创建窗口。在示例程序中,通过如下的语句来创建窗口:m_pMainWnd=new CMainWnd(); new操作符创建对象,对象的构造函数创建应用程序的窗口。用new返回的指针可用于访问对象的成员函数。在示例程序中,CMainWnd类的说明如下:class CMainWnd:public CFrameWnd/类CFrameWnd的派生类CMainWnd的定义public:CMainWnd(); /派生类CMainWnd的定义protected:afx_msg void OnPaint(); /重画消息处理函数DECLARE_MESSAGE_MAP() /声明类CMainWnd将对消息进行处理; CMainWnd类的基类是CFrameWnd,CFrameWnd类本身又是从CWnd类派生出来的。CFrameWnd类收缩了类CWnd的定义,以便包含用作SDI应用程序的主窗口。CMainWnd构造函数只包含两条语句,即创建一个字符串对象和对窗口对象的Create函数的调用:CMainWnd:CMainWnd() /类CMainWnd的构造函数CString WndClass=AfxRegisterWndClass( /注册窗口类CS_HREDRAW|CS_VREDRAW, /指定窗口风格NULL, /指定窗口中所使用的光标(HBRUSH):GetStockObject(LTGRAY_BRUSH), /指定画刷LoadIcon(AfxGetInstanceHandle(),DemoIcon)/指定代表应用程序的图标 ); Create(WndClass,一个简单的应用程序 );Create函数用来创建框架窗口,它是由CFrameWnd定义的。它的主要功能就是创建一个窗口对象。关于窗口的各个属性可以通过传递给函数Create的各个参数来控制。3.3应用程序对象 与Win32应用程序相比较,每一个MFC程序都必须有且只有一个有CWinApp派生的类对象。基于MFC的应用程序其核心是应用程序对象,它的类是由MFC的CWinApp类派生的。具体地讲就是上例中的CMyApp类。在CWinApp类中提供了一些用于初始化应用程序,保存程序设置到磁盘文件之类的公用应用层操作。MFC应用程序有且只有一个应用程序对象,且该对象必须用全局作用域来说明,因此它将在应用程序一开始就被创建。上面的的MFC应用程序从CWinApp派生出一个类,并用创建应用程序的主窗口的某个类重载InitInstance成员函数。上面的程序中派生的应用程序类称为CMyApp,并且定义该类的对象MyApp为全局对象:class CMyApp:public CWinApp / CWinApp 派生/类CMyApp的定义 public:BOOL InitInstance(); /派生类中对基类InitInstance函数的重载;CMyApp MyApp; /声明类CMyApp的对象 一个应用程序的生存周期中只调用InitInstance函数一次,对这个函数的调用刚好在应用程序开始之后,但在应用程序的窗口显示之前。事实上,除非在InitInstance函数中实现创建窗口的操作,否则应用程序就没有窗口。函数UpdateWindow完成创建的窗口的更新操作,它实际上是执行一个强迫重新绘制窗口的操作。由于WinMain函数的执行依赖于应用程序对象,因此在WinMain函数的执行前应用程序对象必须要在内存中存在。 在应用程序启动后,由MFC供给的WinMain调用命名为AfxWinInit的函数来初始化应用程序框架。AfxWinInit的任务包括将传递到WinMain的hInstance,hPrevInstance,lpCmdLine及nCmdShow的参数复制到应用程序对象的成员中,并定义几个预定义的窗口类。如果hPrevInstance是NULL值,WinMain就调用应用程序对象的InitApplication函数。由于hPrevInstance在Win32 环境下总是NULL,因此32位的MFC应用程序能用InitApplication初始化它本身,正像InitInstance一样容易。如果AfxWinInit、InitApplication 和InitInstance函数中的任何一个返回0,则表示程序执行过程中出现了一个错误,这时WinMain就调用AfxWinTerm去消除,然后用一个返回语句终止。只有在所有的这些函数都返回TRUE时,WinMain函数才执行下一个关键步骤。调用应用程序对象的Run函数,对这个函数的调用将开始应用程序的消息循环,当发现消息循环队列空时就调用函数OnIdle进入空闲杂务的处理。消息循环直到WM_QUIT消息传给队列为止。此时,Run从循环中中端,调用ExitInstance并返回到WinMain。WinMain函数通过调用AfxWinTerm函数来清除分配给应用程序的资源和释放内存空间。在AfxWinTerm函数执行完成后,整个应用程序也就结束了。4 应用程序结构4.1主函数4.1.1 Win32应用程序主函数所有的Windows应用程序都有主函数WinMain,为了与DOS C程序的主函数名称相区别,Win32应用程序的主函数名称为WinMain. WinMain函数的原型为:Int WINAPI WinMain( HINSTANCE hInstance, /当前应用程序实例的句柄 HINSTANCE hPrevInstance, /前一个应用程序实例的句柄 LPSTR lpCmdLine, /指向本程序命令的指针 Int nCmdShow, /决定应用程序窗口显示方式的标志 );函数名前面的关键字WINAPI表明这个函数是一个由系统调用的函数。主函数共有两个任务是创建应用程序窗口和建立消息循环。主函数至少要调用七个API函数,其中四个用来创建显示应用程序窗口,三个用来建立消息循环。l 窗口类型:一个窗口只能有一个窗口函数,但多个窗口可以工业一个窗口函数。l 注册窗口类型:注册RegisterClass()把定义好的窗口属性向系统进行登记。RegisterClass()函数原型为:BOOL RegisterClass(WNDCLASS&wc);l 创建窗口:程序使用API函数CreateWindow()来创建窗口。创建窗口成功之后,函数返回窗口的句柄,如果应用函数使用该窗口,该句柄应保存在实现dingy的句柄变量中。l 显示窗口:调用CreateWindow()函数在内存中创建窗口之后,还应用如下两个函数,将窗口显示在计算机显示屏上。 BOOL UpdateWindow( HWND hWnd, /窗口句柄 Int nCmdShow /窗口的显示方法 ); 和 BOOL UpdateWindow( HWND hWnd /窗口句柄 );l 消息循环:窗口一旦创建并显示,应用程序的初始化及告完工,随后便是程序的消息循环部分。while(GetMessage(&msg,NULL,NULL,NULL) TranslateMessage(&msg); DispatchMessage(&msg); /把消息派送给系统4.1.2 MFC应用程序主函数MFC把主函数WinMain函数封装起来,隐藏在应用程序的基本框架内部,在应用程序启动时会调用 WinMain函数完成注册注册窗口等功能。在运行用户的应用程序时,程序的首要框架首先取得控制权,做一些程序的初始化工作。然后构造应用程序类的对象,每一个MFC程序都必须有且只有一个有CWinApp派生的类对象。当创建完所有的的静态和全局对象后,调用入口函数WinMain。WinMain函数首先获得指向应用程序类对象的指针;然后进行初始化工作;接着调用应用程序类的Run函数,运行程序的消息循环,完成函数功能;最后调用应用程序类的ExitInstance函数结束程序,删除注册的窗口,释放内存等。MFC程序运行的流程图见图3。WinMain()InitInstance()Run()ExitInstance()调用调用调用图3 MFC程序运行流程图 在MFC程序代码头文件中共有5个头文件类型:1)FirstMFC.h,FirstMFC.cpp:用户程序的应用类CFirstMFC的头文件和源代码文件,该类由CWinApp类派生;2)FirstMFCDoc.h,FirstMFCDoc.cpp:用户程序的文件档CFirstMFCDoc的头文件和源代码文件,该类由CDocument类派生;3)FirstMFCView.h,FirstMFCView.cpp:用户程序的视图档CFirstMFC的头文件和源代码文件,该类由CView类派生;4)MainFrm.h,MainFrm.cpo:用户程序的主框架窗口类CMainFrm的头文件和源代码文件;5)ChildFrm.h,ChildFrm.cpp:用户程序的主框架窗口类CChildFrm的头文件和源代码文件。4.2程序资源分离4.2.1 Win32程序资源分离在Win32应用程序中,向菜单、对话框、位图、光标等可视的对象都被从代码中分离出来,这些资源都放在资源文件中资源文件中,资源编译器编译这些并将他们存储在应用程序中,这样大大简化了用户界面的设计。另外,Windows使用一个称之为句柄的标识符来引用其环境中的每一个对象,比如窗口、内存块、文件、光标、位图等等。句柄是非常方便的数字标识符,用于标识系统已经分配给Windows应用程序的资源。4.2.2 MFC程序资源分离 MFC提供了文档/视图模型以实现数据和现实的分离。文档类(Dcument)用来维护、管理数据,包括数据的读取、存储与修改;视图类(View)用来接收显示数据,将这些数据交给文档类来处理。 在文档/视图结构中,MFC文档对象将数据读入或写入永久存储区,并提供数据驻留位置的接口。而一个视图对象可以管理数据显示,包括在窗口中显示数据。编辑数据等。MFC可以利用文档/视图结构使用一个单独的视图对象表示每个数据视图,还可以使用文档对象同时更新所有试图。MFC文档/视图将数据结构的存储与维护同其是分开的,图4显示了文档与视图的关系。文档视图当前可见的文档视图图4 文档与视图的关系 文档/视图结构类的各自主要作用:1)文档用于管理应用程序的数据;2)视图的主要作用是以图形方式显示文档数据,以及接收用户的输入并将其解释为对文档的操作;3)MFC框架使用框架窗口来包含视图,框架窗口提供了用于环绕视图的可见框架(菜单、最小化和最大化窗口等),使用窗口框架类管理框架,使用视图类管理框架中的视图,用户与文档之间的交互操作发生在视图的客户区内,而不是框架窗口的客户区内;4)框架使用了两个文档模板类用于管理创建文档及关联的视图和框架窗口的复杂过程,由应用程序对象创建文档模板,由文件模板创建文档和框架窗口,而由框架窗口创建文档的对应视图。5. 消息机制的架构5.1 MFC消息管理机制l 标准的Windows消息:所有以WM_为前缀的消息都是标准的Windows消(WM_COMMAND消息除外),如WM_PAINT、WM_QUIT等,这些消息通常含有用于确定如何对消息进行处理的一些参数。标准的Windows 消息一般由窗口对象和视图对象进行处理。l 控件消息:使用唯一ID号来进行标识,使用控件类来操纵。例如,当用户对编辑框中的文本进行修改时,编辑框将发送给父窗口一条包含控件通知码EN_CHANGE的WM_COMMAND消息。窗口的消息处理函数将以某种适当的方式对通知消息作出响应,如检索编辑框中的文本。与其他标准的Windows消息一样,控件消息也是由窗口对象和视图对象进行处理。l 命令消息:命令消息主要包括由用户界面对象发送的ON_COMMAND消息,用户界面对象是指菜单、工具栏、快捷键等。它和控件消息的区别在于:控件消息只能由特定控件向Windows系统传送,而命令消息是由用户界面发送的,它可以被更多的对象处理。在文档对象、视图对象、窗体对象、控件对象中都能处理这种消息。5.2消息处理程序 首先,定义消息ID:#define WM_MY_MESSAGE (WM_USER+100) /定义自已的消息;然后,定义消息处理函数: afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);接着,建立消息和消息处理函数之间的映射:ON_MESSAGE(WM_MY_MESSAGE,CtestMessageDlg:OnMyMessage);最后,编写消息处理函数: LRESULT CtestMessageDlg:OnMyMessage(WPARAM wParam, LPARAM lParam) . /上述代码为消息处理函数的具体实现5.2.1消息循环函数WindowProc处理MFC默认的系统消息,用户可以自定义新的消息及消息响应函数。消息处理程序WindowProc主要完成对分发来的信息的处理工作。函数WindowProc的定义如下:LRESULT CWnd:WindowProc(UINT message,WPARAM wparam,LPARAM lparam) switch(message) case.: break; case.: break; default.: break; MFC应用程序消息循环中存在空闲处理机制,即应用程序在没有消息可以处理时,进行空闲处理,等待消息的到来。在处理完一个消息或进入消息循环时,如果消息队列中没有消息要处理,则应用程序执行一次空闲处理。空闲处理由函数OnIdle完成,其原型为BOOL OnIdle(LONG lCout)。参数的含义是当空闲处理周期已经完成了多少次OnIdle调用后,空闲处理函数第一次调用时,该参数设为1,此后每调用一次加1.返回值表示当前空闲处理周期是否继续调用函数OnIdle,返回TRUE表示仍需要执行空闲处理,返回FASLEA则表示消息队列中有消息要处理,当前的空闲处理周期结束后不再执行空闲处理。5.2.2消息的发送l 函数SendMessage():用于向一个或多个窗口传送消息,该函数将调用目标窗口的窗口函数,直到目标窗口处理完收到的息,该函数才返回。l 函数PostMessage():用于向一个或多个窗口传送消息,它把消息放在窗口创建的线程的消息队列中,然后不等消息处理完就返回。l 函数SendDlgItemMessage():用于向对话框中指定的控件发送消息,直到目标控件处理完收到的消息,该函数才返回。5.2.3消息映射 MFC库提供了自动处理功能。MFC的框架结构通过消息映射机制,将Windows消息直接映射到一个成员函数进行处理,简化了消息的处理方式,即MFC提供的消息处理机制使得消息的处理更加容易。 MFC采用了消息映射(message map)的机制来处理消息。这种消息机制包括一组消息映射宏,一条消息映射宏把一个windows消息和其消息处理函数联接起来: BEGIN_MESSAGE_MAP(CLessonView, CView) / 标准打印命令 ON_COMMAND(ID_FILE_PRINT, &CView:OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT,&CView:OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW,&CView:OnFilePrintPreview) END_MESSAGE_MAP()通过消息映射,由Windows操作系统传送到应用程序的WM_PAINT消息转换成了对函数CMainWnd:OnPaint的调用。实际上,消息映射是使消息与处理这些消息的成员函数发生联系的一种表。从CCmdTarget派生的任何类都可能包含一个消息映射。对于每一个需要处理的消息,用户需要写一个类的成员函数,并将一个相应的输出项添加到类的消息映射上。系统将负责在消息到达时,适当的成员函数得到调用。建立对消息的处理的第一步是添加成员函数去处理它们。准备应用程序去接收和处理消息的第二步是用消息映射把消息和消息处理程序连接在一起。包含对消息进行处理的每一个类必须声明对消息的处理,这可以通过宏命令DECLARE_MESSAGE_MAP( )来实现。一般都在类定义的结尾处调用DECLARE_MESSAGE_MAP( )来声明该类将对消息进行处理。因此,对消息进行处理的类声明时一般具有下面的形式:class CMyWnd : public CFrameWnd /成员声明 DECLARE_MESSAGE_MAP( ); 在运行程序时,这些通过DECLARE_MESSAGE_MAP( )宏命令加入的成员能使MFC确定是否给定的类可以处理特定的消息。并且,如果可能的话,还可以获取消息处理函数的地址。当一个消息到达时,如果预期的类中没有相应的消息处理函数,MFC就检查基类的消息映射,直到找到能处理该消息的类,如果所有的类都不处理这个消息,那么这个消息就发送给函数DefWindowProc进行处理。 在声明了类对消息的处理后,还必须建立具体的消息和类成员函数之间的连接。 宏命令的参数分别标识消息映射的类和其基类。MFC需要知道进行消息映射的类的基类,这样它才能成功地传递未处理的消息。消息输入项宏命令用来标识类将在BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()之间处理的消息。示例程序中只指定类CMainWnd处理消息ON_WM_PAINT。每一个消息输入项都将向_messageEntries数组中添加一个数组元素。调用宏命令END_MESSAGE_MAP()表示数组_messageEntries的结束。5.3消息处理程序5.3.1 Win32的一个特殊数据结构句柄 Win32使用的一个唯一的整数值,是4字节长的数值,用于标识应用程序中不同的对象和同类对象中不同的实例。在Win32应用程序中,存在着诸如窗口、按钮、图标、滚动条等复杂的程序对象和实例。为了在程序中分别和使用它们,必须对它们进行标识。不同Win32对象的句柄具有不同的类型。5.3.2窗口函数 Win32应用程序,必须有一个“窗口函数”来处理各种消息,它是完成用户任务的核心,也是需要程序员编写大量代码的地方。该函数的定义为:LRESULT CALLBACK WndProc(HWND hwnd, /派送消息的窗口句柄 UINT message, /系统传递来的消息标识 WPARAM wParam, /消息的附加参数(32位) LPARAM lparam /消息的附加参数(32位) ) 在主函数中定义窗口类型是,必须把这个窗口函数的名称赋给WNDCLASS结构的域lpfnWndProc。5.3.3消息循环系统为每一个应用程序都建立了一个叫做消息队列的存储空间,在程序的运行过程中如果发生了一个事件,Windows就会把这个时间所对应的消息送入消息列队等待使用。应用程序可以通过调用Windows提供的API函数GetMessage()从消息列队中获取消息。并利用GetMessage()函数的返回值(当获取消息时,该函数返回TRUE,否则返回FALSE)组织一个循环,从而不断从消息队列获取消息,一旦获取了一个消息,就把这个消息发送给系统。在Windows应用程序中,消息循环的代码如下:while(GetMessage(&msg,NULL,NULL,NULL) TranslateMessage(&msg); DispatchMessage(&msg); /把消息派送给系统函数TranslateMessage()用来把键盘消息转化为字符信息,当函数DispatchMessage()把消息派送给系统后,系统会根据消息的hwnd找到应该接受消息的程序窗口并根据窗口提供信息,以消息为参数来调用一个用户编写的“窗口函数”的函数,以消息中的消息标识message为依据查找并执行该消息所对应的程序段,对消息进行处理。5.3.4消息的传输在Windows中,从消息的传递途径上来看,消息大体上分为两种:一种是先把消息送达消息列队,然后由应用程序的消息循环通过函数DispatchMessage()获取并通过系统发送给窗口,这类型消息叫做列队消息,鼠标和键盘消息问列对消息;另一种消息则不经过消息列队而直接送到窗口,这类型消息叫做非列队消息,系统事件产生的消息一般为非列队消息。Win32系统把用户应用程序分割成两部分:一个是以消息循环为主的获取和发送消息的部分;另一个是专门处理消息的窗口函数部分。鼠标、键盘等事件事件转化为消息系统消息列队进程消息对列窗口消息应用程序的信息循环while(GetMessage)TranslateMessage(&msg);DispatchMessage(&msg); 应用程序用于处理消息的窗口进程非队列消息图5 事件及其消息的传递过程5.4.5消息处理函数 Win32应用程序在某种意义上是面对对象的,用户采用“选择对象-操作对象”的方式进行工作。Win32应用程序采取基于事件的消息驱动运行机制,即Win32应用程序通过相应Windows消息来处理事件。事件是系统产生的动作,事件通过消息进行描述和标识。事件驱动是程序设计围绕事件或消息产生驱动运行处理函数。消息是描述事件发生的信息。在window系统中,程序的执行顺序完全取决于时间的发生顺序。这就使得程序的运行不是由事件的顺序来控制,而是由事件的发生来控制。时间的发生是随机的、不确定的,这就允许了用户用各种合理的顺序来安排程序的流程。这种面向用户的程序设计,更多考虑了用户可能的各种操作,程序员可以有针对性地设计相应的处理程序。 事件的驱动模式是一种“被动”的程序设计模型,程序一开始运行就处于等待用户输入的状态,取得事件后作出相应反应,处理完毕又返回等待时间的状态。 Win32应用程序是按照“事件消息处理”的运行机制。当有某个事件(如单击鼠标、键盘输入和执行菜单命令)等发生时,Win32会根据具体的事件产生相对应的消息,并发送到指定应用程序的消息队列,应用程序从消息队列中取出消息,并根据不同的消息进行处理。接受并处理消息的主角就是窗口。每一个窗口都应该有一个处理消息的函数,就是消息处理函数。6 MFC与Win32程序设计优缺点 最初,面向对象程序设计的提出是为了解决传统程序设计方法结构化程序设计所不能解决的代码重复问题。结构化程序设计依程序功能为中心,应用程序由如干功能模块组成,随着用户需求的变化和软、硬件技术的发展,结构化的应用程序就显得缺乏灵活性和稳定性,代码重用性很低。面向对象程序设计以数据为中心,采用对象来描述问题,使问题的共性得以抽象,从而大大提高了代码的可重用性。具有相同操作和属性的对象集合被称为类,不同的操作和属性可以通过不同的类来表示。直接针对Windows API进行程序设计有一定难度,且工作量较大。MFC类库的一个最重要的特点就是实现了对Windows API的封装,使得Windows应用程序开发更加建明快捷。此外,MFC应用程序框架,为Windows应用程序停工了标准化的结构,用户只需向框架内添加实现特殊功能的代码,而不必担心框架程序的编写。MFC的这一特性在为用户带来巨大方便的同时,也使基于MFC的Windows应用程序更为清晰,代码更为高效。MFC作为微软基础类库,是用来编写Windows应用程序的C+类集,它具备了面向对象程序设计的主要特征:抽象、继承和封装。MFC的重要特征之一就是它实现了对Windows API的封装,从而避免了对复杂的Windows API函数的直接操作,大大简化了应用程序的编写。此外,MFC还实现了对应用程序概念、COM/OLE特性、ODBC功能的封装。 MFC最大的优点在于它是Win32应用程序开发的宏观框架体系。MFC通过对应用程序概念等一系列的封装,形成了应用程序开发的模板,如单文件应用程序的模板、多文件应用程序的模板扩展DLL应用程序的模板、OLE/ACTIVEX应用程序的模板等。这些模板都是基于文档视图结构,每一个模板都包含一组特定的类。框架体系的存在使得用户可以不必考虑标准Wind32应用程序框架的细节设计,而把主要的精力放在程序的功能扩展上,极大地缩短了程序的开发周期。MFC以高效简洁的方式为编程者做了所有标准部分的工作,特别是编程者可以在不需要写一行代码的情况下完成一个完整的应用程序框架(约需千行代码)。MFC中包含了成千上万行功能强大的、经过优化的Win32程序代码。编程者只要定义了某个类的对象,就可以调用该类的成员函数,轻轻松松完成本该由你自己一行行编写的程序代码。从这点上说,MFC极大地降低了程序开发难度。下面我们分别利用Win32和MFC程序设计了一个关于个人的信息(姓名、年龄和工资)的输入、存储、显示、消息机制的架构、主函数的特点、数据与显示方法的分离、数据的保存等等。详见附录1和附录2。图6 Win32程序设计显示图图7 MFC程序设计显示图第2章 模式对话框与非模式对话框1对话框1.1模式对话框模式对话框显示时,将阻碍主线程的执行,直到对话框被关闭。例如,程序中弹出的消息对话框,如果用户不点击“确定”或“取消”按钮关闭对话框,将无法操作程序。下面介绍模式对话框的创建及显示。模式对话框就是在不处理它时,就没法处理父窗口,例如:在桌面上右击我的电脑,选择属性,弹出系统属性窗口,点击下面的技术支持,弹出技术支持信息,现在再对系统属性窗口进行操作就操作不了,这种叫做模式对话框。 首先为模式对话框声明一个对象,然后调用该对象的DoModal方法进行显示,要关闭模式对话框可以调用CDialog类的OnOK方法或OnCancel方法。l DoModal方法:该方法用于创建并显示一个模式对话框。该方法返回一个整数值,该数值可以应用于EndDialog方法。如果方法返回值为-1,表示没有创建模式对话框;如果为IDABORT,表示有其他错误发生。语法:virtual int DoModal( );l OnOK方法:该方法在用户单击“OK”按钮(按钮ID为IDOK)时调用,OnOK方法在内部调用了EndDialog方法,因此,用户单击“OK”按钮时会关闭对话框。通常情况下,用户需要改写该方法,禁止调用基类的OnOK方法。语法:virtual int OnOK( );l OnCancel方法:当用户在对话框中单击“Cancel”按钮或按键,框架将自动调用OnCancel方法。语法:virtual int OnCancel( );其中,DoModal方法是一个虚拟方法,用户可以改写该方法,实现自己的动作。默认情况下,DoModal方法在内部调用EndDialog方法。如果用户在一个非模式对话框中实现DoModal方法,需要在内部调用DestroyWindow方法,不要调用基类的OnCancel方法,因为它调用EndDialog方法将使对话框不可见,但不销毁对话框。创建并显示模式对话框的代码如下:CResDlg dlg;dlg.DoModal( );关闭模式对话框的代码如下:CDialog:OnOK( );/或CDialog:OnCancel( );1.2非模式对话框非模式对话框类似于普通的窗口,在显示时不会影响其他路线处理消息。非模态对话框的在创建完后程序可以继续执行,对话框可以成为后台对话框,所以也可以用函数来关闭 。非模式对话框的显示和模式对话框不同,显示非模式对话框要先调用CDialog类的DestroyWin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026浙江舟山市海洋经济发展局下属事业单位招聘1人笔试参考试题及答案详解
- 2026年伊春市新青区中小学编制教师招聘笔试参考题库及答案详解
- 泸州航空发展投资集团有限公司下属四川焜仑投资管理有限公司2026年第二次社会公开招聘考试备考试题及答案详解
- 2026北京市大兴区庞各庄镇面向社会招聘第四次全国农业普查人员14人参考题库及完整答案详解(名师系列)
- 2026西南石油大学计算机与软件学院科研助理招用2人模拟试卷(全优)附答案详解
- 2026福建晋江经济开发区社区卫生服务中心劳务派遣工作人员招聘5人笔试备考试题及答案详解
- 2026浙江舟山群岛新区甬舟海洋发展有限公司招聘1人笔试题库(预热题)附答案详解
- 招2人!盐湖资源绿色高值利用重点实验室科研助理招聘参考题库及完整答案详解【有一套】
- 甘孜州民生人力资源管理有限公司 见习工作人员招聘(2人)笔试备考题库及答案详解
- 攀枝花市中西医结合医院2026年医疗卫生辅助岗位招募笔试参考试题及答案详解
- 2026海南省海洋与渔业科学院招聘事业编制人员4人(第1号)笔试参考试题及答案详解
- 2026年无菌操作技术考核试题及答案
- 2026入伍军检面试题目及答案
- 2026学年甘肃省陇南市三年级数学期末深度自测实战演练题(附答案)详细答案和解析
- 2026浙江省杭州市萧山区区长电话受理中心招聘重点基础提升(共500题)附带答案详解
- 《昆虫记》全阅读测试题及答案
- 2026年兰石化企业考核笔综合提升练习题及答案详解(考点梳理)
- 2026年人教版初一政治(道德与法治)下学期期末考试试卷及答案(共七套)
- 2024年7天连锁酒店员工手册
- 2026年湖北省黄冈市八年级地理生物会考真题试卷(+答案)
- 循环流化床锅炉(CFB炉)设计计算大纲
评论
0/150
提交评论