首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C# WinForms/GDI+ 繪製圓角邊框控件完整實現

     編輯:更多程式設計知識

通過重寫控件 Paint 事件,使用 GraphicsPath 構建圓角矩形路徑,配合 Pen 繪製,實現任意控件的圓角邊框效果。本文提供可直接復用的核心算法與集成指南。

核心繪製算法


private void DrawRoundedBorder(Graphics g, Control ctrl) {
    float width = ctrl.Width - 1;
    float height = ctrl.Height - 1;
    float radius = 2f;  // 圓角半徑(像素)

    // 定義 12 個關鍵點構建圓角矩形
    PointF[] points = {
        new PointF(radius, 0),           // 左上橫邊起點
        new PointF(width - radius, 0),   // 右上橫邊終點
        new PointF(width, radius),       // 右上彎曲起點
        new PointF(width, height - radius), // 右下彎曲終點
        new PointF(width - radius, height), // 右下橫邊終點
        new PointF(radius, height),      // 左下橫邊起點
        new PointF(0, height - radius),  // 左下彎曲終點
        new PointF(0, radius)            // 左上彎曲起點
    };

    using (GraphicsPath path = new GraphicsPath()) {
        path.AddLines(points);  // 直線連接,實際為倒角而非真圓弧
        // 真圓弧需用 path.AddArc 配合四個角
        
        using (Pen pen = new Pen(Color.FromArgb(150, Color.Blue), 1)) {
            pen.DashStyle = DashStyle.Solid;
            g.DrawPath(pen, path);
        }
    }
}

真正的圓角矩形:AddArc 版本(推薦)


private void DrawTrueRoundedRect(Graphics g, Control ctrl, float radius, Pen pen) {
    RectangleF rect = new RectangleF(0, 0, ctrl.Width - 1, ctrl.Height - 1);
    using (GraphicsPath path = new GraphicsPath()) {
        // 四個圓弧 + 四條直線
        path.AddArc(rect.X, rect.Y, radius * 2, radius * 2, 180, 90);           // 左上
        path.AddArc(rect.Right - radius * 2, rect.Y, radius * 2, radius * 2, 270, 90); // 右上
        path.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90); // 右下
        path.AddArc(rect.X, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90); // 左下
        path.CloseFigure();
        
        g.DrawPath(pen, path);
    }
}

控件集成:三步走

  1. 繼承目標控件(如 Panel、Button、TextBox)
  2. 設置 ResizeRedraw = true 保證尺寸變化重繪
  3. 重寫 OnPaint 或訂閱 Paint 事件

public class RoundedPanel : Panel {
    public float CornerRadius { get; set; } = 8f;
    public Color BorderColor { get; set; } = Color.Blue;
    public float BorderWidth { get; set; } = 2f;

    public RoundedPanel() {
        ResizeRedraw = true;  // 關鍵!
        BackColor = Color.White;
    }

    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;  // 抗鋸齒
        
        using (var pen = new Pen(BorderColor, BorderWidth))
        using (var path = GetRoundedRectPath(ClientRectangle, CornerRadius)) {
            e.Graphics.DrawPath(pen, path);
        }
    }

    private GraphicsPath GetRoundedRectPath(RectangleF rect, float radius) {
        var path = new GraphicsPath();
        float d = radius * 2;
        path.AddArc(rect.X, rect.Y, d, d, 180, 90);
        path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90);
        path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90);
        path.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90);
        path.CloseFigure();
        return path;
    }
}

進階:填充背景 + 圓角邊框 + 內容裁剪


protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    var g = e.Graphics;
    g.SmoothingMode = SmoothingMode.AntiAlias;
    
    var rect = ClientRectangle;
    float r = CornerRadius;
    using (var path = GetRoundedRectPath(rect, r)) {
        // 1. 填充背景
        using (var brush = new SolidBrush(BackColor))
            g.FillPath(brush, path);
        
        // 2. 繪製邊框
        using (var pen = new Pen(BorderColor, BorderWidth))
            g.DrawPath(pen, path);
        
        // 3. 設置裁剪區域,防止子控件溢出圓角
        var oldClip = g.Clip;
        g.SetClip(path);
        // 此處可調用 base.OnPaint 繪制子控件,或手動繪制文本
        g.Clip = oldClip;
    }
}

性能優化提示

  • 緩存 GraphicsPath:尺寸不變時復用路徑對象
  • 避免頻繁創建 Pen/Brush:屬性不變時靜態緩存或池化
  • 啟用 DoubleBuffered:DoubleBuffered = true 減少閃爍
  • 大量控件考慮:WPF/UWP 原生支持圓角,WinForms 繪製開銷較大

總結

GraphicsPath.AddArc 構建真圓角矩形,配合 SmoothingMode.AntiAlias 抗鋸齒,ResizeRedraw=true 保證自適應,封裝為可復用基類即可賦予任意 WinForms 控件圓角外觀。WPF 中直接使用 Border.CornerRadius 更簡潔高效。

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