zoukankan      html  css  js  c++  java
  • 矩形圆角绘制改进版(附源码)

    一、前言

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

    二、圆角半径设计

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

      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);

     

    五、总结

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

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

  • 相关阅读:
    iOS 6 Tutorials
    iPhone:文本设计的注意事项
    Beginning Storyboards in iOS 5 Part 2
    代友招聘一名网站开发人员
    利用反射自己写的一个ModelHelper类
    SQL中 对逻辑值取反赋值的语句
    记点uml的表现方式
    我的2008年
    Framework 4.0 新关键字dynamic 之我见(一)
    我的采集小程序配置篇
  • 原文地址:https://www.cnblogs.com/jasenkin/p/rectangle_round_arc_updated_version.html
Copyright © 2011-2022 走看看