1、1Lesson 07-08 图形设备接口Windows 系统具有丰富的图形界面。 Windows 系统提供许多函数来实现绘图的要求。而图形设备接口(Graphics Device Interface,简写为 GDI)就可看作是这些函数的集合。GDI 表示的是一个抽象的接口。通过该接口可以实现对图形的颜色、线条的粗细等属性的控制(甚至包括输出文字在内) 。应用程序可以通过调用这些 GDI 函数和硬件打交道,而不必知道到底是哪个厂家生产的硬件,从而实现了设备无关性。Windows 系统本身也使用 GDI 来绘制用户界面的各个部分。一、设备环境1设备环境Windows 默认使用客户区坐标系 ,其原点
2、在窗口客户区的左上角,X 轴的正方向指向右边,Y 轴的正方向指向下边。当应用程序并没有设置颜色、字体等时,系统使用默认的设置。这些默认的设置保存在设备环境中。如果没有设备环境,则每输出一个字符串(调用一次 TextOut 函数),就需要把字体和颜色也作为参数传递给 TextOut 函数,而且这样的参数有很多。为了避免这样的麻烦,Windows 就把这些可能会重复的参数放在了设备环境中,这样每次只需要多传入一个设备环境的指针就可以了,大大减少了重复工作。设备环境(Device Context ,缩写为DC,有时译为设备上下文,也称设备描述表)是一种包含各种绘图属性(如字体、颜色等等)和方法(即各
3、种绘图函数)的数据结构(或者集合)。它不仅可以绘制各种图形,而且还可以确定在应用窗口中绘制图形的方式,即确定绘图混和模式和映射模式。用户在绘图之前,必须获取绘图窗口区域的一个设备环境DC,才能进行GDI函数的调用,执行适合于设备环境DC的命令(就像OnDraw函数中的pDC指针)。DC中除了提供绘图的函数(如:TextOut)以外,还会提供给用户改变绘图属性的函数,如颜色。Windows的设备环境是GDI的关键元素,它代表了不同的物理设备。分为4种类型:显示型、打印机型、内存型和信息型。每种类型的设备环境都有各自的特定用途,见下表:设备环境的类型和用途设备环境 用途显示器型 支持视频显示器上的
4、绘图操作打印机型 支持打印机和绘图仪上的绘图操作内存型 支持位图上的绘图操作信息型 支持设备数据的访问2MFC 中的设备环境类在MFC类库中,设备环境被CDC类封装了起来,而CDC类下面又有4个派生类,各有特点,并可以完成不同的功能,如下所示:CMetaFileDC专门用于Windows图元文件,剩下的三种DC类之间存在差别:2CDC类的派生类派生类名称 说明CClientDC 说明一个客户区设备环境,提供对窗口客户区域的图形访问。在窗口中画图时可使用这种DC,但对WM_PAINT消息除外CWindowDC 可以提供在整个窗口(包括客户区和非客户区)中画图的设备环境CPaintDC 这是创建响
5、应WM_PAINT 消息 的设备环境,应用程序可以使用此类更新Windows显示,通常在MFC应用程序的OnPaint() 函数中使用CMetaFileDC 这个设备环境代表Windows元文件,包含一系列命令以重新产生图像。要创建独立于设备的文件时可使用这种DC,用户可以回放这种文件来创建图像CWindowDC类与CPaintDC和CClientDC类的区别绘图区域不同:CWindowDC类与CPaintDC和CClientDC类的区别的一个方面就是绘图区域不同。用CPaintDC 类和 CClientDC类的对象绘制图形时, 绘制区只能是客户区,而不能在非客户区,而CWindowDC可以在
6、非客户区进行图形绘制。绘图坐标系不同:在CWindowDC绘图类下,坐标系是建立在整个屏幕上的,在像素坐标方式下,坐标原点在屏幕的左上角,而在CPaintDC和 CClientDC绘图类下,坐标系是建立在客户区上的,在像素坐标方式下,坐标原点在客户区的左上角。CPaintDC类与CClientDC类的区别绘图机制不同:CPaintDC 类与 CClientDC类都是在窗口的客户区内绘制图形,但两者在绘制机制上有着本质的区别。CPaintDC类应用在OnPaint函数中,以响应Windows的WM_PAINT消息,而CClientDC应用在非响应WM_PAINT消息的情况下。CPaintDC 类
7、响应WM_PAINT消息,自动完成绘制,这对维护图形的完整性有着重要的作用。例如在一个窗口中,已经绘制了n条直线,这个窗口的完整性可能会被破坏(如被对话框覆盖),当破坏完整性的程序结束时,即覆盖取消,这个窗口就会接收到一个WM_PAINT消息,得到此消息后,激活消息处理函数(如OnPaint)进行窗口绘制。CPaintDC类对象就担负着此时的绘制工作。如果现在想在屏幕上再绘制一条直线(如用鼠标实时绘制,当第二次单击鼠标左键时完成绘制),就要用到CClinetDC类,这个类可以实时的将图形绘制在屏幕上。如果用CPaintDC完成同样的工作,只能发出指令让包含要绘制这条直线的屏幕部分重画,把这条直
8、线绘制到屏幕上。当然,这个重画区域内的其他图形元素同时也会重画。适用范围不同:CPaintDC类只能支持屏幕显示,而CClientDC类除了支持屏幕显示以外,还支持打印。 CDC类中的函数除了绘制图形的函数以外,还有以Get开头的获取绘图属性的函数,以Set开头的设置绘图属性的函数。3常用绘图函数示例CDC类中封装了一大批用来绘图的函数,除了文本输出函数TextOut以外,介绍几个常用的绘图函数,函数的原型以及更多的绘图函数用法查阅MSDN。画点/绘制一个彩色点pDC-TextOut(20, 20, “点“);pDC-SetPixel(100, 40, RGB(255,0,0);上面的代码表示
9、用红色画一个点。RGB是一个宏,可以将颜色的三个R(Red)、G(Green)、B(Blue)分量值转换为3Windows的颜色数据类型COLORREF(格式为0x00bbggrr),三个分量分别表示红、绿、蓝颜色的多少,取值范围为0255。常用的8种颜色如下表所示:常用的8种纯色RGB 颜色 RGB值 颜色RGB(0,0,0) 黑色 RGB(255,255,255) 白色RGB(255,0,0) 红色 RGB(0,255,0) 绿色RGB(0,0,255) 蓝色 RGB(255,255,0) 黄色RGB(0,255,255) 青色 RGB(255,0,255) 品红画线段/绘制线段pDC-T
10、extOut(320, 20,“线段“);pDC-MoveTo(400, 40);pDC-LineTo(500, 40);上面的代码画线,MoveTo函数移动画笔到一点,LineTo函数画线。画折线(多义线)/绘制折线pDC-TextOut(20, 170, “折线“);POINT polyline4=240,240,80,120,240,120,80,240;pDC-Polyline(polyline,4);上面的代码将给定的4个点顺序连成折线,函数中第一个参数为折线顶点数组名,第二个参数表示一共有几个点构成折线(最小必须为2)。POINT是Windows的一种结构,用来标识一个点,它有两个
11、成员变量,分别用来表示点的X和Y坐标;在MFC类库中,CPoint封装了这种结构。画矩形/绘制矩形pDC-TextOut(320, 170, “矩形“);pDC-Rectangle(390, 110, 600, 230);此函数只能画平行于屏幕的矩形,前两个参数分别为矩形的左上角点的X和Y坐标,第三、四个参数分别为矩形的右下角点的X和Y坐标。画椭圆/绘制椭圆pDC-TextOut(20, 320, “椭圆“);pDC-Ellipse(80, 260, 280, 380);此函数画一个由4个参数表示的矩形的内切椭圆。CDC里没专门画圆的函数,画圆仍然使用Ellipse函数。使X和Y方向的长度相等
12、,这时画出来的就是一个圆。画多边形/绘制多边形pDC-TextOut(320, 320, “多边形“);POINT polygon3=380,330,530,260,500,360;pDC-Polygon(polygon,3);上面的代码将给定三个点顺序首尾连成封闭的多边形,函数中第一个参数为多边形顶点数组名,第二个参数表示多边形顶点的数目。新建一个Graph单文档工程,并在CGraphView类的OnDraw函数中加入上述代码:4编译并运行程序,可见输出的图形。4获取设备环境在窗口中绘图,必须首先取得窗口的设备环境,如果不在CDC类中进行绘制,就必须首先想办法获取对应的设备环境(或者一个指向
13、设备环境的指针)。使用GetDC函数GetDC函数用于获取指定窗口工作区的显示器设备环境,其原型声明如下:CDC* CWnd:GetDC( );函数不带任何参数,如果函数调用成功,则返回标识CWnd客户区的设备环境,否则返回NULL。返回指针可能是临时性的,所以应该把它保存下来供以后使用。对于公用的设备环境,GetDC成员函数为每一次被获取的设备环境指定默认属性。对于私有的设备环境GetDC成员函数保持它先前所具有的属性不变。设备环境可以用于图形设备接口(GDI)函数在客户区中绘图。一般完成作图之后,用GetDC成员函数获取的设备环境必须通过调用ReleaseDC成员函数来释放。因为在一个给定
14、的时刻,系统只有五个公共的设备环境是可用的,如果使用了设备环境后不释放,有可能会妨碍其他的应用程序访问设备环境。ReleaseDC用于释放一个设备环境,以便该设备环境可以被其他应用程序申请使用。其原型声明如下:int ReleaseDC( CDC* pDC );其中pDC为待释放的设备环境的指针。如果释放成功,函数返回非零值,否则,函数返回零。下面的代码表示在单击某个菜单时画一个椭圆:void CGraphView:OnDrawEllipse() CDC * pDC;/调用CGraphView:GetDC()获取设备环境pDC = GetDC();pDC-Ellipse(0, 0, 100,
15、100);/使用完后调用CGraphView:ReleaseDC()释放设备环境ReleaseDC(pDC);直接构造CDC对象声明一个CDC类或者其派生类对象,获取设备环境,方法如下:CClientDC dc(CWnd* );构造一个对象,间接使用了 GetDC 成员函数。当用一个 C+的类声明一个对象时,系统会自动调用该类的构造函数,而在 CClientDC 类的构造函数中就调用 GetDC 函数。当对象被释放时,又会自动调用该类的析构函数,而在其析构函数中,则调用了 ReleaseDC 函数来释放设备环境。因此,前面的代码可以改为:void CGraphView:OnDrawEllips
16、e() CClientDC dc(this);dc.Ellipse(0, 0, 100, 100);这样不用用户自己去释放设备环境,在 CClinetDC 对象被折构时会自动释放。5二、GDI 对象Windows 的 GDI 对象类型是通过 MFC 库中的类来表示的,其中 CGdiObject 类是所有GDI 对象的 抽象基类,其派生类包括 CBitmap 类、CBrush 类、CFont 类、CPen 类、CRgn类和 CPalette 类,继承关系如下图所示。这些派生类对于绘制图形和图像都是非常重要的,经常要使用这些类来创建绘图工具,而很少直接使用基类 CGdiObject。设备环境和图形
17、设备接口是实现计算机绘图的两个重要的组成部分,设备环境主要定义了绘图的状态和方式,而图形设备接口则主要定义了用来绘图的工具。设备环境中包含有默认的 GDI 对象。CBitmap:位图是一种位矩阵,每一个显示像素都对应于其中的一个或多个位。用户可以利用位图来表示图像,也可以利用它来创建画刷。CBrush:画刷定义了一种位图形式的像素,利用它可对区域内部填充颜色。CFont:字体是一种具有某种风格和尺寸的所有字符的完整集合,它常常被当作资源存于磁盘中,其中有一些还依赖于某种设备。CPen:画笔是一种用来画线及绘制有形边框的工具,用户可以指定它的颜色及厚度,并且可以指定它画实线、点线和虚线。CRgn
18、 :区域是由多边形、椭圆或二者组合形成的一种范围,可以利用它来进行填充、裁剪以及鼠标点中测试。CPalette:调色板是一种颜色映射接口,它允许应用程序在不干扰其他应用程序的前提下,充分利用输出设备的颜色描绘能力。为了使用某种 GDI 对象,一般需要首先构造一个 GDI 对象,然后将这个 GDI 对象放入设备环境中,进行绘制工作。绘制完毕后,还必须将 GDI 对象释放。三、使用画笔画笔是一种用来画线及绘制有形边框的工具。在 MFC 中,用 CPen 类封装了 GDI 的画笔对象。用户可以通过画笔来选择线条的形状、粗细和颜色三种属性。系统默认的画笔是黑色,线宽为 1 个像素、并且是实线。1构造一
19、支画笔MFC 中 CPen 类的构造函数:CPen 类一共重载了三个构造函数:CPen(); /没有参数;CPen( int nPenStyle, /线条类型Int nWidth, /线条宽度COLORREF crColor); /线条颜色CPen( int nPenStyle, /线条类型int nWidth, /线条宽度const LOGBRUSH* pLogBrush, /指向 LOGBRUSH 结构的指针6int nStyleCount=0, /如果非 PS_USERSTYLE,恒为0const DWORD* lpStyle=NULL); /如非 PS_USERSTYLE,恒为空第一个
20、构造函数不带任何参数,由于它所构造的只是一个未初使化的 CPen 对象,构造完成后还必须调用 CPen 类的其他成员函数初始化之后才可以使用。另外,该构造函数总是可以被成功调用。第二个构造函数带有三个参数,分别对画笔的线形、线宽和颜色进行了初始化:参数 nPenStyle:指定画笔的风格(样式) ,也就是画笔的线形,该参数在构造函数中可以为如下所列值:参数 nPenStyle参数值 注释 示例PS_SOLID 创建一个实线画笔 PS_DASH 创建一个虚线画笔,该值只有当画笔宽度小于 1 个设备单位或更小时才有效PS_DOT 创建一个点线画笔,该值只有当画笔宽度小于 1 个设备单位或更小时才有
21、效PS_DASHDOT 创建一个点划线画笔,该值只有当画笔宽度小于 1 个设备单位或更小时才有效PS_DASHDOTDOT 创建一个双点划线画笔,该值只有当画笔宽度小于 1 个设备单位或更小时才有效PS_NULL 创建一个空线画笔PS_INSIDEFRAME 创建一个内框线画笔,该画笔可以在 WindowsGDI 输出函数定义的矩形边界所生成的封闭形状的边框内绘制直线参数 nWidth:指定画笔的宽度。对于该构造函数,如果该值为 0,那么无论是什么映射模式,设备单位的宽度总 1 个像素。注意:如果 nWidth 大于 1,则第一个参数中的 PS_DASH(虚线) 、PS_DOT(点线) 、PS
22、_DASHDOT(点划线) 、PS_DASHDOTDOT(双点划线)风格不可用。参数 crColor:包含了一个画笔所具有的 RGB 颜色。使用了 32 位的 COLORREF 类型值来确定图形颜色值,其结构为 0x00bbggrr(十六进制) ,各部分的数值分别说明如下:bb 代表蓝色值,范围从 00 到 FF(即从 0 到 255) 。gg 代表绿色值,范围从 00 到 FF(即从 0 到 255)r r 代表红色值,范围从 00 到 FF(即从 0 到 255)在程序中还可以使用 RGB 宏来完成相同的功能。第三个构造函数带有 5 个参数。如果需要直接构造一支画笔,只需要一句代码就可以。
23、72使用(选择)画笔在绘图中使用画笔,要把新的画笔选入到设备环境中去。使用 CDC 类的成员函数SelectObject 来把新的 GDI 对象选入到设备环境中 ,同时这个函数将会把设备环境以前的GDI 对象作为函数的返回值返回。CDC 类中一共重载了 5 个 SelectObject()函数:CPen* SelectObject( CPen* pPen );CBrush* SelectObject( CBrush* pBrush );virtual CFont* SelectObject( CFont* pFont );CBitmap* SelectObject( CBitmap* pBit
24、map );int SelectObject( CRgn* pRgn );/选择区域函数的参数就是将要使用的新 GDI 对象,而函数的返回值(除最后一个函数以外)就是设备环境原来使用的 GDI 对象。一般情况下,需要把旧的 GDI 对象保存起来,在画完图以后再把旧的 GDI 对象用 SelectObject 函数选回去,以勉资源的浪费。3画笔使用实例如 TestPen 工程,改写视图类的 OnDraw 函数。改变线宽参数,使它大于 1,观察结果:注意:当线宽大于 1 的时候,虚线、点线、点划线、双点划线风格都被忽略,仍然采用实线画笔。因此,是不可能用构造函数创建线宽为 4 的虚线画笔的。可以看
25、到,使用一支画笔绘图一般为分三步:创建、选择、落选。其他的 GDI 对象的使用方法也基本相同。GDI 对象的使用方法一般为下面 3 大步骤:第 1 步:创建 GDI 对象(可以直接构造,或者用 Greate 函数) ;第 2 步:用 CDC:SelectObject 函数将 GDI 对象选入设备环境(DC)中;第 3 步:使用完之后,再用 CDC:SelectObject 函数将 GDI 对象落选(即选回来) ,最后释放 GDI 对象。注意:有些 GDI 对象可以一步由构造函数直接创建,如 CPen 和 CBrush,而另外一些类如 CFont 和 CRgn 等则必须要两步:首先构造对象,其次
26、进一步调用相应的创建函数。四、使用画刷画刷(Brush)用来对封闭区域内部进行填充。例如用 Ellipse 函数画一个封闭的圆,此圆并不是空心的,圆的中间会用设备环境中默认的画刷来填充(由于默认的画刷为白色,因此在白色背景中,这个圆仿佛就是空心了,实际上是一个白色的实心圆) 。MFC 类库中,画刷被封装在 CBrush 类中。通过该类构造的 CBrush 对象可以传递给任何一个需要画刷的 CDC 成员函数。画刷可以是实线、阴影线或某种图案。1创建画刷CBrush 类有 4 个重载的构造函数:CBrhsh(); /无参数的构造函数CBrhsh(COLORREF crColor); /构造实体画刷
27、CBrush(int nIndex,COLORREF crColor); /构造阴影线模式画刷CBrush(CBitmap* pBitmap); /构造位图画刷第一个构造函数构造了一支未被初始化的画刷,如果用户使用了该构造函数,类似CPen 的无参数构造函数一样,必须调用其他成员函数对所得到的 CBrush 对象进行初始化。其他重载的构造函数分别使用指定的颜色、阴影线模式和颜色或位图指针来构造一支已经被初始化的画刷。8参数 crColor:以 RGB 颜色指定画刷的前景色。如果是表示阴影线模式的画刷,则该参数指定的是阴影线的颜色。参数 nIndex:指定了画刷的阴影线的风格,如下所示:画刷阴影
28、线的样式阴影线参数值 注释HS_BDIAGONAL 从左到右向下成 45的对角线HS_CROSS 水平线和垂直线相交的十字交叉线HS_DIAGCROSS 夹角为 45的斜十字交叉线HS_FDIAGONAL 从左到右向上成 45的对角线HS_HORIZONTAL 水平阴影线HS_VERTICAL 垂直阴影线参数 pBitmap:指向一个 CBitmap 对象,该对象指定了一幅用作画刷的位图。和画笔一样,要直接构造一支画刷,只需要一句代码就可以。2使用(选择)画刷使用画刷,和 CPen 一样,要分三步走:创建、选择、落选。创建名为 TestBrush 单文档工程,其他设置使用默认选项,修改视图类的
29、 OnDraw 函数创建并使用画刷。五、输出文本要使用不同的字体输出文本,需要使用到 GDI 对象字体。MFC 类库中,Windows 的图形设备接口字体和操纵字体的函数都被封装在 CFont 类 中。1用 CreateFont 创建字体创建一个 CFont 对象相对比较复杂, 在使用字体对象之前,必须调用 CFont 类的其他成员函数(如 CreateFont、CreateFontIndirect、CreatePointFont 或 CreatePointFontIndirect 等)对字体对象进行初始化,以便确定字体对象的参数。调用 CerateFont 函数来选择一种字体时,需要很多的参
30、数,该成员函数的原型声明如下:BOOL CreateFont(int nHeight, /字体高度int nWidth, /字体平均宽度int nEscapement, /字体标注行旋转角度int nOrientation, /字符基线角度int nWeight, /字体粗细程度BYTE bItalic, /是否斜体BYTE bUnderline, /是否下划线BYTE cStrikeOut, /是否着重号BYTE nCharSet, /字体的字体集BYTE nOutPrecision, /输出精度BYTE nClipPrecision, /载剪精度BYTE nQuality, /字体质量BY
31、TE nPitchAndFamily, /字体的间距和所属的族LPCTSTR lpszFacename); /字体的名字很多参数一般情况下都不用(除非编写专门的排版软件) ,而且都有默认的设置。9其中参数 nWeight:定义了字体的浓度即字体的粗细程序(像素数/1000) 。如下列出了该参数的通用常量值:字体的浓度值粗细程度常量 值 常量 值FW_DONTCARE 0 FW_SEMIBOLD 600FW_THIN 100 FW_DEMIBOLD 600FW_EXTRALIGHT 200 FW_BOLD 700FW_ULTRALIGHT 200 FW_EXTRABOLD 800FW_LIGHT
32、 300 FW_ULTRABOLD 800FW_NORMAL 400 FW_BLACK 900FW_REGUNAL 400 FW_HEAVY 900FW_MEDIUM 500参数 cCharSet:指出了字体的字体集。如下列出了预定义的字符集常量的值:预定义的字符集常量常量 值ANSI_CHARSET 0DEFAULT_CHARSET 1SYMBOL_CHARSET 2SHIFTJIS_CHARSET 128OEM_CHARSET 255参数 nOutputPrecision:指出所要求的输出精度,该精度确定输出与所要求的字体高度、宽度、控制、字符方位及间距的匹配和接近程度。一般取下列值之一:
33、OUT_CHARACTER_PRECIS,OUT_DEFAULT_PRECIS,OUT_DEVICE_PRECIS,OUT_RASTER_PRECIS,OUT_STRING_PRECIS ,OUT_STROKE_PRECIS 和 OUT_TT_PRECIS。参数 nPitchAndFamily:确定了字体的间距和所属的族。这个 8 位参数的低 4 位确定了字体的间距,可以是 DEFAULT_PITCH,FIXED_PITCH 或 VARIABLE_PITCH。高 4 位指定了字体族。参数 lpszFacename:是一个指向 ASCII 字符串的指针。确定了目标字体的字形名(如“Times N
34、ew Roman”、 “宋体”等等) 。参数值一定不能超过 30 个字符,这个名称可由用户自行定义。2使用字体创建一个字体比创建画笔和画刷的参数要多,但使用方法却和画笔、画刷没有差别:使用时选入设备环境中,使用完毕再选出来。创建 TestFont 单文档工程,在视图类的 OnDraw 函数编写代码。六、坐标系和映射模式无论在平面上或是在空间内绘图,都离不开坐标系,VC+ 涉及两种坐标系:逻辑坐标系和设备坐标系及其相互之间的转换。所谓坐标映射方式就是指这两种坐标系在相互转换时,逻辑单位和设备单位之间存在的某种比例关系。Windows 映射模式就是在 Windows 方式下的屏幕坐标方式。一个实际
35、的物理屏幕是由像素组成的,通常所说的 640480,800600,1024768 等分辨率指的就是物理屏幕的实际宽度和高度的像素数目。1逻辑坐标和设备坐标如下面的画线代码:10pDC-MoveTo(100,200) ;pDC-LineTo(500,200) ;这里坐标(100,200)和(500,200)是逻辑坐标,而 Windows 系统自动使用默认的映射模式把坐标转换为屏幕上的(100 像素,200 像素) , (500 像素,200 像素) ,后者就是设备坐标(这里设备是显示器) 。注意:逻辑坐标可以理解为不带单位的数值,当要在具体的设备上画图时,系统根据相应的映射射模式为这些数值加上单
36、位(1 像素、1 毫米还是 1 英寸等等) ,加上单位后就变成了设备坐标。设备环境中的所有绘图成员函数使用的都是逻辑坐标。因此,同样的代码在不同的映射模式下绘制出来的图形不一样。Windows 默认的映射模式是一个逻辑单位映射成为屏幕上的一个像素。2几种映射模式Windows 提供了几种映射模式(或称为坐标系) ,可以通过它们来和设备坐标相联系。如下为 Windows 的 8 种映射模式:Windows 的 8 种映射模式映射模式 映射识别码 1 逻辑单位 X 轴正向 Y 轴正向MM_TEXT 1 pixels 右 下MM_LOMETRIC 2 0.1mm 右 上MM_HIMETRIC 3 0
37、.01mm 右 上MM_LOENGLISH 4 0.01inch 右 上MM_HIENGLISH 5 0.001inch 右 上MM_TWIPS 6 1/1440inch 右 上MM_ISOTROPIC 7 可变(x 等于 y) 可变的 可变的MM_ANISOTROPIC 8 可变(x 不等于y)可变的 可变的MM_TEXT 映射模式允许应用程序利用设备像素工作,因此用它来表示设备坐标系是再合适不过了。屏幕(窗口)的原点约定在左上角,而 X 和 Y 方向向右向下方增长。MM_TEXT 是 Windows 默认的映射模式。MM_LOMETRIC,MM_HIMETRIC,MM_LOENGLISH,
38、MM_HIENGLISH,MM_TWIPS被称为“固定比例”映射模式。所有固定比例的映射模式的 X 值向右是递增的, Y 值向下是递减的(即正常的笛卡儿坐标系) 。它们之间的区别就是在于设备坐标到逻辑坐标转换的实际比例因子不同。MM_TWIPS 映射模式常常用于打印机,一个“twip”单位相当于1/20 磅(磅是一种度量单位,在 Windows 中 1 磅等于 1/72 英寸) 。MM_ISOTROPIC 和 MM_ANISOTROPIC 两种映射模式被称为 “可变比例”映射模式。在这些模式下,用户可以改变它们的比例因子和坐标原点。借助于这两种映射模式,当用户改变了窗口尺寸时,绘制的图形大小也
39、会发生相应的变化;同样,如果改变某个轴的方向,那么所绘制的图形也会随着该轴的变化发生改变,并且还可以定义任意的比例因子。在 MM_ISOTROPIC 模式下,X 方向与 Y 方向上的比例因子总是相等的(即纵横比为 11) ;而在 MM_ANISOTROPIC 模式下,X 方向与 Y 方向上的比例因子可以不相等(即纵横比任意) 。3设置映射模式调用 CDC 类的成员函数 SetMapMode 可设置映射模式,函数的声明如下:11virtual int SetMapMode( int nMapMode );nMapMode 是映射模式,返回值是设备环境以前的映射模式。举例如:TextMapMode
40、:当没有设置映射模式时,系统使用默认的映射模式 MM_TEXT,一个逻辑坐标对应于一个屏幕像素。七、绘图混和模式绘图混和模式指定了画笔颜色和被填充物体内部颜色是如何与显示平面的颜色相混合的。绘图混合模式描述了两个变量的所有可能的布尔组合(操作符包括 AND、OR 和XOR)和单变量布尔操作(操作符为 NOT) 。设置绘图混和模式使用成员函数 SetROP2,函数的原型声明如下:int CDC:SetROP2( int nDrawMode );函数返回先前的绘图混和模式,参数 nDrawMode 指定新的绘图混和模式,其值如下所示:绘图混和模式参数值 说明R2_BLACK 像素总是黑的R2_WH
41、ITE 像素总是白的R2_NOP 像素颜色保持不变(像素颜色=屏幕颜色)R2_NOT 像素为屏幕颜色的反色(像素颜色=NOT 屏幕颜色)R2_COPYPEN 像素为画笔的颜色(像素颜色=画笔颜色,此参数为系统的默认设置)R2_NOTCOPYPEN 像素为画笔颜色的反色(像素颜色=NOT 画笔颜色)R2_MERGEPENNOT 像素颜色是画笔的颜色和屏幕颜色的反色的组合(像素颜色=(NOT 屏幕颜色)OR 画笔颜色)R2_MASKPENNOT 像素颜色是画笔的颜色和屏幕颜色的反色中共有颜色的组合(像素颜色=(NOT 屏幕颜色)AND 画笔颜色)R2_MERGENOTPEN 像素颜色是屏幕颜色和画
42、笔颜色的反色的组合(像素颜色=(NOT 画笔颜色)OR 屏幕颜色)R2_MASKNOTPEN 像素颜色是屏幕颜色和画笔颜色的反色中共有颜色的组合(像素颜色=(NOT 画笔颜色)AND 屏幕颜色)R2_MERGEPEN 像素颜色是屏幕颜色和画笔颜色的组合(像素颜色=画笔颜色 OR 屏幕颜色)R2_NOTMERGEPEN 像素颜色是屏幕颜色和画笔颜色的组合颜色的反色(像素颜色=NOT(画笔颜色 OR 屏幕颜色)R2_MASKPEN 像素颜色是画笔颜色和屏幕颜色中共有的颜色的组合(像素颜色=画笔颜色 AND 屏幕颜色)R2_NOTMASKPEN 像素颜色是画笔颜色和屏幕颜色中共有的颜色的组合颜色的反
43、色(像素颜色=NOT(画笔颜色 AND 屏幕颜色)R2_XORPEN 像素颜色既是属于画笔颜色又属于屏幕颜色,但并不是两种颜色的公部分的组合颜色(像素颜色=画笔颜色 XOR 屏幕颜色) “XOR”代表“异或”R2_NOTXORPEN 像素颜色是既属于画笔颜色又属于屏幕颜色,但并不是两种颜色的公共部分的组合颜色的反色12(像素颜色=NOT(画笔颜色 XOR 颜色) ) “XOR”代表“异或”绘图混和模式设置方法:第 1 步:创建一个名位 TestROP2 的单文档程。第 2 步:在工程的资源中添加一个菜单项(ID_TEST_ROP2) 。第 3 步:用 ClassWizard 在视图类中为新增加
44、的菜单项添加消息处理函数。第 4 步:在该函数中添加代码,设置绘图混合模式:注意:由于绘图混和模式的作用,红色的画刷变成了奇怪的黑绿色,并交替出现图形;去掉绘图混合模式,不出现交替情况。可以通过成员函数 GetROP2 来获取当前设置环境的绘图混和模式,函数的完整定义如下:int CDC:GetROP2( ) const;八、显示位图显示位图,必须首先创建一个位图,然后把它选进设置环境中,使用完后再从设备环境中选出来,最后删除掉。由于显示器的“位图”就是显示器的映像,因此不能直接选入,必须利用 CDC 的成员函数 CreateCompatibleDC,为位图创建一个特殊的内存设备环境,然后利用
45、 CDC 的BitBlt 或者 StretchBlt 函数,把内存设备环境中的各个位复制到真正的设备环境中去。1从资源中加载位图创建位图要分为两步进行,首先声明一个 CBitmap 的对象,然后使用 LoadBitmap 函数将位图资源加载到 CBitmap 对象中去。因此,还得先准备好位图资源。创建好位图对象以后,才能够将位图显示出来。在应用程序的视图中显示一幅真彩色的位图,具体步骤如下:第 1 步:创建一个 TestBitmap 单文档工程。第 2 步:插入位图资源到 TestBitmap 工程中。准备好将要插入的位图,可以任意找一幅位图,位图既可以是 256 色的,也可以是真彩色的,但超
46、过 256 色的位图不能在资源编辑器中打开编辑。将准备好的位图文件复制到当前工程目录(如:TestBitmap)下。在工程 Resource View 中的任意一个资源项上单击鼠标右键,从弹出的右键菜单中选择 Import 菜单项,此时就会弹出导入资源对话框,在文件类型中选择“所有文件“(*.*)” ,在文件列表中选择刚刚复制进来的位图,然后单击对话框中的 Import 按钮,就可以将选中的位图文件导入到当前工程中。如果文件超过 256 色,Visual C+6.0 会弹出一个消息框,告知用户插入的资源不能被打开编辑。在工程的 Resource View 中就多了一个 Bitmap 文件夹,下
47、面有一项 IDB_BITMAP1 的位图资源。第 3 步:加载位图资源到 CBitmap 类的对象中。声明一个 CBitmap 类的对象,然后使用其成员函数 LoadBitmap 将位图装入。LoadBitmap 函数原型有两个:BOOL LoadBitmap( LPCTSTR lpszResourceName );BOOL LoadBitmap( UINT nIDResource );函数从资源中载入一幅位图,若载入成功则返回 TRUE。参数可以是位图资源的 ID,也可以是位图资源的名字。第 4 步:创建一个视图窗口设备环境的兼容内存设备环境。13用 CDC 类的成员函数 CreateCom
48、patibleDC 创建一个与显示设备环境相兼容的内存设备环境对象。CreateCompatibleDC 的函数原型如下:virtual BOOL CreateCompatibleDC(CDC* pDC);如果产生成功就返回 TRUE。第 5 步:用 CDC:SelectObject 函数将位图对象选入到创建的兼容内存设备环境中。第 6 步:用 CDC:BitBlt 函数显示位图。显示一个在资源中的位图可分为如下 4 步进行:(1)声明一个 CBitmap 对象,并用 CBitmap 的成员函数 LoadBitmap 从资源中装入位图。(2)使用 CDC 的成员函数 CreateCompatibleDC 创建一个兼容 DC。(3)使用 CDC 的成员函数 SelectObject 将位图选入兼容 DC 中。(4)使用 CDC 的成员函数 BitBlt 函数显示位图。2BitBlt 和 StretchBlt 函数BitBlt 函数BitBlt 函数原型如下:BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc,DWORD dwRop );x、y 为显示位图的位置;nWidth、nHeight 为显示位图的宽、高的范围;pSrcDC 为已选入位图的兼容内