开源 C# 快速开发(六)自定义控件--圆环

文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

推荐链接:

开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客

开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客

开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客

开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客

本章节主要内容是:圆环进度控件。

目录:

1.源码分析

2.所有源码

3.效果演示

一、源码分析1. CircularProgress 类详细函数分析

1.1 构造函数 - CircularProgress()

复制代码
public CircularProgress()
{
    // 启用双缓冲,减少绘制闪烁
    this.DoubleBuffered = true;
    
    // 设置控件默认尺寸为200x200像素
    this.Size = new Size(200, 200);
    
    // 配置控件样式标志,优化绘制性能:
    // AllPaintingInWmPaint - 控件忽略WM_ERASEBKGND窗口消息,减少闪烁
    // UserPaint - 控件自行绘制,而不是系统绘制
    // ResizeRedraw - 尺寸改变时自动重绘
    // OptimizedDoubleBuffer - 双缓冲支持
    this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.UserPaint |
                 ControlStyles.ResizeRedraw |
                 ControlStyles.OptimizedDoubleBuffer, true);

    // 初始化文本字体:Segoe UI,12号,粗体
    _textFont = new Font("Segoe UI", 12, FontStyle.Bold);
}

1.2 核心绘制函数 - OnPaint(PaintEventArgs e)

复制代码
protected override void OnPaint(PaintEventArgs e)
{
    // 调用基类绘制方法,确保基础绘制完成
    base.OnPaint(e);

    // 获取Graphics对象用于绘制
    Graphics g = e.Graphics;
    
    // 设置高质量绘制模式:
    g.SmoothingMode = SmoothingMode.AntiAlias;      // 抗锯齿
    g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; // 清晰文本渲染
    g.PixelOffsetMode = PixelOffsetMode.HighQuality; // 高质量像素偏移

    // 1. 绘制圆角矩形背景
    using (GraphicsPath path = CreateRoundRectPath(this.ClientRectangle, 15))
    using (SolidBrush backBrush = new SolidBrush(_backgroundColor))
    {
        g.FillPath(backBrush, path);  // 填充背景色

        // 绘制1像素宽的灰色边框
        using (Pen borderPen = new Pen(Color.FromArgb(200, 200, 200), 1))
        {
            g.DrawPath(borderPen, path);
        }
    }

    // 2. 计算圆环绘制区域
    // 内边距 = 基础内边距10 + 发光大小(为发光效果留空间)
    int padding = 10 + _glowSize;
    
    // 圆环直径 = 控件宽高的最小值 - 两边内边距
    int ringDiameter = Math.Min(this.Width, this.Height) - (padding * 2);
    
    // 计算圆环居中位置
    int x = (this.Width - ringDiameter) / 2;
    int y = (this.Height - ringDiameter) / 2;
    Rectangle rect = new Rectangle(x, y, ringDiameter, ringDiameter);

    // 3. 调整圆环矩形(为圆环宽度留出空间)
    int ringPadding = _ringWidth / 2 + 2;  // 半宽+2像素缓冲
    Rectangle ringRect = new Rectangle(
        rect.X + ringPadding,      // 左边界内缩
        rect.Y + ringPadding,      // 上边界内缩
        rect.Width - ringPadding * 2,  // 宽度减少两边内缩
        rect.Height - ringPadding * 2  // 高度减少两边内缩
    );

    // 4. 绘制发光效果(如果有进度且启用发光)
    if (_showGlow && _value > 0)
    {
        DrawGlowEffect(g, ringRect);  // 参数:Graphics对象,圆环矩形区域
    }

    // 5. 绘制背景圆环(完整的360度圆环)
    using (Pen backPen = new Pen(_ringBackColor, _ringWidth))
    {
        backPen.StartCap = LineCap.Round;  // 圆角起始端
        backPen.EndCap = LineCap.Round;    // 圆角结束端
        g.DrawArc(backPen, ringRect, 0, 360);  // 绘制完整圆环
    }

    // 6. 绘制进度圆环(根据当前进度值)
    if (_value > 0)
    {
        using (Pen progressPen = CreateProgressPen(ringRect))  // 创建进度画笔
        {
            // 计算进度角度:360度 × (当前值/最大值)
            float angle = 360f * _value / _maximum;
            
            // 从起始角度绘制指定角度的圆弧
            g.DrawArc(progressPen, ringRect, _startAngle, angle);
        }
    }

    // 7. 绘制中心文本(如果启用文本显示)
    if (_showText)
    {
        DrawCenterText(g, ringDiameter);  // 参数:Graphics对象,圆环直径
    }
}

1.3 CreateProgressPen(Rectangle ringRect) - 创建进度画笔

复制代码
private Pen CreateProgressPen(Rectangle ringRect)
{
    // 创建基础进度画笔:指定颜色和宽度
    Pen progressPen = new Pen(_ringColor, _ringWidth);
    
    // 设置画笔端点样式为圆形
    progressPen.StartCap = LineCap.Round;
    progressPen.EndCap = LineCap.Round;

    // 检查是否启用渐变效果且圆环足够大(避免小尺寸下的渐变问题)
    if (_useGradient && ringRect.Width > 50)
    {
        // 计算渐变结束颜色:
        // 如果未指定渐变颜色,使用系统方法将主色调亮30%
        Color gradientEnd = _gradientColor.IsEmpty ?
            ControlPaint.Light(_ringColor, 0.3f) : _gradientColor;

        // 创建线性渐变画笔:从左上到右下对角线渐变
        using (var brush = new LinearGradientBrush(
            new Point(ringRect.Left, ringRect.Top),    // 渐变起点
            new Point(ringRect.Right, ringRect.Bottom), // 渐变终点
            _ringColor,     // 起始颜色
            gradientEnd))   // 结束颜色
        {
            progressPen.Brush = brush;  // 将渐变画笔应用到钢笔
        }
    }

    return progressPen;  // 返回配置好的画笔
}

1.4 DrawGlowEffect(Graphics g, Rectangle ringRect) - 绘制发光效果

复制代码
private void DrawGlowEffect(Graphics g, Rectangle ringRect)
{
    // 从最大发光尺寸开始,逐层向内绘制
    for (int i = _glowSize; i > 0; i--)
    {
        // 创建发光效果画笔:
        // 颜色:主色带透明度(30 - i*5),外层更透明
        // 宽度:基础宽度 + i*2,外层更宽
        using (Pen glowPen = new Pen(Color.FromArgb(30 - i * 5, _ringColor), _ringWidth + i * 2))
        {
            glowPen.StartCap = LineCap.Round;  // 圆角端点
            glowPen.EndCap = LineCap.Round;

            // 计算当前进度对应的角度
            float angle = 360f * _value / _maximum;
            
            // 绘制发光圆弧(与进度圆弧相同角度)
            g.DrawArc(glowPen, ringRect, _startAngle, angle);
        }
    }
    // 循环结束后,从外到内绘制了多层半透明圆弧,形成发光效果
}

1.5 DrawCenterText(Graphics g, int ringDiameter) - 绘制中心文本

复制代码
private void DrawCenterText(Graphics g, int ringDiameter)
{
    // 根据格式字符串生成显示文本(如:"45%")
    string text = string.Format(_textFormat, _value);

    // 动态计算字体大小:基于圆环直径的1/8,最小8号字
    float fontSize = Math.Max(8, ringDiameter / 8f);
    
    // 创建字体对象(使用原字体的字体系列和样式,但调整大小)
    using (Font font = new Font(_textFont.FontFamily, fontSize, _textFont.Style))
    using (SolidBrush textBrush = new SolidBrush(_textColor))  // 文本颜色画笔
    {
        // 测量文本尺寸,用于居中计算
        SizeF textSize = g.MeasureString(text, font);
        
        // 计算文本居中位置
        PointF textLocation = new PointF(
            (this.Width - textSize.Width) / 2,   // 水平居中
            (this.Height - textSize.Height) / 2  // 垂直居中
        );

        // 如果启用阴影效果,先绘制阴影层
        if (_showShadow)
        {
            using (SolidBrush shadowBrush = new SolidBrush(_shadowColor))
            {
                // 在文本位置右下方偏移绘制阴影
                g.DrawString(text, font, shadowBrush,
                    textLocation.X + _shadowOffset,  // X偏移
                    textLocation.Y + _shadowOffset); // Y偏移
            }
        }

        // 绘制主文本(在阴影上方)
        g.DrawString(text, font, textBrush, textLocation);
    }
    // using语句自动释放字体和画笔资源
}

1.6 CreateRoundRectPath(Rectangle rect, int radius) - 创建圆角矩形路径

复制代码
private GraphicsPath CreateRoundRectPath(Rectangle rect, int radius)
{
    GraphicsPath path = new GraphicsPath();  // 创建空路径

    // 按顺时针方向添加四个圆弧和连接线:
    
    // 1. 左上角圆弧:从180度到270度(左上角)
    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
    
    // 2. 上边线 + 右上角圆弧:从270度到0度(右上角)
    path.AddArc(rect.X + rect.Width - radius, rect.Y, radius, radius, 270, 90);
    
    // 3. 右边线 + 右下角圆弧:从0度到90度(右下角)
    path.AddArc(rect.X + rect.Width - radius, rect.Y + rect.Height - radius,
               radius, radius, 0, 90);
    
    // 4. 底边线 + 左下角圆弧:从90度到180度(左下角)
    path.AddArc(rect.X, rect.Y + rect.Height - radius, radius, radius, 90, 90);
    
    // 闭合路径(连接回起点)
    path.CloseFigure();

    return path;  // 返回完整的圆角矩形路径
}

1.7 ApplyColorScheme(ColorScheme scheme) - 应用颜色主题

复制代码
public void ApplyColorScheme(ColorScheme scheme)
{
    // 根据枚举值选择对应的颜色组合
    switch (scheme)
    {
        case ColorScheme.Blue:
            // 调用SetColors设置:主色,渐变色,文本色
            SetColors(Color.FromArgb(0, 120, 215), 
                     Color.FromArgb(64, 156, 255), 
                     Color.FromArgb(0, 90, 158));
            break;
        case ColorScheme.Green:
            SetColors(Color.FromArgb(46, 204, 113), 
                     Color.FromArgb(88, 214, 141), 
                     Color.FromArgb(39, 174, 96));
            break;
        // ... 其他13种颜色方案类似
        case ColorScheme.Sunset:
            SetColors(Color.FromArgb(255, 94, 77), 
                     Color.FromArgb(255, 145, 114), 
                     Color.FromArgb(255, 61, 38));
            // 特殊方案额外设置渐变颜色
            _gradientColor = Color.FromArgb(255, 193, 7);
            break;
        // ... 更多case语句
    }
}

1.8 SetColors(Color ringColor, Color gradientColor, Color textColor) - 设置颜色

复制代码
private void SetColors(Color ringColor, Color gradientColor, Color textColor)
{
    _ringColor = ringColor;        // 设置圆环主色
    _gradientColor = gradientColor; // 设置渐变色
    _textColor = textColor;        // 设置文本颜色
    this.Invalidate();             // 触发重绘,立即显示新颜色
}
  1. Form1 类详细函数分析

2.1 SetupControls() - 初始化所有界面控件

复制代码
private void SetupControls()
{
    // 窗体基本设置
    this.Text = "增强版圆环进度控件演示";
    this.Size = new Size(600, 700);
    this.StartPosition = FormStartPosition.CenterScreen;
    this.BackColor = Color.White;

    // 创建并配置圆环进度控件
    circularProgress = new CircularProgress();
    circularProgress.Location = new Point(200, 30);  // 居中偏上位置
    circularProgress.Size = new Size(200, 200);
    // ... 各种属性设置

    // 创建滑块控件用于精确控制进度
    trackBar = new TrackBar();
    trackBar.Location = new Point(50, 250);  // 圆环下方
    trackBar.Size = new Size(500, 45);
    trackBar.Minimum = 0;
    trackBar.Maximum = 100;
    trackBar.Value = 45;
    trackBar.TickFrequency = 10;  // 每10个单位一个刻度
    trackBar.ValueChanged += TrackBar_ValueChanged;  // 事件绑定

    // 创建增减按钮
    btnIncrease = CreateStyledButton("+10", Color.FromArgb(0, 120, 215), 50, 310);
    btnIncrease.Click += BtnIncrease_Click;

    btnDecrease = CreateStyledButton("-10", Color.FromArgb(200, 200, 200), 150, 310);
    btnDecrease.Click += BtnDecrease_Click;

    // 创建颜色方案下拉选择框
    cmbColorScheme = new ComboBox();
    cmbColorScheme.Location = new Point(250, 310);
    cmbColorScheme.Size = new Size(200, 25);
    cmbColorScheme.DropDownStyle = ComboBoxStyle.DropDownList;  // 禁止编辑

    // 填充枚举值到下拉框
    foreach (ColorScheme scheme in Enum.GetValues(typeof(ColorScheme)))
    {
        cmbColorScheme.Items.Add(GetColorSchemeName(scheme));
    }

    cmbColorScheme.SelectedIndex = (int)ColorScheme.Ocean;  // 默认选择
    cmbColorScheme.SelectedIndexChanged += CmbColorScheme_SelectedIndexChanged;

    // 创建效果控制复选框
    chkGradient = CreateCheckBox("渐变效果", 50, 360);
    chkGradient.Checked = true;
    chkGradient.CheckedChanged += ChkGradient_CheckedChanged;

    // ... 创建其他控件

    // 将所有控件添加到窗体
    this.Controls.AddRange(new Control[] {
        circularProgress, trackBar, btnIncrease, btnDecrease, cmbColorScheme,
        chkGradient, chkGlow, chkShadow, lblGlowSize, numGlowSize
    });

    // 创建主题预览面板
    CreateThemePreviewPanel();
}

2.2 CreateStyledButton() - 创建统一样式按钮

复制代码
private Button CreateStyledButton(string text, Color backColor, int x, int y)
{
    return new Button()
    {
        Text = text,                    // 按钮文本
        Location = new Point(x, y),     // 位置坐标
        Size = new Size(80, 30),        // 固定尺寸
        BackColor = backColor,          // 背景色
        // 根据背景亮度自动选择文字颜色(亮背景用黑字,暗背景用白字)
        ForeColor = backColor.GetBrightness() > 0.6 ? Color.Black : Color.White,
        FlatStyle = FlatStyle.Flat,     // 扁平化样式
        Font = new Font("Microsoft YaHei", 9)  // 统一字体
    };
}

2.3 CreateThemePreviewPanel() - 创建主题预览网格

复制代码
private void CreateThemePreviewPanel()
{
    // 创建分组容器
    GroupBox groupBox = new GroupBox()
    {
        Text = "快速主题预览",           // 分组标题
        Location = new Point(50, 400),  // 位置
        Size = new Size(500, 200),      // 尺寸
        ForeColor = Color.FromArgb(64, 64, 64),  // 文字颜色
        Font = new Font("Microsoft YaHei", 9, FontStyle.Bold)  // 粗体标题
    };

    // 创建流式布局面板,支持自动排列和滚动
    FlowLayoutPanel flowPanel = new FlowLayoutPanel()
    {
        Location = new Point(10, 20),   // 分组框内位置
        Size = new Size(480, 170),      // 内部尺寸
        AutoScroll = true               // 启用滚动条
    };

    // 为每个颜色主题创建预览按钮
    foreach (ColorScheme scheme in Enum.GetValues(typeof(ColorScheme)))
    {
        Button themeBtn = new Button()
        {
            Text = GetColorSchemeName(scheme),  // 显示主题名称
            Size = new Size(100, 30),           // 按钮尺寸
            BackColor = GetThemeBaseColor(scheme), // 使用主题主色作为背景
            ForeColor = Color.White,            // 白色文字
            FlatStyle = FlatStyle.Flat,         // 扁平样式
            Tag = scheme,                       // 存储枚举值用于事件处理
            Font = new Font("Microsoft YaHei", 8) // 小号字体
        };
        themeBtn.Click += ThemeBtn_Click;       // 绑定点击事件
        flowPanel.Controls.Add(themeBtn);       // 添加到流式面板
    }

    groupBox.Controls.Add(flowPanel);  // 将面板添加到分组框
    this.Controls.Add(groupBox);       // 将分组框添加到窗体
}

2.4 事件处理函数示例

复制代码
private void TrackBar_ValueChanged(object sender, EventArgs e)
{
    // 同步滑块值和进度控件值
    circularProgress.Value = trackBar.Value;
}

private void BtnIncrease_Click(object sender, EventArgs e)
{
    // 增加10个单位,并同步滑块
    circularProgress.Value += 10;
    trackBar.Value = circularProgress.Value;
}

private void CmbColorScheme_SelectedIndexChanged(object sender, EventArgs e)
{
    if (cmbColorScheme.SelectedIndex >= 0)
    {
        // 将选中索引转换为枚举值并应用主题
        ColorScheme scheme = (ColorScheme)cmbColorScheme.SelectedIndex;
        circularProgress.ApplyColorScheme(scheme);
    }
}
  1. 函数调用关系图

OnPaint() 主绘制流程

├── CreateRoundRectPath() // 创建背景路径

├── DrawGlowEffect() // 绘制发光效果

├── CreateProgressPen() // 创建进度画笔

└── DrawCenterText() // 绘制中心文本

属性设置流程

├── 任何属性setter → Invalidate() → OnPaint()

└── ApplyColorScheme() → SetColors() → Invalidate()

窗体交互流程

├── 用户操作 → 事件处理函数 → 修改CircularProgress属性

└── CircularProgress属性变化 → 自动重绘 → 视觉更新

这个详细分析展示了每个函数的精确功能、参数用途、内部逻辑和相互调用关系,体现了良好的面向对象设计和图形编程实践。

二、所有源码

CircularProgress.cs源码

复制代码
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

namespace _5_cycleCtrl
{
    public class CircularProgress : Control
    {
        private int _value = 0;
        private int _maximum = 100;
        private int _ringWidth = 20;
        private Color _ringColor = Color.FromArgb(0, 120, 215);
        private Color _ringBackColor = Color.FromArgb(240, 240, 240);
        private Color _backgroundColor = Color.White;
        private bool _showText = true;
        private string _textFormat = "{0}%";
        private Font _textFont;
        private Color _textColor = Color.FromArgb(64, 64, 64);
        private bool _showShadow = true;
        private Color _shadowColor = Color.FromArgb(100, 0, 0, 0);
        private int _shadowOffset = 2;
        private float _startAngle = 270f;
        private bool _useGradient = true;
        private Color _gradientColor = Color.Empty;
        private bool _showGlow = true;
        private int _glowSize = 5;

        public CircularProgress()
        {
            this.DoubleBuffered = true;
            this.Size = new Size(200, 200);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                         ControlStyles.UserPaint |
                         ControlStyles.ResizeRedraw |
                         ControlStyles.OptimizedDoubleBuffer, true);

            _textFont = new Font("Segoe UI", 12, FontStyle.Bold);
        }

        // 基本属性
        public int Value
        {
            get { return _value; }
            set
            {
                _value = Math.Max(0, Math.Min(_maximum, value));
                this.Invalidate();
            }
        }

        public int Maximum
        {
            get { return _maximum; }
            set
            {
                _maximum = Math.Max(1, value);
                _value = Math.Min(_value, _maximum);
                this.Invalidate();
            }
        }

        public int RingWidth
        {
            get { return _ringWidth; }
            set
            {
                _ringWidth = Math.Max(1, value);
                this.Invalidate();
            }
        }

        public Color RingColor
        {
            get { return _ringColor; }
            set
            {
                _ringColor = value;
                this.Invalidate();
            }
        }

        public Color RingBackColor
        {
            get { return _ringBackColor; }
            set
            {
                _ringBackColor = value;
                this.Invalidate();
            }
        }

        public Color BackgroundColor
        {
            get { return _backgroundColor; }
            set
            {
                _backgroundColor = value;
                this.Invalidate();
            }
        }

        // 文本相关属性
        public bool ShowText
        {
            get { return _showText; }
            set
            {
                _showText = value;
                this.Invalidate();
            }
        }

        public string TextFormat
        {
            get { return _textFormat; }
            set
            {
                _textFormat = value;
                this.Invalidate();
            }
        }

        public Font TextFont
        {
            get { return _textFont; }
            set
            {
                _textFont = value;
                this.Invalidate();
            }
        }

        public Color TextColor
        {
            get { return _textColor; }
            set
            {
                _textColor = value;
                this.Invalidate();
            }
        }

        // 效果属性
        public bool ShowShadow
        {
            get { return _showShadow; }
            set
            {
                _showShadow = value;
                this.Invalidate();
            }
        }

        public float StartAngle
        {
            get { return _startAngle; }
            set
            {
                _startAngle = value;
                this.Invalidate();
            }
        }

        public bool UseGradient
        {
            get { return _useGradient; }
            set
            {
                _useGradient = value;
                this.Invalidate();
            }
        }

        public Color GradientColor
        {
            get { return _gradientColor; }
            set
            {
                _gradientColor = value;
                this.Invalidate();
            }
        }

        public bool ShowGlow
        {
            get { return _showGlow; }
            set
            {
                _showGlow = value;
                this.Invalidate();
            }
        }

        public int GlowSize
        {
            get { return _glowSize; }
            set
            {
                _glowSize = Math.Max(0, value);
                this.Invalidate();
            }
        }

        // 预设颜色主题
        public void ApplyColorScheme(ColorScheme scheme)
        {
            switch (scheme)
            {
                case ColorScheme.Blue:
                    SetColors(Color.FromArgb(0, 120, 215), Color.FromArgb(64, 156, 255), Color.FromArgb(0, 90, 158));
                    break;
                case ColorScheme.Green:
                    SetColors(Color.FromArgb(46, 204, 113), Color.FromArgb(88, 214, 141), Color.FromArgb(39, 174, 96));
                    break;
                case ColorScheme.Red:
                    SetColors(Color.FromArgb(231, 76, 60), Color.FromArgb(236, 112, 99), Color.FromArgb(192, 57, 43));
                    break;
                case ColorScheme.Purple:
                    SetColors(Color.FromArgb(155, 89, 182), Color.FromArgb(175, 122, 197), Color.FromArgb(142, 68, 173));
                    break;
                case ColorScheme.Orange:
                    SetColors(Color.FromArgb(230, 126, 34), Color.FromArgb(235, 151, 78), Color.FromArgb(211, 84, 0));
                    break;
                case ColorScheme.Teal:
                    SetColors(Color.FromArgb(22, 160, 133), Color.FromArgb(72, 201, 176), Color.FromArgb(19, 141, 117));
                    break;
                case ColorScheme.Pink:
                    SetColors(Color.FromArgb(255, 107, 129), Color.FromArgb(255, 148, 164), Color.FromArgb(255, 71, 97));
                    break;
                case ColorScheme.Gold:
                    SetColors(Color.FromArgb(241, 196, 15), Color.FromArgb(245, 215, 110), Color.FromArgb(213, 172, 13));
                    break;
                case ColorScheme.Cyan:
                    SetColors(Color.FromArgb(0, 188, 212), Color.FromArgb(77, 208, 225), Color.FromArgb(0, 151, 167));
                    break;
                case ColorScheme.Indigo:
                    SetColors(Color.FromArgb(63, 81, 181), Color.FromArgb(106, 120, 205), Color.FromArgb(48, 63, 159));
                    break;
                case ColorScheme.Sunset:
                    SetColors(Color.FromArgb(255, 94, 77), Color.FromArgb(255, 145, 114), Color.FromArgb(255, 61, 38));
                    _gradientColor = Color.FromArgb(255, 193, 7);
                    break;
                case ColorScheme.Ocean:
                    SetColors(Color.FromArgb(0, 150, 199), Color.FromArgb(77, 184, 214), Color.FromArgb(0, 119, 190));
                    _gradientColor = Color.FromArgb(0, 180, 216);
                    break;
                case ColorScheme.Forest:
                    SetColors(Color.FromArgb(56, 142, 60), Color.FromArgb(102, 187, 106), Color.FromArgb(46, 125, 50));
                    break;
                case ColorScheme.Lavender:
                    SetColors(Color.FromArgb(179, 157, 219), Color.FromArgb(204, 191, 231), Color.FromArgb(149, 125, 173));
                    break;
                case ColorScheme.Coral:
                    SetColors(Color.FromArgb(255, 138, 101), Color.FromArgb(255, 173, 148), Color.FromArgb(255, 112, 67));
                    break;
            }
        }

        private void SetColors(Color ringColor, Color gradientColor, Color textColor)
        {
            _ringColor = ringColor;
            _gradientColor = gradientColor;
            _textColor = textColor;
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            // 绘制背景(圆角矩形)
            using (GraphicsPath path = CreateRoundRectPath(this.ClientRectangle, 15))
            using (SolidBrush backBrush = new SolidBrush(_backgroundColor))
            {
                g.FillPath(backBrush, path);

                using (Pen borderPen = new Pen(Color.FromArgb(200, 200, 200), 1))
                {
                    g.DrawPath(borderPen, path);
                }
            }

            // 计算圆环的矩形区域
            int padding = 10 + _glowSize;
            int ringDiameter = Math.Min(this.Width, this.Height) - (padding * 2);
            int x = (this.Width - ringDiameter) / 2;
            int y = (this.Height - ringDiameter) / 2;
            Rectangle rect = new Rectangle(x, y, ringDiameter, ringDiameter);

            // 调整圆环矩形
            int ringPadding = _ringWidth / 2 + 2;
            Rectangle ringRect = new Rectangle(
                rect.X + ringPadding,
                rect.Y + ringPadding,
                rect.Width - ringPadding * 2,
                rect.Height - ringPadding * 2
            );

            // 绘制发光效果
            if (_showGlow && _value > 0)
            {
                DrawGlowEffect(g, ringRect);
            }

            // 绘制圆环底色
            using (Pen backPen = new Pen(_ringBackColor, _ringWidth))
            {
                backPen.StartCap = LineCap.Round;
                backPen.EndCap = LineCap.Round;
                g.DrawArc(backPen, ringRect, 0, 360);
            }

            // 绘制进度圆环
            if (_value > 0)
            {
                using (Pen progressPen = CreateProgressPen(ringRect))
                {
                    float angle = 360f * _value / _maximum;
                    g.DrawArc(progressPen, ringRect, _startAngle, angle);
                }
            }

            // 绘制中心文本
            if (_showText)
            {
                DrawCenterText(g, ringDiameter);
            }
        }

        private Pen CreateProgressPen(Rectangle ringRect)
        {
            Pen progressPen = new Pen(_ringColor, _ringWidth);
            progressPen.StartCap = LineCap.Round;
            progressPen.EndCap = LineCap.Round;

            if (_useGradient && ringRect.Width > 50)
            {
                Color gradientEnd = _gradientColor.IsEmpty ?
                    ControlPaint.Light(_ringColor, 0.3f) : _gradientColor;

                using (var brush = new LinearGradientBrush(
                    new Point(ringRect.Left, ringRect.Top),
                    new Point(ringRect.Right, ringRect.Bottom),
                    _ringColor,
                    gradientEnd))
                {
                    progressPen.Brush = brush;
                }
            }

            return progressPen;
        }

        private void DrawGlowEffect(Graphics g, Rectangle ringRect)
        {
            for (int i = _glowSize; i > 0; i--)
            {
                using (Pen glowPen = new Pen(Color.FromArgb(30 - i * 5, _ringColor), _ringWidth + i * 2))
                {
                    glowPen.StartCap = LineCap.Round;
                    glowPen.EndCap = LineCap.Round;

                    float angle = 360f * _value / _maximum;
                    g.DrawArc(glowPen, ringRect, _startAngle, angle);
                }
            }
        }

        private void DrawCenterText(Graphics g, int ringDiameter)
        {
            string text = string.Format(_textFormat, _value);

            float fontSize = Math.Max(8, ringDiameter / 8f);
            using (Font font = new Font(_textFont.FontFamily, fontSize, _textFont.Style))
            using (SolidBrush textBrush = new SolidBrush(_textColor))
            {
                SizeF textSize = g.MeasureString(text, font);
                PointF textLocation = new PointF(
                    (this.Width - textSize.Width) / 2,
                    (this.Height - textSize.Height) / 2
                );

                if (_showShadow)
                {
                    using (SolidBrush shadowBrush = new SolidBrush(_shadowColor))
                    {
                        g.DrawString(text, font, shadowBrush,
                            textLocation.X + _shadowOffset,
                            textLocation.Y + _shadowOffset);
                    }
                }

                g.DrawString(text, font, textBrush, textLocation);
            }
        }

        private GraphicsPath CreateRoundRectPath(Rectangle rect, int radius)
        {
            GraphicsPath path = new GraphicsPath();

            path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
            path.AddArc(rect.X + rect.Width - radius, rect.Y, radius, radius, 270, 90);
            path.AddArc(rect.X + rect.Width - radius, rect.Y + rect.Height - radius,
                       radius, radius, 0, 90);
            path.AddArc(rect.X, rect.Y + rect.Height - radius, radius, radius, 90, 90);
            path.CloseFigure();

            return path;
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Invalidate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _textFont != null)
            {
                _textFont.Dispose();
            }
            base.Dispose(disposing);
        }
    }

    // 颜色主题枚举
    public enum ColorScheme
    {
        Blue,
        Green,
        Red,
        Purple,
        Orange,
        Teal,
        Pink,
        Gold,
        Cyan,
        Indigo,
        Sunset,
        Ocean,
        Forest,
        Lavender,
        Coral
    }
}

Form1.cs源码

复制代码
using System;
using System.Drawing;
using System.Windows.Forms;

namespace _5_cycleCtrl
{
    public partial class Form1 : Form
    {
        private CircularProgress circularProgress;
        private Button btnIncrease, btnDecrease;
        private ComboBox cmbColorScheme;
        private TrackBar trackBar;
        private CheckBox chkGradient, chkGlow, chkShadow;
        private NumericUpDown numGlowSize;

        public Form1()
        {
            InitializeComponent();
            SetupControls();
        }

        private void SetupControls()
        {
            this.Text = "增强版圆环进度控件演示";
            this.Size = new Size(600, 700);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.BackColor = Color.White;

            // 创建圆环控件
            circularProgress = new CircularProgress();
            circularProgress.Location = new Point(200, 30);
            circularProgress.Size = new Size(200, 200);
            circularProgress.BackgroundColor = Color.White;
            circularProgress.RingBackColor = Color.FromArgb(240, 240, 240);
            circularProgress.RingWidth = 15;
            circularProgress.TextFormat = "{0}%";
            circularProgress.Maximum = 100;
            circularProgress.Value = 45;
            circularProgress.ShowShadow = true;
            circularProgress.UseGradient = true;
            circularProgress.ShowGlow = true;

            // 应用初始颜色主题
            circularProgress.ApplyColorScheme(ColorScheme.Ocean);

            // 创建滑块控件
            trackBar = new TrackBar();
            trackBar.Location = new Point(50, 250);
            trackBar.Size = new Size(500, 45);
            trackBar.Minimum = 0;
            trackBar.Maximum = 100;
            trackBar.Value = 45;
            trackBar.TickFrequency = 10;
            trackBar.ValueChanged += TrackBar_ValueChanged;

            // 创建按钮
            btnIncrease = CreateStyledButton("+10", Color.FromArgb(0, 120, 215), 50, 310);
            btnIncrease.Click += BtnIncrease_Click;

            btnDecrease = CreateStyledButton("-10", Color.FromArgb(200, 200, 200), 150, 310);
            btnDecrease.Click += BtnDecrease_Click;

            // 创建颜色方案选择
            cmbColorScheme = new ComboBox();
            cmbColorScheme.Location = new Point(250, 310);
            cmbColorScheme.Size = new Size(200, 25);
            cmbColorScheme.DropDownStyle = ComboBoxStyle.DropDownList;

            // 添加所有颜色主题
            foreach (ColorScheme scheme in Enum.GetValues(typeof(ColorScheme)))
            {
                cmbColorScheme.Items.Add(GetColorSchemeName(scheme));
            }

            cmbColorScheme.SelectedIndex = (int)ColorScheme.Ocean;
            cmbColorScheme.SelectedIndexChanged += CmbColorScheme_SelectedIndexChanged;

            // 创建效果控制
            chkGradient = CreateCheckBox("渐变效果", 50, 360);
            chkGradient.Checked = true;
            chkGradient.CheckedChanged += ChkGradient_CheckedChanged;

            chkGlow = CreateCheckBox("发光效果", 150, 360);
            chkGlow.Checked = true;
            chkGlow.CheckedChanged += ChkGlow_CheckedChanged;

            chkShadow = CreateCheckBox("文本阴影", 250, 360);
            chkShadow.Checked = true;
            chkShadow.CheckedChanged += ChkShadow_CheckedChanged;

            // 发光大小控制
            Label lblGlowSize = new Label()
            {
                Text = "发光大小:",
                Location = new Point(350, 362),
                Size = new Size(60, 20),
                ForeColor = Color.FromArgb(64, 64, 64)
            };

            numGlowSize = new NumericUpDown()
            {
                Location = new Point(420, 360),
                Size = new Size(50, 20),
                Minimum = 0,
                Maximum = 10,
                Value = 5
            };
            numGlowSize.ValueChanged += NumGlowSize_ValueChanged;

            // 添加到窗体
            this.Controls.AddRange(new Control[] {
                circularProgress, trackBar, btnIncrease, btnDecrease, cmbColorScheme,
                chkGradient, chkGlow, chkShadow, lblGlowSize, numGlowSize
            });

            // 创建主题预览面板
            CreateThemePreviewPanel();
        }

        private Button CreateStyledButton(string text, Color backColor, int x, int y)
        {
            return new Button()
            {
                Text = text,
                Location = new Point(x, y),
                Size = new Size(80, 30),
                BackColor = backColor,
                ForeColor = backColor.GetBrightness() > 0.6 ? Color.Black : Color.White,
                FlatStyle = FlatStyle.Flat,
                Font = new Font("Microsoft YaHei", 9)
            };
        }

        private CheckBox CreateCheckBox(string text, int x, int y)
        {
            return new CheckBox()
            {
                Text = text,
                Location = new Point(x, y),
                Size = new Size(80, 20),
                ForeColor = Color.FromArgb(64, 64, 64),
                Font = new Font("Microsoft YaHei", 9)
            };
        }

        private void CreateThemePreviewPanel()
        {
            GroupBox groupBox = new GroupBox()
            {
                Text = "快速主题预览",
                Location = new Point(50, 400),
                Size = new Size(500, 200),
                ForeColor = Color.FromArgb(64, 64, 64),
                Font = new Font("Microsoft YaHei", 9, FontStyle.Bold)
            };

            FlowLayoutPanel flowPanel = new FlowLayoutPanel()
            {
                Location = new Point(10, 20),
                Size = new Size(480, 170),
                AutoScroll = true
            };

            // 创建主题预览按钮
            foreach (ColorScheme scheme in Enum.GetValues(typeof(ColorScheme)))
            {
                Button themeBtn = new Button()
                {
                    Text = GetColorSchemeName(scheme),
                    Size = new Size(100, 30),
                    BackColor = GetThemeBaseColor(scheme),
                    ForeColor = Color.White,
                    FlatStyle = FlatStyle.Flat,
                    Tag = scheme,
                    Font = new Font("Microsoft YaHei", 8)
                };
                themeBtn.Click += ThemeBtn_Click;
                flowPanel.Controls.Add(themeBtn);
            }

            groupBox.Controls.Add(flowPanel);
            this.Controls.Add(groupBox);
        }

        private string GetColorSchemeName(ColorScheme scheme)
        {
            return scheme.ToString();
        }

        private Color GetThemeBaseColor(ColorScheme scheme)
        {
            switch (scheme)
            {
                case ColorScheme.Blue: return Color.FromArgb(0, 120, 215);
                case ColorScheme.Green: return Color.FromArgb(46, 204, 113);
                case ColorScheme.Red: return Color.FromArgb(231, 76, 60);
                case ColorScheme.Purple: return Color.FromArgb(155, 89, 182);
                case ColorScheme.Orange: return Color.FromArgb(230, 126, 34);
                case ColorScheme.Teal: return Color.FromArgb(22, 160, 133);
                case ColorScheme.Pink: return Color.FromArgb(255, 107, 129);
                case ColorScheme.Gold: return Color.FromArgb(241, 196, 15);
                case ColorScheme.Cyan: return Color.FromArgb(0, 188, 212);
                case ColorScheme.Indigo: return Color.FromArgb(63, 81, 181);
                case ColorScheme.Sunset: return Color.FromArgb(255, 94, 77);
                case ColorScheme.Ocean: return Color.FromArgb(0, 150, 199);
                case ColorScheme.Forest: return Color.FromArgb(56, 142, 60);
                case ColorScheme.Lavender: return Color.FromArgb(179, 157, 219);
                case ColorScheme.Coral: return Color.FromArgb(255, 138, 101);
                default: return Color.Blue;
            }
        }

        private void ThemeBtn_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            if (btn != null)
            {
                ColorScheme scheme = (ColorScheme)btn.Tag;
                circularProgress.ApplyColorScheme(scheme);
                cmbColorScheme.SelectedItem = GetColorSchemeName(scheme);
            }
        }

        private void TrackBar_ValueChanged(object sender, EventArgs e)
        {
            circularProgress.Value = trackBar.Value;
        }

        private void BtnIncrease_Click(object sender, EventArgs e)
        {
            circularProgress.Value += 10;
            trackBar.Value = circularProgress.Value;
        }

        private void BtnDecrease_Click(object sender, EventArgs e)
        {
            circularProgress.Value -= 10;
            trackBar.Value = circularProgress.Value;
        }

        private void CmbColorScheme_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbColorScheme.SelectedIndex >= 0)
            {
                ColorScheme scheme = (ColorScheme)cmbColorScheme.SelectedIndex;
                circularProgress.ApplyColorScheme(scheme);
            }
        }

        private void ChkGradient_CheckedChanged(object sender, EventArgs e)
        {
            circularProgress.UseGradient = chkGradient.Checked;
        }

        private void ChkGlow_CheckedChanged(object sender, EventArgs e)
        {
            circularProgress.ShowGlow = chkGlow.Checked;
        }

        private void ChkShadow_CheckedChanged(object sender, EventArgs e)
        {
            circularProgress.ShowShadow = chkShadow.Checked;
        }

        private void NumGlowSize_ValueChanged(object sender, EventArgs e)
        {
            circularProgress.GlowSize = (int)numGlowSize.Value;
        }
    }
}

三、效果演示

可以选择各种控件参数设置,点击按钮,圆环效果进行更新。

相关推荐
Coovally AI模型快速验证3 小时前
华为发布开源超节点架构,以开放战略叩响AI算力生态变局
人工智能·深度学习·神经网络·计算机视觉·华为·架构·开源
ajassi20004 小时前
开源 java android app 开发(十五)自定义绘图控件--仪表盘
android·java·开源
玉夏4 小时前
【每日算法C#】二进制求和 LeetCode
算法·leetcode·c#
政沅同学5 小时前
C#系统日志
开发语言·c#
胡耀超5 小时前
开源生态与技术民主化 - 从LLaMA到DeepSeek的开源革命(LLaMA、DeepSeek-V3、Mistral 7B)
人工智能·python·神经网络·开源·大模型·llama·deepseek
love530love8 小时前
Windows 系统部署 阿里团队开源的先进大规模视频生成模型 Wan2.2 教程——基于 EPGF 架构
运维·人工智能·windows·python·架构·开源·大模型
说私域8 小时前
定制开发开源AI智能名片S2B2C商城小程序在智慧零售价值链重构中的价值研究
人工智能·小程序·开源
Eiceblue9 小时前
使用 C# 设置 Excel 单元格数据验证
java·c#·excel
mudtools10 小时前
.NET操作Excel:单元格范围 (Range) 的精确定位与常用操作 (下)
c#·.net·excel·wps