GDI+高级编程.docx
《GDI+高级编程.docx》由会员分享,可在线阅读,更多相关《GDI+高级编程.docx(88页珍藏版)》请在冰豆网上搜索。
GDI+高级编程
第13章GDI+高级编程*
本章介绍GDI+的路径、区域、变换、图像处理和图元文件等高级编程容。
路径由许多不同类型的点所构成,用于表示复杂的不规那么图形。
区域是由矩形、椭圆、多边形等几何形状组合构成的一种封闭图形,可用于复杂图形的绘制、剪裁和击中测试等。
Graphics类可对绘制的图形进展平移、旋转和伸缩变换。
矩阵类Matrix那么可用于图形、图像、颜色、路径、区域等对象的变换。
GDI+的图像处理功能强大,可以加载、保存和操作多种格式的图像。
GDI+的图元文件格式为EMF+,可用来保存和重放绘图记录,也能用于交互绘图的重绘操作。
13.1路径
路径〔path〕是一系列相互连接的直线和曲线,由许多不同类型的点所构成,用于表示复杂的不规那么图形,也叫做图形路径〔graphicspath〕。
路径可被以画轮廓和填充的形式显示输出,也可以用于创立区域和路径渐变刷等。
虽然在GDI中也有路径〔本课件未讲〕,但是它只是作为DC的一种状态才能存在。
独立的路径对象,那么是GDI+新增加的。
13.1.1图形路径
在GDI+中,路径由图形路径类GraphicsPath表示,它是GDI+基类GdiplusBase的直接派生类。
1.构造函数
GraphicsPath类有三个构造函数:
GraphicsPath(FillModefillMode=FillModeAlternate);//构造一个空路径
GraphicsPath(constPoint*points,constBYTE*types,INTcount,FillModefillMode=FillModeAlternate);//构造含指定整数型点数组的路径
GraphicsPath(constPointF*points,constBYTE*types,INTcount,FillModefillMode=FillModeAlternate);//构造含指定浮数型点数组的路径
其中:
●填充模式参数fillMode在上一章的画填充多边形和曲线时已经讲过,枚举类型FillMode除了可取这里的默认值FillModeAlternate〔交替填充模式〕之外,还有一个可取的值是FillModeWinding〔环绕替填充模式〕。
●点数组参数points,可以是整数类型的,也可以是浮点数类型的。
●点类型数组参数types,主要点类型有路径起点、直线端点和贝塞尔点。
●计数参数count为数组points和types的元素数,这两种数组中的元素数必须一致。
2.点的种类
构造函数中,点的类型取值为枚举类型PathPointType常量;
typedefenum{
PathPointTypeStart=0,//起点
PathPointTypeLine=1,//直线端点
PathPointTypeBezier=3,//贝塞尔〔曲线的控制〕点
PathPointTypePathTypeMask=0x7,//点类型掩码〔只保存低三位〕
PathPointTypePathDashMode=0x10,//未使用
PathPointTypePathMarker=0x20,//标记点〔用于路径分段〕
PathPointTypeCloseSubpath=0x80,//闭子路径〔图形〕的终点
PathPointTypeBezier3=3//同PathPointTypeBezier
}PathPointType;
其中,主要的点类型有起点、直线端点、贝塞尔点、标记点和闭子路径终点。
其他曲线类型〔如弧、椭圆和基样条曲线等〕在路径中都是用贝塞尔曲线来表示的。
路径是由点组成的,但这里的点,不光指其坐标位置,还包括点的类型。
同样的点坐标,不同的点类型,最后得到的路径可能大相径庭。
例如,同一组点,定义两个路径,一个的点类型全是直线端点,另一个的起点之后有3个贝塞尔点,最后才是两个直线点〔参见图13-1,其中自定义画点列函数/方法DrawPoints,在画曲线时用过,源码参见12.6.5的1.〕:
Pointpoints[]={Point(40,140),Point(275,200),
Point(105,225),Point(190,300),Point(50,350),
Point(20,180)};//定义点数组
//定义点类型数组〔为了节省篇幅,有些直接用了枚举的整数值〕
BYTElineTypes[]={PathPointTypeLine,1,1,1,1,1};
BYTEtypes[]={PathPointTypeStart,PathPointTypeBezier,
3,3,PathPointTypeLine,1};
GraphicsPathpath1(points,lineTypes,6),//创立直线路径
path2(points,types,6);//创立复合路径
Graphicsgraph(pDC->m_hDC);//创立图形对象
//填充直线路径、画直线、画点列
graph.FillPath(&SolidBrush(Color:
:
Lime),&path1);
graph.DrawLines(&Pen(Color:
:
Violet),points,6);
DrawPoints(graph,Color:
:
Red,4,points,6);
graph.TranslateTransform(300,0);//右移300像素
//填充复合路径、画直线、画点列
graph.FillPath(&SolidBrush(Color:
:
Aqua),&path2);
graph.DrawLines(&Pen(Color:
:
Magenta),points,6);
DrawPoints(graph,Color:
:
Red,4,points,6);
图13-1点类型
3.路径的构成
前面已经讲过,路径是一系列相互连接的直线和曲线,它们最终都是由有序点列所组成。
可以利用GraphicsPath类的后两个构造函数,将点数组直接参加路径中。
不过,路径中的直线和曲线等图形,一般是通过调用路径类的假设干添加图形方法给加进去的。
每个被参加的图形都可以是一个子路径〔subpath〕。
路径对象,会将被参加图形〔包括封闭图形〕中的点尾首相接,连成一条完整的路径。
在路径中的图形都是开图形〔起点和终点可能是同一个点,例如矩形、椭圆、多边形和闭曲线等〕,可以调用图形路径类的CloseFigure或CloseAllFigures方法:
StatusCloseFigure(VOID);//关闭当前子路径
StatusCloseAllFigures(VOID);//关闭所有子路径
来显式闭合路径对象中的当前子路径或所有子路径。
例如〔参见图13-2〕:
Graphicsgraph(pDC->m_hDC);//创立图形像对象
Penpen(Color:
:
Blue);//定义蓝色笔
GraphicsPathpath;//创立路径对象
path.AddLine(10.0f,50.0f,200.0f,50.0f);//加水平直线
//path.StartFigure();//断开两条直线之间的连接〔即分成两个子路径〕
path.AddLine(60.0f,10.0f,60.0f,80.0f);//加垂直直线
path.AddEllipse(10,100,200,120);//加椭圆
path.AddBezier(Point(220,200),Point(250,150),
Point(300,50),Point(400,200));//加贝塞尔曲线
intn=path.GetPointCount();//获取路径中的点数
Point*points=newPoint[n];//新建点数组
path.GetPathPoints(points,n);//获取路径中的点
//path.SetFillMode(FillModeWinding);//设置填充模式
//填充〔开〕路径
//graph.FillPath(&SolidBrush(Color:
:
Aqua),&path);
graph.DrawLines(&Pen(Color:
:
Green),points,n);//画折线
//path.CloseAllFigures();//关闭所有子路径
graph.DrawPath(&pen,&path);//画路径轮廓
//graph.FillPath(&SolidBrush(Color:
:
Red),&path);//画填充路径
//DrawPoints(graph,Color:
:
Red,4,points,n);//画路径中的点
4.添加图形
图形路径类GraphicsPath中的以下方法,用于添加图形到路径中〔重载和参数都与Graphics类中对应的绘图方法一样,但是前缀都从Draw改成了Add〕:
点列与路径填充〔开〕路径
开〔子〕路径闭〔子〕路径
图13-2路径的构成
●加直线:
AddLine
●加折线:
AddLines
●加多边形:
AddPolygon
●加矩形:
AddRectangle
●加矩形组:
AddRectangles
●加弧:
AddArc
●加饼:
AddPie
●加椭圆:
AddEllipse
●加贝塞尔曲线:
AddBezier
●加相连的多段贝塞尔曲线:
AddBeziers
●加基样条曲线:
AddCurve
●加闭基样条曲线:
AddClosedCurve
●加串:
AddString
5.绘制路径
可以用Graphics类的方法DrawPath来画路径的轮廓,用其另一个方法FillPath来填充路径的部〔对开路径,会先自动封闭,然后再进展填充〕:
StatusDrawPath(constPen*pen,constGraphicsPath*path);
StatusFillPath(constBrush*brush,constGraphicsPath*path);
当然你也可以用GraphicsPath类的方法SetFillMode和GetFillMode来设置不同的填充模式或者获取当前的填充模式:
StatusSetFillMode(FillModefillmode);
FillModeGetFillMode(VOID);
关于画路径轮廓和填充路径的例子,前面已经有了很多,这里就不再列举了。
6.获取点信息
在创立路径并添加各种几何图形或字符串之后,我们可以调用如下一些GraphicsPath类的方法,来获取路径中点的信息。
包括点的坐标信息和点的类型信息:
INTGetPointCount(VOID);//获取路径中的总点数
StatusGetPathPoints(Point*points,INTcount);//获取路径中〔指定数目的〕整数点数组
StatusGetPathPoints(PointF*points,INTcount);//获取路径中〔指定数目的〕浮点数点数组
StatusGetPathTypes(BYTE*types,INTcount);//获取路径中〔指定数目的〕点类型数组
例如:
GraphicsPathpath;
……//添加假设干图形到路径
intn=path.GetPointCount();
Point*points=newPoint[n];
path.GetPathPoints(points,n);
graph.DrawLines(&Pen(Color:
:
Green),points,n);
DrawPoints(graph,Color:
:
Red,4,points,n);
13.1.2路径渐变刷
路径可以表示复杂的图形,可以用于绘制这些图形的轮廓和填充,也可以用于创立区域〔在下一节介绍〕和颜色渐变刷。
后者在前面美术字局部的彩心字符串例中〔参见12.8.3的5.〕,我们已经用过。
与其它具体刷〔如实心刷、条纹刷和纹理刷等〕类一样,路径渐变〔梯度〕刷类PathGradientBrush,也是Brush类的派生类。
它有3个构造函数:
PathGradientBrush(constGraphicsPath*path);
PathGradientBrush(constPoint*points,INTcount,
WrapModewrapMode=WrapModeClamp);
PathGradientBrush(constPointF*points,INTcount,
WrapModewrapMode=WrapModeClamp);
第一个构造函数从现有路径对象来创立画刷,后两个那么是从整数或浮点数点集来直接创立画刷,而且它们两个还有一个指定重复排列的输入参数wrapMode,默认值为WrapModeClamp〔不重复排列〕。
路径刷的颜色,一般是从路径点〔周边轮廓〕向路径中心渐变。
路径刷的默认中心为路径的形心,可以用路径刷方法SetCenterPoint来重新设置:
StatusSetCenterPoint(constPoint&point);
StatusSetCenterPoint(constPointF&point);
其中的中心点,可以位于任何位置,包括在路径的围之外。
对应的获取刷中心的方法是:
StatusGetCenterPoint(Point*point);
StatusGetCenterPoint(PointF*point);
其它常用的路径刷方法有:
StatusSetCenterColor(constColor&color);//设置刷中心颜色
StatusSetSurroundColors(constColor*colors,INT*count);//设置路径点颜色
StatusGetCenterColor(Color*color);//获取刷中心颜色
INTGetSurroundColorCount(VOID);//获取路径点颜色数目
StatusGetSurroundColors(Color*colors,INT*count);//获取路径点颜色数组
其中,路径刷的中心色和路径点色,默认都为背风光〔白色〕。
例如〔用路径刷画五角星,参见图13-3〕:
INTcount=10;
Pointpoints[]={Point(100,0),Point(122,69),
Point(195,69),Point(137,111),Point(159,181),
Point(100,138),Point(41,181),Point(63,111),
Point(5,69),Point(78,69)};
GraphicsPathpath;
path.AddPolygon(points,count);
Graphicsgraph(pDC->m_hDC);
PathGradientBrushpgBrush(&path);
pgBrush.SetCenterColor(Color:
:
Red/*Green*/);
graph.FillPath(&pgBrush,&path);
Colorcols[]={Color:
:
Black,Color:
:
Green,Color:
:
Blue,
Color:
:
White,Color:
:
Black,Color:
:
Green,Color:
:
Blue,
Color:
:
White,Color:
:
Black,Color:
:
Green};
/*Colorcols[]={Color:
:
Cyan,Color:
:
Aqua,Color:
:
Blue,
Color:
:
Chartreuse,Color:
:
Coral,Color:
:
CadetBlue,
Color:
:
HotPink,Color:
:
Turquoise,Color:
:
LightSkyBlue,
Color:
:
DeepPink};
pgBrush.SetCenterColor(Color:
:
White);*/
pgBrush.SetSurroundColors(cols,&count);
graph.TranslateTransform(200.0f,0);
graph.FillPath(&pgBrush,&path);
for(inti=0;icols[i]=Color(rand()%255,rand()%255,rand()%255);
pgBrush.SetSurroundColors(cols,&count);
pgBrush.SetCenterColor(Color(rand()%255,rand()%255,
rand()%255));
graph.TranslateTransform(-200.0f,200.0f);
graph.FillPath(&pgBrush,&path);
for(inti=0;icols[i]=Color(rand()%255,rand()%255,rand()%255);
pgBrush.SetSurroundColors(cols,&count);
pgBrush.SetCenterColor(Color(rand()%255,rand()%255,
rand()%255));
graph.TranslateTransform(200.0f,0.0f);
graph.FillPath(&pgBrush,&path);
输出结果见图13-3〔由于下排的两个五角星,使用的是随机色,所以每次刷新时,颜色都不一样〕。
如果将边点全改成红色、绿色或蓝色,中心改为白色,那么输出效果如图13-4所示。
又例如〔用路径刷画平铺六边形,参见图13-5和图13-6〕:
a)b)
图13-3路径刷五角星
a)上排左为红心和白边点,上排右为红心和和黑、绿、蓝、白边点
b)上排的左右皆为绿心,边点色同a)的
a)和b)下排的中心点和边点都为随机色,刷新后颜色会变
图13-4路径刷五角星〔白心,红、绿、蓝边〕
*include
……
voidFillHexagon(HDChdc,RectF&rect)//用路径刷画平铺六边形
{
floatradian=3.1415926f/180.0f;
floatl=50.0f,fh=l*sin(60.0f*radian);
PointFpts[]={PointF(50.0f,0.0f),
PointF(50.0f*1.5f,0.0f),PointF(50.0f,0.0f),
PointF(50.0f/2.0f,-fh),PointF(-50.0f/2.0f,-fh),
PointF(-50.0f,0.0f),PointF(-50.0f*1.5f,0.0f),
PointF(-50.0f,0.0f),PointF(-50.0f/2.0f,fh),
PointF(50.0f/2.0f,fh)};
PathGradientBrushpgBrush(pts,10);
pgBrush.SetWrapMode(WrapModeTile);
Graphicsgraph(hdc);
图13-5六边形坐标
pgBrush.SetCenterColor(Color:
:
Red);
graph.FillRectangle(&pgBrush,rect);
graph.TranslateTransform(75.0f,fh);
pgBrush.SetCenterColor(Color:
:
Green);
graph.FillRectangle(&pgBrush,-75.0f,-fh,rect.Width,
rect.Height);
}
voidCGdipDrawView:
:
OnDraw(CDC*pDC){
……
RECTsrect;
GetClientRect(&srect);
RectFrect(0.0f,0.0f,REAL(srect.right),
REAL(srect.bottom));
FillHexagon(pDC->m_hDC,rect);//用路径刷画平铺六边形
}
图13-6路径刷平铺六边形
13.2区域
区域〔region〕是由假设干几何形状所构成的一种封闭图形,主要用于复杂图形的绘制、图形输出的剪裁和鼠标击中的测试等。
最简单也是最常用的区域是矩形,其次是椭圆和多边形以及它们的组合。
这些也正是GDI所支持的区域类型。
GDI+中的区域是一种显示外表的围〔anareaofthedisplaysurface〕,可以是任意形状〔的图形的组合〕,边界一般为路径。
除了上面所讲的矩形、椭圆、多边形之外,其边界还可以含直线、折线、弧、贝塞尔曲线和基样条曲线等开图形,其容还可以包含饼、闭贝塞尔曲线和基样条曲线等闭图形。
在GDI+中,区域所对应的类是Region,它是一个独立的类〔没有基类,也没有派生类〕。
但是它有假设干相关的类,如各种图形类和图形路径类等。
13.2.1构造函数
Region类有6个构造函数:
Region(VOID);//创立一个空区域
Region(constRect&rect);//创立一个整数型矩形区域
Region(constRectF&rect);//创立一个浮点数型矩形区域
Region(constGraphicsPath*path);//由图形路径来创立区域
Region(constBYTE*regionData,INTsize);//由〔另一〕区域的数据构造区域
Region(HRGNhRgn);//由GDI的区域句柄构造区域
其中,创立矩形区域最简单,由路径创立区域最常用。
13.2.2其他方法
区域类的其他方法有〔其中的图形对象g也用于坐标计算〕:
Region*Clone(VOID);//克隆〔复制〕
//判断本区域是否与另一区域region相等:
BOOLEquals(constRegion*region,constGraphics*g)const;
BOOL