您的位置:首页 > 其它

MFC基本图形的绘制(一)设备环境类CDC、画笔和画刷

2014-03-25 00:59 309 查看
Windows的GDI(设备图形接口),提供了绘图的基本工具,如:画点、线、多边形、位图以及文本输出等。MFC的设备环境类CDC封装了全部的绘图函数,使得绘制的图形即可以显示,又可以打印。

概述

Visual C++的CDC(Device Context,设备环境)类是MFC中最重要的类之一,它封装了 绘图所需要的操作,是用户编写图形和文字处理程序必不可少的。当然,绘制图形和文字时还必须指定相应的设备环境。设备环境是由Windows保存的一个数据结构,该结构包含应用程序向设备输出时所需要的信息。

1、 设备环境类CDC

设备环境是由Windows保存的一个数据结构,该结构包含应用程序向设备输

出时所需要的信息,例如:图形是在屏幕上显示还是通过打印机输出。为了能让用户使用一些特殊的设备环境,基类CDC还派生了以下各类:

(1)CPaintDC类,此类比较特殊,它的构造函数和析构函数都是针对OnPaint进

行的。用户一旦获得相关的CDC指针,就可以将它当做任何设备环境(包括屏幕、打印机)指针来使用,CPaintDC类的构造函数会自动调用BeginPaint,而它的析构函数则会自动调用EndPaint。

(2)CClientDC和CWindowDC

A、CClientDC只能在窗口的客户区(不包括边框、标题栏、选单栏以及状态栏)进行绘图,点(0,0)通常指的是客户区的左上角。其构造函数调用GetDC,析构函数调用ReleaseDC函数

B、CWindowDC允许在窗口的任意位置中进行绘图,点(0,0)指整个窗口的左上角。其构造函数调用GetWindowDC,析构函数调用ReleaseDC函数。

(3)CMetaFileDC封装了在一个Windows图元文件中绘图的方法。图元文件是一系列与设备无关的图片的集合,由于它对图像的保存比像素更精确,因而往往在要求较高的场合下使用,例如:AutoCAD的图像保存等。目前的Windows已使用增强格式(enhanced-format)的32位图元文件来进行操作。

2、 图形设备接口

Windows为设备环境提供了各种各样的绘图工具,例如:画笔、画刷、字体等。MFC封装了这些工具,并提供相应的类来作为应用程序的图形设备接口(GDI,Graphics Device Interface),这些类有一个共同的抽象基类CGdiObject,如下所示:

类 名 说 明

CBitmap “位图”是一种位矩阵,每一个显示像素都对应于其中的一个或多个位,用户可以利用位图来表示图象,也可以利用它来创建画刷

CBrush “画刷”定义了一种位图形式的像素,利用它可对区域内部填充颜色或样式

CFont “字体”是一种具有某种风格和尺寸的所有字符的完整集合,它常常

被当做资源存于磁盘中,其中有一些还依赖于某种设备

CPalette “调色板”是一种颜色映射接口,它允许应用程序在不干扰其它应用

程序的前提下,充分利用输出设备的颜色描绘能力

CPen “画笔”是一种用于画线及绘制有形边框的工具,用户可以指定它的

颜色及宽度,并且可以指定它实线、点线或虚线等

CRgn “区域”是由多边形、椭圆或二者组合形成的一种范围,可以利用它来进行填充、裁剪以及鼠标点中测试等

2.1、使用GDI对象

选择GDI对象进行绘图时,一般要遵循下列步骤:

(1)定义一个GDI对象(如CPen、CBrush对象),然后用相应的函数(如CreatePen、CreateSolidBrush)创建此GDI对象。但要注意;有些GDI派生类的构造函数允许用户提供足够的信息,从而一步即可完成对象的创建任务,这些类有CPen、CBrush

(2)将构造的GDI对象选入当前设备坏境中,但不要忘记原来的GDI对象保存起来。

(3)绘图结束后,恢复当前设备环境中原来的GDI对象

如下列代码:

void CMyView::OnDraw(CDC *pDC)
{  CPen penBlack;//定义一个画笔变量
penBlack.CreatePen(PS_SOLID,2,rgb(0,0,0);//创建画笔
CPen *pOldPen=pDC->SelectObject(&penBlack);//将此画笔选入当前设备环境并
//保存原来的画笔
//用此画笔绘图
pDC->MoveTo(…);
pDC->LineTo(…);
//其他绘图函数
pDC->SelectObject(pOldPen);//恢复设备环境中原来的画笔
}


2.2、库存的GDI对象

除了自定义的GDI对象外,Windows还包含了一些预定义的库存GDI对象。由于它们是Windows系统的一部分,因此用户用不着删除它们。CDC的成员函数

SelectStockObject可以把一个库存对象选入当前设备环境中,并返回原先被选中的对象指针,同时使原先被选中的对象从设备环境中分离出来。如下代码:

void CMyView::OnDraw(CDC *pDC)
{
CPen newPen(PS_SOLID,2,RGB(0,0,0))
pDC->SelectObject(&newPen);
pDC->MoveTo(…);
pDC->LineTo(…);
…   //其它绘图函数
pDC->SelectStockObject(BLACK_PEN);//newPen被分离出来
}


SelectStockObject函数可选用的库存GDI对象类型可以是下列值之一:

BLACK_BRUSH              黑色画刷
DKGRAY_BRUSH            深灰色画刷
GRAY_BRUSH               灰色画刷
HOLLOW_BRUSH            中空画刷
LTGRAY_BRUSH             淡灰色画刷
NULL_BRUSH                空画刷
WHITE_BRUSH               白色画刷
BLACK_PEN                 黑色画笔
NULL_PEN                   空画笔
WHITE_PEN                  白色画笔
DEVICE_DEFAULT_FONT      设备默认字体
SYSTEM_FONT               系统字体


图形的绘制通常需要先创建画笔和画刷,然后调用相应的绘图函数。

3、 画笔

画笔是Windows应用程序中用于绘制各种直线和曲线的图形工具。它可分为修饰画笔和几何画笔两种类型。在这2种类型中,几何画笔的定义最复杂,它不但有修饰画笔的属性,而且还和画笔的样式、阴影线类型有关,通常用在对绘图有较高要求的场合。而修饰画笔只有简单的几种属性,通常用在简单的直线和曲线等场合。

一个修饰画笔通常具有宽度、风格和颜色3种属性。画笔的宽度用于确定所画的线条宽度,它是用设备单位表示的。默认的画笔宽度是一个像素单位。画笔的颜色确定了所画的线条颜色。画笔的风格确定了所绘图形的线型,它通常有实线、虚线、点线、点划线、双点划线、不可见线和内框线等7种风格。这些风格在Windows中都是以PS_为前缀的预定义的标识。以下为修饰画笔的风格:

PS_SOLID
实线

PS_DASH虚线

PS_DOT点线

PS_DASHDOT
点画线

PS_DASHDOTDOT双点画线

PS_NULL不可见线

PS_INSIDEFRAME
内框线

几何画笔这里不做介绍。

创建一个修饰画笔,可以使用CPen类的CreatePen函数,其原形如下:

BOOL CreatePen(int nPenStyle,int nWidth,COLORREF crColor);

参数分别表示画笔的:风格 宽度 颜色

此外,还有一个CrearePenIndirect函数也是用于创建画笔对象,它的作用与CreatePen函数是完全一样的,只是画笔的3个属性不是直接出现在函数参数中,而是通过一个LOGPEN结构间接地给出。

BOOL CreatePenIndirect(LPLOGPEN lpLogPen);

此函数用由LOGPEN结构指针指定的相关参数创建画笔。LOGPEN结构如下。

typedef struct tagLOGPEN
{
/* lgpn*/
UINT lopnStyle;//画笔风格,
POINT lopnWidth;//POINT结构的y不起作用,而用x表示画笔宽度
COLORREF lopnColor;//画笔颜色
}LOGPEN;


值得注意的是:

(1)当修饰画笔的宽度大于1个像素时,画笔的风格只能取PS_NULL、

PS_SOLID或PS_INSIDEFRAME定义,为其他风格不会起作用。

(2)画笔的创建工作也可在画笔的构造函数进行,它具有下列原形:

CPen(int nPenStyle,int nWidth,COLORREF crColor);

4、 画刷

画刷用于指定充填的特性,许多窗口、控件以及其它区域都需要用画刷进行充填绘制,它比画笔的内容更加丰富。画刷的属性通常包括填充色、填充图案和填充样式3种,画刷的填充色和画笔颜色一样,都是使用COLORREF颜色类型,画刷的填充图案通常是用户定义的8*8位图,而填充样式往往是CDC内部定义的一些特性,它们是以HS_为前缀的标识,如书308页图7.3所示。

CBrush类根据画刷属性提供了相应的创建函数,例如创建填充色画刷和填充样式画刷的函数为CreateSolidBrush和CreateHatchBrush,它们的原型如下:

BOOL CreateSolidBrush(COLORREF crColor);//创建填充色画刷

BOOL CreateHatchBrush(int nlndex,COLORREF crColor);//创建填充样式画刷

其中:nIndex用于指定画刷的内部填充样式,而crColor表示画刷的填充色。

与画笔相类似,也有一个LOGBRUSH逻辑结构用于画刷属性的定义,并通过CBrush的成员函数CreateBrushIndirect来创建,其原型如下:

BOOL CreateBrushIndirect(const LOGBRUSH *lpLogBrush);

其中:LOGBRUSH逻辑结构如下定义:

typedef struct tagLOGBRUSH
{          //lb
UINT  lbStyle; //风格
COLORREF lbColor;//填充色
LONG lbHatch;//填充样式
}LOGBRUSH;


另外,还需注意:

(1)画刷的创建工作也可在其构造函数中进行,它具有下列原型:

CBrush(COLORREF crColor);
CBrush(int nIndex,COLORREF crColor);
CBrush(CBitmap *pBitmap);


(2)画刷也可用位图来指定其填充图案,但该位图应该是8*8像素,若位图太大,Windows则只使用其左上角的8*8的像素。

(3)画刷仅对绘图函数Chord、Ellipse、FillRect、FrameRect、InvertRect、Pie、Polygon、PolyPolygon、Rectangle、RoundRect有效。

例:绘制一条由点连起的曲线(简单图形)

1、 建一个单文档的应用程序

2、在Viwe.cpp的OnDraw(CDC *pDC)函数里加如下代码:

int data[20]={19,21,32,40,41,39,42,35,33,23,21,20,24,
11,9,19,22,32,40,42};
CRect rc;
GetClientRect(rc);
rc.DeflateRect(50,50);
int gridXnums=10,gridYnums=8;
int dx=rc.Width()/gridXnums;
int dy=rc.Height()/gridYnums;
CRect gridRect(rc.left,rc.top,rc.left+
dx *gridXnums,rc.top+dy *gridYnums);
CPen gridPen(0,0,RGB(0,100,200));
CPen *oldPen=pDC->SelectObject(&gridPen);
for(int i=0;i<=gridXnums;i++)
{
pDC->MoveTo(gridRect.left+i *dx,gridRect.bottom);
pDC->LineTo(gridRect.left+i *dx,gridRect.top);
}
for(int j=0;j<=gridYnums;j++)
{
pDC->MoveTo(gridRect.left,gridRect.top+j *dy);
pDC->LineTo(gridRect.right,gridRect.top+j *dy);
}
pDC->SelectObject(oldPen);
gridPen.Detach();
gridPen.CreatePen(0,0,RGB(0,0,200));
pDC->SelectObject(&gridPen);
CBrush gridBrush(RGB(255,0,0));
CBrush *oldBrush=pDC->SelectObject(&gridBrush);
POINT ptRect[4]={{-3,-3},{-3,3},{3,3},{3,-3}},ptDraw[4];
int deta;
POINT pt[256];
int nCount=20;
deta=gridRect.Width()/nCount;
for(i=0;i<nCount;i++)
{
pt[i].x=gridRect.left+i *deta;
pt[i].y=gridRect.bottom-
(int)(data[i]/60.0 *gridRect.Height());
for(j=0;j<4;j++)
{
ptDraw[j].x=ptRect[j].x+pt[i].x;
ptDraw[j].y=ptRect[j].y+pt[i].y;
}
pDC->Polygon(ptDraw,4);
}
pDC->Polyline(pt,nCount);
pDC->SelectObject(oldPen);
pDC->SelectObject(oldBrush);


(待完善)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: