ProgressBarF 圆环扇区进度条调用文档
命名空间:CConUI
继承:ProgressBarBase → Control
可见性:public class ProgressBarF
默认尺寸:150 × 150(正方形)
定位:圆环扇区进度条——自适应绘制正圆;底层是背景圆,中间是可选装饰内环,主环从 12 点顺时针扫过,表示进度;中央可显示文字。
一、作用
在控件区域内绘制一个居中的正圆环,采用扇形扫过的经典进度表现方式:
背景圆:
ColorBack铺满整圆;装饰内环:可选(
ShowInnerRing),用ColorCore画一条 2px 细圆环,位于主环内侧,形成层次感;进度圆环:用
ColorCore以PieWidth厚度绘制,从 12 点(-90°)顺时针扫过与Value对应的角度;外边框:
BorderColor/BorderSize围最外一圈;中央文字:
Text/Font/ForeColor。
视觉示意
| 进度 | 视觉效果 |
|---|---|
Value ≤ Min | 仅显示背景圆 + 装饰内环 + 边框 + 文字,主环不显示 |
| 0 < 进度 < 100% | 主环从 12 点方向开始顺时针扩展,弧线长度随进度增加 |
| 进度 = 100% | 主环扫过 360°,圆环完整一圈 |
与其它进度条风格对比:
ProgressBarB:填充式扇形(从 12 点顺时针填充到圆心);
ProgressBarC:从底部向两侧对称展开(填充区域);
ProgressBarD:水位 + 波浪(填充,动画);
ProgressBarE:环被切块、逐块点亮(动画 loading);
ProgressBarF:圆环扫过(描边弧线),中间保持空心(可选加装饰内环),视觉更“轻盈”、更“仪表盘”。
二、快速上手
using System.Drawing;
using System.Windows.Forms;
using CConUI;
// 1. 创建控件(默认 150 × 150)
var bar = new ProgressBarF();
// 2. 放入容器
bar.Parent = panel1;
bar.Location = new Point(20, 20);
// 也可 bar.Dock = DockStyle.None; bar.Size = new Size(150, 150);
// 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 = 2;
bar.PieWidth = 20; // 主环厚度
bar.ShowInnerRing = true; // 显示装饰内环
bar.ForeColor = Color.White;
bar.Font = new Font("Microsoft YaHei", 10F, FontStyle.Bold);三、构造函数
public ProgressBarF()
| 项目 | 说明 |
|---|---|
| 参数 | 无 |
| 作用 | 构造圆环扇区进度条 |
| 实际行为 | ① 调用 ProgressBarBase 无参构造(基类已处理 UserPaint / 双缓冲等);② 设置 Size = new Size(150, 150) |
| 默认尺寸 | 150 × 150(正方形,绘制出来就是正圆) |
| 默认属性 | PieWidth = 20、ShowInnerRing = true;其它属性(Min / Max / Value / 颜色)继承基类默认 |
var bar = new ProgressBarF
{
Parent = panel1,
Location = new Point(20, 20)
};四、公开属性
4.1 本类新增的属性
public int PieWidth
| 项目 | 说明 |
|---|---|
| 类型 | int(像素) |
| 默认 | 20 |
| Category | CCon |
| DefaultValue | 20 |
| 作用 | 主环(进度弧)的厚度,即画笔宽度 |
| 取值范围 | Math.Max(1, value)——自动 clamp 到 ≥1,防止画笔宽度为 0 造成绘制异常 |
| 额外保护 | 绘制时 pw = min(PieWidth, d/2 - 1),保证厚度不超过半径,避免内圆消失、数学计算越界 |
| 副作用 | 赋值后 Invalidate() 重绘 |
| 备注 | 此属性同时影响装饰内环的位置:内环半径 = 外圆半径 − PieWidth − 6px 间距 |
bar.PieWidth = 12; // 细环 bar.PieWidth = 30; // 粗环
public bool ShowInnerRing
| 项目 | 说明 |
|---|---|
| 类型 | bool |
| 默认 | true |
| Category | CCon |
| DefaultValue | true |
| 作用 | 是否绘制装饰性的内圈细圆环:true → 在主环内侧绘制一条 2px 宽、ColorCore 颜色的圆环;false → 不绘制内环 |
| 副作用 | 赋值后 Invalidate() 重绘;值未变化时不触发重绘 |
| 绘制保护 | 内环半径 = 外圆半径 − (PieWidth + 6);若这个直径 ≤ 10px,则不绘制,避免内环缩成一点 |
bar.ShowInnerRing = false; // 隐藏装饰内环 bar.ShowInnerRing = true; // 显示
4.2 继承自 ProgressBarBase 的成员(由本类绘制逻辑引用)
| 成员 | 类型 | 在本类中的作用 | 用法示例 |
|---|---|---|---|
Min | int | 进度下限;计算扫过角度时的起点 | bar.Min = 0; |
Max | int | 进度上限;计算扫过角度时的终点 | bar.Max = 100; |
Value | int | 当前进度;决定主环的扫过角度 | bar.Value = 45; |
ColorBack | Color | 背景圆填充色 | bar.ColorBack = Color.FromArgb(45, 45, 48); |
ColorCore | Color | 主环 + 装饰内环的颜色 | bar.ColorCore = Color.DodgerBlue; |
BorderColor | Color | 外圈边框颜色 | bar.BorderColor = Color.Black; |
BorderSize | int | 外圈边框粗细(像素);绘制时会被 clamp 到圆半径以内 | bar.BorderSize = 2; |
事件(如
Change/ValueChanged)请参考ProgressBarBase。
4.3 绘制逻辑引用到的 Control 成员
| 成员 | 来源 | 说明 |
|---|---|---|
Text | Control | 圆中央文字 |
Font | Control | 文字字体 |
ForeColor | Control | 文字颜色 |
ClientSize | Control | 计算圆直径与居中 |
Size | Control | 构造时设置为 150 × 150 |
Invalidate() | Control | 属性变化后触发重绘 |
五、公开方法
ProgressBarF没有新增 public 方法,全部公开方法继承自ProgressBarBase与Control(如Invalidate()、Focus()、BringToFront()等)。
内部重写方法(protected override,外部不可直接调用)
| 方法 | 可见性 | 作用 |
|---|---|---|
OnPaint(PaintEventArgs e) | protected override | 整体绘制:背景圆 → 装饰内环 → 进度弧 → 文字 → 外边框 |
六、公开成员速查表
| 成员 | 来源 | 类型 | 说明 |
|---|---|---|---|
ProgressBarF() | 本类 | 构造函数 | 默认尺寸 150×150,PieWidth=20,ShowInnerRing=true |
PieWidth | 本类 | 属性(int) | 主环厚度(默认 20,≥1) |
ShowInnerRing | 本类 | 属性(bool) | 是否绘制装饰内环(默认 true) |
Min / Max / Value | ProgressBarBase | 属性(int) | 进度范围与当前值 |
ColorBack / ColorCore / BorderColor / BorderSize | ProgressBarBase | 属性 | 背景圆 / 主环 / 边框外观 |
Text / Font / ForeColor | Control | 属性 | 中央文字 |
Size / ClientSize | Control | 属性(Size) | 建议保持正方形;否则只绘制居中的正圆 |
Invalidate() | Control | 方法 | 触发重绘 |
OnPaint(e) | 本类(override) | 方法(protected) | 绘制逻辑,外部不可直接调用 |
事件(如
Change/ValueChanged)请参考ProgressBarBase。
七、绘制原理(深入理解)
以下分析帮你在调整尺寸、环厚、边框、进度范围时理解
ProgressBarF的具体表现。
7.1 计算外圆
float side = Math.Min(ClientSize.Width, ClientSize.Height); if (side <= 4) return; float d = side - 1f; // 直径,减 1 防描边被裁 float ox = (ClientSize.Width - d) / 2f; // 水平居中 float oy = (ClientSize.Height - d) / 2f; // 垂直居中 var outer = new RectangleF(ox, oy, d, d);
| 要点 | 说明 |
|---|---|
min(宽, 高) | 无论控件是否正方形,都绘制正圆;非正方形时多出的空间留白 |
d = side - 1f | GDI+ 抗锯齿下,直径等于 side 时最右/下边缘会被裁半像素,减 1 保证完整 |
side ≤ 4 | 控件过小时直接不绘制,避免异常 |
7.2 主环厚度与路径矩形
float pw = Math.Min(this._pieWidth, d / 2f - 1f); if (pw <= 0) return; var arcRect = RectangleF.Inflate(outer, -pw / 2f, -pw / 2f);
| 要点 | 说明 |
|---|---|
pw 上限 d/2 - 1 | Pen 是居中描边,半径最多 d/2。若 pw = d/2,内圆半径为 0(整块实心),不美观。限制到 d/2 - 1 保留内圆 |
arcRect = outer 内缩 pw/2 | Pen 居中描边时,外边缘会超出路径 pw/2。内缩 pw/2 后,主环外边缘正好贴到 outer 边界 |
7.3 绘制背景圆
using (var brush = new SolidBrush(this.ColorBack)) g.FillPie(brush, outer.X, outer.Y, outer.Width, outer.Height, -90f, 360f);
用 FillPie(360°)而不是 FillEllipse,与进度弧走同一条 GDI+ 弧线路径族,抗锯齿边缘像素级重合,避免露出背景缝。绘制在 outer(而不是 arcRect)上,因为背景圆需要铺满整个外圆。
7.4 绘制装饰内环
if (this._showInnerRing)
{
float innerOffset = pw + 6f;
if (d - innerOffset * 2 > 10)
{
using (var pen = new Pen(this.ColorCore, 2f))
{
var penRect = RectangleF.Inflate(outer, -innerOffset, -innerOffset);
g.DrawEllipse(pen, penRect);
}
}
}| 要点 | 说明 |
|---|---|
innerOffset = pw + 6f | 内环半径相对外圆半径的偏移量 = 主环厚度 + 6px 间距,保证内环在主环内侧且留出空档 |
d - innerOffset * 2 > 10 | 内环直径 = d - innerOffset × 2。若 ≤ 10px,则不绘制,防止内环缩成一点 |
| 固定 2px 宽 | 内环是装饰线,宽度不通过属性开放;固定 2px,用主色 ColorCore |
outer 内缩 innerOffset | 绘制直径 = d - innerOffset × 2 的圆环,圆心与外圆一致 |
7.5 绘制进度弧
float sweep = 0f;
if (this.Max > this.Min)
{
int v = Math.Max(this.Min, Math.Min(this.Max, this.Value));
sweep = 360f * (v - this.Min) / (this.Max - this.Min);
}
if (sweep > 0f)
{
using (var pen = new Pen(this.ColorCore, pw) { StartCap = LineCap.Flat, EndCap = LineCap.Flat })
g.DrawArc(pen, arcRect, -90f, sweep);
}| 要点 | 说明 |
|---|---|
Max > Min 保护 | 避免除零 |
Math.Max / Math.Min | 先把 Value clamp 到 [Min, Max],防止越界导致角度 > 360 或 < 0 |
360 × (v - Min) / (Max - Min) | 线性映射:v = Min → 0°;v = Max → 360° |
StartCap / EndCap = Flat | 平头端点,让弧线两端是直线切口,视觉上不带“圆头”装饰,更干净 |
-90f | 从 12 点方向开始(GDI+ 0° 在 3 点方向,顺时针为正) |
arcRect(已内缩 pw/2) | 配合 Pen 居中描边,外边缘贴合 outer |
7.6 绘制文字与边框
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);
}
int border = Math.Min(this.BorderSize, (int)(d / 2) - 1);
if (border > 0)
{
float half = border / 2f;
var penRect = RectangleF.Inflate(outer, -half, -half);
using (var pen = new Pen(this.BorderColor, border))
g.DrawEllipse(pen, penRect);
}| 要点 | 说明 |
|---|---|
文字绘制在 outer 内 | 居中于圆的正中心 |
border = min(BorderSize, d/2 - 1) | 边框半径不超过圆半径 |
penRect = outer 内缩 half | 同 arcRect 逻辑:Pen 居中描边,内缩一半线宽让外边缘贴到 outer |
| 边框最后画 | 覆盖在最外层,视觉上把内容“包”在圆内 |
八、完整使用示例
示例 1:基础圆环进度条
using System.Drawing;
using System.Windows.Forms;
using CConUI;
var bar = new ProgressBarF
{
Parent = panel1,
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 = 2,
PieWidth = 20,
ShowInnerRing = true,
ForeColor = Color.White,
Font = new Font("Microsoft YaHei", 10F, FontStyle.Bold)
};示例 2:配合计时器动态更新
var bar = new ProgressBarF
{
Parent = this,
Min = 0,
Max = 100,
Value = 0,
Text = "0%",
ColorBack = Color.FromArgb(50, 50, 50),
ColorCore = Color.OrangeRed,
BorderColor = Color.FromArgb(20, 20, 20),
BorderSize = 3,
PieWidth = 16,
ShowInnerRing = false,
Font = new Font("Segoe UI", 11F, 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 ProgressBarF
{
Parent = this,
Size = new Size(120, 120),
Max = 100,
Value = 70,
PieWidth = 10,
ShowInnerRing = false, // 只显示一圈细弧
ColorCore = Color.LimeGreen,
ColorBack = Color.FromArgb(30, 30, 30)
};示例 4:粗环 + 装饰内环(仪表盘风格)
var bar = new ProgressBarF
{
Parent = this,
Size = new Size(180, 180),
Max = 100,
Value = 82,
Text = "82%",
PieWidth = 26,
ShowInnerRing = true,
ColorCore = Color.FromArgb(0, 200, 255),
ColorBack = Color.FromArgb(40, 40, 44),
BorderColor = Color.FromArgb(20, 20, 20),
BorderSize = 2,
ForeColor = Color.White,
Font = new Font("Consolas", 14F, FontStyle.Bold)
};示例 5:非正方形控件(自动绘制正圆)
// 即使控件是长方形,圆环仍是正圆,周围留白
var bar = new ProgressBarF
{
Parent = this,
Size = new Size(300, 120), // 实际圆直径 = min(300, 120) - 1 = 119
Max = 100,
Value = 60,
PieWidth = 14,
ColorCore = Color.DodgerBlue
};转载请注明出处。