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

​ProgressBarB 圆形进度条调用文档

作品墙3天前


命名空间:CConUI
继承:ProgressBarBase(自定义基类) → Control
可见性:public class ProgressBarB(可外部使用)
定位:圆形进度条——以圆环/扇形方式显示进度,继承 ProgressBarBase 的所有公共成员,仅重写绘制逻辑。


一、作用

在控件区域内绘制一个居中的圆形进度环:

  • 底层是一个填满的背景圆(颜色 ColorBack);

  • 上层是一个扇形进度(颜色 ColorCore),从 12 点方向开始顺时针扩展;

  • 最外层绘制一个圆环边框(BorderColor / BorderSize);

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

适用于:圆形下载/加载指示器、环形进度展示、仪表盘风格的状态指示等场景。


二、快速上手

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

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

// 2. 放入容器
bar.Parent = panel1;
bar.Dock = DockStyle.None;
bar.Size = new Size(120, 120);   // 必须接近正方形,圆形才会是正圆
bar.Location = new Point(30, 30);

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

// 4. 外观
bar.ColorBack = Color.FromArgb(50, 50, 50);       // 背景圆
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);

// 5. 监听进度变化(请以 ProgressBarBase 实际事件名为准,
//    若基类使用 ValueChanged,则订阅它;若使用 Change,则改为 bar.Change)
bar.Value = 80;
bar.Invalidate();   // 若基类 Value 不自动重绘,可手动 Invalidate

三、构造函数

public ProgressBarB()

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

四、公开成员

4.1 本类新增/重写的成员

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

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

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

以下是 ProgressBarB.OnPaint 中实际访问到的成员,它们由 ProgressBarBase 提供,语义应与其同名成员一致:

成员类型(推断)在本类中的作用用法示例
Minint进度下限;用于计算扇形角度bar.Min = 0;
Maxint进度上限;用于计算扇形角度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;

其它可能存在于 ProgressBarBase 中的成员(例如文本/字体/前景色、事件 Change 或 ValueChanged、等待特效等),本源码未直接引用,请以 ProgressBarBase 源码为准。常见场景下,基类至少会提供:

  • Text / Font / ForeColor(继承自 Control,本类绘制中使用了 Text、Font、ForeColor);

  • Change 或 ValueChanged 事件(用于监听 Value 变化);

  • BorderSize 的合理默认值、ColorBack / ColorCore / BorderColor 的默认颜色。

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

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

五、公开方法

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

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

因此:

  • 如需使用基类提供的“等待特效”,需要确认基类的 OnPaint 是否会绘制矩形条;若是,则会与 ProgressBarB 的圆形绘制叠加,视觉效果混乱;

  • 建议只把 ProgressBarB 用于“静态圆形进度”的场景。


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

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

6.1 计算外圆

float side = Math.Min(ClientSize.Width, ClientSize.Height);
if (side
要点说明
正方形判断以 min(宽, 高) 作为直径,保证在非正方形控件中也是正圆(多出的空间留白)
d = side - 1f减 1 像素:因为 GDI+ 的 DrawEllipse / FillPie 在抗锯齿模式下,如果直径恰好等于 side,最右/最下边缘会被裁掉半像素。减 1 让外圆完整落在控件内
ox / oy让外接正方形在客户区内居中:(Client - d) / 2 是左右/上下多余的半宽/半高
side ≤ 4太小不绘制,避免出现异常半径导致绘制错误

6.2 计算边框粗细

int border = Math.Min(base.BorderSize, (int)(d / 2) - 1);
要点说明
上限 d/2 - 1边框半径不能超过圆的半径,否则整个圆都会被边框覆盖。减 1 是安全余量
最小值BorderSize 为负数或 0 时 border 为 0,跳过边框绘制

6.3 绘制背景圆

using (var b = new SolidBrush(base.ColorBack))
    g.FillPie(b, outer.X, outer.Y, outer.Width, outer.Height, -90f, 360f);
要点说明
用 FillPie 而不是 FillEllipse为了让背景圆与进度扇形走同一条 GDI+ 路径族(FillPie 在 Windows 下可能有细微的像素处理差异)。这样两者弧线才能完美重合,避免边缘出现“锯齿叠锯齿”
-90f, 360f从 12 点方向(-90°)开始,扫过 360°,也就是完整圆。GDI+ 角度单位是度,0° 在 3 点方向,顺时针为正

6.4 绘制进度扇形

float sweep = 0f;
if (base.Max > base.Min)
{
    int v = Math.Max(base.Min, Math.Min(base.Max, base.Value));
    sweep = 360f * (v - base.Min) / (base.Max - base.Min);
}

if (sweep > 0f)
{
    var fill = RectangleF.Inflate(outer, 0.5f, 0.5f);   // 膨胀 0.5 像素
    using (var b = new SolidBrush(base.ColorCore))
        g.FillPie(b, fill.X, fill.Y, fill.Width, fill.Height, -90f, sweep);
}
要点说明
Max > Min 保护如果 Max ≤ Min(例如默认 0/100 但用户误设 Max = 0),跳过绘制,避免除零得到 NaN
Math.Max/Clamp先把 Value 夹到 [Min, Max] 内,防止越界导致角度超过 360°
360f * (v - Min) / (Max - Min)线性映射:v = Min 时 sweep = 0;v = Max 时 sweep = 360
RectangleF.Inflate(outer, 0.5f, 0.5f)把外接矩形向外膨胀 0.5 像素,让进度弧比背景弧稍微大一点,从而覆盖掉背景圆在抗锯齿下可能露出的 1 像素“漏白”
sweep > 0f进度为 0 时不绘制,避免画出一根发丝状的线

6.5 绘制文本

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

6.6 绘制圆环边框

if (border > 0)
{
    float half = border / 2f;
    var penRect = RectangleF.Inflate(outer, -half, -half);  // 向内缩 half
    using (var p = new Pen(base.BorderColor, border))
        g.DrawEllipse(p, penRect);
}
要点说明
RectangleF.Inflate(outer, -half, -half)GDI+ 的 Pen 默认对齐方式是居中——描边会以绘制路径为中轴,向内外各扩展 border/2。如果直接 DrawEllipse(outer),一半边框会画到 outer 外面。向内缩 half,使描边的外边缘正好落在 outer 上
边框最后绘制为什么最后画:进度扇形膨胀了 0.5 像素,可能会盖住背景圆的边缘。边框放在最后绘制,可以覆盖掉这 0.5 像素的溢出,让边缘干净整齐
border 上限前面已限制为不超过 d/2 - 1,保证 penRect 内接矩形仍然有效

七、公开成员速查表

成员来源类型说明
ProgressBarB()本类(隐式)构造函数默认无参构造,调用基类初始化
MinProgressBarBase属性(int)进度下限
MaxProgressBarBase属性(int)进度上限
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 ProgressBarB
{
    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 ProgressBarB
{
    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:圆形下载指示器

var bar = new ProgressBarB
{
    Parent = this,
    Size = new Size(80, 80),
    BorderSize = 3,
    ColorBack = Color.FromArgb(240, 240, 240),
    ColorCore = Color.DodgerBlue,
    BorderColor = Color.LightGray,
    Font = new Font("Microsoft YaHei", 8F)
};

// 模拟下载
int total = 500;
int current = 0;
bar.Max = total;
bar.Value = 0;

var timer = new Timer { Interval = 50 };
timer.Tick += (s, e) =>
{
    current += 10;
    if (current >= total)
    {
        current = total;
        timer.Stop();
    }
    bar.Value = current;
    bar.Text = (current * 100 / total) + "%";
    bar.Invalidate();
};
timer.Start();

示例 4:多个圆形进度条(网格排布)

for (int i = 0; i < 4; i++)
{
    var bar = new ProgressBarB
    {
        Parent = panel1,
        Size = new Size(90, 90),
        Location = new Point(10 + i * 100, 10),
        Min = 0,
        Max = 100,
        Value = 25 * (i + 1),
        Text = (25 * (i + 1)) + "%",
        ColorCore = Color.FromArgb(0, 150 + i * 30, 200 - i * 30),
        BorderSize = 4
    };
}





转载请注明出处。

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

相关文章

已经实现的一些算法

编码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定位:虚线蚂蚁线...