MFC深入浅出-完整版ljj

所需积分/C币:10 2018-02-23 11:09:58 1.76MB PDF
收藏 收藏
举报

MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作:AppWizard可以用来生成初步的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用户接口;ClassWizard用来协助添加代码到框架文件;最后,
对不同的应用和目的,程序员采用不同的模板。例如,SDI应用程序的模板,MDI应用程 序的模板,规则DIL应用程序的模板,扩展DLL应用程序的模板, OLE/ACTIVEX应用程 序的模板,等等 这些模板都采用了以文档-视为中心的思想,每一个模板都包含一组特定的类。典型的MDI 应用程序的构成将在下节具体讨论 为了支持对应用程序概念的封装,MFC内部必狈作大量的工作。例如,为了实现消息映射 机淛,MFC编程框架必须要保证首先得到消息,然后按既定的方法行处理。又如,为了 实现对DLL编程的支持和多线程编程的支持,MFC内部使用了特别的处理方法,使用模块 状态、线稈状态等来管理一些重要信息。虽然,这些内部处理对程序员来说是透明的,但是, 懂得和理解MFC内部机制有助于写出功能灵活而强大的程序。 总之,MFC封装」Win32API, OLE API, ODBC API等底层函数的功能,并提供更高一层 的接口,简化了 Windows编程。同时,MFC支持对底层API的直接调用 MFC提供了个 Windows应用程序开发模式,对程序的控制主要是由MFC框架完成的, 而且MFC也完成了人部分的功能,预定义或实现了许多事件和消息处理,等等。框架或者 由其本身处理事件,不依赖程序员的代码;或者调用程序员的代码米处理应用程序特定的事 件 MFC是C++类库,程序员就是通过使用、继承和护展适当的类来实现特定的目的。例如, 继承时,应用程序特定的事件由程序员的派生类来处理,不感兴趣的由基类处理。实现这种 功能的基础是C++对继承的支持,对虚拟函数的支持,以及MFC实现的消息映射机制。 12MD应用程序的构成 本节解释个典型的MD应用程序的构成 月 App wizard产生一个MDI工程t(无OLE等支持), App wizard创建了一系列文件,构成 了一个应用程序框架。这些文件分四类:头文件(h),实现文件(cpp),资源文件(rc),模 块定义文件(deD),等 构成应用程序的对象 图1-1解释了该应用程序的结构,箭头表小信息流向。 主边框窗口对索 MB正a 立用程序对家 winAnt 工具条对象 ToolBar 文档模板对象 CDocT'errplate 文档边窗口对录 hDIChidfrarme 文档对家 视对象 CView 状态栏对家 图1一~MDI应用和序的构成 从 CWinApp、 CDocument、CⅤiew、 CMDIFrameWnd、 CMDIChildwnd类对应地派出 TAPp、 CTOc、 CVIew、 MAin frame、 CChildframe五个类,这五个类的实例分别是应用程序对 象、文档对象、视对象、主框架窗口对象和文档边框窗口对象。主框架窗口包含了视窗口、 工具条和状态栏。对这些类或者对象解释如下 (1)应用程序 应用程序类派牛于 CWinApp。基于框架的应用程序必须有且只有一个应用程序对象,它负 责应用程序的初始化、运行和结束。 (2)边框窗口 如果是SDI应用程序,从 CFramc Wnd类派生边框窗口类,边框窗口的客户子窗口( MDIClient) 直接包含视窗口;如果是MDI应用程序,从 CMDIFrame wnd类派生边框窗口类,边框窗 口的客户子窗口( MDIClient)直接包含文档边框窗口。 如果要支持工具条、状态栏,则派生的边框窗凵类还要添加 TOolbar和 STatus bar类型的 成员变量,以及在一个 On create消息处理函数中初始化这两个控制窗口。 边框窗口用来管理文档边框窗口、视窗口、工具条、菜单、加速键等,协调半模式状态(如 上下文的帮助( SHIFT+F1模式)和打印预览) (3)文档边框窗口 文档边框窗凵类从 CMDIChildwnd类派生,MDl应用程序使用文档边框窗凵米包含视窗凵。 (4)文档 文档类从¢ Document类派生,用来管理数据,数据的变化、存取都是通过文档实现的。视 窗∏通过文档对象来访问和更新数据。 (5)视 视类从 CView或它的派生类派生。视和文档联系在一起,在文档和用户之间起中介作用, 即视在屏幕上显示文档的内容,并把用户输入转换成对文档的操作。 (6)文档模板 文档模板类一股不需要派生。M)用程序使用多文档模板类 CMultiDoc Template;SD应 用程序使用单文档模板类 CSingleDoc Template。 应用程序通过文档模板类对象来管理上述对象(应用程序对象、文档对象、主边框窗口对象 文档边框窗口对象、祧对象)的创建。 构成应用程序的对象之间的关系 这里,用图的形式可直观地表小所涉及的MFC类的继承或者派生关系,如图1-2所小意 CObject CCmdTarget CWinThread CD ocTemplte CDoCument W坦d CWinApp CFrameWnd CY CCantrolBar CSingiedocterrmate iDIframew'nd COntro上at CMultiDocTemplate 工IC1dwd Statusbar 图1-2—些MFC芙的层次 图1-2所示的类都是从 Cobject类派生出来的;所有处理消息的类都是从 CCmdTarget类派 生的。如果是多文档应用程序,文档模板使用 CMultiDoc Temple,主框架窗凵从 CMdifarme Wnd派生,它包含工具条、状态栏和文档框架窗口。文档框架窗口从 CMdichildwnd派生,文档框架窗口包含视,视从CⅤicw或其派生类派生。 构成应用程序的文件 通过上述分析,可知 App Wizard产生的MD框架程序的内容,所定义和实现的类。下面, 从文件的角度来考察 App wizard生成了哪些源码文件,这些文件的作用是什么。表1-1列出 了 App wizard所牛成的头文件,表1-2列出了了 App wizard所牛成的实现文件及其对头文 件的包含关系。 表1-1 App wizard所生成的头文件 头文件 用途 stdafx. h标准AFX头文件 resource. h定义了各种资源ID t h include" resource. h 定义了从 CWinApp派的应用程序对象 TAPp childfrm.h定义了从 CMDIChildWnd派的文档框架窗口对象 CTChildframe mainfrm h定义了从 CMDIFrame Wnd派生的框架窗口对象 MAin frame tdoc. h 定义了从 CDocument派生的文档对象 CTOc view. h 定义了从CⅤiew派生的视图对象 CVIew 表1-2 App wizard所生成的实现文件 实现文件 所包含的头文件 实现的内容和功能 stdafx. cpp #include stdafx h 用米产生预编译的类型信息 t.cpp includc "stdafx. h" 定义 CTApp的实现,并定义 TAPp类 H include"Ch 型的全局变量 theapp f include "Main Frm. h #include "tdoc. h' #includc "tvicw h childfrm. cpp finlcude"stdafx. h 实现了类 CChildframe #include th" Include“ childern.h” childfrm. cpp finlcude stdafx h 实现了类 MAinframe #include "th" #include"childfrm. h' tdoc. cpp #f include stdafx. h' 实现了类 CTOC include " t f include tdoc. h view.cpp tf include stdafx. h" 实现了类 CView include ". h" include tdoc. h #f include "tview, h 从衣1-2中的包含关系栏可以看出 CAPp的实现用到所有的用户定义对象,包含了他们的定义; CView的实现用到 CToc; 其他对象的实现只涉及自己的定义 当然,如果增加其他操作,引用其他对象,则要包含相应的类的定义文件 对预编译头文件说明如下 所谓头文件预编译,就是把个工程( Project中使用的些MFC标准头文件(如 Windows.h AfxwinH)预先编译,以后该工程编译时,不雨编译这部分头文件,仅仅使用预编译的结果。 这样可以加快编译速度,节省时间 预编译头文件通过编译 stdafx. cpp生成,以工程名命名,由于预编译的头文件的后缀是¨pch'’, 所以编译结果文件是 dHID rojcctnamc pch mmhttiEDc 屈作①DC的~含撒编译器通过个头文件 tdafx h来使用预编详头文 indIC 件。 stdafx. h这个头文件名是 可以在 projecl的编译设置里 用①C的沒撒定的。编泽器认为,所有 CDC 在指令# include" 'stdafx. h"前 的代码都是预编译的,它跳 222和隔bD的过 ncludc"tdax.h指令 使用 projectname. pch编译这 条指令之后的所有代码 因此,所有的CPP实现文件第一条语句都是:# include" stdafx h"。 另外,每一个实现文件CPP都包含了如卜语句: #ifdcf DEBUG #undef this file static char BASED CODE THIS FILEd- FILe 并 endif 这是表示,如果生成调试版木,要指示当前文件的名称。FILE是一个宏,在编译器编 译过稈中给它赋值为当前正在编译的文件名称。 和 21 MfC Object和 Windows object的关系 MHC中最重要的封装是对win32API的封装,因此,理解 Windows object和 MFC Object(C 对象,一个C艹+类的实例)之间的关系是理解MFC的关键之一。所谓 Windows objecL ( Windows对象)是win32下用句柄表示的 Windows操作系统对象;所谓 MFC Object(MFC 对象)是C++对象,是个C++类的实例,这里(本书范围内) MFC Object是有特定含义的, 指封装 Windows Object的C++ Object,并非指任意的C++ Object MFC Object和 Windows Object是不一样的,但两者紧密联系。以窗口对象为例: 一个MFC窗口对象是一个C++CWnd类(或派生类)的实例,是程序直接创建的。在程序 执行中它随着窗口类构造睬数的调用而牛成,随着析构函数的调用而消失。而 Windows窗 ∏则是 Windows系统的个内部数据结构的实例,由个“窗∏句柄标识, Windows系统 创建它并给它分配系统资源。 Windows窗口在MFC窗口对象创建之后,由CWnd类的 Create 成员函数创建,“窗口句柄”保存在窗口对象的 m hWnd成员变量中。 Windows窗口可以被 个程序销毁,也可以被用户的动作销毁。MFC窗口对象和 Windows窗口对象的关系如图 2-1所示。其他的 Windows Object和对应的 MFC Object有类似的关系。 下面,对 MFC Object和 Windows object作一个比较。有些论断对设备描述表(MC类是CDC, 句村是HDC)可能不适用,但具体涉及到时会指出。 从数据结构上比较 MFC Object是相应CH类的实例,这些类是MFC或者程序员定义的 Windows Object是 Windows系统的内部结构,通过一个句枘来引用; MFC给这些类定义了一个成员变量来保存 MFC Object对应的 Windows Object的句柄。对 于设各描述衣CDC类,将保存两个HDC句柄 从层次上讲比较 MFC Object是高层的, Windows Object是低层的; MFC Object封装了 Windows object的大部分或全部功能, MFC Object的使用者不需要直接 应用 Windows Object的 HANDLE句柄)使用Win32API,代替它的是引用相应的 MFC Object 的成员函数。 从创建上比较 MFC Object通过构造函数由程序直接创建; Windows Object由相应的SDK函数创建 MFC中,使用这些 MFC Object,般分两步: 首先,创建一个 MFC Object,或者在 STACK中创建,或者在HEAP中创建,这时, MFC Object 的句柄实例变量为空,或者说不是一个有效的句柄。 然后,调用 MFC Object的成员函数创建相应的 Windows object,MFC的句枘变量存储一个 有效句柄 CDC(设备描述表类)的创建有所不同,在后面的23节会具体说明CDC及其派生类的创建和 使用。 当然,可以在 MFC Object的构造函数中创建相应的 Windows对象,MHC的GDl类就是如 此实现的,但从实质上讲, MFC Object的创建和 Windows objecl的创建是两回事。 从转换上比较 可以从个 MFC Object得到对应的 Windows Object的句柄;般使用 MFC Object的成员 函数 Get Safehandle得到对应的句柄 可以从一个已存在的 Windows object创建一个对应的 MFC Object:一般使用 MFC Object 的成员函数Auch或者 Fromhandle来创建,前者得到一个永久性对象,后者得到的可能是 一个临时对象。 从使用范围上比较 MFC Object对系统的其他进程来说是不可见、不可用的:而 Windows Object一且创建,其 句柄是整个 Windows系统全局的。一些句柄可以被其他进程使用。典型地,一个进程可以 获得另·进程的窗∏句柄,并给该窗∏发送消息 对同一个进程的线程来说,只可以使用本线程创建的 MFC Object,不能使用其他线程的MFC 从销毁上比较 MFC Object随着析构函数的调用而消失;但 Windows Object必须由相应的 Window系统函 数销毁 设备描述表CDC类的对象有所不同,它对应的HDC句柄对象可能不是被销毁,而是被释 放 当然,可以在 MFC Object的析构函数中完成 Windows Object的销毁, MFC Object的GDl 类等就是如此实现的,但是,应该看到:两者的销毁是不同的 每类 Windows object都有对应的 MFC Object,下面用衣格的形式列出它们之间的对应关系, 如表2-1所示: 表2-1 MFC Object和 Windows Object的对应关系 描述 Windows句柄 MFC Object 窗口 HWND CWnd and CWnd-derived classes 设备上下HDC CDC and CDc-derived classes 文 菜单 HMENU CMenu 笔 HEN CGdiobject类,CPen和 CPen-derived classes 刷子 HBRUSH CGdiobject类, CBrush和 CBrush- derived 字体 HFONT CGdiobject类, CFont和 CFont-derived classes 位图 HBITMAP CGdiobject类, CBitmap和 CBitmap- derived 调色板 hPaleTte CGdiObject CPalette TH CPalette-derived classes 区域 HRGN CGdiobject类,CRgn和CRgn- derived classes 图像列表 himagelist CimageList和 CimageList-derived classes 套接字 SOCKET CSocket, CAsyn Socket及其派生类 表2-1中的 OBJECT分以下几类: Windows对象, 设备上下文对象, GDI Xf (BITMAP, BRUSH, FONT, PALETTE, PEN, RGN) 菜单, 图像列表, 网络套接字接口 从广义上来看,文档对象和文件可以看作一对 MFC Object和 Windows Object,分别用 CDocument类和文件句柄描述 后续几节分别对前四类作一个简明扼要的论述。 2.2. Windows object 用SDK的win32API编写各种 Windows应用程序,有其共同的规律:首先是编写 Winmain 凶数,编写处理消息和事件的窗凵过程 WndProc,在 Winmain里头注册窗凵( Register Window),创建窗口,然后开始应用程序的消息循环。 MFC应用程序也不例外,因为MFC是一个建立在 SDK API基础上的编程框架。对程序员 来说所不同的是:一般情况下,MFC框架自动完成了 Windows登记、创建等工作。 面,简要介绍 MFC Window对 Windows window的封装 的注册 一个应用程序在创建某个类型的窗口前,必须首先注册该“窗口类( Windows Class)注意 这里不是C类的类。 Register Window把窗口过程、窗口类型以及其他类型信息和要登记 的窗口类关联起来。 “窗口类”的数据结构 窗凵类”是 Windows系统的数据结构,可以把它理解为 Windows系统的类型定义,而 Windows窗口则是相应“窗口类”的实例。 Windows使用一个结构来描述“窗口类”,其定义如 typedef struct WNDCLASSEX uint cbSize;∥该结构的字节数 UINT style;/口类的风格 WNDPROC lpfn WndProc;/窗口过程 int cbClsextra int cb dextra hANDLE hInstance;∥该窗口类的窗口过程所属的应用实例 hICON hIcon;∥该窗口类所用的像标 HCURSOR cUrsor;∥该窗口类所用的光标 HBRUSH hbr Background:∥该窗口类所用的背景刷 LPCTSTR lpszMenuName,∥该窗∏类所用的菜单資源 LPCTSTR lpsz Class Name;该窗口类的名称 hiCON hIcon Sm;∥该窗口类所用的小像标 B WNDCLASSEX; 从“窗口类”的定义可以看出,它包含了一个窗口的重要信息,如窗口风格、窗口过程、显示 和绘制窗∏所需要的信息,等等。关于窗冂过程,将在后面消息映射等有关章节作详细论述。 Windows系统在初始化时,会注册( Register)些全局的“窗口类”,例如通用控制窗口类。应 用程序在创建自己的窗口时,首先必须注册自己的窗口类。在MFC环境下,有几种方法可 以用来注册“窗口类”,卜面分别予以讨论。 调用 AfxRegisterClass注册 AfxRegisterClas函数是MC全局函数。 AfxRegister Class的函数原型: BOOL AFXAPI AfxRegisterClass(WNDCLASS "lp Wndclass 参数 IpWndClass是指向 WNDCLASS结构的指针,表示一个“窗口类” 首先, AfxRegister Class检查希望注册的“窗冂类”是否已经注册,如果是则衣示已注册,返 回TRUE,否则,继续处理。 接着,调用: Register Class(lp Wndclass注册窗山类; 然后,如果当前模块是DLL模块,则把注册“窗口类”的名宇加入到模块状态的域 m sz. UnrcgistcrList中。该域是一个固定长度的缓汁区,依次存放模块注册的“窗口类”的名字 (每个名字是以“nO0”结尾的字符串)。之所以这样做,是为了DLL退出时能自动取消 Unregister它注册的窗口类。至于模块状态将在后面第9章详细的讨论。 最后,返回TRUE表示成功注册。

...展开详情
试读 127P MFC深入浅出-完整版ljj
立即下载 低至0.43元/次 身份认证VIP会员低至7折
抢沙发
一个资源只可评论一次,评论内容不能少于5个字
  • 分享达人

    成功上传6个资源即可获取
关注 私信 TA的资源
上传资源赚积分,得勋章
最新推荐
MFC深入浅出-完整版ljj 10积分/C币 立即下载
1/127
MFC深入浅出-完整版ljj第1页
MFC深入浅出-完整版ljj第2页
MFC深入浅出-完整版ljj第3页
MFC深入浅出-完整版ljj第4页
MFC深入浅出-完整版ljj第5页
MFC深入浅出-完整版ljj第6页
MFC深入浅出-完整版ljj第7页
MFC深入浅出-完整版ljj第8页
MFC深入浅出-完整版ljj第9页
MFC深入浅出-完整版ljj第10页
MFC深入浅出-完整版ljj第11页
MFC深入浅出-完整版ljj第12页
MFC深入浅出-完整版ljj第13页
MFC深入浅出-完整版ljj第14页
MFC深入浅出-完整版ljj第15页
MFC深入浅出-完整版ljj第16页
MFC深入浅出-完整版ljj第17页
MFC深入浅出-完整版ljj第18页
MFC深入浅出-完整版ljj第19页
MFC深入浅出-完整版ljj第20页

试读结束, 可继续阅读

10积分/C币 立即下载 >