当前位置:首页 > 人生 > 作品墙 > 正文内容

ProgressBarC 圆形进度条调用文档

作品墙3天前


命名空间:CConUI
继承:ProgressBarBase(自定义基类) → Control
可见性:public class ProgressBarC(可外部使用)
定位:圆形进度条(另一种风格)——以「从底部两侧对称向上展开」的方式显示进度,与 ProgressBarB(从 12 点顺时针扇形展开)视觉风格不同,两者 API 相同,可互换使用。


一、作用

在控件区域内绘制一个居中的圆形进度环,进度视觉是「从底部隆起,向两侧对称展开,逐渐扩张至整个圆」:

  • 底层:填满的背景圆(ColorBack);

  • 上层:进度填充区域(ColorCore),从底部两侧向上生长;

  • 最外层:圆环边框(BorderColor / BorderSize);

  • 中央可显示文本 Text(ForeColor / Font)。

视觉进度示意

进度视觉效果
Value = Min 或 0不绘制进度,只剩背景圆 + 边框 + 文字
0 < 进度 < 50%底部出现一个小小的"碗形/月牙"填充,随进度增高
进度 = 50%填充恰好填满下半圆(从底部到水平直径)
50% < 进度 < 100%"碗形"继续向上隆起,弦从水平直径向上抬升
进度 = 100%填满整个圆

与 ProgressBarB 的区别:ProgressBarB 是「从 12 点顺时针扫过扇形」,ProgressBarC 是「从底部向两侧对称展开」。API 相同,可根据 UI 风格需要二选一。


二、快速上手

using System.Drawing;
using System.Windows.Forms;
using CConUI;

// 1. 创建控件
var bar = new ProgressBarC();

// 2. 放入容器(建议尺寸接近正方形)
bar.Parent = panel1;
bar.Size = new Size(120, 120);
bar.Location = new Point(20, 20);

// 3. 设置范围与当前值
bar.Min = 0;
bar.Max = 100;
bar.Value = 45;
bar.Text = "45%";

// 4. 外观
bar.ColorBack = Color.FromArgb(45, 45, 48);
bar.ColorCore = Color.FromArgb(0, 200, 120);
bar.BorderColor = Color.FromArgb(30, 30, 30);
bar.BorderSize = 4;
bar.ForeColor = Color.White;
bar.Font = new Font("Microsoft YaHei", 10F, FontStyle.Bold);

三、构造函数

public ProgressBarC()

项目说明
参数无(本类未定义构造函数,使用 C# 隐式默认构造函数)
实际行为调用 ProgressBarBase 的无参构造函数进行初始化
默认尺寸以 ProgressBarBase 为准;使用本控件时建议手动设置接近正方形的 Size(如 100×100、120×120),否则圆形会被压缩成椭圆
var bar = new ProgressBarC
{
    Parent = panel1,
    Size = new Size(120, 120)
};

四、公开成员

4.1 本类新增/重写的成员

成员类型可见性说明
OnPaint(PaintEventArgs e)方法(override)protected override重写绘制逻辑,改为圆形进度绘制。外部无法直接调用,仅在控件需要重绘时由 WinForms 自动调用

ProgressBarC 本身没有新增 public 属性、方法或事件,它的所有对外接口完全继承自 ProgressBarBase。

4.2 继承自 ProgressBarBase 的成员(由本类绘制逻辑推断)

成员类型(推断)在本类中的作用用法示例
Minint进度下限;小于此值的 Value 会按 Min 显示bar.Min = 0;
Maxint进度上限;进度映射的分母。注意为 0 时不绘制进度bar.Max = 100;
Valueint当前进度;决定填充区的高度bar.Value = 45;
ColorBackColor背景圆的填充色bar.ColorBack = Color.Gray;
ColorCoreColor进度填充区的颜色bar.ColorCore = Color.Lime;
BorderColorColor圆环边框颜色bar.BorderColor = Color.Black;
BorderSizeint圆环边框粗细(像素)bar.BorderSize = 4;

事件(如 Change / ValueChanged)与其它方法请参考 ProgressBarBase 源码。

4.3 绘制逻辑所使用到的 Control 继承成员

成员来源说明
TextControl控件文本;本类在圆形中央居中绘制
FontControl文本字体
ForeColorControl文本颜色
ClientSizeControl用于计算圆的直径和位置
Invalidate()Control属性变化后触发重绘

五、公开方法

ProgressBarC 没有定义任何 public 方法,全部公开方法由 ProgressBarBase 与 Control 继承。

若 ProgressBarBase 中定义了类似 LoadStart() / LoadPause() / LoadEnd() 等「等待特效」方法,在 ProgressBarC 中不会被重写——ProgressBarC 只重写了 OnPaint,所以调用这些方法仍然有效,但由于绘制逻辑已被替换为「圆形进度」,等待特效的视觉效果不会体现在 ProgressBarC 的绘制里(除非 ProgressBarBase.OnPaint 里本身有相关逻辑被 base.OnPaint(e) 调用——实际上 ProgressBarC 第一行就调用了 base.OnPaint(e),所以基类的绘制会被执行,但 ProgressBarC 会在其之上再次绘制圆形,可能造成视觉重叠)。


六、绘制原理(深入理解)

以下分析帮助你在调整尺寸、边框、颜色、进度范围时理解 ProgressBarC 的具体表现。

6.1 计算外圆与内圆

float side = Math.Min(ClientSize.Width, ClientSize.Height);
if (side
要点说明
正方形判断以 min(宽, 高) 作为直径,保证在非正方形控件中也是正圆(多出的空间留白)
d = side - 1f减 1 像素:GDI+ 抗锯齿模式下,若直径等于 side,最右/最下边缘会被裁掉半像素。减 1 让外圆完整落在控件内
ox / oy让外接正方形在客户区内居中
side ≤ 4太小不绘制,避免异常半径
border 的上限 d/2 - 1边框半径不能超过圆半径,否则内圆消失。减 1 是安全余量。
负值兜底为 0(Math.Max(0, ...))
inner 计算内圆 = 外圆向内缩 border 像素。所有进度填充都画在 inner 内,边框最后画在外圆上覆盖边缘
inner.Width ≤ 0 检查如果边框异常粗导致内圆为空,直接返回,避免绘制错误

6.2 绘制背景圆

using (var brush = new SolidBrush(this.ColorBack))
    g.FillPie(brush, inner.X, inner.Y, inner.Width, inner.Height, -90f, 360f);
要点说明
用 FillPie 而不是 FillEllipse为了让背景圆与进度扇形走同一条 GDI+ 路径族,两者弧线像素级重合,避免露出 1px 背景缝
-90f, 360f从 12 点方向开始,扫过 360°,即完整圆。GDI+ 角度单位是度,0° 在 3 点方向,顺时针为正

6.3 绘制进度填充(核心:半圆对称展开)

int v = this.Value > this.Min ? this.Value : this.Min;
if (this.Max > 0 && v > 0)
{
    float a = 180f / this.Max * v;                   // 0~Max 映射到 0~180°
    if (a > 0f)
    {
        using (var path = new GraphicsPath())
        {
            path.AddArc(inner, 90f, a);              // 从正下方顺时针画 a
            path.AddArc(inner, 90f - a, a);          // 从对称位置顺时针画 a
            using (var brush = new SolidBrush(this.ColorCore))
                g.FillPath(brush, path);
        }
    }
}
要点说明
v 下限保护Math.Max(Value, Min):小于 Min 时按 Min 处理,保证不会出现「比下限还低」的进度
Max > 0 保护避免 Max = 0 时除以 0 得到 NaN/Infinity
v > 0 保护如果 Min < 0 且 Value <= Min,v 可能为负数或 0,直接跳过(避免画反)
a = 180f / Max * v核心映射公式:0 ~ Max 线性映射到 0° ~ 180°。
注意:分母是 Max 而不是 (Max - Min),因此当 Min > 0 时,Value = Min 不会得到 0°,而是 180° × Min / Max。若需「Min 时刻 0 进度」的严格语义,请自行保证 Min = 0,或在外部把 Value / Min / Max 转成 0 ~ Max 的等价区间
path.AddArc(inner, 90f, a)从 90°(正下方)开始,顺时针画弧扫过 a 度:
a=0 → 无弧;a=90 → 从底部到右侧(90°→180°);a=180 → 从底部绕左半到顶部
path.AddArc(inner, 90f - a, a)从对称位置(90° - a)开始,顺时针画弧扫过 a 度:
a=90 → 从 0°(右侧)扫到 90°(底部);a=180 → 从 -90°(顶部)扫到 90°(底部)
两段弧组合GraphicsPath 会把第一段弧的终点与第二段弧的起点自动用直线连接,形成封闭区域。
这产生「底部圆弧 + 顶部弦线」的填充效果,即从底部对称向上的「碗形/月牙」
不同进度的表现a=45°(25%):底部小碗形。
a=90°(50%):弦恰好在水平直径处,填满下半圆。
a=135°(75%):弦向上抬起,填充超出下半圆。
a=180°(100%):两段弧端点重合,形成完整圆。

6.4 绘制文本

if (!string.IsNullOrEmpty(this.Text))
{
    using (var brush = new SolidBrush(this.ForeColor))
    using (var sf = new StringFormat
    {
        Alignment = StringAlignment.Center,
        LineAlignment = StringAlignment.Center
    })
        g.DrawString(this.Text, this.Font, brush, outer, sf);
}
要点说明
绘制在 outer 内即外接正方形,文字在圆的中心居中
Center / Center水平居中 + 垂直居中

6.5 绘制圆环边框

if (border > 0)
{
    float half = border / 2f;
    var penRect = new RectangleF(outer.X + half, outer.Y + half,
                                 outer.Width - border,
                                 outer.Height - border);
    using (var pen = new Pen(this.BorderColor, border))
        g.DrawEllipse(pen, penRect);
}
要点说明
手算内缩 halfGDI+ 的 Pen 默认居中描边:会以绘制路径为中轴,向内外各扩展 border/2。若直接 DrawEllipse(outer),一半边框画到外面。
不使用 PenAlignment.Inset:在 DrawEllipse 上,PenAlignment 的行为在不同 GDI+ 版本中表现不一致(有时无效或部分无效),因此本类采用「手动内缩半个线宽」的稳妥方案
内缩后矩形X/Y 各 + half,W/H 各 - border(因为两侧各缩 half,合计 border)
边框最后绘制放在最后,可以覆盖进度填充在内外边界上可能出现的抗锯齿半像素溢出,保证边缘干净

七、公开成员速查表

成员来源类型说明
ProgressBarC()本类(隐式)构造函数默认无参构造,调用基类初始化
MinProgressBarBase属性(int)进度下限
MaxProgressBarBase属性(int)进度上限(用于比例映射;为 0 时不绘制进度)
ValueProgressBarBase属性(int)当前进度
ColorBackProgressBarBase属性(Color)背景圆颜色
ColorCoreProgressBarBase属性(Color)进度填充色
BorderColorProgressBarBase属性(Color)圆环颜色
BorderSizeProgressBarBase属性(int)圆环粗细
TextControl属性(string)圆中央文字
FontControl属性(Font)文字字体
ForeColorControl属性(Color)文字颜色
Size / ClientSizeControl属性(Size)建议设为正方形
Invalidate()Control方法触发重绘
OnPaint(e)本类(override)方法(protected)圆形绘制逻辑,外部不可直接调用

事件(如 Change / ValueChanged)与其它方法请参考 ProgressBarBase 源码。


八、完整使用示例

示例 1:基础圆形进度条

using System.Drawing;
using System.Windows.Forms;
using CConUI;

var bar = new ProgressBarC
{
    Parent = panel1,
    Size = new Size(120, 120),
    Location = new Point(20, 20),
    Min = 0,
    Max = 100,
    Value = 45,
    Text = "45%",
    ColorBack = Color.FromArgb(45, 45, 48),
    ColorCore = Color.FromArgb(0, 200, 120),
    BorderColor = Color.FromArgb(30, 30, 30),
    BorderSize = 4,
    ForeColor = Color.White,
    Font = new Font("Microsoft YaHei", 10F, FontStyle.Bold)
};

示例 2:配合计时器动态变化

var bar = new ProgressBarC
{
    Parent = this,
    Size = new Size(150, 150),
    Min = 0,
    Max = 100,
    BorderSize = 6,
    ColorBack = Color.FromArgb(50, 50, 50),
    ColorCore = Color.OrangeRed,
    BorderColor = Color.FromArgb(20, 20, 20),
    Font = new Font("Segoe UI", 12F, FontStyle.Bold)
};

var timer = new Timer { Interval = 50 };
timer.Tick += (s, e) =>
{
    if (bar.Value >= bar.Max)
    {
        timer.Stop();
        bar.Text = "完成";
        return;
    }
    bar.Value += 1;
    bar.Text = bar.Value + "%";
    bar.Invalidate();   // 若基类 Value 不自动刷新,需手动 Invalidate
};
timer.Start();

示例 3:与 ProgressBarB 互换(同一套 API)

// 两者仅视觉风格不同,API 相同。如果要切换风格:
ProgressBarBase bar = someCondition
    ? new ProgressBarB { /* B 配置 */ }
    : new ProgressBarC { /* C 配置 */ };

bar.Parent = this;
bar.Size = new Size(120, 120);
bar.Min = 0;
bar.Max = 100;
bar.Value = 60;
bar.ColorBack = Color.FromArgb(45, 45, 48);
bar.ColorCore = Color.DodgerBlue;
bar.BorderSize = 4;
bar.Text = "60%";

示例 4:非正方形控件下的正圆(居中 + 留白)

// 即使控件是长方形,进度条仍会绘制一个居中的正圆
var bar = new ProgressBarC
{
    Parent = this,
    Size = new Size(240, 100),      // 长方形,实际圆直径 = min(240, 100) = 100 - 1 = 99
    BorderSize = 3,
    ColorCore = Color.Lime,
    BorderColor = Color.Black,
    Text = "Loading",
    Font = new Font("Consolas", 9F)
};




转载请注明出处。

本文链接:http://www.pythonopen.com/?id=7976

相关文章

已经实现的一些算法

编码CConA1是一种可复原的编码算法,用于将文本或字节转换为纯字母。可用于文件名混淆,避免因包含违...

横向滚动条HScrollBar 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control版本:基于所提供...

纵向滚动条VScrollBar 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control版本:基于所提供...

菜单MenuItem 与 ContextMenu 控件调用文档

命名空间:CConUI依赖:System.Windows.Forms、System.Drawing、...

图片框PictureBox 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control定位:自绘图片框...

蚂蚁线AntLine 控件调用文档

命名空间:CConUI继承:System.Windows.Forms.Control定位:虚线蚂蚁线...