如何修改ProgressBar类 使ForeColor/BackColor在设计与运行时生效
解决自定义ProgressBarEx控件ForeColor和BackColor不生效的问题
原生ProgressBar控件依赖系统主题渲染,默认会忽略ForeColor和BackColor属性,导致修改后在设计模式和运行时都不生效。我们需要重写控件的绘制逻辑,完全接管绘制流程,同时确保设计模式下的正确渲染。
以下是修改后的完整代码:
using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; [ToolboxItem(true)] public class ProgressBarEx : ProgressBar { private Color _percentageColor = Color.Black; private int _percentageDecimals = 0; public ProgressBarEx() { // 开启自定义绘制,启用双缓冲避免闪烁 SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); } [DefaultValue(typeof(Color), "Black")] public Color PercentageColor { get => _percentageColor; set { if (_percentageColor != value) { _percentageColor = value; Invalidate(); } } } [DefaultValue(0), Description("Number of decimals (0-4)")] public int PercentageDecimals { get => _percentageDecimals; set { if (_percentageDecimals != value) { _percentageDecimals = Math.Max(Math.Min(value, 4), 0); Invalidate(); } } } // 重写ForeColor,确保修改时触发重绘 public override Color ForeColor { get => base.ForeColor; set { base.ForeColor = value; Invalidate(); } } // 重写BackColor,确保修改时触发重绘 public override Color BackColor { get => base.BackColor; set { base.BackColor = value; Invalidate(); } } // 暴露Font属性到属性面板 [Browsable(true)] public override Font Font { get => base.Font; set { base.Font = value; Invalidate(); } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); var graphics = e.Graphics; graphics.SmoothingMode = SmoothingMode.AntiAlias; // 绘制背景 using (var backgroundBrush = new SolidBrush(BackColor)) { graphics.FillRectangle(backgroundBrush, ClientRectangle); } // 计算进度宽度 float progressWidth = (float)Value / Maximum * ClientRectangle.Width; if (progressWidth > 0) { // 绘制进度条 using (var progressBrush = new SolidBrush(ForeColor)) { graphics.FillRectangle(progressBrush, 0, 0, progressWidth, ClientRectangle.Height); } } // 绘制百分比文本 string percentageText = ((float)Value / Maximum).ToString($"P{_percentageDecimals}"); var textSize = TextRenderer.MeasureText(percentageText, Font); var textLocation = new Point( (ClientRectangle.Width - textSize.Width) / 2, (ClientRectangle.Height - textSize.Height) / 2 ); TextRenderer.DrawText(graphics, percentageText, Font, textLocation, _percentageColor); } }
关键改动说明
- 构造函数中开启
ControlStyles.UserPaint,完全接管控件绘制,不再依赖系统主题渲染,让ForeColor和BackColor属性生效。 - 重写
ForeColor和BackColor属性,确保修改时调用Invalidate()触发重绘。 - 重写
OnPaint方法,依次绘制背景、进度条和百分比文本,替代原有的WndProc处理逻辑,更符合WinForms自定义控件规范,同时保证设计模式下能正确渲染。 - 添加双缓冲设置,避免绘制时出现闪烁。
修改后,无论是在设计模式调整ForeColor/BackColor,还是运行时动态修改,控件都会立即更新显示效果,同时保留原有的百分比文本显示功能。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

