扩展ProgressBar会导致第一次值更改延迟

时间:2013-12-05 04:49:50

标签: c# winforms progress-bar

我创建了一个扩展ProgressBar的类 - 主要是为了允许更多的自定义,所以我可以在条上绘制刻度,选择我想要的颜色,并删除默认情况下获得的动画,它在大多数情况下工作正常,但是第一次更改值时,在实际更新之前总会有大约一秒的延迟。所有后续更改都会立即发生,只是第一次从0变为1才会延迟。我试图确定是否存在某种内置延迟,我必须以某种方式规避?这是我的代码的相关部分:

public class FancyProgressBar : ProgressBar
{
    //... various properties and fields

    public FancyProgressBar()
    {
        this.SetStyle(ControlStyles.UserPaint, true);
        this.DoubleBuffered = true;

        InitializeComponent();
    }
    public FancyProgressBar(IContainer container)
    {
        this.SetStyle(ControlStyles.UserPaint, true);
        this.DoubleBuffered = true;

        container.Add(this);

        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Rectangle rec = e.ClipRectangle;

        rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;

        if (ProgressBarRenderer.IsSupported)
            ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
        else
            e.Graphics.DrawRectangle(Pens.Gray, 0, 0, this.Width, this.Height);

        rec.Height = rec.Height - 4;

        DrawBar(e.Graphics, new Color[] { Color1, Color2, Color3 }, e.ClipRectangle, rec);

        if (Ticks > 0)
        {
            int lineHeight = this.Height * TickHeight / 100;
            float spacing = this.Width / Ticks;
            for (int i = 1; i < Ticks; i++)
            {
                Pen pen = new Pen(new SolidBrush(TickColor));
                e.Graphics.DrawLine(pen, new Point((int)(spacing * i)-2, Height), new Point((int)(spacing * i)-2, Height - lineHeight));
            }
        }
    }

    //This is broken out into a separate function because I have another version
    //that draws more than one bar.  Shouldn't make a difference though.
    private void DrawBar(Graphics g, Color[] colors, Rectangle clipRec, Rectangle drawRec)
    {
        using (System.Drawing.Drawing2D.LinearGradientBrush l =
            new System.Drawing.Drawing2D.LinearGradientBrush(clipRec, Color.Green, Color.Red, 0f))
        {
            System.Drawing.Drawing2D.ColorBlend lb = new System.Drawing.Drawing2D.ColorBlend();
            lb.Colors = colors;
            lb.Positions = new float[] { 0, PositionColor2, 1.0f };
            l.InterpolationColors = lb;

            g.FillRectangle(l, 2, 2, drawRec.Width, drawRec.Height);
        }

        using (System.Drawing.Drawing2D.LinearGradientBrush l2 =
            new System.Drawing.Drawing2D.LinearGradientBrush(clipRec,
                Color.FromArgb(147, 255, 255, 255),
                Color.FromArgb(0, 255, 255, 255),
                System.Drawing.Drawing2D.LinearGradientMode.Vertical))
        {
            System.Drawing.Drawing2D.ColorBlend lb = new System.Drawing.Drawing2D.ColorBlend();
            lb.Colors = new Color[] { Color.FromArgb(40, 255, 255, 255), Color.FromArgb(147, 255, 255, 255),
                Color.FromArgb(40, 255, 255, 255), Color.FromArgb(0, 255, 255, 255) };
            lb.Positions = new float[] { 0, 0.12f, 0.39f, 1.0f };
            l2.InterpolationColors = lb;

            l2.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
            g.FillRectangle(l2, 2, 2, drawRec.Width, drawRec.Height);
        }
    }

编辑: 我应该声明我没有使用ProgressBar作为实际的进度条。在加载东西的时候它没有运行,只是在UI中显示一些值,所以没有其他一些昂贵的计算同时发生。

2 个答案:

答案 0 :(得分:0)

使用BackgroundWorker尝试使用ProgressBar,因为UI元素与Thread有区别。像这样:

    BackgroundWorker bwEx = new BackgroundWorker();
    bwEx.DoWork += bwEx_DoWork;
    bwEx.RunWorkerCompleted += bwEx_RunWorkerCompleted;
    bwEx.ProgressChanged += bwEx_ProgressChanged;
    bwEx.WorkerReportsProgress = true;
    bwEx.RunWorkerAsync();

    private void bwEx_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       yourProgress.Value = e.ProgressPercentage;
    }

    private void bwEx_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

    private void bwEx_DoWork(object sender, DoWorkEventArgs e)
    {

    }

答案 1 :(得分:0)

好的,我终于想出了一个真正的解决方案。 ProgressBar的东西完全没必要。我刚刚将FancyProgressBar更改为Control而不是ProgressBar,然后为ValueMinimumMaximum和{{添加了字段1}},这是我仍然使用的Step的唯一部分,因为我已经覆盖了绘图部分。只有我必须添加的其他内容是每当值发生变化时在进度条上调用ProgressBar。从Invalidate()扩展时这不起作用,ProgressBar似乎有某种内置延迟,可能是因为它被设计为多线程对象。由于我实际上并没有将它用作加载条,因此完全没必要使用多线程。