基于GDI+的VC图形多种充填
?? XXX?????????????XXX??????XXX ???????? CNPC测井重点实验室? 石油大学(北京) 盆地中心??? 东方地球物理公司研究院???????? 摘要:本文简要介绍GDI+ (或GDI PLUS)的新增功能,重点介绍GDI+的画刷种类及其如何创建、应用等。并以实例演示应用GDI+实现VC图形的多种充填模式,实现了原GDI不易实现的功能。 关键词:图形编程 GDI+ VC 画刷充填 ? ??? GDI+(Graphics Device Interface Plus)是原Windows GDI的扩展,增加了新功能并对原来功能模块进行了优化,易于开发设备无关性的应用程序。GDI+是Microsoft的下一代操作系统Microsoft? Whistler的子系统之一,负责屏幕显示和打印输出。因GDI+的强大功能及其xx的性能,微软倡导新应用程序的开发基于GDI+进行。 一、????? GDI+新增功能 GDI+新功能的增加,使得编程人员更易实现多种高级功能,使得应用程序图形界面更加美观。其新功能有:渐变的画刷(Gradient Brushes)、基数样条函数(Cardinal Splines)、持久路径对象(Persistent Path Objects)、变形和矩阵对象(Transformations & Matrix Object)、可伸缩区域 (Scalable Regions)、α混合(Alpha Blending)以及对多种图像格式支持。GDI+还支持其它技术,譬如重新着色、颜色校正、元数据、图形容器等,这里不详述,可以参见MSDN。 对开发人员来讲,GDI+提供了一系列的C++类这样的应用程序编程接口,使得VC程序员很容易就能编写出基于GDI+的应用程序。 二、????? GDI+的画刷 大多数GDI绘画函数都要同时使用画笔和刷子。它们使用画笔来绘制各种图形的周边,使用刷子来填充图形的内部。这样就能使用不同的颜色的画笔和刷子来绘制一个完整的图形。GDI+提供如下几种刷子来完成对一个闭合区域的充填,如单色刷子(SolidBrush),阴影线刷子(HatchBrush),纹理刷子(TextureBrush),线型渐变刷子(LinearGradientBrush)和路径渐变刷子(PathGradientBrush)。 1. 单色刷子(SolidBrush) 这是一种最简单的刷子,填充时用一种颜色填满图形内部。要获得这样一个刷子对象非常容易。如下示例创建一个单色充填的椭圆: //创建画刷,Color()的创建见MSDN SolidBrush mySolidBrush(Color(255, 255, 0, 0)); //应用创建的画刷对象充填椭圆。 myGraphics.FillEllipse(&mySolidBrush, 0, 0, 60, 40); 2. 纹理刷子(TextureBrush) 可以使用图象创建刷子,这样可以用图像平铺地填满整个区域。 Image myImage(L"MyTexture.bmp");??????? //创建图形对象 TextureBrush myTextureBrush(&myImage);? //创建纹理刷子 // 应用纹理刷子对象充填椭圆 myGraphics.FillEllipse(&myTextureBrush, 0, 0, 100, 50); 3. 线性渐变刷子(LinearGradientBrush) //创建线性渐变的刷子 LinearGradientBrush myLinearGradientBrush(myRect, Color(255, 0, 0, 255), Color(255, 0, 255, 0), ?? ???????? LinearGradientModeHorizontal); myGraphics.FillEllipse(&myLinearGradientBrush, myRect); 4. 路径渐变刷子(PathGradientBrush) 路径渐变刷子要较其它刷子复杂的多,其创建函数为: PathGradientBrush::PathGradientBrush(Point * points, INT count, WrapMode wrapMode) 参数说明: (1) Point * points:组成路径的直线和曲线的点数组; (2) INT count:点的数目,即点数组的大小; (3) WrapMode wrapMode:可选项,缺省值为WrapModeClamp,其值用于决定充填图形模式。 5.阴影线刷子(HatchBrush) 在MFC中我们只能创建六种阴影线样式的刷子,且只能指定阴影线的前景。在GDI+中,对这一方面进行了扩充,可以创建53种阴影线样式,可以同时指定前景和背景。这就满足了我们平时作图充填的需要,也解决了以前做多种充填样式时需要做位图再接着用纹理刷子来实现充填的繁琐。 其创建函数为: HatchBrush( HatchStyle hatchStyle, const Color& foreColor, ??? ?????????????????????????????????????????????? const Color& backColor) 参数说明: (1) HatchStyle hatchStyle:阴影线的样式;其值可以为0-52,如HatchStyleHorizontal为水平阴影线。其用法见实例分析。 (2) const Color& foreColor:阴影线的前景色。 (3) const Color& backColor:可选项,设置阴影线的背景色。如果没有设置这一值,背景色将为黑色(black) ? 三、????? 实例分析及演示 作者在开发《油气成藏体系定量评价系统》这一软件时,需要将大量的数据进行可视化,开始时使用不同的位图刷子在同一图形中进行不同数据项的区分显示,在编程的过程中发现这一方法实现较繁琐。后经查阅相关文档,发现有关GDI+的新增功能及新特性介绍,经实践后认识到用GDI+实现数据可视化具有编码量少,实现容易及功能{zy1}的优点。下面就《油气成藏体系定量评价系统》中的一个交互图形控件作一实例演示。开发发环境为WINDOWS2000+VC6.0,开发步骤如下:(限于篇幅,本文主要对GDI+应用部分进行讲解) 1.建立一个带有视图的控件(MFC ActiveX) 在stdafx.h文件中包括如下内容: #include <vector>??? #define ULONG_PTR DWORD #include "gdiplus.h" 2.初始化GDI+和关闭GDI+ ULONG_PTR m_gdiplusToken; //在InitInstance()中初始化GDI+ Gdiplus::GdiplusStartupInput?? gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL); //在ExitInstance()中关闭GDI+ Gdiplus::GdiplusShutdown(m_gdiplusToken); 3.曲线图元的定义 typedef struct tagLINE{ ??????? CArray<CPoint,CPoint>* ptArray;???????????? //曲线数据点数组 ??????? int???????? FillMode;?????????????????????? //充填模式 ??????? COLORREF??? Color;????????????????????????? //充填前景色 ??????? COLORREF??? bColor;???????????????????????? //充填背景色 }LINE; typedef std::vector<LINE>?? VECTOR_LINE;??????? //线图元的数据容器 4.变量定义 VECTOR_LINE???????? m_listLine;???????????????? //曲线图元链表 5.加载数据 创建曲线图元,加载曲线的数据点坐标和设置曲线的充填阴影线模式、前景色、背景色。在控件中以接口的形式实现,也可以在控件运行时交互地改变区域充填属性。 6.绘图 ??? VECTOR_LINE::iterator iter;???? //图元链表指针 …… ??? //使用GDI+绘制每条曲线并对曲线所构成区域充填 ??? using namespace Gdiplus; ??? Graphics graphics(pDC->m_hDC); ??? for (iter = m_listLine.begin(); iter != m_listLine.end();iter++) ??? {?? ??????? //依据曲线属性设置绘图环境 ??????? BYTE colorR,colorG,colorB;????? //前景色的颜色构成 ??????? colorR=GetRValue(iter->Color); ??????? colorG=GetGValue(iter->Color); ??????? colorB=GetBValue(iter->Color); ??????? BYTE colorR1,colorG1,colorB1;?????? //背景色的颜色构成 ??????? colorR1=GetRValue(iter->bColor); ??????? colorG1=GetGValue(iter->bColor); ??????? colorB1=GetBValue(iter->bColor); ??????? //创建阴影线模式的刷子,注意要用static_cast<HatchStyle>,要不然编译通不过。 ??????? HatchBrush hBrush(static_cast<HatchStyle>(iter->FillMode), Color(colorR,colorG,colorB),Color(colorR1,colorG1,colorB1)); ??????? //把MFC的Cpoint转换成GDI+的Point ??????? int totalPointNum=iter->ptArray->GetSize()+2; ??????? Point* pArray=NULL; ??????? pArray=new Point[totalPointNum]; ??????? Point pt; ??????? for(int i=0;i<=iter->ptArray->GetSize()-1;i++) ??????? { ??????????? pt.X=iter->ptArray->GetAt(i).x; ??????????? pt.Y=iter->ptArray->GetAt(i).y; ??????????? pArray[i]=pt; ??????? } //常量PAGE_LEFT_MARGIN, PAGE_TOP_MARGIN分别为绘图区的左边界和上边界,这里的闭合区域是曲线与Y轴所组成的区域,见示例图形 ??????? pt.X=PAGE_LEFT_MARGIN ;pArray[i]=pt; ??????? pt.Y=PAGE_TOP_MARGIN;pArray[i+1]=pt; ??????? Pen curPen(Color(colorR,colorG,colorB),1); ??????? //用指定画刷充填曲线所包围的区域 ??????? graphics.FillPolygon(&hBrush,pArray,totalPointNum); ??????? //用指定画笔绘制曲线 ??????? graphics.DrawPolygon(&curPen,pArray,totalPointNum); } 在该程序示例中,我们使用了MFC和GDI+成功地实现了图形控件的开发,在应用程序中利用所开发的控件增强了数据的分类可视化功能,取得了良好的界面效果。 从开发的实践过程来看,使用MFC和GDI+进行图形编程相对xx用MFC实现要容易些,且最终的图形功能也更强大。GDI+不仅是Microsoft Visual Studio.net的组成部分,也是WindowXP的重要组成部分。相信GDI将逐渐退出历史舞台,未来是GDI+的天下。 ? 参考文献: [1]、(美)Jon Bates,Tim Tompkins著 ; 何健辉 董方鹏等译,实用Visual C++ 6.0 教程 , 清华大学出版社,2000年8月。 [2]、王国印著,Visual C++ 技术内幕 ,清华大学出版社, 1994年。 [3]、王华等,Visual C++编程实例与技巧,机械工业出版社,1999年。 |