GDI编程.docx

上传人:b****6 文档编号:6532293 上传时间:2023-01-07 格式:DOCX 页数:24 大小:137.14KB
下载 相关 举报
GDI编程.docx_第1页
第1页 / 共24页
GDI编程.docx_第2页
第2页 / 共24页
GDI编程.docx_第3页
第3页 / 共24页
GDI编程.docx_第4页
第4页 / 共24页
GDI编程.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

GDI编程.docx

《GDI编程.docx》由会员分享,可在线阅读,更多相关《GDI编程.docx(24页珍藏版)》请在冰豆网上搜索。

GDI编程.docx

GDI编程

GDI编程

一、GDI相关概念

1、GDI(Graphics DeviceInterfase):

图形设备接口,是一个应用程序与输出设备之间的中介。

它提供了一套函数库,这些函数在不同的输出设备上输出图形和文字。

一方面,GDI向应用程序提供一个与设备无关的编程环境,另一方面,它又以设备相关的格式和具体的设备打交道。

2、DC(DeviceContext):

设备描述表(设备上下文),是一种Windows数据结构,包括了如线的宽度和颜色、刷子的样式和颜色、字体、剪裁区域等信息。

所有的绘制操作通过一个设备描述表进行,绘制线条、形状和文本的WindowsAPI函数都与DC有关。

设备可以是显示器,打印机等。

Win32下获取DC的API函数有:

HDCBeginPaint(HWNDhwnd,LPPAINTSTRUCTlpPaint):

特定用于WM_PAINT消息

HDCGetDC(HWNDhWnd):

用于获得hWnd参数所指定窗口的客户区域的HDC。

HDCGetWindowDC(HWNDhWnd):

返回hWnd参数所指定的窗口的HDC,包括非客户区,如标题栏、菜单、滚动条,以及边框等。

hWnd为NULL时,获取整个屏幕的HDC。

3、GDI对象:

DC定义了一组GDI对象,包括画笔,画刷,字体,位图,调色板,剪裁区域,路径层(Path)。

他们有MFC和Win32两套实现版本,其对应关系如下:

要使用这些对象,可以使用Win32函数SelectObject来将其选入DC中:

HGDIOBJSelectObject(

HDChdc,//设备上下文句柄

HGDIOBJhgdiobj//GDI对象句柄

);

当然,使用之前,这些对象必须存在,可以通过如下Win32函数来创建这些对象:

或者,通过Win32函数HGDIOBJGetStockObject(intfnObject)来获取系统预先定义好的如下备用对象:

fnObject参数含义

二、设备描述表DC在MFC中的实现

MFC提供了CDC类作为设备描述表类的基类,它封装了Windows的HDC设备描述表对象和相关函数。

CDC类包含了各种类型的Windows设备描述表的全部功能,封装了所有的Win32GDI函数和设备描述表相关的SDK函数。

在MFC下,使用CDC的成员函数来完成所有的窗口绘制工作。

CDC类有两个成员变量:

m_hDC,m_hAttribDC,它们都是Windows设备描述表句柄。

CDC的成员函数作输出操作时,使用m_Hdc;要获取设备描述表的属性时,使用m_hAttribDC。

在创建一个CDC类实例时,缺省的m_hDC等于m_hAttribDC。

CDC在封装Win32函数SelectObject(HDChdc,HGDIOBJECThgdiobject)时,采用了重载技术,即它针对不同的GDI对象,提供了如下名同而参数不同的成员函数:

SelectObject(CPen*pen)//用于选入笔

SelectObject(CBitmap*pBitmap)//用于选入位图

SelectObject(CRgn*pRgn)//用于选入剪裁区域

SelectObject(CBrush*pBrush)//用于选入刷子

SelectObject(CFont*pFont)//用于选入字体

SelectPalette(CPalette*pPalette,BOOLbForceBackground)//选入调色板到DC

RealizePalletter()//实现逻辑调色板到物理调色板的映射

直接使用CDC的例子是内存设备上下文,例如:

CDCdcMem.CreateCompatibleDC(&dc);//创建设备描述表

CDCpbmOld=dcMem.SelectObject(&m_bmBall);//更改设备描述表属性

//作一些绘制操作

dcMem.SelectObject(pbmOld);//恢复设备描述表的属性

dcMem.DeleteDC();//可以不调用,而让析构函数去删除设备描述表

从CDC派生出四个功能更具体的DC类。

继承层次如下图所示:

下面分别讨论这四种设备描述表。

●CCientDC:

代表窗口客户区的设备描述表。

其构造函数CClientDC(CWnd*pWin)通过:

:

GetDC获取指定窗口的客户区的设备描述表HDC,并且使用成员函数Attach把它和CClientDC对象捆绑在一起;其析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用:

:

ReleaseDC释放设备描述表HDC。

●CPaintDC:

仅仅用于响应WM_PAINT消息时绘制窗口,因为它的构造函数调用了:

:

BeginPaint获取设备描述表HDC,并且使用成员函数Attach把它和CPaintDC对象捆绑在一起;析构函数使用成员函数Detach把设备描述表句柄HDC分离出来,并调用:

:

EndPaint释放设备描述表HDC,而:

:

BeginPaint和:

:

EndPaint仅仅在响应WM_PAINT时使用。

例如,MFC中CView对WM_PAINT消息的实现方法如下:

voidCView:

:

OnPaint()

{

CPaintDCdc(this);

OnPrepareDC(&dc);

OnDraw(&dc);

}

●CMetaFileDC:

用于生成元文件。

●CWindowDC:

代表整个窗口区(包括非客户区)的设备描述表。

其构造函数CWindowDC(CWnd*pWin)通过:

:

GetWindowDC获取指定窗口的客户区的设备描述表HDC,并使用Attach把它和CWindowDC对象捆绑在一起;其析构函数使用Detach把设备描述表HDC分离出来,调用:

:

ReleaseDC释放设备描述表HDC。

三、Win32环境下绘图的基本过程

●获取或者创建设备描述表;

●必要的话,改变设备描述表的属性;

●使用设备描述表完成绘制操作;

●释放或删除设备描述表。

第一种绘图方式是对WM_PAINT消息的处理

voidCAaView:

:

OnPaint()

{

CPaintDCdc(this);//得到绘图DC

dc.TextOut(100,100,"HelloWorld");

}

或者

voidCAaView:

:

OnDraw(CDC*pDC)

{

pDC->TextOut(100,100,"HelloWorld");

}

上面的程序可以在窗口的100,100位置处,打印HelloWorld字符串。

那么什么时候会产生WM_PAINT消息呢?

由于Windows是一个多任务环境,某个应用程序的窗口上面可能被对话框或窗口覆盖,当撤消这些对话框或窗口时,这个应用程序窗口中就有一个"空洞",这个"空洞"就是一块无效的用户区域。

为重新显示无效用户区域,Windows发送WM_PAINT消息实现。

要求Windows发送WM_PAINT的情况有:

改变窗口大小,覆盖用户区的菜单或对话框关闭,使用UpdateWindow和ScrollWindow函数等。

Windows发送WM_PAINT消息时,把它放到应用程序队列的最后,使得其它的输入能够先于WM_PAINT消息被处理。

GetMessage函数也得到队列中WM_PAINT消息之后的其它消息,即只有有没有其它消息的情况下,才从队列中取出WM_PAINT消息进行处理。

这样做是为了让应用程序首先完成影响窗口显示结果的其它操作,不致因为频繁地执行输出操作而引起显示器的闪烁。

Windows把WM_PAINT消息放在队列最后就是这个原因。

Windows并非WM_PAINT消息的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息。

这两个函数把用户区全部或部分标记成无效用户区而要求重新显示。

下面的函数调用是把整个用户区标记成无效:

InvalidateRect(hWnd,NULL,TRUE);

上面代码把hWnd句柄参数指定的窗口用户区标记成无效。

作为矩形结构的NULL参数指定整个用户区,TRUE参数表示擦除背景。

第二种绘图的方式是在非OnDraw/OnPaint中绘图

voidCAaView:

:

OnLButtonDown(UINTnFlags,CPointpoint)

{

CClientDCdc(this);

dc.Ellipse(point.x-50,point.y-50,point.x+50,point.y+50);

}

这段程序实现了:

以鼠标的当前位置为圆心,画一个半径为50的圆。

基本的画线函数有以下几种

CDC:

:

MoveTo(intx,inty);改变当前点的位置

CDC:

:

LineTo(intx,inty);画一条由当前点到参数指定点的线

CDC:

:

BOOLArc(LPCRECTlpRect,POINTptStart,POINTptEnd);画弧线

CDC:

:

BOOLPolyline(LPPOINTlpPoints,intnCount);将多条线依次序连接

基本的作图函数有以下几种:

CDC:

:

BOOLRectangle(LPCRECTlpRect);矩形

CDC:

:

RoundRect(LPCRECTlpRect,POINTpoint);圆角矩形

CDC:

:

Draw3dRect(intx,inty,intcx,intcy,

COLORREFclrTopLeft,COLORREFclrBottomRight);3D边框

CDC:

:

Chord(LPCRECTlpRect,POINTptStart,POINTptEnd);扇形

CDC:

:

Ellipse(LPCRECTlpRect);椭圆形

CDC:

:

Pie(LPCRECTlpRect,POINTptStart,POINTptEnd);

CDC:

:

Polygon(LPPOINTlpPoints,intnCount);多边形

对于矩形,圆形或类似的封闭曲线,系统会使用画笔绘制边缘,使用刷子填充内部。

如果你不希望填充或是画出边缘,你可以选入空(NULL_PEN)笔或空(NULL_BRUSH)刷子。

多边形和剪贴区域

CreateRectRgn由矩形创建一个多边形

CreateEllipticRgn由椭圆创建一个多边形

CreatePolygonRgn创建一个有多个点围成的多边形

PtInRegion某点是否在内部

CombineRgn两个多边形相并

EqualRgn两个多边形是否相等

基本的绘图函数

CDC类中提供各种各样的输出操作,从画线到写字应有尽有。

为了画线、矩形、圆、扇形和写字,可相应地调用一些函数。

这些函数使用已选择的画笔和画刷,来画出边框,并填写图形内部区域,以及使用已选择的字体写字。

●画点函数SetPixel

COLORREFCDC:

:

SetPixel(intx,inty,COLORREFcclrref);

该函数把x和y指定的点置为clrref指定的颜色。

●画线函数LineTo与移动函数MoveTo

LineTo函数用来画线,并且通常与MoveTo函数配合使用,如画一条从点(10,70)到点(250,100)的线:

MoveTo(10,70);

LineTo(250,100);

●画矩形函数Rectangle

Rectangle函数用来画矩形。

它使用已选择的画笔画出边框,使用已选择的刷子填满矩形内部。

下面的例子画一个左上角位于点(10,20),右下角位于点(40,100)的矩形:

Rectangle(10,20,40,100);

●画圆或椭圆函数Ellipse

Ellipse函数用来画圆或椭圆。

它使用已选择的笔画框,使用已选择的刷填满圆或椭圆的内部。

下面的例子画一个用点(10,20)和点(40,100)构成矩形框中的椭圆:

Ellipse(10,20,40,100);

●画圆弧函数Arc

Arc函数用来画一段弧,这段弧由包围它的矩形和弧的开始点和结束点共同定义。

下面的例子在点(10,90)和点(360,120)所指定的矩形中画一段弧,它的起点和终点分别是点(15,90)和点(360,90):

Arc(10,90,360,120,15,90,360,110);

弧的起点坐标和终点坐标精确地位于弧上。

●画扇形函数Pie

Pie函数用来画扇形。

扇形由一段弧和两条从弧焦点到弧端点的半径组成。

Pie函数使用已选择的笔画框,使已选择的刷填满扇形内部。

下面的例子画一个用点(310,30)和点(360,80)构成的矩形围成的扇形。

其起点和终点分别为点(360,30)和点(360,80):

Pie(310,30,360,80,310,30,360,80);

弧的起点和终点不必精确地位于弧线上。

四、GDI对象

前面的程序只能画基本的图形,我们不能改变线条的颜色,线条的大小,不能填充颜色,也不能改变字体,显示一张位图等。

要实现这些功能,我们就要使用GDI对象。

这里,需强调一下:

GDI对象要选入Windows设备描述表后才能使用;用毕,要恢复设备描述表的原GDI对象,并删除该GDI对象。

一般按如下步骤使用GDI对象:

a、先创建或得到一个GDI对象

b、然后把它选入设备描述表

c、绘图

d、恢复设备描述表原来的GDI对象并删除刚新创建的GDI对象。

MFCGDI对象

MFC用一些类封装了WindowsGDI对象和相关函数,层次结构如图所示:

(1)画笔

画笔决定了线条的颜色、宽度和线型(实线、点线或点划线等)。

Windows使用当前在设备描述表中已选择的画笔来画线。

程序中可以选择Windows的予定义画笔,也可以选择自定义的画笔。

预定义画笔有三种:

BLACK_PEN(黑色笔)、WHITE_PEN(白色笔)和NULL_PEN(空笔),这些都在windows.h中已经定义好了,程序员可使用GetStockObject函数来选择其中的一种,系统缺省的画笔为黑色笔。

Windows.h包含了HPEN的数据类型定义,使用该类型可以定义画笔句柄的变量。

仅靠系统提供的预定义画笔远远不能满足需求,应用程序可根据实际需要创建一种自定义的逻辑画笔。

其步骤一般为:

首先用CreatePen或CreatePenIndirect函数建立一支画笔,再调用SelectObject函数将其选入设备描述表,此后就可使用该画笔在选定的设备描述表中进行绘图操作。

任何时候某一设备描述表只能有一支画笔被选入作为当前画笔,当一支画笔被选入时,原先已选入的画笔便不再有效。

完成绘图操作后,可以通过调用DeleteObject来释放已建立的画笔。

*函数CreatePen()

语法:

HPENCreatePen(intfnPenStyle,intnWidth,COLORREFclrref);

说明:

该函数创建一个逻辑画笔。

其中

fnPenStyle参数指定画笔的线型,该参数可取由windows.h定义的七个标识符之一,其含义为:

PS_SOLID实线

PS_DASH虚线

PS_DOT点线

PS_DASHDOT夹一点虚线

PS_DASHDOTDOT夹二点虚线

PS_NULL无

PS_INSIDEFRAME线画在所有构件框架内

nWidth参数是用逻辑单位表示的画笔的宽度;

clrref参数是一个COLORREF类型的颜色值,指定画笔的颜色,可用宏指令RGB构造这个值,如:

clrref=RGB(byRed,byGreen,byBlue);

在使用CreatPen函数时,要检查其返回值,确保它是一个有效的句柄。

下面给出一段程序,说明建立、选择和释放画笔的一般方法,假定程序要用一支宽度为3的黑色作图,则程序如下:

CPen*p_Pen;

CDCdc;

p_Pen->CreatePen(PS_SOLD,3,RGB(0,0,0));

if(p_Pen)

{

dc.SelectObject(p_Pen);

//…//这里进行绘图操作

}

Deletep_Pen;//删除hPen画笔,释放空间

*函数CreatePenIndirect()

语法:

HPENCreatePenIndirect(LOGPENFAR*lpLogPen);

说明:

该函数用lpLogPen所指的LOGPEN结构中的信息创建一个逻辑画笔。

LOGPEN的结构如下:

typedefstructtagLOGPEN(

WORDlopnStyle;

POINTlopnWidth;

COLORREFlopnColor;

)LOGPEN;

其中lopnStyle指定画笔线型,该参数可取下列值之一:

PS_SOLID0

PS_DASH1

PS_DOT2

PS_DASHDOT3

PS_DASHDOTDOT4

PS_NULL5

PS_INSIDEFRAME6

nWidth参数是用逻辑单位表示的画笔的宽度

clrref参数是一个COLORREF类型的颜色值,指定画笔的颜色,可用宏指令RGB构造这个值。

 

(2)刷子

当我们在绘制一些区域图形时,其内部往往需要以某种图案进行填充,这就需要选定"刷子"作为绘图工具。

Windows系统不仅为用户提供了预定义刷子,而且还允许应用程序自定义刷子。

Windows系统中预定义的刷子有如下七种:

BLACK_BRUSH黑色刷子

DKGRAY_BRUSH深灰色刷子

GRAY_BRUSH灰色刷子

HOLLOW_BRUSH中空刷子,画边界而不填充

LTGRAY_BRUSH浅灰色刷子

NULL_BRUSH空刷子

WHITE_BRUSH白色刷子

应用程序可以调用GetStockObject函数选用其中一个,系统缺省的刷子是白色刷子。

Window.h包含了HBRUSH数据类型的定义,使用该类型就可定义刷子句柄的变量。

仅靠这七种刷子往往不能满足要求,应用程序通过调用如下几种函数创建逻辑刷子,这些函数返回值均为刷子句柄。

*函数CreateHatchBrush()

语法:

HBRUSHCreateHatchBrush(intfnStyle,COLORREFclrref);

说明:

该创建一个带阴影的逻辑刷子。

FnStyle指定的阴影格式如下:

HS_BDLAGONAL45度向上斜线组成的阴影图案(自左到右)

HS_CROSS水平和垂直交叉组成的阴影图案

HS_DIAGCROSS45度斜线交叉组成的阴影图案

HS_FDIAGONAL45度向下斜线组成的阴影图案(自左到右)

HS_HORZONA水平线组成的阴影图案

HS_VERTICAL垂直线组成的阴影图案

Clrref是具有COLORREF类型定义的刷子颜色值,可用宏指令RGB构造这个值。

*函数CreateSolidBrush()

语法:

HBRUSHCreateSolidBrush(COLORREFclrre);

说明:

该函数创建的是一种实心颜色的逻辑刷子。

clrre含义同上。

同样,使用创建刷子的函数时,要检查其返回,确保它是一个有效的句柄。

一旦创建了绘图工具之后,可以SelectObject函数把它选择到显示缓冲区里。

在使用显示缓冲区之前,并不一定非要创建和选择绘图工具,Windows为每个显示缓冲区提供默认的绘图工具。

例如:

黑色笔,白色刷子和系统字体。

DeleteObject函数用来删除不再需要的绘图工具,但不能删除一个已选进显示缓冲区的绘图工具,而是应该使用SelectObject函数恢复原有的绘图工具,然后再删除需要删除的工具。

(3)填充图形

绘制一些需要以某种图案进行填充的区域图形时,需要选定"刷子"作为绘图工具。

Windows系统中预定义的刷子有七种,应用程序可以调用GetStockObject函数选用其中一个,系统缺省的刷子是白色刷子。

当靠这七种刷子不能满足要求时,应用程序通过调用Windows函数创建逻辑刷子,这些函数返回值均为刷子句柄。

(4)文字与字体

Windows是使用定义好的与设备无关的字符集,Windows的"文本"字符也是图形,所以屏幕上所显示的用打印机或绘图仪等输出品的文本完全一样,做到"所见即所得"。

文本绘制函数有:

TextOut以当前的字体写一字符串

DrawText在一个特定矩形区中绘制某一格式的文本

ExtTextOut在一个特定矩形区中,以当前字体写一字符串

GrayString用灰色文本写一字符串

TabbedTextOut写一带扩展字符的字符串

要输出文本就离不开字体。

获取字体的相关信息可以使用函数:

BOOLGetTextMetrics(LPTEXTMETRIClpMetrics)

结构TEXTMETRIC的定义如下所示:

typedefstructtagTEXTMETRIC{//tm

LONGtmHeight;//字符高度

LONGtmAscent;//字符上部高度(基线以上)

LONGtmDescent;//字符下部高度(基线以下)

LONGtmInternalLeading;//由tmHeight定义的字符高度的顶部空间数目

LONGtmExternalLeading;//加在两行之间的空间数目

LONGtmAveCharWidth;//平均字符宽度

LONGtmMaxCharWidth;//最宽字符的宽度

LONGtmWeight;//字体的粗细轻重程度

LONGtmOverhang;//加入某些拼接字体上的附加高度

LONGtmDigitizedAspectX;//字体设计所针对的设备水平方向

LONGtmDigitizedAspectY;//字体设计所针对的设备垂直方向

BCHARtmFirstChar;//为字体定义的第一个字符

BCHARtmLastChar;//为字体定义的最后一个字符

BCHARtmDefaultChar;//字体中所没有字符的替代字符

BCHARtmBreakChar;//用于拆字的字符

BYTEtmItalic;//字体为斜体时非零

BYTEtmUnderlined;//字体为下划线时非零

BYTEtmStruckOut;//字体被删去时非零

BYTEtmPitchAndFamily;//字体间距(低4位)和族(高4位)

BYTEtmCharSet;//字体的字符集

}TEXTMETRIC;

GDI字体族和字样

GDI字体族和字样表如下表所示:

字体族字体族常量字样说明

DontcareFF_DONTCARESystem当不能提供字体信息或字体并不

重要时使用

DecorativeFF_DECORATIVESymbol

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

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1