画刷Brush

GDI+中定义了五种画刷类型,他们都派生于Brush类,他们分别是:

注意:画刷与画笔不同,画刷只是用来填充区域,所以,画刷无宽度、长度可言。

单色画刷SolidBrush

一、构造函数

[cpp] view plaincopy
  1. SolidBrush greenBrush(Color(255,0,255,0)); //在GDI+中颜色值,没有RGB()构造,只能用Color()构造

二、所使用的填充函数

[cpp] view plaincopy
  1. graphics.FillClosedCurve();//填充闭合曲线
  2. graphics.FillEllipse();  //填充椭圆
  3. graphics.FillPath(); //填充路径
  4. graphics.FillPie();  //填充扇形
  5. graphics.FillPolygon(); //填充多边形
  6. graphics.FillRectangle(); //填充矩形
  7. graphics.FillRectangles(); //填充矩形集
  8. graphics.FillRegion(); //填充区域

对于这些区域填充函数的使用,已经在前面讲过了,大家可以参考《GDI+学习及代码总结之------画线、区域填充、写字》这一篇文章

影线画刷HatchBrush

影线画刷,故名思意,就是用前景色与背景色,根据预定好的横线、竖线及斜线组成的图形,影线画刷用HatchBrush定义,其构造函数为:

[cpp] view plaincopy
  1. HatchBrush::HatchBrush(hatchStyle, foreColor, backColor);//hatchstyle是一个枚举类,枚举了53种风格的影线画刷,forColor:前景色 ,backColor:背景色

大家看hatchStyle定义:

[cpp] view plaincopy
  1. enum HatchStyle{
  2. HatchStyleHorizontal = 0,
  3. HatchStyleVertical = 1,
  4. HatchStyleForwardDiagonal = 2,
  5. HatchStyleBackwardDiagonal = 3,
  6. HatchStyleCross = 4,
  7. HatchStyleDiagonalCross = 5,
  8. HatchStyle05Percent = 6,
  9. HatchStyle10Percent = 7,
  10. HatchStyle20Percent = 8,
  11. HatchStyle25Percent = 9,
  12. HatchStyle30Percent = 10,
  13. HatchStyle40Percent = 11,
  14. HatchStyle50Percent = 12,
  15. HatchStyle60Percent = 13,
  16. HatchStyle70Percent = 14,
  17. HatchStyle75Percent = 15,
  18. HatchStyle80Percent = 16,
  19. HatchStyle90Percent = 17,
  20. HatchStyleLightDownwardDiagonal = 18,
  21. HatchStyleLightUpwardDiagonal = 19,
  22. HatchStyleDarkDownwardDiagonal = 20,
  23. HatchStyleDarkUpwardDiagonal = 21,
  24. HatchStyleWideDownwardDiagonal = 22,
  25. HatchStyleWideUpwardDiagonal = 23,
  26. HatchStyleLightVertical = 24,
  27. HatchStyleLightHorizontal = 25,
  28. HatchStyleNarrowVertical = 26,
  29. HatchStyleNarrowHorizontal = 27,
  30. HatchStyleDarkVertical = 28,
  31. HatchStyleDarkHorizontal = 29,
  32. HatchStyleDashedDownwardDiagonal = 30,
  33. HatchStyleDashedUpwardDiagonal = 31,
  34. HatchStyleDashedHorizontal = 32,
  35. HatchStyleDashedVertical = 33,
  36. HatchStyleSmallConfetti = 34,
  37. HatchStyleLargeConfetti = 35,
  38. HatchStyleZigZag = 36,
  39. HatchStyleWave = 37,
  40. HatchStyleDiagonalBrick = 38,
  41. HatchStyleHorizontalBrick = 39,
  42. HatchStyleWeave = 40,
  43. HatchStylePlaid = 41,
  44. HatchStyleDivot = 42,
  45. HatchStyleDottedGrid = 43,
  46. HatchStyleDottedDiamond = 44,
  47. HatchStyleShingle = 45,
  48. HatchStyleTrellis = 46,
  49. HatchStyleSphere = 47,
  50. HatchStyleSmallGrid = 48,
  51. HatchStyleSmallCheckerBoard = 49,
  52. HatchStyleLargeCheckerBoard = 50,
  53. HatchStyleOutlinedDiamond = 51,
  54. HatchStyleSolidDiamond = 52,
  55. HatchStyleTotal,
  56. HatchStyleLargeGrid = HatchStyleCross,
  57. HatchStyleMin = HatchStyleHorizontal,
  58. HatchStyleMax = HatchStyleTotal - 1
  59. };

这个定义有些长,而且让人搞不懂他们分别对应什么图形,让我们看下面的图像,他们从左至右、从上到下排列,序号分别是0-52,(前景色为:红色,背景色为:绿色),CSDN处理的有些失真,大家可以在MSDN上看下这个枚举类,有对应的图形。

我们简单使用一下影线画刷,用它来填充两个矩形,示例:

[cpp] view plaincopy
  1. Color forColor(255,0,0,0);
  2. Color bkColor(255,255,0,255);
  3. HatchBrush brush(HatchStyleHorizontal, forColor, bkColor);
  4. graphics.FillRectangle(&brush, 20, 20, 100, 50);
  5. HatchBrush brush1(HatchStyleVertical, forColor, bkColor);
  6. graphics.FillRectangle(&brush1, 140, 20, 100, 50);

影线画刷的单个与整体

从构成上看,影线画刷是小正方形图案的简单重复,单个的正方形图案决定了画刷的整体外观。下图所示为影线画刷的基本构成:

左图所示是影线画刷放大后的基本图案,该图案由前景色和背景色两部分构成。右图,就是由这些个小的基本图案重复而成。上面所枚举的53种图案,都是由它自己的基本图案重复平铺而成。

设置影线画刷的绘制原点

绘制原点,即在什么地方开始绘制,它并不是指相对所要填充的矩形原点的填充位置,而是对基本图案而言的。设置绘制原点的语句为:

[cpp] view plaincopy
  1. Graphics::SetRenderingOrigin(x, y);//X为相对X轴方向的偏移量,Y为相对Y轴方向的偏移量

如果我们设置这样一条语句,setRenderingOrigin(0,3);会是什么效果呢?看下面讲解;

我们说了,是相对基本图案而言,我们还是3-13的图,

所以,它先从基本图案的纵向偏移3个相素,然后用偏移后的图案开始绘制

示例:(向下偏移4个相素)

[cpp] view plaincopy
  1. HatchBrush hatchBrush(
  2. HatchStyle(52),
  3. Color(255, 255, 0, 0),     // red
  4. Color(255, 0, 255, 255));  // aqua
  5. graphics.FillRectangle(&hatchBrush, 0, 0, 100, 50);//未偏移前
  6. graphics.SetRenderingOrigin(0,4);
  7. graphics.FillRectangle(&hatchBrush, 120, 0, 100, 50);//偏移4个相素

纹理画刷TextureBrush

纹理画刷,与影线画刷类似,也是使用同样的基本图案在水平和垂直方向上按一定的顺序平铺。不同的是,纹理画刷使用的是基本的图像来做基本图案的。

一、构造函数(待完)

[cpp] view plaincopy
  1. TextureBrush(Image* image, Rect& dstRect, ImageAttributes* imageAttributes)
  2. TextureBrush(Image* image, RectF& dstRect, ImageAttributes* imageAttributes)
  3. TextureBrush(image, wrapMode)
  4. TextureBrush(Image* image, WrapMode wrapMode, Rect& dstRect)
  5. TextureBrush(Image* image, WrapMode wrapMode, RectF& dstRect)
  6. TextureBrush(Image* image, WrapMode wrapMode, INT dstX, INT dstY, INT dstWidth, INT dstHeight)
  7. TextureBrush(Image* image, WrapMode wrapMode, REAL dstX, REAL dstY, REAL dstWidth, REAL dstHeight)

这里不考虑对于ImageAttributes的设置(后面补充),只考虑除第一个外的其它五个构造函数的使用。
参数说明:

image:指定纹理画刷所使用的源图像,但这个图像并不一定是最终用来画图所用的图像,这只是一个源图,dstRect所指定的区域才是最终所使用的绘图单元图案;

dstRect:用于指定图案中用于画刷中的矩形区域。这个区域是从image中裁剪的。注意,它的大小不能超过基本图案的范围,否则,填充不会成功,也会报错。

wrapMode:指定在画刷中如何排列基本图案。

imageAtributes:用于指定基本图案的附加特征参数。

先看下示例:

基本图案:

代码:

[cpp] view plaincopy
  1. RectF rect1(10,10,200,200);
  2. RectF rect2(210,10,200,200);
  3. RectF rect3(410,10,200,200);
  4. Image image(L"img.jpg");
  5. TextureBrush tBrush1(&image);
  6. graphics.FillRectangle(&tBrush1,rect1); //完整图案填充
  7. TextureBrush tBrush2(&image,Rect(10,10,50,50));
  8. graphics.FillRectangle(&tBrush2,rect2);//从源图截取一部分填充
  9. TextureBrush tBrush3(&image);
  10. tBrush3.SetTransform(&Matrix(0.5f,0.0f,0.0f,0.5f,0.0f,0.0f));
  11. graphics.FillRectangle(&tBrush3,rect3);//缩小0。5倍填充


这里是填充了,效果也出来了,但有个问题,这里可能大家不会发现,因为图像太乱了,我们单独出一个示例,

代码:

[cpp] view plaincopy
  1. Image image(L"img.jpg");
  2. UINT X=image.GetWidth();
  3. UINT Y=image.GetHeight();
  4. RectF rect(20,230,image.GetWidth(),image.GetHeight());
  5. TextureBrush tBrush(&image);
  6. graphics.FillRectangle(&tBrush,rect);

大家有没有看出问题来,我这里构造了一个矩形,矩形的大小与图像的一样,按说,它的填充效果,应该是图片正好将整个框填满,但事实上,原图左边却少了一块,右边却多出一块来,好像是向右移了20个相素似的,如果我们把

[cpp] view plaincopy
  1. RectF rect(20,230,image.GetWidth(),image.GetHeight());

改成

[cpp] view plaincopy
  1. RectF rect(0,230,image.GetWidth(),image.GetHeight());

会怎样呢?

看效果图:

到这大家可能就清楚了,画刷是先把图像从原点(0,0)平铺,然后在要显示的位置截取这一块,显示出来,并不是以要显示的区域的原点为平铺原点的!!!!

二、平铺方式

WrapMode枚举了五种平铺方式;

[cpp] view plaincopy
  1. enum WrapMode{
  2. WrapModeTile,  //普通平铺
  3. WrapModeTileFlipX,  //水平方向翻转并平铺
  4. WrapModeTileFlipY,  //垂直方向翻转并平铺
  5. WrapModeTileFlipXY,  //在水平和垂直方向都翻转并平铺,它是WrapModeTileFlipX与WrapModeTileFlipY效果的组合
  6. WrapModeClamp  //不进行平铺,只在以(0,0)位置为原点显示一张图片
  7. };

示例:

[cpp] view plaincopy
  1. Image image(L"img.jpg");
  2. TextureBrush tBrush1(&image,WrapModeClamp);//不进行平铺
  3. graphics.FillRectangle(&tBrush1,Rect(0,0,170,200));
  4. TextureBrush tBrush2(&image,WrapModeTile);  //平铺
  5. graphics.FillRectangle(&tBrush2,Rect(220,0,170,200));
  6. TextureBrush tBrush3(&image,WrapModeTileFlipX);  //水平方向翻转并平铺
  7. graphics.FillRectangle(&tBrush3,Rect(430,0,170,200));
  8. TextureBrush tBrush4(&image,WrapModeTileFlipY);  //垂直方向翻转并平铺
  9. graphics.FillRectangle(&tBrush4,Rect(640,0,170,200));
  10. TextureBrush tBrush5(&image,WrapModeTileFlipXY); //在水平和垂直方向都翻转并平铺,它是WrapModeTileFlipX与WrapModeTileFlipY效果的组合
  11. graphics.FillRectangle(&tBrush5,Rect(850,0,170,200));

三、画刷变换

纹理画刷的变换分为三种:旋转变换(RotateTransform)、缩放变换(ScaleTransform)和平移变换(TranslateTransform)。基本上与画笔的变换差不多,旋转变换,是将基本图案向左或向右旋转N度;缩放变换是将基本图案放大或缩小;平移变换容易让人迷,它是在绘图原点(0,0)向左移动、向右和向上、向下平移后,再进行平铺。

三种旋转方式的参数代码为:

[cpp] view plaincopy
  1. TextureBrush::RotateTransform(angle, order) //旋转变换,angle为度数,order指定向左还是向右转
  2. TextureBrush::ScaleTransform(sx, sy, order) //缩放变换,sx为水平放大的倍数,1为不变;sy为垂直放大的倍数,同样,1为不变,不能设为0
  3. TextureBrush::TranslateTransform(dx, dy, order) //平移变换,dx,dy分别指定沿X轴,沿Y轴平移的相素数,order是指向左平移还是向右平移

示例:

[cpp] view plaincopy
  1. Image img(L"img.jpg");
  2. TextureBrush tBrush(&img);
  3. //原图
  4. tBrush.ResetTransform();
  5. graphics.FillRectangle(&tBrush,RectF(0,228,img.GetWidth(),img.GetHeight()));
  6. //相对绘制原点平移,这里相对的是(0,0)点
  7. tBrush.TranslateTransform(30,0,MatrixOrderPrepend);
  8. graphics.FillRectangle(&tBrush,RectF(0,10,200,200));
  9. //旋转
  10. tBrush.RotateTransform(60,MatrixOrderAppend);//原本是MatrixOrderAppend是向右转,MatrixOrderPrepend是向左转,但这里设置了后并没有用,两个全都向右转了,说明API有问题
  11. graphics.FillRectangle(&tBrush,RectF(220,10,200,200));
  12. //放大缩小
  13. tBrush.ResetTransform();
  14. tBrush.ScaleTransform(2,1);//水平放大两倍
  15. graphics.FillRectangle(&tBrush,RectF(430,10,200,200));

线性渐变画刷(LinearGradientBrush))

一、构造方法

线性渐变画刷有两种构造方式,两点构造和两条直线构造(矩形构造)

[cpp] view plaincopy
  1. LinearGradientBrush(Point& point1, Point& point2, Color& color1, Color& color2) ;
  2. LinearGradientBrush(PointF& point1, PointF& point2, Color& color1, Color& color2) ;//两点构造
  3. LinearGradientBrush(Rect& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable) ;
  4. LinearGradientBrush(RectF& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable) ;
  5. LinearGradientBrush(Rect& rect, Color& color1, Color& color2, LinearGradientMode mode) ;
  6. LinearGradientBrush(RectF& rect, Color& color1, Color& color2, LinearGradientMode mode) ;//矩形构造

前两个是两点构造,后四个是矩形构造,这里分别讲解。

(一)两点构造

使用两个点来定义色彩渐变区域时,只需用直线两个点连接起来即可,所有与这条连线平等的直线就构成渐变区域,这些直线中的任一条在外观上都是相同的,并且,每条直线色彩的变化反映着整个区域的色彩渐变。如图所示,为使用两个点定义的渐变区域的效果图。

1、构造函数:

[cpp] view plaincopy
  1. LinearGradientBrush(Point& point1, Point& point2, Color& color1, Color& color2) ;
  2. LinearGradientBrush(PointF& point1, PointF& point2, Color& color1, Color& color2) ;

示例:

[cpp] view plaincopy
  1. LinearGradientBrush lgBrush1(PointF(0,0),PointF(40,0),Color(255,255,0,0),Color(255,0,0,255));//水平渐变
  2. LinearGradientBrush lgBrush2(PointF(0,0),PointF(40,40),Color(255,0,255,0),Color(255,255,255,0));//斜向渐变
  3. graphics.FillRectangle(&lgBrush1,0,0,200,200);
  4. graphics.FillRectangle(&lgBrush2,240,0,200,200);

2、平铺方式

设置平铺方式的函数:

[cpp] view plaincopy
  1. LinearGradientBrush::SetWrapMode(wrapMode);//wrapMode是个枚举类,包括:
  2. //WrapModeTile,WrapModeTileFlipXWrapModeTileFlipY,WrapModeTileFlipXY,WrapModeClamp
  3. //WrapModeClamp不能在这里使用。原因见下面的注意讲解

与TextureBrush类似,TextureBrush类的成员函数SetWrapMode可设置平铺方式,图片可以使用水平翻转、垂直翻转或水平垂直叠加翻转方式在目标区域中平铺显示。其实我们的线性渐变画刷在目标区域中也可以这样控制填充方式。

我们可以把线性渐变画刷定义的区域(两点间的连线区域)看成一个单独的基本图案。对线性渐变画刷的填充方式进行控件,也就相当于在纹理画刷中对基本图案排列方式进行控制,是一样的。

示例:

[cpp] view plaincopy
  1. LinearGradientBrush lgBrush2(PointF(0,0),PointF(40,40),Color(255,0,255,0),Color(255,255,255,0));//斜向渐变
  2. //普通平铺
  3. lgBrush2.SetWrapMode(WrapModeTile);//默认
  4. graphics.FillRectangle(&lgBrush2,RectF(0,0,200,200));
  5. //水平方向翻转并平铺
  6. lgBrush2.SetWrapMode(WrapModeTileFlipX);
  7. graphics.SetRenderingOrigin(210,0);//设置绘画原点,默认是从(0,0)开始
  8. graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
  9. //垂直方向翻转并平铺
  10. lgBrush2.SetWrapMode(WrapModeTileFlipY);
  11. graphics.SetRenderingOrigin(420,0);
  12. graphics.FillRectangle(&lgBrush2,RectF(420,0,200,200));
  13. //在水平和垂直方向都翻转并平铺,它是WrapModeTileFlipX与WrapModeTileFlipY效果的组合
  14. lgBrush2.SetWrapMode(WrapModeTileFlipXY);
  15. graphics.SetRenderingOrigin(630,0);
  16. graphics.FillRectangle(&lgBrush2,RectF(630,0,200,200));


注意:需要强调的是,在纹理画刷中使用的WrapModeClamp图片翻转方式,并不能在线性渐变画刷中使用,主要原因是因为纹理画刷和图片是有固定大小的,而线性渐变画刷没有大小,在绘图平面中也无法独立放置。

(二)矩形构造

线性渐变画刷的渐变区域可以通过两条平行的直线来定义。如图所示为使用平行线定义渐变区域的效果图。

假设如图所示的线条1是红色的,线条2是蓝色的,在线条1与线条2之间的区域就是一个从红色到蓝色的渐变区域。使用这种方式定义渐变区域有一个特点,就是在渐变区域中任一与定义区域的直线相平行的直线的色彩都是由一种色彩构成,单条直线的色彩不存在渐变。

构造函数

[cpp] view plaincopy
  1. LinearGradientBrush(Rect& rect, Color& color1, Color& color2, LinearGradientMode mode)
  2. LinearGradientBrush(RectF& rect, Color& color1, Color& color2, LinearGradientMode mode)
  3. LinearGradientBrush(Rect& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable)
  4. LinearGradientBrush(RectF& rect, Color& color1, Color& color2, REAL angle, BOOL isAngleScalable)

前两个通过指定矩形的大小的色彩及填充方式来定义画笔。

后两个更自由,可以通过指定填充角度来指定色彩的渐变方向。

前两个构造函数中有一个参数LinearGradientMode,这是个枚举类,定义了色彩有渐变方向;

[cpp] view plaincopy
  1. enum LinearGradientMode{
  2. LinearGradientModeHorizontal = 0,//水平渐变
  3. LinearGradientModeVertical   = 1, //垂直渐变
  4. LinearGradientModeForwardDiagonal  = 2,//从左上角到右下角渐变(矩形对角线方向)
  5. LinearGradientModeBackwardDiagonal = 3//从右上角到左下角渐变(另一条矩形对角线方向)
  6. };

前两个构造函数示例:

[cpp] view plaincopy
  1. LinearGradientBrush lgBrush1(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeHorizontal);
  2. graphics.FillRectangle(&lgBrush1,RectF(0,0,200,200));
  3. LinearGradientBrush lgBrush2(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeVertical);
  4. graphics.SetRenderingOrigin(210,0);
  5. graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
  6. LinearGradientBrush lgBrush3(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeForwardDiagonal);
  7. graphics.SetRenderingOrigin(420,0);
  8. graphics.FillRectangle(&lgBrush3,RectF(420,0,200,200));
  9. LinearGradientBrush lgBrush4(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),LinearGradientModeBackwardDiagonal);
  10. graphics.SetRenderingOrigin(630,0);
  11. graphics.FillRectangle(&lgBrush4,RectF(630,0,200,200));


后两个的示例(指定填充方向,相当于旋转度数):

[cpp] view plaincopy
  1. //不旋转
  2. LinearGradientBrush lgBrush1(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),0.0f);
  3. graphics.FillRectangle(&lgBrush1,RectF(0,0,200,200));
  4. //旋转30度
  5. LinearGradientBrush lgBrush2(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),30.0f);
  6. graphics.SetRenderingOrigin(210,0);
  7. graphics.FillRectangle(&lgBrush2,RectF(210,0,200,200));
  8. //旋转60度
  9. LinearGradientBrush lgBrush3(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),60.0f);
  10. graphics.SetRenderingOrigin(420,0);
  11. graphics.FillRectangle(&lgBrush3,RectF(420,0,200,200));
  12. //旋转90度
  13. LinearGradientBrush lgBrush4(RectF(0,0,40,20),Color(255,0,255,0),Color(255,0,255,255),90.0f);
  14. graphics.SetRenderingOrigin(630,0);
  15. graphics.FillRectangle(&lgBrush4,RectF(630,0,200,200));


二、多色渐变

线性渐变画刷的多色渐变是指在画刷的起点、终点两种色彩的渐变过程中加入了其它色彩作为变化的过渡色,这种过渡色有时又称为插值色(Interpolation color) 。如图所示为一个“红-》绿-》蓝”3色渐变画刷的填充效果图。

注意,60这个位置,叫做混合位置,也叫插入位置,它在整个渐变区域的1/3位置,这个1/3我们以后会用到的,这里大家先注意一下;

实现多色渐变画刷的过程是,指明参与渐变的每一个过渡色彩值,然后指定每一个色彩值的插入位置。GDI+中实现多色渐变画刷是通过函数SetInterpolationColors实现的,定义如下:

[cpp] view plaincopy
  1. Status SetInterpolationColors(
  2. const Color* presetColors,//一个包含多种预定义过渡色的数组。
  3. const REAL* blendPositions,//下面具体讲解
  4. INT count//过渡色的个数
  5. );

blendPositions:包含色彩合成位置的数组。在GDI+中,合成位置是用百分比表示的,即从起点到时合成位置的长度占整个区域的百分比。该数组的第一个和最后一个位置必须是0%和100%,分别代表起止点色彩的位置,否则定义出的渐变画刷是不能正常工作的,所以这里的色彩就把定义画刷时我渐变色彩给替代了,也就是如果用了插入色彩来进行多色渐变,定义画刷时色彩就没用了。

示例(三色渐变):

[cpp] view plaincopy
  1. Color colors[] = {
  2. Color(255, 255, 0, 0),   // red
  3. Color(255, 0, 0, 255),   // blue
  4. Color(255, 0, 255, 0)};  // green
  5. REAL positions[] = {
  6. 0.0f,   // 红色位置,必须是0
  7. 0.3f,   // 蓝色在30%位置
  8. 1.0f};  //绿色在右边界,必须是1,看上面的blendPositions说明
  9. //注意,这里原定义的是黑色到白色的渐变,上面插入的颜色将他们替换掉了。
  10. LinearGradientBrush linGrBrush(Point(0, 0), Point(200, 0),
  11. Color(255, 0, 0, 0),         // 黑色
  12. Color(255, 255, 255, 255));  // 白色
  13. linGrBrush.SetInterpolationColors(colors, positions, 3);
  14. graphics.FillRectangle(&linGrBrush, 0, 0, 400, 250);


三、定制线性渐变画刷的色彩渐变行为

对于双色渐变画刷,默认情况下,其色彩的渐变是沿着水平方向逐渐进行的,两种色彩的差异在渐变区域的中央部分达到最小(最模糊)。线性渐变画刷引入了“合成因子”(Blend Factors)这个概念来量化“彩色差异最小”这个模糊的概念。简单地说,合成因子以百分比的形式代表色彩渐变的度。GDI+中全成因子的默认值为100%,表示色彩完全转换。任何使用小于100%的合成因子值进行的渐变,被渐变的色彩都会不完全地转换成第2种颜色。如果将该值设置成0,这意味着色彩将不进行渐变。对于双色渐变画刷,合成因子代表的终点色的转变程序,0表示不转变成终点色,1表示全部转变成终点色;对于多色渐变画刷,合成因子代表着每一个参与渐变的过渡色的渐变程度。

使用SetBlend函数可以改变默认的色彩渐变行为,该函数的定义为:

[cpp] view plaincopy
  1. Status SetBlend(
  2. const REAL* blendFactors,
  3. const REAL* blendPositions,
  4. INT count
  5. );

blendFactiors:包含合成因子的数组,每一个数组成员的取值范围为0-1,0表示不转变成终点色,1表示完全转变成终点色。

blendPosition:包含合成位置的数组,每一个数组成员依次代表着参与渐变的过渡色的合成位置。注意:该数组的第一个和最后一个变量代表了起止点色彩的合成位置,这两个值必须是0%和100%。

count:合成点位置数。与blendPosition数组大小一致。

SetBlend函数功能在于告诉GDI+在什么地方进行了色彩合成,色彩的合成度是多少。

看例子:

[cpp] view plaincopy
  1. REAL factors[4]={0.0f,0.9f,0.3f,0.0f};
  2. REAL position[4]={0.0f,0.1f,0.6f,1.0f};
  3. RectF rect(0,0,200,200);
  4. LinearGradientBrush lgbrush(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
  5. lgbrush.SetBlend(factors,position,4);
  6. 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),我们可以通过函数改变它的位置,让他在指定位置合成。

改变最终色合成位置的函数如下:

[cpp] view plaincopy
  1. LinearGradientBrush::SetBlendTriangularShape(focus, scale);//基于三角形的渐变
  2. LinearGradientBrush::SetBlendBellShape(focus, scale);//基于钟型曲线的渐变

这两种方法都能实现合成位置的改变,而且实现的效果上不会有太大差异,一般选中哪个都可以。

示例:

[cpp] view plaincopy
  1. RectF rect(0,0,200,200);
  2. LinearGradientBrush lgbrush(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
  3. LinearGradientBrush lgbrush2(rect,Color::Red,Color::Green,LinearGradientModeHorizontal);
  4. //使用三角形渐变
  5. lgbrush.SetBlendTriangularShape(0.1f,0.8);
  6. lgbrush2.SetBlendBellShape(0.1,0.8);
  7. //使用钟形渐变
  8. graphics.FillRectangle(&lgbrush,rect);
  9. graphics.FillRectangle(&lgbrush2,RectF(0,210,200,200)


说明:从效果图上可以看出,最终色的合成位置被移到了0.1处,从效果来看,钟形曲线渐变效果更平滑一些。

路径渐变画刷(GraphicsPath)--未学

暂时用不到,先不学习,待以后用到的时候再学吧,嘿嘿

GDI+学习及代码总结之------画刷Brush .相关推荐

  1. GDI+ 学习记录(11): 路径渐变画刷 - PathGradientBrush

    为什么80%的码农都做不了架构师?>>>    //路径渐变画刷 varg: TGPGraphics;path: TGPGraphicsPath;pb: TGPPathGradien ...

  2. GDI+ 学习记录(10): 线性渐变画刷 - LinearGradientBrush

    为什么80%的码农都做不了架构师?>>>    //线性渐变画刷 varg: TGPGraphics;lb: TGPLinearGradientBrush;rect: TGPRect ...

  3. GDI+学习记录(10)- 影线画刷HatchBrush

    影线画刷(HatchBrush)的基本使用: private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Gr ...

  4. MFC之学习绘制椭圆、库画刷使用

    1.笔记 1.1绘制椭圆 函数原型: BOOL CDC::Ellipse(int x1,int y1,int x2,int y2); BOOL CDC::Ellipse(LPCRECT lpRect) ...

  5. windows phone 前台布局以及画刷Brush使用

    大家都知道windows phone前台使用sliverlight的xaml来进行布局,但是当我们要做一个软件的时候也许我们会随便拖几个控件放在界面上,,这样也不可以说不行,但是如果界面复杂,控件繁多 ...

  6. CSharp代码示例每日一讲: 在GDI+中使用画笔和画刷

    CSharp代码示例每日一讲,为刚刚学习编程的人准备,利用最简单的代码介绍CSharp编程知识! 画笔和画刷是图形应用中最常用的两种对象.笔用于绘制图形对象的轮廓,如线条和曲线;刷子是用来填充图形对象 ...

  7. 虚幻四学习笔记(3)—— 使用BSP画刷创建简单场景

    文章目录 前言 准备工作 创建一个盒子 加入一些障碍物 为画刷添加一些材质 保存关卡和关卡设置 前言 参考资料: https://www.bilibili.com/video/BV164411Y732 ...

  8. MFC更换画笔(画刷)颜色以及画眼睛(GDI画图)

    MFC画眼睛 换画笔(画刷)颜色(参考链接:https://blog.csdn.net/sunxiving/article/details/51272001) 由于画笔一旦创建后就无法修改.所以要修改 ...

  9. 深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例

    深入WPF中的图像画刷(ImageBrush)之1--ImageBrush使用举例 2010年06月11日 星期五 15:20 昨天我在<简述WPF中的画刷(Brush) >中简要介绍了W ...

  10. QPainter 画笔(QPen)和画刷(QBrush)

    Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕上和绘图·设备上进行绘制,主要基于QPainter.QPainterDevice和QPainterEngine这3个类.QPainter执行绘 ...

最新文章

  1. 如何用TF Object Detection API训练交通信号灯检测神经网络?
  2. 实战ALV OO技术实现添加工具条按钮
  3. 苹果芯片工程师又被挖!这次是微软,要自研Azure服务器芯片
  4. 在brew开发中遇到的一些问题
  5. win8计算机休眠的区别,详细说明win8和win10系统中待机,休眠和睡眠的功能和区别_Computer Basics_IT /...
  6. junit4 单元测试框架_超越JUnit –测试框架的替代方案
  7. python众数问题给定含有n个元素的多重集合s_分治法求众数 给定含有n个元素的多重集合S 联合开发网 - pudn.com...
  8. springboot项目中mybatis实现数据的基本查询
  9. Go语言学习Day04
  10. [CTO札记]好部下的3个层次
  11. springcloud 图片和数据一起提交_SpringCloud网上商城系统(附源码及教程)
  12. 《Two Dozen Short Lessons in Haskell》学习(三)
  13. 关于分行数字化转型工作的几点思考
  14. python画十字_Python解决十字消除棋
  15. shell脚本中 EOF的意思
  16. IPD的主要难点在I即集成,这需要在别人身上穿洞
  17. 戏说cosplay武媚娘传奇
  18. 程序封装真的是令人讨厌_网络上最令人讨厌的黑暗模式
  19. 关于22年应届生就业难发表一些自己的想法
  20. 详细描述NAND FLASH FTL 层算法

热门文章

  1. 【混凝土强度预测】基于matlab BP神经网络混凝土强度预测【含Matlab源码 695期】
  2. 【图像边缘检测】基于matlab元胞自动机图像边缘检测【含Matlab源码 427期】
  3. @scheduled注解配置时间_《SpringBoot整合redis、Scheduled/quartz定时任务》
  4. 数据应用apply练习
  5. python制作中秋贺卡图片_中秋贺卡手工制作图片
  6. 文件大小超过配置限制(2560000),代码洞察功能不可用怎么办?
  7. python defaultdict 递归_在Python中使用defaultdict初始化字典以及应用方法
  8. ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
  9. Asp.net core 学习笔记 ( OData )
  10. 12.10 Nginx访问日志;12.11 Nginx日志切割;12.12 静态文件不记录日志和过期