首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 圓角矩形繪製進化版:ArcRadius 結構支援四角獨立半徑控制

     編輯:關於C#

前言:從枚舉組合轉向參數化控制

上版本雖以位元運算涵蓋所有組合,但程式碼冗長且無法控制四個圓角的半徑差異。本版引入 ArcRadius 結構,各角獨立指定半徑,邏輯大幅簡化:只需檢查半徑 > 0 即繪製對應圓弧,無需列舉所有組合。

改進版效果圖
圖 1:四角半徑可獨立設定的效果展示

ArcRadius 結構:四角半徑封裝

public struct ArcRadius
{
    public static readonly ArcRadius Empty = new ArcRadius(0);
    private int _leftTop, _rightTop, _leftBottom, _rightBottom;

    public ArcRadius(int radius) : this(radius, radius, radius, radius) { }
    public ArcRadius(int leftTop, int rightTop, int leftBottom, int rightBottom)
    {
        _leftTop = Math.Max(0, leftTop);
        _rightTop = Math.Max(0, rightTop);
        _leftBottom = Math.Max(0, leftBottom);
        _rightBottom = Math.Max(0, rightBottom);
    }

    public int LeftTop { get => _leftTop; set => _leftTop = Math.Max(0, value); }
    public int RightTop { get => _rightTop; set => _rightTop = Math.Max(0, value); }
    public int LeftBottom { get => _leftBottom; set => _leftBottom = Math.Max(0, value); }
    public int RightBottom { get => _rightBottom; set => _rightBottom = Math.Max(0, value); }

    public int All
    {
        get => (_leftTop == _rightTop && _leftTop == _leftBottom && _leftTop == _rightBottom) ? _leftTop : -1;
        set { LeftTop = RightTop = LeftBottom = RightBottom = Math.Max(0, value); }
    }

    public static bool operator ==(ArcRadius a, ArcRadius b)
        => a._leftTop == b._leftTop && a._rightTop == b._rightTop && a._leftBottom == b._leftBottom && a._rightBottom == b._rightBottom;
    public static bool operator !=(ArcRadius a, ArcRadius b) => !(a == b);
    public override string ToString() => $"{LeftTop}, {RightTop}, {LeftBottom}, {RightBottom}";
}

GraphicsPathHelper 核心邏輯:線性路徑建構

單一方法 CreateRoundPath 依序繞矩形四周建構路徑:

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(rect.Left + arcRadius.LeftTop, rect.Top, 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(rect.Right, rect.Top + arcRadius.RightTop, 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(rect.Right - arcRadius.RightBottom, rect.Bottom, 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(rect.Left, rect.Bottom - arcRadius.LeftBottom, rect.Left, rect.Top + arcRadius.LeftTop);

    path.CloseFigure();
    return path;
}

關鍵優勢:路徑點序順時針連續,無需判斷組合,自動處理任意半徑組合 (含零半徑即銳角)。

繪製封裝:DrawRoundRectangle

支援漸層背景、邊框、內邊框三層繪製:

public static void DrawRoundRectangle(Graphics g, RoundRectangleArg arg)
{
    if (g == null || arg.Rectangle.Width == 0 || arg.Rectangle.Height == 0) return;
    using (var sm = new SmoothingModeGraphics(g, SmoothingMode.AntiAlias))
    using (var path = CreateRoundPath(arg.Rectangle, arg.ArcRadius))
    {
        if (arg.DrawBackground)
        {
            using (var brush = new LinearGradientBrush(arg.Rectangle, arg.StartColor, arg.EndColor, arg.LinearGradientMode))
            {
                var blend = new ColorBlend(2) { Positions = new[] { 0f, 1f }, Colors = new[] { arg.StartColor, arg.EndColor } };
                brush.InterpolationColors = blend;
                g.FillPath(brush, path);
            }
        }
        if (arg.DrawBorder)
            using (var pen = new Pen(new SolidBrush(arg.BorderColor), arg.BorderWidth)) g.DrawPath(pen, path);
        if (arg.DrawInnerBorder)
        {
            Rectangle inner = arg.Rectangle; inner.Inflate(-2, -2);
            using (var innerPath = CreateRoundPath(inner, arg.ArcRadius))
            using (var pen = new Pen(new SolidBrush(arg.InnerBorderColor), arg.InnerBorderWidth))
                g.DrawPath(pen, innerPath);
        }
    }
}

使用範例

var arg = new RoundRectangleArg
{
    Rectangle = rect,
    ArcRadius = new ArcRadius(leftTop, rightTop, leftBottom, rightBottom),
    DrawBackground = true, DrawBorder = true, DrawInnerBorder = false,
    StartColor = Color.Blue, EndColor = Color.LightBlue,
    LinearGradientMode = LinearGradientMode.Vertical,
    BorderColor = Color.DarkBlue, BorderWidth = 2
};
GraphicsPathHelper.DrawRoundRectangle(g, arg);

總結

改進版以資料導向取代邏輯導向,程式碼從 150+ 行精簡至 50 行核心邏輯,並獲得四角獨立半徑控制能力。更符合開閉原則,易於維護與擴充。

原始碼下載:矩形圓角繪製改進版

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved