一、前言
上一篇繪制矩形圓角的方式不夠完善,感覺寫的太過於復雜,將簡單的問題復雜化了,本文對此進行了相應的改進,增強對各個圓角的半徑的控制。繪制後的圓角效果圖如下:
二、圓角半徑設計
對於矩行而言,圓角分為左上角、右上角、左下角和右下角。每一個角都會存在相應的半徑,用於控制每一個圓角的繪制。設計如下:
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/