图形设备接口

本文详细介绍了Windows中的图形设备接口(GDI)和设备上下文,包括GDI的作用、设备上下文的类型如CPaintDC、CClientDC、CWindowDC等,以及如何使用这些设备上下文进行绘制操作。还提到了与设备上下文相关的数据类型如CPoint、CSize和CRect,以及如何在窗口非客户区和客户区进行绘制。此外,文章还讨论了画笔对象(CPen)的创建和使用,以及字体效果的创建,包括空心字、渐变字和特殊光栅模式。最后,文章讨论了映射模式,包括预定义模式和自定义坐标系统,展示了如何在不同映射模式下进行坐标转换和图形输出。
摘要由CSDN通过智能技术生成
 

图形设备接口

事实上,图形设备接口(Graphics Device InterfaceGDI)是指这样的一个可执行程序,它处理来自Windows应用程序的图形函数调用,然后把这些调用传递给合适的设备驱动程序,由设备驱动程序来执行与硬件相关的函数并产生最后的输出结果。GDI可以看作是一个应用程序与输出设备之间的中介,一方面,GDI向应用程序提供了一个设备无关的编程环境,另一方面,它又以设备相关的格式和具体的设备打交道。

经常同图形设备接口相提并论的另一个概念是设备上下文(Device ContextDC)。设备上下文是一种Windows数据结构,它包括了与一个设备(如显示器或打印机)的绘制属性相关的信息。所有的绘制操作通过一个设备上下文对象进行,该对象封装了实现绘制线条、形状和文本的Windows API函数。设备上下文可以用来向屏幕、打印机和图元文件输出结果。

Windows应用程序中,我们通常在绘制之前调用BeginPaint函数,然后在设备上下文中进行一系列的绘制操作,最后调用EndPaint函数结束绘制。MFCCPaintDC封装了这一过程。在构造CPaintDC对象的同时,其构造函数自动调用BeginPaint函数;在消毁CPaintDC对象的同时,其析构函数自动调用EndPaint函数。因此前面所讲述的过程可以对应于下面的三个步骤:构造一个CDC对象,进行绘制操作,消毁该CDC对象。在基于文档/视结构的应用程序框架中,这个过程被进一步的简化。回忆前几章中讲述的内容,我们一般在视类的OnDraw成员函数中处理有关重绘的操作。通过OnPrepareDC成员函数,框架自动的向OnDraw成员函数传递一个类型为CPaintDC的设备上下文对象。我们只需简单的通过该对象进行绘制,而不需要关心这一对象的构造和消毁。这一过程由框架自动的完成,而且,隐藏在背后的设备上下文在对OnDraw的调用返回时由框架进行释放。

除了上面的CPaintDC类外,MFC还提供了其它的一些封装不同设备上下文的类。如CClientDC类,它所封装的设备上下文仅代表了一个窗口的客户区。在CClientDC的构造函数中调用的不是BeginPaint函数,而是GetDC函数;相应的,ReleaseDC函数在类CClientDC的析构函数被自动调用。与此对应的还有另一个类CWindowDC,它所封装的设备上下文代表的是整个窗口,不仅包括其客户区,也同时包括窗口的边框及其它非客户区对象。

所有的设备上下文类中比较特殊的是类CMetaFileDC,通过CMetaFileDC对象所进行的绘制操作不是对一个实在的设备来进行的,这些操作都被记录到一个Windows图元文件中。不象自动传递给OnDraw成员函数的CPaintDC对象,如果要在这种情况下使用CMetaFileDC对象的话,我们必须自己调用OnPrepareDC成员函数。

所有的这些设备上下文类都以类CDC作为其基类。

一般情况下,很多绘制操作都是在应用程序的视类的OnDraw成员函数中进行的,前面说到过,当视类窗口收到消息WM_PAINT时,该消息对应的处理函数OnPaint被调用,该处理函数构造一个CPaintDC对象,并将指向该对象的指针传递给OnDraw成员函数。这里我们考虑这样一种情况,如果我们正在编写的是一个通过鼠标在屏幕上绘图的应用程序。这时我很显然需要为鼠标的移动消息添加消息处理函数,而且,我们希望用户在移动鼠标的过程中立即就可以看到所绘制的内容,而不是等到窗口收到WM_PAINT消息(即发生重绘事件)才调用成员函数OnDraw绘制窗口。在这种情况下,我们更倾向于直接在鼠标消息处理函数中进行绘制,这时,就需要创建一个设备上下文对象,然后通过该对象调用一系列的绘制方法。

Windows本身是一个图形界面的操作系统,进行Windows程序设计随时都会同设备上下文打交道,甚至在本书前面的章节中的一些示例程序中我们也已经用到了设备上下文,只不过在当时我们回避了与设备上下文有关的很多复杂东西。本章的目的之一就是系统的讨论这些前面已经用到但没有加以阐述的概念和技巧,并补充一些尚未涉及的内容,这些内容包括:

使用设备上下文进行绘制

绘图对象

直线与曲线

填充形状

字体和文本

颜色

坐标空间及变换

这些概念往往是交织起来的,哪怕是一个很简单的绘制操作,往往都需要用到不只一个绘图对象,因此我们很难将它们人为的分割开来进行讲述。在本章上,各节的标题只代表了本节的侧重点,而对于某一个概念的叙述或使用,则有可能分散在不只一个小节中。事实上,一个应用程序是一个整体,它常常需要很多个部件共同协调工作才可以正常工作。因此,出现这种情况是很自然的。

第一节 设备上下文

MFC应用程序中,绘制操作通常涉及三类对象,一类是输出对象,亦即设备上下文对象,包括CDC及其派生类;一类是绘制工具对象,亦即前面所说的图形对象,如果CFontCBrushCPen等;另一类属于Windows编程中需要用到的的基本数据类型,如CPointCSizeCRect等。

不同的设备上下文类封装了不同类型的设备上下文类对象,如表1所示。

除了设备上下文以外,在Windows中进行绘制通常还需要各种绘制工具,如用来绘制线条的笔、用来填充一个图形内部的刷子以及用来绘制文本的字体等。这些工具称作图形对象,它们由Windows系统提供,MFC提供的图形对象类对它们进行了封装,表2给出了这些图形对象以及与它们等价的Windows图形设备句柄类型。

1 MFC中的设备上下文类

设备上下文类

描述

CDC

所有设备上下文类的基类。可用来直接访问整个显示器或如打印机之类的非显示设备上下文。

CPaintDC

在窗口的OnPaint成员函数中使用的一种显示上下文。在其构造过程中自动调用BeginPaint,在其析构过程中自动调用EndPaint

CClientDC

代表窗口的客户区的显示上下文。通常在需要直接在窗口客户区进行绘制时使用。

CWindowDC

代表整个窗口的显示上下文,包括客户区和非客户区。

CMetaFileDC

代表Windows图元文件的设备上下文。一个Windows图元文件包括一系列的图形设备接口命令,可以通过重放这些命令来创建图形。向CMetaFileDC对象进行的各种绘制操作可以被记录到一个图元文件中。

 

2 MFC中的Windows GDI对象类

图形对象类

等价的Windows图形设备句柄

描述

CBrush

HBRUSH

用来填充正在绘制的对象的内部

CPen

HPEN

用来绘制对象的边线

CFont

HFONT

用来绘制文本

CBitmap

HBITMAP

用来提供操作位图的接口

CPalette

HPALETTE

用作应用程序和色彩输出设备(如显示器)之间的接口

 

1.1 几个与图形绘制有关的简单数据类型

在讲述设备上下文和图形对象之前,我们来介绍几个常用的数据结构类。

(1) CPoint

CPoint类封装了一个点的坐标。它事实上是从POINT结构派生而来的。结构POINTWin32 SDK中定义。因此,CPoint也继承了POINT结构的数据成员xyCPoint对象可以用在任何使用POINT结构的场合。CPoint对象还可以和另一种简单数据类型CSizeSIZE结构相互进行转换。

CPoint类具有多种形式的构造函数:

CPoint( );

CPoint( int initX, int initY );

CPoint( POINT initPt );

CPoint( SIZE initSize );

CPoint( DWORD dwPoint );

当使用DWORD类型的值来构造CPoint对象时,其低位字将被赋值给CPoint对象的成员x,高位字将被赋值给成员y

CPoint的成员函数Offset可以设置点的偏移量,同时,在类中定义的一些运算符,如??????等大大的简化了对点坐标的各种运算和比较。

(2) CSize

如果要表示距离以及相对位置,可以使用CSize对象。MFCCSize事实上是从SIZE派生而来的,因此,CSize继承了SIZE结构的数据成员cxcy。构造一个CSize对象与用对应的方法构造CPoint对象非常相似,因此我们不需讲述。同样,我们可以使用一个DWORD值来构造CSize对象,这时,其低位字被赋值给CSize对象的成员cx ,高位字被赋值给成员cy。在类Size中定义了六个运算符:??????????

(3) CRect

CRect类是编程时经常使用的几个简单数据结构之一,它从RECT结构派生,因此,CRect类继承了RECT结构的数据成员lefttoprightbottom。它们是CRect的公有成员。

一个CRect对象可以传递给任何以RECT结构或LPCRECTLPRECTW指针为参数的函数。

注意:

在指定一个CRect对象时,一般情况下我们需要使它的左边界的坐标小于右边界的坐标和上边界的坐标小于下边界的坐标。我们称满足该条件的矩形为常态矩形。很多函数要求传递给它的CRect对象表示一个常态矩形,否则这些函数将有可能返回一个错误的结果。我们可以通过调用成员函数NormalizeRect来将一个非常态矩形转换为一个常态矩形。在程序中出现非常态矩形并不一定的程序员的疏忽大意。这里举一个例子,如果当前显示上下文的映射模式为MM_LOENGLISH,将一个表示常态矩形的CRect对象传递给成员函数CDC::DPtoLP,将得到一个非常态矩形,该矩形的高度将成为一个负值。这是因为在MM_LOENGLISH映射模式中,纵坐标的方向是向上的。

相比我们在前面所讲述的CPoint类和CSize类来说,类CRect要庞大得多。表列出了在类CRect中定义的成员函数。

3 CRect的成员函数

成员函数

描述

Width

计算矩形的宽度

Height

计算矩形的高度

Size

计算矩形的大小

续表3

成员函数

描述

TopLeft

返回矩形的左上角

BottomRight

返回矩形的右下角

CenterPoint

返回矩形的中点

IsRectEmpty

判断矩形是否为空。空的矩形的宽和高都为0

IsRectNull

判断矩形的topbottomleftright成员变量是否全都为0

PtInRect

判断指定点是否的矩形内

SetRect

设置矩形的大小

SetRectEmpty

将矩形设置为空(所有坐标均为0)

CopyRect

从源矩形中拷贝维度到矩形中

EqualRect

判断两个矩形是否相等

InflateRect

扩大矩形的宽和高

DeflateRect

减小矩形的宽和高

NormalizeRect

使用矩形的宽和高标准化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值