收藏 分享(赏)

MFC微软基础类库.doc

上传人:hyngb9260 文档编号:4684494 上传时间:2019-01-07 格式:DOC 页数:45 大小:424.85KB
下载 相关 举报
MFC微软基础类库.doc_第1页
第1页 / 共45页
MFC微软基础类库.doc_第2页
第2页 / 共45页
MFC微软基础类库.doc_第3页
第3页 / 共45页
MFC微软基础类库.doc_第4页
第4页 / 共45页
MFC微软基础类库.doc_第5页
第5页 / 共45页
点击查看更多>>
资源描述

1、微软基础类库(英语:Microsoft Foundation Classes,简称 MFC)是一个微软公司提供的类库(class libraries),以 C+类的形式封装了 Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量 Windows 句柄封装类和很多 Windows 的内建控件和组件的封装类。中文名微软基础类库外文名MicrosoftFoundationClasses简 称MFC类 型C/C+的图形化界面语言开发者微软特 点效率损失低目录1 定义2MFC和 Win321定义编辑MFC(MicrosoftFoundationClass

2、es)是微软基础类库的简称,是微软公司实现的一个 c+类库,主要封装了大部分的 windows API 函数,vc+是微软公司开发的 c/c+的集成开发环境,所谓集成开发环境,就是说利用它你可以编辑,编译,调试,而不是使用多种工具轮换操作,灵活性较大。有时人们说 vc 呢也指它的内部编译器,集成开发环境必须有一个编译器内核,要不有什么用,例如 DevC+其中一个编译器内核就是 gcc。 MFC 除了是一个类库以外,还是一个框架,你应该试过,在 vc+里新建一个 MFC 的工程,开发环境会自动帮你产生许多文件,同时它使用了 mfcxx.dll。xx 是版本,它封装了 mfc 内核,所以你在你的代

3、码看不到原本的SDK 编程中的消息循环等等东西,因为 MFC 框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率但是 MFC 的封装很浅,所以效率上损失不大。2MFC和 Win32 编辑MFC Object 和 Windows Object 的关系MFC 中最重要的封装是对 Win32 API 的封装,因此,理解 Windows Object 和 MFC Object (C+对象,一个 C+类的实例)之间的关系是理解 MFC 的关键之一。所谓 Windows Object( Windows

4、 对象)是 Win32 下用句柄表示的 Windows 操作系统对象;所谓 MFC Object (MFC 对象)是 C+对象,是一个 C+类的实例,这里(本书范围内)MFC Object 是有特定含义的,指封装 Windows Object 的 C+ Object,并非指任意的 C+ Object。MFC Object 和 Windows Object 是不一样的,但两者紧密联系。以窗口对象为例:一个 MFC 窗口对象是一个 C+ CWnd 类(或派生类)的实例,是程序直接创建的。在程序执行中它随着窗口类构造函数的调用而生成,随着析构函数的调用而消失。而 Windows 窗口则是 Windo

5、ws 系统的一个内部数据结构的实例,由一个 “窗口句柄” 标识,Windows 系统创建它并给它分配系统资源。Windows 窗口在 MFC 窗口对象创建之后,由 CWnd 类的 Create 成员函数创建,“窗口句柄”保存在窗口对象的 m_hWnd 成员变量中。Windows 窗口可以被一个程序销毁,也可以被用户的动作销毁。MFC 窗口对象和 Windows 窗口对象的关系如图 2-1 所示。其他的 Windows Object 和对应的 MFC Object 也有类似的关系。下面,对 MFC Object 和 Windows Object 作一个比较。有些论断对设备描述表 (MFC 类是C

6、DC,句柄是 HDC)可能不适用,但具体涉及到时会指出。从数据结构上比较MFC Object 是相应 C+类的实例,这些类是 MFC 或者程序员定义的;Windows Object 是 Windows 系统的内部结构,通过一个句柄来引用;MFC 给这些类定义了一个成员变量来保存 MFC Object 对应的 Windows Object 的句柄。对于设备描述表 CDC 类,将保存两个 HDC 句柄。从层次上讲比较MFC Object 是高层的, Windows Object 是低层的;MFC Object 封装了 Windows Object 的大部分或全部功能, MFC Object 的使用

7、者不需要直接应用 Windows Object 的 HANDLE(句柄)使用 Win32 API,代替它的是引用相应的 MFC Object 的成员函数。从创建上比较MFC Object 通过构造函数由程序直接创建;Windows Object 由相应的 SDK 函数创建。MFC 中,使用这些 MFC Object,一般分两步:首先,创建一个 MFC Object,或者在 STACK 中创建,或者在 HEAP 中创建,这时,MFC Object 的句柄实例变量为空,或者说不是一个有效的句柄。然后,调用 MFC Object 的成员函数创建相应的 Windows Object,MFC 的句柄变量

8、存储一个有效句柄。CDC(设备描述表类) 的创建有所不同,在后面的 2.3 节会具体说明 CDC 及其派生类的创建和使用。当然,可以在 MFC Object 的构造函数中创建相应的 Windows 对象,MFC 的 GDI 类就是如此实现的,但从实质上讲,MFC Object 的创建和 Windows Object 的创建是两回事。从转换上比较可以从一个 MFC Object 得到对应的 Windows Object 的句柄;一般使用 MFC Object 的成员函数 GetSafeHandle 得到对应的句柄。可以从一个已存在的 Windows Object 创建一个对应的 MFC Obje

9、ct; 一般使用 MFC Object 的成员函数 Attach 或者 FromHandle 来创建,前者得到一个永久性对象,后者得到的可能是一个临时对象。从使用范围上比较MFC Object 对系统的其他进程来说是不可见、不可用的;而 Windows Object 一旦创建,其句柄是整个 Windows 系统全局的。一些句柄可以被其他进程使用。典型地,一个进程可以获得另一进程的窗口句柄,并给该窗口发送消息。对同一个进程的线程来说,只可以使用本线程创建的 MFC Object,不能使用其他线程的MFC Object。从销毁上比较MFC Object 随着析构函数的调用而消失;但 Windows

10、 Object 必须由相应的 Windows 系统函数销毁。设备描述表 CDC 类的对象有所不同,它对应的 HDC 句柄对象可能不是被销毁,而是被释放。当然,可以在 MFC Object 的析构函数中完成 Windows Object 的销毁,MFC Object 的GDI 类等就是如此实现的,但是,应该看到:两者的销毁是不同的。每类 Windows Object 都有对应的 MFC Object,下面用表格的形式列出它们之间的对应关系,如表 2-1 所示:表 2-1 MFC Object 和 Windows Object 的对应关系描述Windows 句柄 MFC Object窗口 HWND

11、 CWnd and CWnd-derived classes设备上下文 HDC CDC and CDC-derived classes菜单 HMENU CMenu笔 HPEN CGdiObject 类,CPen 和 CPen-derived classes刷子 HBRUSH CGdiObject 类,CBrush 和 CBrush-derived classes字体 HFONT CGdiObject 类,CFont 和 CFont-derived classes位图 HBITMAP CGdiObject 类,CBitmap 和 CBitmap-derived classes调色板 HPALET

12、TECGdiObject 类,CPalette 和 CPalette-derived classes区域 HRGN CGdiObject 类,CRgn 和 CRgn-derived classes图像列表 HimageLIST CimageList 和 CimageList-derived classes套接字 SOCKET CSocket,CAsynSocket 及其派生类表 2-1 中的 OBJECT 分以下几类:Windows 对象,设备上下文对象,GDI 对象(BITMAP ,BRUSH,FONT ,PALETTE,PEN,RGN),菜单,图像列表,网络套接字接口。从广义上来看,文档对

13、象和文件可以看作一对 MFC Object 和 Windows Object,分别用CDocument 类和文件句柄描述。后续几节分别对前四类作一个简明扼要的论述。Windows Object用 SDK 的 Win32 API 编写各种 Windows 应用程序,有其共同的规律:首先是编写WinMain 函数,编写处理消息和事件的窗口过程 WndProc,在 WinMain 里头注册窗口(Register Window),创建窗口,然后开始应用程序的消息循环。MFC 应用程序也不例外,因为 MFC 是一个建立在 SDK API 基础上的编程框架。对程序员来说所不同的是:一般情况下,MFC 框架

14、自动完成了 Windows 登记、创建等工作。下面,简要介绍 MFC Window 对 Windows Window 的封装。Windows 的注册一个应用程序在创建某个类型的窗口前,必须首先注册该“窗口类 ”(Windows Class)。注意,这里不是 C+类的类。Register Window 把窗口过程、窗口类型以及其他类型信息和要登记的窗口类关联起来。“窗口类” 的数据结构“窗口类” 是 Windows 系统的数据结构,可以把它理解为 Windows 系统的类型定义,而Windows 窗口则是相应“窗口类 ”的实例。Windows 使用一个结构来描述“ 窗口类”,其定义如下:type

15、def struct _WNDCLASSEX UINT cbSize; /该结构的字节数UINT style; /窗口类的风格WNDPROC lpfnWndProc; /窗口过程int cbClsExtra;int cbWndExtra;HANDLE hInstance; /该窗口类的窗口过程所属的应用实例HICON hIcon; /该窗口类所用的像标HCURSOR hCursor; /该窗口类所用的光标HBRUSH hbrBackground; /该窗口类所用的背景刷LPCTSTR lpszMenuName; /该窗口类所用的菜单资源LPCTSTR lpszClassName; /该窗口类的

16、名称HICON hIconSm; /该窗口类所用的小像标 WNDCLASSEX;从“窗口类” 的定义可以看出,它包含了一个窗口的重要信息,如窗口风格、窗口过程、显示和绘制窗口所需要的信息,等等。关于窗口过程,将在后面消息映射等有关章节作详细论述。Windows 系统在初始化时,会注册 (Register)一些全局的“窗口类” ,例如通用控制窗口类。应用程序在创建自己的窗口时,首先必须注册自己的窗口类。在 MFC 环境下,有几种方法可以用来注册“窗口类”,下面分别予以讨论。调用 AfxRegisterClass 注册AfxRegisterClass 函数是 MFC 全局函数。AfxRegiste

17、rClass 的函数原型:BOOL AFXAPI AfxRegisterClass(WNDCLASS *lpWndClass);参数 lpWndClass 是指向 WNDCLASS 结构的指针,表示一个“ 窗口类”。首先,AfxRegisterClass 检查希望注册的“窗口类”是否已经注册,如果是则表示已注册,返回 TRUE,否则,继续处理。接着,调用:RegisterClass(lpWndClass)注册窗口类;然后,如果当前模块是 DLL 模块,则把注册“窗口类”的名字加入到模块状态的域m_szUnregisterList 中。该域是一个固定长度的缓冲区,依次存放模块注册的“ 窗口类”的

18、名字(每个名字是以“n0”结尾的字符串)。之所以这样做,是为了 DLL 退出时能自动取消(Unregister)它注册的窗口类。至于模块状态将在后面第 9 章详细的讨论。最后,返回 TRUE 表示成功注册。调用 AfxRegisterWndClass 注册AfxRegisterWndClass 函数也是 MFC 全局函数。AfxRegisterWndClass 的函数原型:LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,HCURSOR hCursor, HBRUSH hbrBackground, HICON hIcon)参数 1 指定窗口

19、类风格;参数 2、3、4 分别指定该窗口类使用的光标、背景刷、像标的句柄,缺省值是 0。此函数根据窗口类属性动态地产生窗口类的名字,然后,判断是否该类已经注册,是则返回窗口类名;否则用指定窗口类的属性(窗口过程指定为缺省窗口过程),调用AfxRegisterCalss 注册窗口类,返回类名。动态产生的窗口类名字由以下几部分组成(包括冒号分隔符):如果参数 2、3、4 全部为 NULL,则由三部分组成。“Afx”+“:”+模块实例句柄 ”+“:”+“窗口类风格”否则,由六部分组成:“Afx”+“:”+模块实例句柄 +“:”+“窗口类风格”+“:”+光标句柄+“:”+背景刷句柄+“:”+像标句柄。

20、比如:“Afx:400000:b:13de:6:32cf”。该函数在 MFC 注册主边框或者文档边框“窗口类”时被调用。具体怎样用在 5.3.3.3 节会指出。隐含的使用 MFC 预定义的的窗口类MFC4.0 以前的版本提供了一些预定义的窗口类,4.0 以后不再预定义这些窗口类。但是,MFC 仍然沿用了这些窗口类,例如:用于子窗口的“AfxWnd”;用于边框窗口(SDI 主窗口或 MDI 子窗口)或视的“AfxFrameOrView”;用于 MDI 主窗口的“AfxMDIFrame”;用于标准控制条的“AfxControlBar”。这些类的名字就 是“AfxWnd”、“AfxFrameOrVi

21、ew”、“AfxMdiFrame”、 “AfxControlBar”加上前缀和后缀(用来标识版本号或是否调试版等)。它们使用标准应用程序像标、标准文档像标、标准光标等标准资源。为了使用这些“窗口类”,MFC 会在适当的时候注册这些类:或者要创建该类的窗口时,或者创建应用程序的主窗口时,等等。MFC 内部使用了函数BOOL AFXAPI AfxEndDeferRegisterClass(short fClass)来帮助注册上述原 MFC 版本的预定义“窗口类”。参数 fClass 区分了那些预定义窗口的类型。根据不同的类型,使用不同的窗口类风格、窗口类名字等填充 WndClass 的域,然后调用

22、AfxRegisterClass 注册窗口类。并且注册成功之后,通过模块状态的 m_fRegisteredClasses 记录该窗口类已经注册,这样该模块在再次需要注册这些窗口类之前可以查一下m_fRegisteredClasses,如果已经注册就不必浪费时间了。为此,MFC 内部使用宏AfxDeferRegisterClass(short fClass)来注册“窗口类”,如果 m_fRegisteredClasses 记录了注册的窗口类,返回 TRUE,否则,调用 AfxEndDeferRegisterClass 注册。注册这些窗口类的例子:MFC 在加载边框窗口时,会自动地注册“AfxFr

23、ameOrView”窗口类。在创建视时,就会使用该“窗口类” 创建视窗口。当然,如果创建视窗口时,该“窗口类” 还没有注册,MFC 将先注册它然后使用它创建视窗口。不过,MFC 并不使用”AfxMDIFrame”来创建 MDI 主窗口,因为在加载主窗口时一般都指定了主窗口的资源,MFC 使用指定的像标注册新的 MDI 主窗口类(通过函数AfxRegisterWndClass 完成,因此“ 窗口类”的名字是动态产生的)。MDI 子窗口类似于上述 MDI 主窗口的处理。在 MFC 创建控制窗口时,如工具栏窗口,如果“AfxControlBar”类还没有注册,则注册它。注册过程很简单,就是调用:In

24、itCommonControl 加载通用控制动态连接库。调用:RegisterWndClass。直接调用 Win32 的窗口注册函数:RegisterWndClass 注册“窗口类” ,这样做有一个缺点:如果是 DLL 模块,这样注册的“窗口类”在程序退出时不会自动的被取消注册(Unregister)。所以必须记得在 DLL 模块退出时取消它所注册的窗口类。子类化子类化(Subclass )一个“窗口类” ,可自动地得到它的“窗口类 ”属性。MFC 窗口类 CWnd在 Windows 系统里,一个窗口的属性分两个地方存放:一部分放在“窗口类” 里头,如上所述的在注册窗口时指定;另一部分放在 W

25、indows Object 本身,如:窗口的尺寸,窗口的位置(X,Y 轴),窗口的 Z 轴顺序,窗口的状态(ACTIVE,MINIMIZED,MAXMIZED,RESTORED),和其他窗口的关系(父窗口,子窗口),窗口是否可以接收键盘或鼠标消息,等等。为了表达所有这些窗口的共性,MFC 设计了一个窗口基类 CWnd。有一点非常重要,那就是 CWnd 提供了一个标准而通用的 MFC 窗口过程,MFC 下所有的窗口都使用这个窗口过程。至于通用的窗口过程却能为各个窗口实现不同的操作,那就是 MFC 消息映射机制的奥秘和作用了。这些,将在后面有关章节详细论述。CWnd 提供了一系列成员函数,或者是对

26、 Win32 相关函数的封装,或者是 CWnd 新设计的一些函数。这些函数大致如下。(1)窗口创建函数这里主要讨论函数 Create 和 CreateEx。它们封装了 Win32 窗口创建函数:CreateWindowEx。Create 的原型如下:BOOL CWnd:Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,const RECT得到窗口像标GetDlgItem( int nID);得到窗口类指定 ID 的控制子窗口GetDC(); 得到窗口的设备上下文SetMenu(CMenu *pMenu); 设置

27、窗口菜单GetMenu();得到窗口菜单(4)用于完成窗口动作的函数用于更新窗口,滚动窗口,等等。一部分成员函数设计成或可重载(Overloaded)函数,或虚拟(Overridden)函数,或 MFC 消息处理函数。这些函数或者实现了一部分功能,或者仅仅是一个空函数。如:有关消息发送的函数:SendMessage( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );给窗口发送发送消息,立即调用方式PostMessage( UINT message,WPARAM wParam = 0, LPARAM lParam = 0 );给窗口发送消息

28、,放进消息队列有关改变窗口状态的函数MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );移动窗口到指定位置ShowWindow(BOOL );显示窗口,使之可见或不可见.实现 MFC 消息处理机制的函数:virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam ); 窗口过程,虚拟函数virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam );处理命令消息消息处理函数:OnCreate( LPCREATESTRU

29、CT lpCreateStruct );MFC 窗口消息处理函数,窗口创建时由MFC 框架调用OnClose();MFC 窗口消息处理函数,窗口创建时由 MFC 框架调用其他功能的函数CWnd 的导出类是类型更具体、功能更完善的窗口类,它们继承了 CWnd 的属性和方法,并提供了新的成员函数(消息处理函数、虚拟函数、等等)。常用的窗口类及其层次关系见图 1-1。在 MFC 下创建一个窗口对象MFC 下创建一个窗口对象分两步,首先创建 MFC 窗口对象,然后创建对应的 Windows窗口。在内存使用上,MFC 窗口对象可以在栈或者堆(使用 new 创建) 中创建。具体表述如下:创建 MFC 窗口

30、对象。通过定义一个 CWnd 或其派生类的实例变量或者动态创建一个 MFC窗口的实例,前者在栈空间创建一个 MFC 窗口对象,后者在堆空间创建一个 MFC 窗口对象。调用相应的窗口创建函数,创建 Windows 窗口对象。例如:在前面提到的 AppWizard 产生的源码中,有 CMainFrame(派生于CMDIFrame(SDI)或者 CMDIFrameWnd(MDI))类。它有两个成员变量定义如下:CToolBar m_wndToolBar;CStatusBar m_wndStatusBar;当创建 CMainFrame 类对象时,上面两个 MFC Object 也被构造。CMainFr

31、ame 还有一个成员函数OnCreate(LPCREATESTRUCT lpCreateStruct),它的实现包含如下一段代码,调用 CToolBar 和 CStatusBar 的成员函数 Create 来创建上述两个 MFC 对象对应的工具栏 HWND 窗口和状态栏 HWND 窗口:int CMainFrame:OnCreate(LPCREATESTRUCT lpCreateStruct)if (!m_wndToolBar.Create(this) |!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)TRACE0(“Failed to create toolb

32、arn“);return -1; / fail to createif (!m_wndStatusBar.Create(this) |!m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)TRACE0(“Failed to create status barn“);return -1; / fail to create关于工具栏、状态栏将在后续有关章节作详细讨论。在 MFC 中,还提供了一种动态创建技术。动态创建的过程实际上也如上所述分两步,只不过 MFC 使用这个技术是由框架自动地完成整个过程的。通常框

33、架窗口、文档框架窗口、视使用了动态创建。介于 MFC 的结构,CFrameWnd 和 CView 及其派生类的实例即使不使用动态创建,也要用 new 在堆中分配。理由见窗口的销毁(2.2.5 节)。至于动态创建技术,将在下一章具体讨论。在 Windows 窗口的创建过程中,将发送一些消息,如:在创建了窗口的非客户区(Nonclient area)之后,发送消息 WM_NCCREATE;在创建了窗口的客户区(client area)之后,发送消息 WM_CREATE;窗口的窗口过程在窗口显示之前收到这两个消息。如果是子窗口,在发送了上述两个消息之后,还给父窗口发送 WM_PARENATNOTIF

34、Y 消息。其他类或风格的窗口可能发送更多的消息,具体参见 SDK 开发文档。MFC 窗口的使用MFC 提供了大量的窗口类,其功能和用途各异。程序员应该选择哪些类来使用,以及怎么使用他们呢?直接使用 MFC 提供的窗口类或者先从 MFC 窗口类派生一个新的 C+类然后使用它,这些在通常情况下都不需要程序员提供窗口注册的代码。是否需要派生新的 C+类,视 MFC 已有的窗口类是否能满足使用要求而定。派生的 C+类继承了基类的特性并改变或扩展了它的功能,例如增加或者改变对消息、事件的特殊处理等。主要使用或继承以下一些 MFC 窗口类(其层次关系图见图 1-1):框架类 CFrameWnd,CMdiF

35、rameWnd ;文档框架 CMdiChildWnd;视图 CView 和 CView 派生的有特殊功能的视图如:列表 CListView,编辑 CEditView,树形列表 CTreeView,支持 RTF 的 CRichEditView,基于对话框的视 CFormView 等等。对话框 CDialog。通常,都要从这些类派生应用程序的框架窗口和视窗口或者对话框。工具条 CToolBar状态条 CStatusBar其他各类控制窗口,如列表框 CList,编辑框 CEdit,组合框 CComboBox,按钮 Cbutton等。通常,直接使用这些类。在 MFC 下窗口的销毁窗口对象使用完毕,应该

36、销毁。在 MFC 下,一个窗口对象的销毁包括 HWND 窗口对象的销毁和 MFC 窗口对象的销毁。一般情况下,MFC 编程框架自动地处理了这些。(1)对 CFrameWnd 和 CView 的派生类这些窗口的关闭导致销毁窗口的函数 DestroyWindow 被调用。销毁 Windows 窗口时,MFC 框架调用的最后一个成员函数是 OnNcDestroy 函数,该函数负责 Windows 清理工作,并在最后调用虚拟成员函数 PostNcDestroy。CFrameWnd 和 CView 的 PostNcDestroy 调用delete this 删除自身这个 MFC 窗口对象。所以,对这些窗

37、口,如前所述,应在堆(Heap)中分配,而且,不要对这些对象使用delete 操作。(2)对 Windows Control 窗口在它们的析构函数中,将调用 DestroyWidnow 来销毁窗口。如果在栈中分配这样的窗口对象,则在超出作用范围的时候,随着析构函数的调用,MFC 窗口对象和它的 Windows window 对象都被销毁。如果在堆(Heap )中分配,则显式调用 delete 操作符,导致析构函数的调用和窗口的销毁。所以,这种类型的窗口应尽可能在栈中分配,避免用额外的代码来销毁窗口。如前所述的CMainFrame 的成员变量 m_wndStatusBar 和 m_wndTool

38、Bar 就是这样的例子。(3)对于程序员直接从 CWnd 派生的窗口程序员可以在派生类中实现上述两种机制之一,然后,在相应的规范下使用。后面章节将详细的讨论应用程序退出时关闭、清理窗口的过程。设备描述表设备描述表概述当一个应用程序使用 GDI 函数时,必须先装入特定的设备驱动程序,然后为绘制窗口准备设备描述表,比如指定线的宽度和颜色、刷子的样式和颜色、字体、剪裁区域等等。不像其他Win32 结构,设备描述表不能被直接访问,只能通过系列 Win32 函数来间接地操作。如同 Windows“窗口类” 一样,设备描述表也是一种 Windows 数据结构,用来描述绘制窗口所需要的信息。它定义了一个坐标

39、映射模式、一组 GDI 图形对象及其属性。这些 GDI 对象包括用于画线的笔,绘图、填图的刷子,位图,调色板,剪裁区域,及路径(Path)。表 2-2 列出了设备描述表的结构和各项缺省值,表 2-3 列出了设备描述表的类型,表 2-4显示设备描述表的类型。表 2-2 设备描述表的结构属性 缺省值 Background colorBackground color setting from Windows Control Panel (typically, white)Background modeOPAQUE Bitmap None Brush WHITE_BRUSH Brush origin(

40、0,0) Clipping regionEntire window or client area with the update region clipped, as appropriate. Child and pop-up windows in the client area may also be clipped Palette DEFAULT_PALETTE Current pen position(0,0) Device originUpper left corner of the window or the client area Drawing modeR2_COPYPEN Fo

41、nt SYSTEM_FONT (SYSTEM_FIXED_FONT for applications written to run with Windows versions 3.0 and earlier) Intercharacter spacing0 Mapping modeMM_TEXT Pen BLACK_PEN Polygon-fill modeALTERNATE Stretch modeBLACKONWHITE Text color Text color setting from Control Panel (typically, black) Viewport extent(1

42、,1) Viewport origin(0,0) Window extent(1,1) Window origin(0,0) 表 2-3 设备描述表的分类Display 显示设备描述表,提供对视频显示设备上的绘制操作的支持Printer 打印设备描述表,提供对打印机、绘图仪设备上的绘制操作的支持Memory 内存设备描述表,提供对位图操作的支持Information 信息设备描述表,提供对操作设备信息获取的支持表 2-3 中的显示设备描述表又分三种类型,如表 2-4 所示。表 2-4 显示设备描述表的分类名称 特点 功能Class DeviceContexts提供对 Win16 的向后兼容Co

43、mmonDeviceContexts在 Windows 系统的高速缓冲区,数量有限Applicaion 获取设备描述表时,Windows 用缺省值初始化该设备描述表,Application 使用它完成绘制操作,然后释放PrivateDeviceConte没有数量限制,用完不需释放一次获取,多次使用过程中,每次设备描述表属性的任何修改或变化都会被保存,以支持快速绘制xts 多次使用(1)使用设备描述表的步骤要使用设备描述表,一般有如下步骤:获取或者创建设备描述表;必要的话,改变设备描述表的属性;使用设备描述表完成绘制操作;释放或删除设备描述表。Common 设备描述表通过:GetDC,:GetD

44、CEx,:BeginPaint 来获得一个设备描述表,用毕,用:ReleaseDC 或:EndPaint 释放设备描述表;Printer 设备描述表通过:CreateDC 创建设备描述表,用:DeleteDC 删除设备描述表。Memory 设备描述表通过:CreateCompatibleDC 创建设备描述表,用 :DeleteDC 删除。Information 设备描述表通过:CreateIC 创建设备描述表,用:DeleteDC 删除。(2)改变设备描述表属性的途径要改变设备描述表的属性,可通过以下途径:用:SelectObject 选入新的除调色板以外的 GDI Object 到设备描述表

45、中;对于调色板,使用:SelectPalette 函数选入逻辑调色板,并使用:RealizePalette 把逻辑调色板的入口映射到物理调色板中。用其他 API 函数改变其他属性,如:SetMapMode 改变映射模式。设备描述表在 MFC 中的实现MFC 提供了 CDC 类作为设备描述表类的基类,它封装了 Windows 的 HDC 设备描述表对象和相关函数。CDC 类CDC 类包含了各种类型的 Windows 设备描述表的全部功能,封装了所有的 Win32 GDI 函数和设备描述表相关的 SDK 函数。在 MFC 下,使用 CDC 的成员函数来完成所有的窗口绘制工作。CDC 类有两个成员变

46、量:m_hDC,m_hAttribDC,它们都是 Windows 设备描述表句柄。CDC 的成员函数作输出操作时,使用 m_Hdc;要获取设备描述表的属性时,使用m_hAttribDC。在创建一个 CDC 类实例时,缺省的 m_hDC 等于 m_hAttribDC。如果需要的话,程序员可以分别指定它们。例如,MFC 框架实现 CMetaFileDC 类时,就是如此: CMetaFileDC 从物理设备上读取设备信息,输出则送到元文件(metafile)上,所以 m_hDC 和 m_hAttribDC 是不同的,各司其责。还有一个类似的例子:打印预览的实现,一个代表打印机模拟输出,一个代表屏幕显

47、示。CDC 封装:SelectObject(HDC hdc,HGDIOBJECT hgdiobject)函数时,采用了重载技术,即它针对不同的 GDI 对象,提供了名同而参数不同的成员函数:SelectObject(CPen *pen)用于选入笔;SelectObject(CBitmap* pBitmap)用于选入位图;SelectObject(CRgn *pRgn)用于选入剪裁区域;SelectObject(CBrush *pBrush)用于选入刷子;SelectObject(CFont *pFont)用于选入字体;至于调色板,使用 SelectPalette(CPalette *pPale

48、tte,BOOL bForceBackground )选入调色板到设备描述表,使用 RealizePalletter()实现逻辑调色板到物理调色板的映射。从 CDC 派生出功能更具体的设备描述表下面,分别讨论派生出的四种设备描述表。CClientDC代表窗口客户区的设备描述表。其构造函数 CClientDC(CWnd *pWin)通过:GetDC 获取指定窗口的客户区的设备描述表 HDC,并且使用成员函数 Attach 把它和 CClientDC 对象捆绑在一起;其析构函数使用成员函数 Detach 把设备描述表句柄 HDC 分离出来,并调用:ReleaseDC 释放设备描述表 HDC。CPa

49、intDC仅仅用于响应 WM_PAINT 消息时绘制窗口,因为它的构造函数调用了:BeginPaint 获取设备描述表 HDC,并且使用成员函数 Attach 把它和 CPaintDC 对象捆绑在一起;析构函数使用成员函数 Detach 把设备描述表句柄 HDC 分离出来,并调用:EndPaint 释放设备描述表HDC,而:BeginPaint 和:EndPaint 仅仅在响应 WM_PAINT 时使用。CMetaFileDC用于生成元文件。CWindowDC代表整个窗口区(包括非客户区)的设备描述表。其构造函数 CWindowDC(CWnd *pWin)通过:GetWindowDC 获取指定窗口的客户区的设备描述表 HDC,并使用 Attach 把它和CWindowDC 对象捆绑在一起;其析构函数使用 Detach 把设备描述表 HDC 分离出来,调用:ReleaseDC 释放设备描述表 HDC。MFC 设备描述表类的使用使用 CPaintDC、CClientDC 、CWindowDC 的方法首先,定义一个这些类的实例变量,通常在栈中定义。然后,使用它

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 教育教学 > 微软认证

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报