欢迎光临
我们一直在努力

矩形圆角绘制改进版(附源码)

一、前言

上一篇绘制矩形圆角的方式不够完善,感觉写的太过于复杂,将简单的问题复杂化了,本文对此进行了相应的改进,增强对各个圆角的半径的控制。绘制后的圆角效果图如下:

矩形圆角绘制改进版(附源码)

二、圆角半径设计

对于矩行而言,圆角分为左上角、右上角、左下角和右下角。每一个角都会存在相应的半径,用于控制每一个圆角的绘制。设计如下:

  1     public struct arcradius
  2     {
  3         private int _rightBottom;
  4         private int _rightTop;
  5         private int _leftBottom;
  6         private int _leftTop;
  7 
  8         public static readonly ArcRadius Empty =new ArcRadius(0);
  9 
 10         public ArcRadius(int radiusLength)
 11         {
 12             if (radiusLength < 0)
 13             {
 14                 radiusLength = 0;
 15             }
 16 
 17             this._rightBottom = this._rightTop = this._leftBottom = this._leftTop = radiusLength;
 18         }
 19 
 20         public ArcRadius(int leftTop, int rightTop, int leftBottom, int rightBottom)
 21         {
 22             this._rightBottom = rightBottom < 0 ? 0 : rightBottom;
 23             this._rightTop = rightTop < 0 ? 0 : rightTop;
 24             this._leftBottom = leftBottom < 0 ? 0 : leftBottom;
 25             this._leftTop = leftTop < 0 ? 0 : leftTop;
 26         }
 27 
 28         private bool IsAllEqual()
 29         {
 30             return ((this.RightBottom == this.RightTop)
 31                  && (this.RightBottom == this.LeftBottom))
 32                  && (this.RightBottom == this.LeftTop);
 33         }
 34 
 35         public int All
 36         {
 37             get
 38             {
 39                 if (!IsAllEqual())
 40                 {
 41                     return -1;
 42                 }
 43 
 44                 return this.RightBottom;
 45             }
 46             set
 47             {
 48                 if (value < 0)
 49                 {
 50                     value = 0;
 51                 }
 52 
 53                 this.RightBottom = this.RightTop = this.LeftBottom = this.LeftTop = value;
 54             }
 55         }
 56 
 57         public int LeftTop
 58         {
 59             get
 60             {
 61                 return this._leftTop;
 62             }
 63             set
 64             {
 65                 if (value < 0)
 66                 {
 67                     value = 0;
 68                 }
 69 
 70                 this._leftTop = value;
 71             }
 72         }
 73  
 74         public int RightTop
 75         {
 76             get
 77             {
 78                 return this._rightTop;
 79             }
 80             set
 81             {
 82                 if (value < 0)
 83                 {
 84                     value = 0;
 85                 }
 86 
 87                 this._rightTop = value;
 88             }
 89         }
 90        
 91         public int LeftBottom
 92         {
 93             get
 94             {
 95                 return this._leftBottom;
 96             }
 97             set
 98             {
 99                 if (value < 0)
100                 {
101                     value = 0;
102                 }
103 
104                 this._leftBottom = value;
105             }
106         }
107 
108         public int RightBottom
109         {
110             get
111             {
112                 return this._rightBottom;
113             }
114             set
115             {
116                 if (value < 0)
117                 {
118                     value = 0;
119                 }
120 
121                 this._rightBottom = value;
122             }
123         }
124 
125         public static bool operator ==(ArcRadius p1, ArcRadius p2)
126         {
127             return ((((p1.RightTop == p2.RightTop) 
128                 && (p1.RightBottom == p2.RightBottom))
129                 && (p1.LeftBottom == p2.LeftBottom)) 
130                 && (p1.LeftTop == p2.LeftTop));
131         }
132 
133         public static bool operator !=(ArcRadius p1, ArcRadius p2)
134         {
135             return !(p1 == p2);
136         }
137 
138         public override string ToString()
139         {
140             return LeftTop + "" + RightTop + "" + LeftBottom + "" + RightBottom;
141         }
142     }

 

三、GraphicsPathHelper类

主要包括如下两个方法:

public static void DrawRoundrectangle(Graphics g,RoundRectanglearg arg)           用于绘制带有圆角的矩形
public static GraphicsPath CreateRoundPath(Rectangle rect, ArcRadius arcRadius)  用于创建圆角路径,对上文的改进主要在于此方法。不需要对圆角组合进行判断,只需要根据每一个圆角的半径是否大于0而进行相应的圆角绘制。

 

 1     public static class GraphicsPathHelper
 2     {
 3         public static void DrawRoundRectangle(Graphics g,RoundRectangleArg arg)
 4         {
 5             if (g == null || arg.Rectangle.Width == 0 || arg.Rectangle.Height == 0)
 6             {
 7                 return;
 8             }
 9 
10             using (SmoothingModeGraphics smoothingMode = new SmoothingModeGraphics(g, SmoothingMode.AntiAlias))
11             {
12                 using (var path = CreateRoundPath(arg.Rectangle, arg.ArcRadius))
13                 {
14                     if (arg.DrawBackground)
15                     {
16                         using (var fillBrush = new LinearGradientBrush(
17                             arg.Rectangle, arg.StartColor, arg.EndColor, arg.LinearGradientMode))
18                         {
19                             var blend = new ColorBlend(2);
20                             blend.Positions[0] = 0.0f;
21                             blend.Positions[1] = 1.0f;
22                             blend.Colors[0] = arg.StartColor;
23                             blend.Colors[1] = arg.EndColor;
24                             fillBrush.InterpolationColors = blend;
25                             g.FillPath(fillBrush, path);
26                         }
27                     }
28 
29                     if (arg.DrawBorder)
30                     {
31                         using (var pen = new Pen(new SolidBrush(arg.BorderColor), arg.BorderWidth))
32                             g.DrawPath(pen, path);
33                     }
34 
35                     if (arg.DrawInnerBorder)
36                     {
37                         Rectangle rectangle = arg.Rectangle;
38                         rectangle.Inflate(-2, -2);
39                         var innerPath = CreateRoundPath(rectangle, arg.ArcRadius);
40 
41                         using (var pen = new Pen(new SolidBrush(arg.InnerBorderColor), arg.InnerBorderWidth))
42                         {
43                             g.DrawPath(pen, innerPath);
44                         }
45                     }
46                 }
47             }
48         }
49 
50         public static GraphicsPath CreateRoundPath(Rectangle rect, ArcRadius arcRadius)
51         {
52             var path = new GraphicsPath();
53 
54             if (rect.Width == 0 || rect.Height == 0)
55             {
56                 return path;
57             }
58 
59             if (arcRadius.LeftTop > 0)
60             {
61                 path.AddArc(
62                     rect.Left, rect.Top, arcRadius.LeftTop, arcRadius.LeftTop, 18090);
63             }
64 
65             path.AddLine(new Point(rect.Left + arcRadius.LeftTop, rect.Top),
66                          new Point(rect.Right - arcRadius.RightTop, rect.Top));
67 
68             if (arcRadius.RightTop > 0)
69             {
70                 path.AddArc(rect.Right - arcRadius.RightTop, rect.Top,
71                     arcRadius.RightTop, arcRadius.RightTop, -9090);
72             }
73 
74             path.AddLine(new Point(rect.Right, rect.Top + arcRadius.RightTop),
75                          new Point(rect.Right, rect.Bottom - arcRadius.RightBottom));
76 
77             if (arcRadius.RightBottom > 0)
78             {
79                 path.AddArc(rect.Right - arcRadius.RightBottom, rect.Bottom - arcRadius.RightBottom,
80                     arcRadius.RightBottom, arcRadius.RightBottom, 090);
81             }
82 
83             path.AddLine(new Point(rect.Right - arcRadius.RightBottom, rect.Bottom),
84                          new Point(rect.Left + arcRadius.LeftBottom, rect.Bottom));
85 
86             if (arcRadius.LeftBottom > 0)
87             {
88                 path.AddArc(rect.Left, rect.Bottom - arcRadius.LeftBottom,
89                     arcRadius.LeftBottom, arcRadius.LeftBottom, 9090);
90             }
91 
92             path.AddLine(new Point(rect.Left, rect.Bottom - arcRadius.LeftBottom),
93                          new Point(rect.Left, rect.Top + arcRadius.LeftTop));
94 
95             path.CloseFigure();
96 
97             return path;
98         }
99     }

 

、应用

 应用的话比较简单,只需要设置RoundRectangleArg参数,然后调用GraphicsPathHelper.DrawRoundRectangle即可。

 RoundRectangleArg arg = new RoundRectangleArg();
 arg.Rectangle = rectangle;
 arg.ArcRadius = new ArcRadius((int)this.numericLeftBottomRadiuds.Value, (int)this.numericRightTopRadiuds.Value,
                         (int)this.numericLeftTopRadiuds.Value, (int)this.numericRightBottomRadiuds.Value);
 arg.BorderColor = Color.FromName((this.cboBorderColors.SelectedItem ?? string.Empty).ToString());
 arg.InnerBorderColor = Color.FromName((this.cboInnerBorderColors.SelectedItem ?? string.Empty).ToString());
 arg.StartColor = Color.FromName((this.cboStartColors.SelectedItem ?? string.Empty).ToString());

 arg.EndColor = Color.FromName((this.cboEndColors.SelectedItem ?? string.Empty).ToString());
 arg.LinearGradientMode = gradientMode;
 arg.DrawInnerBorder = this.ckbDrawInnerBorder.Checked;
 arg.DrawBorder = this.ckbDrawBorder.Checked;
 arg.DrawBackground = this.ckbDrawBg.Checked;
 arg.BorderWidth = (int)this.numericBorderWidth.Value;
 arg.InnerBorderWidth = (int)this.numericInnerBorderWidth.Value;

               

 GraphicsPathHelper.DrawRoundRectangle(graphic, arg);

 

五、总结

 前一篇的随笔主要是应用位操作来处理枚举,将问题复杂化了。本文进行了相应的改进,代码相对来说更加清晰与简洁。 改进版的源码下载如下:

 

 源码下载:矩形圆角绘制改进版

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《矩形圆角绘制改进版(附源码)》
文章链接:https://www.456zj.com/20336.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址