原文地址:http://blog.csdn.net/harvic880925/article/details/9071795
画刷Brush
GDI+中定义了五种画刷类型,他们都派生于Brush类,他们分别是:
注意:画刷与画笔不同,画刷只是用来填充区域,所以,画刷无宽度、长度可言。
单色画刷SolidBrush
一、构造函数
SolidBrush greenBrush(Color(255,0,255,0)); //在GDI+中颜色值,没有RGB()构造,只能用Color()构造
二、所使用的填充函数
- graphics.FillClosedCurve();
- graphics.FillEllipse();
- graphics.FillPath();
- graphics.FillPie();
- graphics.FillPolygon();
- graphics.FillRectangle();
- graphics.FillRectangles();
- graphics.FillRegion();
对于这些区域填充函数的使用,已经在前面讲过了,大家可以参考《GDI+学习及代码总结之------画线、区域填充、写字》这一篇文章
影线画刷HatchBrush
影线画刷,故名思意,就是用前景色与背景色,根据预定好的横线、竖线及斜线组成的图形,影线画刷用HatchBrush定义,其构造函数为:
- HatchBrush::HatchBrush(hatchStyle, foreColor, backColor);
大家看hatchStyle定义:
- enum HatchStyle{
- HatchStyleHorizontal = 0,
- HatchStyleVertical = 1,
- HatchStyleForwardDiagonal = 2,
- HatchStyleBackwardDiagonal = 3,
- HatchStyleCross = 4,
- HatchStyleDiagonalCross = 5,
- HatchStyle05Percent = 6,
- HatchStyle10Percent = 7,
- HatchStyle20Percent = 8,
- HatchStyle25Percent = 9,
- HatchStyle30Percent = 10,
- HatchStyle40Percent = 11,
- HatchStyle50Percent = 12,
- HatchStyle60Percent = 13,
- HatchStyle70Percent = 14,
- HatchStyle75Percent = 15,
- HatchStyle80Percent = 16,
- HatchStyle90Percent = 17,
- HatchStyleLightDownwardDiagonal = 18,
- HatchStyleLightUpwardDiagonal = 19,
- HatchStyleDarkDownwardDiagonal = 20,
- HatchStyleDarkUpwardDiagonal = 21,
- HatchStyleWideDownwardDiagonal = 22,
- HatchStyleWideUpwardDiagonal = 23,
- HatchStyleLightVertical = 24,
- HatchStyleLightHorizontal = 25,
- HatchStyleNarrowVertical = 26,
- HatchStyleNarrowHorizontal = 27,
- HatchStyleDarkVertical = 28,
- HatchStyleDarkHorizontal = 29,
- HatchStyleDashedDownwardDiagonal = 30,
- HatchStyleDashedUpwardDiagonal = 31,
- HatchStyleDashedHorizontal = 32,
- HatchStyleDashedVertical = 33,
- HatchStyleSmallConfetti = 34,
- HatchStyleLargeConfetti = 35,
- HatchStyleZigZag = 36,
- HatchStyleWave = 37,
- HatchStyleDiagonalBrick = 38,
- HatchStyleHorizontalBrick = 39,
- HatchStyleWeave = 40,
- HatchStylePlaid = 41,
- HatchStyleDivot = 42,
- HatchStyleDottedGrid = 43,
- HatchStyleDottedDiamond = 44,
- HatchStyleShingle = 45,
- HatchStyleTrellis = 46,
- HatchStyleSphere = 47,
- HatchStyleSmallGrid = 48,
- HatchStyleSmallCheckerBoard = 49,
- HatchStyleLargeCheckerBoard = 50,
- HatchStyleOutlinedDiamond = 51,
- HatchStyleSolidDiamond = 52,
- HatchStyleTotal,
- HatchStyleLargeGrid = HatchStyleCross,
- HatchStyleMin = HatchStyleHorizontal,
- HatchStyleMax = HatchStyleTotal - 1
- };
这个定义有些长,而且让人搞不懂他们分别对应什么图形,让我们看下面的图像,他们从左至右、从上到下排列,序号分别是0-52,(前景色为:红色,背景色为:绿色),CSDN处理的有些失真,大家可以在MSDN上看下这个枚举类,有对应的图形。
我们简单使用一下影线画刷,用它来填充两个矩形,示例:
- Color forColor(255,0,0,0);
- Color bkColor(255,255,0,255);
-
- HatchBrush brush(HatchStyleHorizontal, forColor, bkColor);
- graphics.FillRectangle(&brush, 20, 20, 100, 50);
-
- HatchBrush brush1(HatchStyleVertical, forColor, bkColor);
- graphics.FillRectangle(&brush1, 140, 20, 100, 50);
影线画刷的单个与整体
从构成上看,影线画刷是小正方形图案的简单重复,单个的正方形图案决定了画刷的整体外观。下图所示为影线画刷的基本构成:
左图所示是影线画刷放大后的基本图案,该图案由前景色和背景色两部分构成。右图,就是由这些个小的基本图案重复而成。上面所枚举的53种图案,都是由它自己的基本图案重复平铺而成。
设置影线画刷的绘制原点
绘制原点,即在什么地方开始绘制,它并不是指相对所要填充的矩形原点的填充位置,而是对基本图案而言的。设置绘制原点的语句为:
- Graphics::SetRenderingOrigin(x, y);
如果我们设置这样一条语句,setRenderingOrigin(0,3);会是什么效果呢?看下面讲解;
我们说了,是相对基本图案而言,我们还是3-13的图,
所以,它先从基本图案的纵向偏移3个相素,然后用偏移后的图案开始绘制
示例:(向下偏移4个相素)
- HatchBrush hatchBrush(
- HatchStyle(52),
- Color(255, 255, 0, 0),
- Color(255, 0, 255, 255));
-
- graphics.FillRectangle(&hatchBrush, 0, 0, 100, 50);
- graphics.SetRenderingOrigin(0,4);
- graphics.FillRectangle(&hatchBrush, 120, 0, 100, 50);
纹理画刷TextureBrush
纹理画刷,与影线画刷类似,也是使用同样的基本图案在水平和垂直方向上按一定的顺序平铺。不同的是,纹理画刷使用的是基本的图像来做基本图案的。
一、构造函数(待完)
- TextureBrush(Image* image, Rect& dstRect, ImageAttributes* imageAttributes)
- TextureBrush(Image* image, RectF& dstRect, ImageAttributes* imageAttributes)
- TextureBrush(image, wrapMode)
- TextureBrush(Image* image, WrapMode wrapMode, Rect& dstRect)
- TextureBrush(Image* image, WrapMode wrapMode, RectF& dstRect)
- TextureBrush(Image* image, WrapMode wrapMode, INT dstX, INT dstY, INT dstWidth, INT dstHeight)
- TextureBrush(Image* image, WrapMode wrapMode, REAL dstX, REAL dstY, REAL dstWidth, REAL dstHeight)
这里不考虑对于ImageAttributes的设置(后面补充),只考虑除第一个外的其它五个构造函数的使用。
参数说明:
image:指定纹理画刷所使用的源图像,但这个图像并不一定是最终用来画图所用的图像,这只是一个源图,dstRect所指定的区域才是最终所使用的绘图单元图案;
dstRect:用于指定图案中用于画刷中的矩形区域。这个区域是从image中裁剪的。注意,它的大小不能超过基本图案的范围,否则,填充不会成功,也会报错。
wrapMode:指定在画刷中如何排列基本图案。
imageAtributes:用于指定基本图案的附加特征参数。
先看下示例:
基本图案:
代码:
- RectF rect1(10,10,200,200);
- RectF rect2(210,10,200,200);
- RectF rect3(410,10,200,200);
-
- Image image(L"img.jpg");
-
- TextureBrush tBrush1(&image);
- graphics.FillRectangle(&tBrush1,rect1);
-
- TextureBrush tBrush2(&image,Rect(10,10,50,50));
- graphics.FillRectangle(&tBrush2,rect2);
-
- TextureBrush tBrush3(&image);
- tBrush3.SetTransform(&Matrix(0.5f,0.0f,0.0f,0.5f,0.0f,0.0f));
- graphics.FillRectangle(&tBrush3,rect3);
这里是填充了,效果也出来了,但有个问题,这里可能大家不会发现,因为图像太乱了,我们单独出一个示例,
代码:
- Image image(L"img.jpg");
- UINT X=image.GetWidth();
- UINT Y=image.GetHeight();
- RectF rect(20,230,image.GetWidth(),image.GetHeight());
- TextureBrush tBrush(&image);
- graphics.FillRectangle(&tBrush,rect);
大家有没有看出问题来,我这里构造了一个矩形,矩形的大小与图像的一样,按说,它的填充效果,应该是图片正好将整个框填满,但事实上,原图左边却少了一块,右边却多出一块来,好像是向右移了20个相素似的,如果我们把
- RectF rect(20,230,image.GetWidth(),image.GetHeight());
改成
- RectF rect(0,230,image.GetWidth(),image.GetHeight());
会怎样呢?
看效果图:
到这大家可能就清楚了,画刷是先把图像从原点(0,0)平铺,然后在要显示的位置截取这一块,显示出来,并不是以要显示的区域的原点为平铺原点的!!!!
二、平铺方式
WrapMode枚举了五种平铺方式;
- enum WrapMode{
- WrapModeTile,
- WrapModeTileFlipX,
- WrapModeTileFlipY,
- WrapModeTileFlipXY,
- WrapModeClamp
- };
示例:
- Image image(L"img.jpg");
-
- TextureBrush tBrush1(&image,WrapModeClamp);
- graphics.FillRectangle(&tBrush1,Rect(0,0,170,200));
-
- TextureBrush tBrush2(&image,WrapModeTile);
- graphics.FillRectangle(&tBrush2,Rect(220,0,170,200));
-
- TextureBrush tBrush3(&image,WrapModeTileFlipX);
- graphics.FillRectangle(&tBrush3,Rect(430,0,170,200));
-
- TextureBrush tBrush4(&image,WrapModeTileFlipY);
- graphics.FillRectangle(&tBrush4,Rect(640,0,170,200));
-
- TextureBrush tBrush5(&image,WrapModeTileFlipXY);
- graphics.FillRectangle(&tBrush5,Rect(850,0,170,200));
三、画刷变换
纹理画刷的变换分为三种:旋转变换(RotateTransform)、缩放变换(ScaleTransform)和平移变换(TranslateTransform)。基本上与画笔的变换差不多,旋转变换,是将基本图案向左或向右旋转N度;缩放变换是将基本图案放大或缩小;平移变换容易让人迷,它是在绘图原点(0,0)向左移动、向右和向上、向下平移后,再进行平铺。
三种旋转方式的参数代码为:
- TextureBrush::RotateTransform(angle, order)
- TextureBrush::ScaleTransform(sx, sy, order)
- TextureBrush::TranslateTransform(dx, dy, order)
示例:
- Image img(L"img.jpg");
- TextureBrush tBrush(&img);
-
- tBrush.ResetTransform();
- graphics.FillRectangle(&tBrush,RectF(0,228,img.GetWidth(),img.GetHeight()));
-
- tBrush.TranslateTransform(30,0,MatrixOrderPrepend);
- graphics.FillRectangle(&tBrush,RectF(0,10,200,200));
-
- tBrush.RotateTransform(60,MatrixOrderAppend);
- graphics.FillRectangle(&tBrush,RectF(220,10,200,200));
-
- tBrush.ResetTransform();
- tBrush.ScaleTransform(2,1);
- graphics.FillRectangle(&tBrush,RectF(430,10,200,200));
线性渐变画刷(LinearGradientBrush))
一、构造方法
线性渐变画刷有两种构造方式,两点构造和两条直线构造(矩形构造)
- LinearGradientBrush(Point& point1, Point& point2, Color& color1, Color& color2) ;
- LinearGradientBrush(PointF& point1, PointF& point2, Color& color1, Color& color2) ;
- LinearGradientBrush(Rect& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable) ;
- LinearGradientBrush(RectF& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable) ;
- LinearGradientBrush(Rect& rect, Color& color1, Color& color2, LinearGradientMode mode) ;
- LinearGradientBrush(RectF& rect, Color& color1, Color& color2, LinearGradientMode mode) ;
前两个是两点构造,后四个是矩形构造,这里分别讲解。
(一)两点构造
使用两个点来定义色彩渐变区域时,只需用直线两个点连接起来即可,所有与这条连线平等的直线就构成渐变区域,这些直线中的任一条在外观上都是相同的,并且,每条直线色彩的变化反映着整个区域的色彩渐变。如图所示,为使用两个点定义的渐变区域的效果图。
1、构造函数:
- LinearGradientBrush(Point& point1, Point& point2, Color& color1, Color& color2) ;
- LinearGradientBrush(PointF& point1, PointF& point2, Color& color1, Color& color2) ;
示例:
- LinearGradientBrush lgBrush1(PointF(0,0),PointF(40,0),Color(255,255,0,0),Color(255,0,0,255));
- LinearGradientBrush lgBrush2(PointF(0,0),PointF(40,40),Color(255,0,255,0),Color(255,255,255,0));
-
- graphics.FillRectangle(&lgBrush1,0,0,200,200);
- graphics.FillRectangle(&lgBrush2,240,0,200,200);
2、平铺方式
设置平铺方式的函数:
- LinearGradientBrush::SetWrapMode(wrapMode);
-
-
与TextureBrush类似,TextureBrush类的成员函数SetWrapMode可设置平铺方式,图片可以使用水平翻转、垂直翻转或水平垂直叠加翻转方式在目标区域中平铺显示。其实我们的线性渐变画刷在目标区域中也可以这样控制填充方式。
我们可以把线性渐变画刷定义的区域(两点间的连线区域)看成一个单独的基本图案。对线性渐变画刷的填充方式进行控件,也就相当于在纹理画刷中对基本图案排列方式进行控制,是一样的。
示例:
- LinearGradientBrush lgBrush2(PointF(0,0),PointF(40,40),Color(255,0,255,0),Color(255,255,255,0));
-
- lgBrush2.SetWrapMode(WrapModeTile);
- graphics.FillRectangle(&lgBrush2,RectF(0,0,200,200));
-
- lgBrush2.SetWrapMode(WrapModeTileFlipX);
- graphics.SetRenderingOrigin(210,0);
- graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
-
- lgBrush2.SetWrapMode(WrapModeTileFlipY);
- graphics.SetRenderingOrigin(420,0);
- graphics.FillRectangle(&lgBrush2,RectF(420,0,200,200));
-
- lgBrush2.SetWrapMode(WrapModeTileFlipXY);
- graphics.SetRenderingOrigin(630,0);
- graphics.FillRectangle(&lgBrush2,RectF(630,0,200,200));
注意:需要强调的是,在纹理画刷中使用的WrapModeClamp图片翻转方式,并不能在线性渐变画刷中使用,主要原因是因为纹理画刷和图片是有固定大小的,而线性渐变画刷没有大小,在绘图平面中也无法独立放置。
(二)矩形构造
线性渐变画刷的渐变区域可以通过两条平行的直线来定义。如图所示为使用平行线定义渐变区域的效果图。
假设如图所示的线条1是红色的,线条2是蓝色的,在线条1与线条2之间的区域就是一个从红色到蓝色的渐变区域。使用这种方式定义渐变区域有一个特点,就是在渐变区域中任一与定义区域的直线相平行的直线的色彩都是由一种色彩构成,单条直线的色彩不存在渐变。
构造函数
- LinearGradientBrush(Rect& rect, Color& color1, Color& color2, LinearGradientMode mode)
- LinearGradientBrush(RectF& rect, Color& color1, Color& color2, LinearGradientMode mode)
- LinearGradientBrush(Rect& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable)
- LinearGradientBrush(RectF& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable)
前两个通过指定矩形的大小的色彩及填充方式来定义画笔。
后两个更自由,可以通过指定填充角度来指定色彩的渐变方向。
前两个构造函数中有一个参数LinearGradientMode,这是个枚举类,定义了色彩有渐变方向;
- enum LinearGradientMode{
- LinearGradientModeHorizontal = 0,
- LinearGradientModeVertical = 1,
- LinearGradientModeForwardDiagonal = 2,
- LinearGradientModeBackwardDiagonal = 3
- };
前两个构造函数示例:
- LinearGradientBrush lgBrush1(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeHorizontal);
- graphics.FillRectangle(&lgBrush1,RectF(0,0,200,200));
-
- LinearGradientBrush lgBrush2(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeVertical);
- graphics.SetRenderingOrigin(210,0);
- graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
-
- LinearGradientBrush lgBrush3(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeForwardDiagonal);
- graphics.SetRenderingOrigin(420,0);
- graphics.FillRectangle(&lgBrush3,RectF(420,0,200,200));
-
- LinearGradientBrush lgBrush4(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeBackwardDiagonal);
- graphics.SetRenderingOrigin(630,0);
- graphics.FillRectangle(&lgBrush4,RectF(630,0,200,200));
后两个的示例(指定填充方向,相当于旋转度数):
-
- LinearGradientBrush lgBrush1(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),0.0f);
- graphics.FillRectangle(&lgBrush1,RectF(0,0,200,200));
-
- LinearGradientBrush lgBrush2(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),30.0f);
- graphics.SetRenderingOrigin(210,0);
- graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
-
- LinearGradientBrush lgBrush3(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),60.0f);
- graphics.SetRenderingOrigin(420,0);
- graphics.FillRectangle(&lgBrush3,RectF(420,0,200,200));
-
- LinearGradientBrush lgBrush4(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),90.0f);
- graphics.SetRenderingOrigin(630,0);
- graphics.FillRectangle(&lgBrush4,RectF(630,0,200,200));
二、多色渐变
线性渐变画刷的多色渐变是指在画刷的起点、终点两种色彩的渐变过程中加入了其它色彩作为变化的过渡色,这种过渡色有时又称为插值色(Interpolation color) 。如图所示为一个“红-》绿-》蓝”3色渐变画刷的填充效果图。
注意,60这个位置,叫做混合位置,也叫插入位置,它在整个渐变区域的1/3位置,这个1/3我们以后会用到的,这里大家先注意一下;
实现多色渐变画刷的过程是,指明参与渐变的每一个过渡色彩值,然后指定每一个色彩值的插入位置。GDI+中实现多色渐变画刷是通过函数SetInterpolationColors实现的,定义如下:
- Status SetInterpolationColors(
- const Color* presetColors,
- const REAL* blendPositions,
- INT count
- );
blendPositions:包含色彩合成位置的数组。在GDI+中,合成位置是用百分比表示的,即从起点到时合成位置的长度占整个区域的百分比。
该数组的第一个和最后一个位置必须是0%和100%,分别代表起止点色彩的位置,否则定义出的渐变画刷是不能正常工作的,所以这里的色彩就把定义画刷时我渐变色彩给替代了,也就是如果用了插入色彩来进行多色渐变,定义画刷时色彩就没用了。
示例(三色渐变):
- Color colors[] = {
- Color(255, 255, 0, 0),
- Color(255, 0, 0, 255),
- Color(255, 0, 255, 0)};
-
- REAL positions[] = {
- 0.0f,
- 0.3f,
- 1.0f};
-
- LinearGradientBrush linGrBrush(Point(0, 0), Point(200, 0),
- Color(255, 0, 0, 0),
- Color(255, 255, 255, 255));
-
- linGrBrush.SetInterpolationColors(colors, positions, 3);
- graphics.FillRectangle(&linGrBrush, 0, 0, 400, 250);
三、定制线性渐变画刷的色彩渐变行为
对于双色渐变画刷,默认情况下,其色彩的渐变是沿着水平方向逐渐进行的,两种色彩的差异在渐变区域的中央部分达到最小(最模糊)。线性渐变画刷引入了“合成因子”(Blend Factors)这个概念来量化“彩色差异最小”这个模糊的概念。简单地说,合成因子以百分比的形式代表色彩渐变的度。GDI+中全成因子的默认值为100%,表示色彩完全转换。任何使用小于100%的合成因子值进行的渐变,被渐变的色彩都会不完全地转换成第2种颜色。如果将该值设置成0,这意味着色彩将不进行渐变。对于双色渐变画刷,合成因子代表的终点色的转变程序,0表示不转变成终点色,1表示全部转变成终点色;对于多色渐变画刷,合成因子代表着每一个参与渐变的过渡色的渐变程度。
使用SetBlend函数可以改变默认的色彩渐变行为,该函数的定义为:
- Status SetBlend(
- const REAL* blendFactors,
- const REAL* blendPositions,
- INT count
- );
blendFactiors:包含合成因子的数组,每一个数组成员的取值范围为0-1,0表示不转变成终点色,1表示完全转变成终点色。
blendPosition:包含合成位置的数组,每一个数组成员依次代表着参与渐变的过渡色的合成位置。注意:该数组的第一个和最后一个变量代表了起止点色彩的合成位置,这两个值必须是0%和100%。
count:合成点位置数。与blendPosition数组大小一致。
SetBlend函数功能在于告诉GDI+在什么地方进行了色彩合成,色彩的合成度是多少。
看例子:
- REAL factors[4]={0.0f,0.9f,0.3f,0.0f};
- REAL position[4]={0.0f,0.1f,0.6f,1.0f};
-
- RectF rect(0,0,200,200);
- LinearGradientBrush lgbrush(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
-
- lgbrush.SetBlend(factors,position,4);
- graphics.FillRectangle(&lgbrush,rect);
说明:positions变量指明了色彩渐变在4个相对的位置进行,factors具体指明了在每个相对位置进行渐变的合成因子。factors的第一个成员值是0.0f,表示绿色不参与渐变,所以在第一个位置全部是红色,形成红色光带。在第2个位置的合成因子是0.9f,表示该位置90%显示绿色,10%显示红色,进行色彩合成,所以基本保持了绿色原貌,所以形成绿色光带;在第3个位置的合成因子是0.3f,表示蓝色以30%的程度叠加上70%的红色,形成该部位的颜色值,红色成了主色,所以红色光带再次形成。最后位置的合成因子为0,所以根第一个位置一样,全部显示为红色。
需要再次强调的是:对于双色画刷,合成因子是终点色相对于起点色的渐变程度。
四、改变合成位置
在双色渐变中,我们可以通过上面的SetBlend()来定制画刷的渐变形为,这种方法比较简单易用,我们还有另一种方法来定制画刷的渐变形为,但并没有上面的SetBlend()强大,只能改变最终色的合成位置,在默认情况下,最终色的合成位置在最右边(比例位置为1.0),我们可以通过函数改变它的位置,让他在指定位置合成。
改变最终色合成位置的函数如下:
- LinearGradientBrush::SetBlendTriangularShape(focus, scale);
- LinearGradientBrush::SetBlendBellShape(focus, scale);
这两种方法都能实现合成位置的改变,而且实现的效果上不会有太大差异,一般选中哪个都可以。
示例:
- RectF rect(0,0,200,200);
- LinearGradientBrush lgbrush(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
- LinearGradientBrush lgbrush2(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
-
- lgbrush.SetBlendTriangularShape(0.1f,0.8);
- lgbrush2.SetBlendBellShape(0.1,0.8);
-
- graphics.FillRectangle(&lgbrush,rect);
- graphics.FillRectangle(&lgbrush2,RectF(0,210,200,200)
说明:从效果图上可以看出,最终色的合成位置被移到了0.1处,从效果来看,钟形曲线渐变效果更平滑一些。