一、前言
上一篇繪制矩形圓角的方式不夠完善,感覺寫的太過於復雜,將簡單的問題復雜化了,本文對此進行了相應的改進,增強對各個圓角的半徑的控制。繪制後的圓角效果圖如下:

二、圓角半徑設計
對於矩行而言,圓角分為左上角、右上角、左下角和右下角。每一個角都會存在相應的半徑,用於控制每一個圓角的繪制。設計如下:
public struct ArcRadius
{
private int _rightBottom;
private int _rightTop;
private int _leftBottom;
private int _leftTop;
public static readonly ArcRadius Empty =new ArcRadius(0);
public ArcRadius(int radiusLength)
{
if (radiusLength < 0)
{
radiusLength = 0;
}
this._rightBottom = this._rightTop = this._leftBottom = this._leftTop = radiusLength;
}
public ArcRadius(int leftTop, int rightTop, int leftBottom, int rightBottom)
{
this._rightBottom = rightBottom < 0 ? 0 : rightBottom;
this._rightTop = rightTop < 0 ? 0 : rightTop;
this._leftBottom = leftBottom < 0 ? 0 : leftBottom;
this._leftTop = leftTop < 0 ? 0 : leftTop;
}
private bool IsAllEqual()
{
return ((this.RightBottom == this.RightTop)
&& (this.RightBottom == this.LeftBottom))
&& (this.RightBottom == this.LeftTop);
}
public int All
{
get
{
if (!IsAllEqual())
{
return -1;
}
return this.RightBottom;
}
set
{
if (value < 0)
{
value = 0;
}
this.RightBottom = this.RightTop = this.LeftBottom = this.LeftTop = value;
}
}
public int LeftTop
{
get
{
return this._leftTop;
}
set
{
if (value < 0)
{
value = 0;
}
this._leftTop = value;
}
}
public int RightTop
{
get
{
return this._rightTop;
}
set
{
if (value < 0)
{
value = 0;
}
this._rightTop = value;
}
}
public int LeftBottom
{
get
{
return this._leftBottom;
}
set
{
if (value < 0)
{
value = 0;
}
this._leftBottom = value;
}
}
public int RightBottom
{
get
{
return this._rightBottom;
}
set
{
if (value < 0)
{
value = 0;
}
this._rightBottom = value;
}
}
public static bool operator ==(ArcRadius p1, ArcRadius p2)
{
return ((((p1.RightTop == p2.RightTop)
&& (p1.RightBottom == p2.RightBottom))
&& (p1.LeftBottom == p2.LeftBottom))
&& (p1.LeftTop == p2.LeftTop));
}
public static bool operator !=(ArcRadius p1, ArcRadius p2)
{
return !(p1 == p2);
}
public override string ToString()
{
return LeftTop + ", " + RightTop + ", " + LeftBottom + ", " + RightBottom;
}
}
三、GraphicsPathHelper類
主要包括如下兩個方法:
public static void DrawRoundRectangle(Graphics g,RoundRectangleArg arg) 用於繪制帶有圓角的矩形
public static GraphicsPath CreateRoundPath(Rectangle rect, ArcRadius arcRadius) 用於創建圓角路徑,對上文的改進主要在於此方法。不需要對圓角組合進行判斷,只需要根據每一個圓角的半徑是否大於0而進行相應的圓角繪制。
public static class GraphicsPathHelper
{
public static void DrawRoundRectangle(Graphics g,RoundRectangleArg arg)
{
if (g == null || arg.Rectangle.Width == 0 || arg.Rectangle.Height == 0)
{
return;
}
using (SmoothingModeGraphics smoothingMode = new SmoothingModeGraphics(g, SmoothingMode.AntiAlias))
{
using (var path = CreateRoundPath(arg.Rectangle, arg.ArcRadius))
{
if (arg.DrawBackground)
{
using (var fillBrush = new LinearGradientBrush(
arg.Rectangle, arg.StartColor, arg.EndColor, arg.LinearGradientMode))
{
var blend = new ColorBlend(2);
blend.Positions[0] = 0.0f;
blend.Positions[1] = 1.0f;
blend.Colors[0] = arg.StartColor;
blend.Colors[1] = arg.EndColor;
fillBrush.InterpolationColors = blend;
g.FillPath(fillBrush, path);
}
}
if (arg.DrawBorder)
{
using (var pen = new Pen(new SolidBrush(arg.BorderColor), arg.BorderWidth))
g.DrawPath(pen, path);
}
if (arg.DrawInnerBorder)
{
Rectangle rectangle = arg.Rectangle;
rectangle.Inflate(-2, -2);
var innerPath = CreateRoundPath(rectangle, arg.ArcRadius);
using (var pen = new Pen(new SolidBrush(arg.InnerBorderColor), arg.InnerBorderWidth))
{
g.DrawPath(pen, innerPath);
}
}
}
}
}
public static GraphicsPath CreateRoundPath(Rectangle rect, ArcRadius arcRadius)
{
var path = new GraphicsPath();
if (rect.Width == 0 || rect.Height == 0)
{
return path;
}
if (arcRadius.LeftTop > 0)
{
path.AddArc(
rect.Left, rect.Top, arcRadius.LeftTop, arcRadius.LeftTop, 180, 90);
}
path.AddLine(new Point(rect.Left + arcRadius.LeftTop, rect.Top),
new Point(rect.Right - arcRadius.RightTop, rect.Top));
if (arcRadius.RightTop > 0)
{
path.AddArc(rect.Right - arcRadius.RightTop, rect.Top,
arcRadius.RightTop, arcRadius.RightTop, -90, 90);
}
path.AddLine(new Point(rect.Right, rect.Top + arcRadius.RightTop),
new Point(rect.Right, rect.Bottom - arcRadius.RightBottom));
if (arcRadius.RightBottom > 0)
{
path.AddArc(rect.Right - arcRadius.RightBottom, rect.Bottom - arcRadius.RightBottom,
arcRadius.RightBottom, arcRadius.RightBottom, 0, 90);
}
path.AddLine(new Point(rect.Right - arcRadius.RightBottom, rect.Bottom),
new Point(rect.Left + arcRadius.LeftBottom, rect.Bottom));
if (arcRadius.LeftBottom > 0)
{
path.AddArc(rect.Left, rect.Bottom - arcRadius.LeftBottom,
arcRadius.LeftBottom, arcRadius.LeftBottom, 90, 90);
}
path.AddLine(new Point(rect.Left, rect.Bottom - arcRadius.LeftBottom),
new Point(rect.Left, rect.Top + arcRadius.LeftTop));
path.CloseFigure();
return path;
}
}
四、應用
應用的話比較簡單,只需要設置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);
五、總結
前一篇的隨筆主要是應用位操作來處理枚舉,將問題復雜化了。本文進行了相應的改進,代碼相對來說更加清晰與簡潔。 改進版的源碼下載如下:
源碼下載:矩形圓角繪制改進版
http://www.cnblogs.com/jasenkin/admin/矩形圓角繪制改進版
作者:JasenKin
出處:http://www.cnblogs.com/jasenkin/