VC第5章图形绘制 1.docx
《VC第5章图形绘制 1.docx》由会员分享,可在线阅读,更多相关《VC第5章图形绘制 1.docx(103页珍藏版)》请在冰豆网上搜索。
![VC第5章图形绘制 1.docx](https://file1.bdocx.com/fileroot1/2023-5/17/341753e9-b7d3-461c-acc9-4a718939f010/341753e9-b7d3-461c-acc9-4a718939f0101.gif)
VC第5章图形绘制1
第5章图形绘制
在VisualC++6.0中,掌握图形程序设计方法是非常重要的。
因为图形在任何一个可视化工程项目中都是不可缺少的。
CDC(设备环境)类封装了图形绘制所需要的各种操作。
一、设备环境与设备环境类(CDC)
1设备环境
设备环境也称设备上下文(DeviceContext,简称DC),是计算机物理设备的代表,也是图形设备接口的主要组成部分。
由于Windows是一个与设备无关的操作系统,即Windows不允许直接访问硬件,如果用户想将文本和图形绘制到显示器或其它设备中去,必须通过“设备环境”这个抽象层与硬件进行通信,设备上下文对象的作用就是实现Windows的设备无关性,任何向屏幕上进行输出的功能都要间接地通过它来完成。
设备上下文是Windows的一种数据结构,它包含了有关如显示器或打印机等设备的绘图属性信息。
所有绘画都是通过设备上下文对象来实现的,该对象封装了Windows的画线、图形和文本的API函数。
设备上下文允许在Windows下独立于设备的绘画。
设备上下文不仅能够被用来在屏幕上绘画,它也可以将绘画输出到打印机和图元文件中。
2设备环境类
设备环境类CDC直接继承于CObject类,该类定义了一类设备对象。
CDC对象提供了非常多的成员函数,与设备环境的显示器、打印机等一起工作。
例如,如果要在显示器等设备上绘制图形,我们可以用MFC提供的设备环境类CDC类,因为CDC类中包含了绘图所需要的所有成员函数。
同时。
MFC还提供了以下几个CDC的派生类:
1、CPaintDC类
此类比较特殊,它的构造函数和析构函数都是针对OnPaint进行的。
用户一旦获得相关的CDC指针,就可以将它当做任何设备环境(包括屏幕、打印机)指针来使用,CPaintDC类的构造函数会自动调用BeginPaint,而它的析构函数则会自动调用EndPaint。
2、CClientDC和CWindowDC类
CClientDC只能在窗口的客户区(不包括边框、工具条、标题栏、滚动条、菜单栏以及状态栏)进行绘图,点(0,0)通常指的是客户区的左上角。
其构造函数调用GetDC,析构函数调用ReleaseDC函数。
CWindowDC允许在窗口的任意位置中进行绘图,点(0,0)指整个窗口的左上角。
其构造函数调用GetWindowDC,析构函数调用ReleaseDC函数。
3、CMetaFileDC类
封装了在一个Windows图元文件中绘图的方法。
图元文件是一系列与设备无关的图片的集合,由于它对图像的保存比像素更精确,因而往往在要求较高的场合下使用,例如:
AutoCAD的图像保存等。
目前的Windows已使用增强格式(enhanced-format)的32位图元文件来进行操作。
设备环境类CDC及其派生类。
5.2绘图程序
5.2.1CDC基类
CDC类是其它DC类的基类,CDC类封装了使用设备环境的各种图形设备接口(GDI)函数,它用于定义一个设备环境对象,并提供了在显示器、打印机和窗口的客户区域上画图的方法。
1、在视图类的OnDraw()函数中绘图
在视图类的OnDraw函数中绘图时,直接使用OnDraw()函数中的CDC形参指针pDC,调用它的函数进行绘图:
例5.1绘制矩形与文本
(1)创建一个单文档应用程序,名为:
显示绘图
(2)在视图类的实现文件“显示绘图
View.cpp”的OnDraw函数中加如下代码:
voidCMyView:
:
OnDraw(CDC*pDC)
{CMyDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//选择画刷,浅灰色画刷,见表5.2
pDC->SelectStockObject(LTGRAY_BRUSH);
CRectrect(10,10,200,70);//定义一个矩形
pDC->Rectangle(rect);//绘制一个矩形
pDC->TextOut(20,80,"我们会编制图形程序了!
");//绘制文本
pDC->TextOut(20,100,”努力学好VisualC++!
”);
}
3)编译运行
4)说明:
SelectStockObject()该函数检索预定义的备用笔、刷子、字体或者调色板的句柄。
参数:
LTGRAY_BRUSH:
亮灰色画笔;BLACK_BRUSH黑色画笔;NULL_BRUSH:
空画笔(相当于HOLLOW_BRUSH); WHITE_BRUSH:
白色画笔;BLACK_PEN:
黑色钢笔;......
2、在视图类的一般函数中绘图
例5.2在鼠标放下函数WM_LBUTTONDOWN函数中绘图
(1)创建一个单文档应用程序,名为:
一般函数绘图
(2)利用MFCClassWizard将鼠标放下WM_LBUTTONDOWN消息映射到视图类CMyView中,并添加代码:
voidCMyView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{//定义一个矩形
CRectrect(0,0,100,100);
//GetDC检索整个屏幕的设备上下文环境
CDC*pDC=GetDC();
pDC->Rectangle(rect);//绘制矩形
ReleaseDC(pDC);//释放pDC空间
CView:
:
OnLButtonDown(nFlags,point);
}
(3)编译运行,鼠标点击窗口
5.2.2CPaintDC类
CPaintDC对象代表了一个窗口的绘图画面,主要用来绘图。
它可以用来处理来自Windows的WM_PAINT消息。
改变窗口大小或移动覆盖在窗上的窗口或对话框时,Windows会发送WM_PAINT消息以通知客户区的变动,而WM_PAINT消息的处理是在OnPaint()消息处理函数中进行的。
例5.3在WM_PAINT消息函数中绘图
(1)创建一个单文档的应用程序,名为:
绘图
(2)利用MFCClassWizard将WM_PAINT消息映射到视图类(View)中,并添加代码:
voidCMyView:
:
OnPaint()
{//CPaintDCdc(this);
//调用MoveTo函数,定点到点(10,10)
dc.MoveTo(10,10);
//调用LineTo函数,画线到点(100,100)
dc.LineTo(100,100);//画线
//调用画椭圆函数Ellipse画椭圆
dc.Ellipse(120,120,160,160);
}
(3)编译运行
5.2.3CClientDC类
CClientDC对象用来自动处理对描述窗口的客户程序区域的设备环境进行调用和释放。
在CClientDC对象创建时自动调用GetDC(),在撤销时将自动调用ReleaseDC()。
例5.4在客户区画一条直线
(1)创建一个单文档的应用程序,名为:
画直线
(2)利用MFCClassWizard将鼠标放下WM_LBUTTONDOWN消息映射到视图类CMyView中,并添加代码:
voidCMyView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{CClientDCdc(this);
CRectrect;//定义一个矩形。
//取得客户区矩形区域
GetClientRect(&rect);
//调用MoveTo,定点到客户区的左上角
dc.MoveTo(rect.left,rect.top);
//调用LineTo函数,画线到客户区的右下角
dc.LineTo(rect.right,rect.bottom);
}
(3)编译运行。
5.3图形设备接口(GDI)对象
GDI(GraphicDeviceInterface)对象与设备环境对象的关系,类似于笔和纸的关系。
也就是说,GDI提供了用于在DC上画图的绘图工具。
MFC的GDI中包含了各种绘图类并提供各类的绘图函数即定义了若干种对于Windows的绘图工具的对象,该类的继承关系;GDI中包含的各种绘图类有一个共同的抽象基类CGdiObject,
1、使用GDI对象
选择GDI对象进行绘图时,一般要遵循下列步骤:
(1)定义一个GDI对象(如CPen、CBrush对象),然后用相应的函数(如CreatePen、CreateSolidBrush)创建此GDI对象。
但要注意;有些GDI派生类的构造函数允许用户提供足够的信息,从而一步即可完成对象的创建任务,这些类有CPen、CBrush。
(2)将构造的GDI对象选入当前设备坏境中,但不要忘记将原来的GDI对象保存起来。
(3)绘图结束后,恢复当前设备环境中原来的GDI对象。
2、库存的GDI对象
除了自定义的GDI对象外,Windows还包含了一些预定义的库存GDI对象。
由于它们是Windows系统的一部分,因此用户用不着删除它们。
CDC的成员函数SelectStockObject可以把一个库存对象选入当前设备环境中,并返回原先被选中的对象指针,同时使原先被选中的对象从设备环境中分离出来。
函数SelectStockObject可选用的库存GDI对象类型可以是表5.2所示值之一。
表5.1MFC的GDI类
类名说明
CBitmap“位图”是一种位矩阵,每一个显示像素都对应于其中的一个或多个位,用户可以
利用位图来表示图象,也可以利用它来创建画刷
CBrush“画刷”定义了一种位图形式的像素,利用它可对区域内部填充颜色或样式
CFont“字体”是一种具有某种风格和尺寸的所有字符的完整集合,它常常
被当做资源存于磁盘中,其中有一些还依赖于某种设备
CPalette“调色板”是一种颜色映射接口,它允许应用程序在不干扰其它应用
程序的前提下,充分利用输出设备的颜色描绘能力
CPen“画笔”是一种用于画线及绘制有形边框的工具,用户可以指定它的
颜色及宽度,并且可以指定它实线、点线或虚线等
CRgn“区域”是由多边形、椭圆或二者组合形成的一种范围,可以利用它
来进行填充、裁剪以及鼠标点中测试等
表5.2函数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系统字体
5.3.1画笔CPen类
CPen类封装了一个WindowsGDI画笔,并且提供了用于操作CPen对象的若干方法。
CPen类用来决定画线的风格和颜色。
在使用画笔之前,首先必须构造画笔对象,有2种方法:
(1)构造和初始化对象都在带参数的构造函数中一步完成,如:
生成颜色为绿色,宽度为2个像素的实心画笔:
CPennewPen(PS_SOLID,2,RGB(0,255,0));
(2)构造初始化分2步完成:
构造由不带参数的构造函数完成,而初始化由初始化函数完成。
如:
生成颜色为红色,宽度为2个像素的实心画笔:
CPennewPen;
newPen.CreatePen(PS_SOLID,2,RGB(255,0,0));
参数:
PS_SOLID:
画笔的风格,见表5.3所示
2:
画笔的宽度(2个像素)
RGB(255,0,0):
画笔的颜色
表5.3修饰画笔的风格
风格含义图例
PS_SOLID实线—————
PS_DASH虚线--------------
PS_DOT点线..……………
PS_DASHDOT点画线-.-.-.-.-.-.-.-.-.
PS_DASHDOTDOT双点画线-..-..-..-..-..-..-
PS_NULL不可见线
PS_INSIDEFRAME内框线___________
(3)CreatePenIndirect函数也是用于创建画笔对象,它的作用与CreatePen函数完全一样,只是画笔的3个属性不是直接出现在函数参数中,而是通过一个LOGPEN结构间接地给出。
BOOLCreatePenIndirect(LPLOGPENlpLogPen);
此函数用由LOGPEN结构指针指定的相关参数创建画笔。
LOGPEN结构如下:
TypedefstructtagLOGPEN
{UINTlopnStyle//画笔风格
POINTlopnWidth;//POINT结构的y不起作用,而用x表示画笔宽度
COLORREFlopnColor//画笔颜色
}LOGPEN
注意:
1、当修饰画笔的宽度大于1个像素时,画笔的风格只能取PS_NULL、PS_SOLID或PS_INSIDEFRAME,定义为其它风格不会起作用。
2、画笔的创建工作也可在画笔的构造函数中进行,它具有下列原型:
CPen(intnPenStyle,intnWidth,COLORREFcrColor);
例5.5用颜色为蓝色,宽度为8个像素的实心画笔,画线和画椭圆。
(1)创建一个单文档的应用程序,名为:
画笔
(2)利用ClassWizard将WM_PAINT消息映射到视图类(View)中,并加代码:
voidCMyView:
:
OnPaint()
{CDC*pDC=GetDC();//获得显示设备环境DC的指针pDC
CPennewPen;//定义图笔对象
//生成一支颜色为蓝色,宽度为8个像素的实心画笔
newPen.CreatePen(PS_SOLID,8,RGB(0,0,255));
//将创建的画笔选入内存DC,同时暂停挤出并保存原画笔
CPen*poldpen=pDC->SelectObject(&newPen);
pDC->MoveTo(10,10);//调用MoveTo函数,定位于点(10,10)
pDC->LineTo(100,100);//调用LineTo函数,画线至点(100,100)
pDC->Ellipse(120,120,160,160);//调用画椭圆函数Ellipse
//恢复内存DC中原有的画笔
pDC->SelectObject(poldpen);
ReleaseDC(pDC);//释放显示DC
}
(3)编译运行。
注意:
默认的画笔为黑色、一个像素的宽度、
实心。
默认的画刷为白色。
5.3.2画刷CBrush类
CBrush类封装了一个WindowGDI画刷,并且提供了用于操作CBrush对象的若干方法。
画刷可设置画刷的色彩和区域填充的绘图方法。
在使用画笔、画刷之前,首先必须构造画笔、画刷对象,有2种构造方法。
(1)构造和初始化对象都在带参数的构造函数中一步完成,如:
CBrushnewBrush(RGB(0,0,255));//蓝色画刷
(2)构造和初始化分2步完成,构造由不带参数的构造函数完成,而初始化由初始化函数完成,如:
CBrushnewBrush;
newBrush.CreateSolidBrush(RGB(0,0,255));
(3)CBrush类根据画刷属性提供了相应的创建函数,例如创建填充画刷和填充样式画刷函数为:
CreateSolidBrush和CreateHatchBrush,它们的原型如下:
BOOLCreateSolidBrush(COLORREFcrColor);//创建填充色画刷
BOOLCREATEhATCHbRUSH(intnIndex,COLORREFcrColor);//创建填充样式画刷
参数:
nIndex用于指定画刷的内部填充样式
crColor表示画刷的填充色
与画笔类似,画刷也有一个LOGBRUSH逻辑结构用于画刷属性的定义,并通过CBrush的成员函数CreateBrushIndirect来创建,其原型如下:
BOOLCreateBrushIndirect(constLOGBRUSH*lpLogBrush);
参数:
LOGBRUSH结构如:
TypedefstructtagLOGBRUSH
{UINTlbStyle;//风格
COLORREFlbColor;//填充色
LONGlbHatch;//填充样式
}LOGBRUSH;
(4)画刷的创建工作也可在其构造函数中进行,它具有下列原型:
CBrush(COLORREFcrColor);
CBrush(intnIndex,COLORREFcrColor);
CBrush(CBitmap*pBitmap);
(5)画刷也可用位图来指定其填充图案,但该位图应该是8*8像素,若畏途太大,Windows则只使用其左上角的8*8的像素。
(6)画刷仅对一些绘图函数有效,如:
Ellipse、FillRect函数等。
例5.6用颜色为红色、宽度为6个像素的实心画笔画矩形,并用绿色画刷填充矩形内部。
(1)创建一个单文档的应用程序,名为:
画刷
(2)利用ClassWizard将WM_PAINT消息映射到视图类(View)中,并加代码:
voidCMyView:
:
OnPaint()
{CDC*pDC=GetDC();//获得显示设备环境DC的指针pDC
CPennewPen;//定义画笔对象
//生成一支颜色为红色,宽度为6个像素的实心画笔
newPen.CreatePen(PS_SOLID,6,RGB(255,0,0));
CBrushnewBrush;//定义画刷对象
newBrush.CreateSolidBrush(RGB(0,255,0));//绿色画刷
//将创建的画笔选入内存DC,同时暂时挤出并保存原画笔
CPen*poldpen=pDC->SelectObject(&newPen);
//将创建的画刷选入内存DC,同时暂时挤出并保存原画刷
CBrush*poldbrush=pDC->SelectObject(&newBrush);
pDC->MoveTo(10,10);//调用MoveTo函数,定点到点(10,10)
pDC->LineTo(100,100);//调用LineTo函数,画线到点(100,100)
//调用画矩形函数Rectangle
pDC->Rectangle(120,120,200,200);
//恢复内存DC中原有的画笔
pDC->SelectObject(poldpen);
//恢复内存DC中原有的画刷
pDC->SelectObject(poldbrush);
//释放显示DC
ReleaseDC(pDC);
}
(3)编译运行。
画刷的属性通常包括填充色、填充图案和填充样式3种。
画刷的填充色和画笔颜色一样,都是使用COLORREF颜色类型,画刷的填充图案通常是用户定义的8*8位图,而填充样式往往是CDC内部定义的一些特性,它们都是以HS_为前缀的标识,如表5.4所示。
5.4坐标映射
在某个设备环境中绘制一个高为100个像素,宽也为100个像素的方块,语句如下:
pDC->Rectangle(CRect(0,0,100,100));//Rectangle绘制矩形,长方形
表5.4画刷的填充样式
标识填充样式
HS_BDIAGONAL向下点斜线
HS_CROSS方格
HS_DIAGCROSS向下点斜线与斜线复合
HS_FDIAGONAL向上点斜线
HS_HORIZONTAL横条
HS_VERTICAL竖条
由于默认的映射模式是MM_TEXT,其逻辑坐标(在各种映射模式下的坐标)和设备坐标(显示设备或打印设备坐标系下的坐标)相等。
因此这个方块在1024*768的显示器上看起来要比在640*480的显示器上显得小一些,而且若将它打印在600dpi精度的激光打印机上,这个方块就会显得更小了。
为了能保证打印的结果不受设备的影响,Windows定义了一些映射模式,如表5.5所示,这些映射决定了设备坐标和逻辑坐标之间的关系。
表5.5映射模式
映射模式含义
MM_TEXT每个逻辑单位等于一个设备像素,x向右为正,y向下为正
MM_HIENGLISH每个逻辑单位为0.001英寸,x向右为正,y向上为正
MM_LOENGLISH每个逻辑单位为0.01英寸,x向右为正,y向上为正
MM_HIMETRIC每个逻辑单位为0.01mm,x向右为正,y向上为正
MM_LOMETRIC每个逻辑单位为0.1mm,x向右为正,y向上为正
MM_TWIPS每个逻辑单位为一个点的1/20(一个点是1/72英寸),x向右为正,y向上为正
MM_ANISOTRPICx,y可变比例
MM_ISOTROPICx,y等比例
这样,我们就可以通过调用CDC:
:
SetMapMode(intnMapMode)来设置相应的映射模
式。
例如:
若将映射模式设置为MM_LOMETRIC,那么不管在什么设备中调用上述语句,都将显示出20*20mm的方块。
而MM_ISOTROPIC映射模式下:
纵横比总是1:
1,也就是说,无论比例因子如何变化,圆总是圆的。
但,MM_ANISOTROPIC映射模式下,x和y的比例因子可以独立地变化,即圆可以被拉扁成椭圆形状。
在映射模式MM_ANISOTROPIC和MM_ISOTROPIC中,常常可以调用CDC:
:
SetWindowExt(设置窗口大小)和CDC:
:
SetViewportExt(设置视口大小)函数来设置所需要的比例因子。
“窗口”和“视口”的概念往往不易理解。
所谓“窗口”,可以理解是一种逻辑坐标下的窗口,而“视口”是我们实际看到的那个窗口,也就是设备坐标下的窗口,根据“窗口”和“视口”的大小就可以确定x和y的比例因子,它们的关系如下:
x比例因子=视口x大小/窗口x大小
y比例因子=视口y大小/窗口y大小
例5.7:
将一个椭圆绘制在视窗中央,且当视图的大小发生改变时,椭圆的形状也会
随之改变。
(通过设置窗口和视口大小来改变显示的比例)
1)建一个单文档应用程序,名为:
椭圆的绘制
2)在View类的OnDraw函数里加如下代码:
voidCMyView:
:
OnDraw(CDC*pDC)
{//CMyDoc*pDoc=GetDocument();
//ASSERT_VALID(pDoc);
CRectrectClient;//定义矩形对象
GetClientRect(rectClient);//获得当前窗口的客户区大小
//设置MM_ANISOTROPIC映射模式,x,y可变比例,见表5.5所示
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000,1000);//设置窗口范围