You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:10:25