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

一、前言

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

二、圆角半径设计

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

  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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值