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

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

概述

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

1、 设备环境类CDC

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

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

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

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

2CClientDCCWindowDC

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

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

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

 

2、 图形设备接口

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

类  名      说   明

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

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

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

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

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

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

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

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

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

 

2.1、使用GDI对象

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

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

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_SOLIDPS_INSIDEFRAME定义,为其他风格不会起作用。

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

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

 

4、 画刷

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

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

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)画刷仅对绘图函数ChordEllipseFillRectFrameRectInvertRectPiePolygonPolyPolygonRectangleRoundRect有效。  

 

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

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

2、在Viwe.cppOnDraw(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);


(待完善)

  • 9
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法哥2012

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值