更改值时禁用.NET进度条动画?

时间:2011-03-16 22:28:19

标签: .net winforms animation progress-bar

我意识到关于动画和进度条的SO还有其他问题,但它们似乎围绕着摆脱在进度条上绘制的动画,即。在它上面的亮点。

我想要做的是摆脱设置进度条新值时使用的动画。我现在遇到的问题是正在运行的操作完成,然后在操作完成后,进度条继续增加到最大位置

换句话说,如果我将进度条的Value属性设置为50,我希望它立即前进到中途位置(如果max是100),而不是像现在那样慢慢地将进度条建立到该位置。

如果确实有一个关于SO的问题已经解决了这个问题,那么请关闭它,我会高兴地将其删除,但我找不到任何问题。

这是我发现的那个:Disabling WinForms ProgressBar animation,它处理动画的高光,这不是我所说的。

这是一个显示问题的简单LINQPad演示:

void Main()
{
    using (var fm = new Form())
    {
        var bt = new Button
        {
            Text = "Start",
            Location = new Point(8, 8),
            Parent = fm,
        };
        var pb = new ProgressBar
        {
            Top = bt.Top + bt.Height + 8,
            Width = fm.ClientRectangle.Width - 16,
            Left = 8,
            Parent = fm
        };

        bt.Click += (s, e) =>
        {
            bt.Enabled = false;
            Thread t = new Thread(new ThreadStart(() =>
            {
                Thread.Sleep(1000);
                bt.BeginInvoke(new Action(() => { pb.Value = 50; }));
                Thread.Sleep(1000);
                bt.BeginInvoke(new Action(() => { pb.Value = 100; }));
                bt.BeginInvoke(new Action(() => { bt.Enabled = true; }));
            }));
            t.Start();
        };
        fm.ShowDialog();
    }
}

编辑1:这是Windows 7,Glass主题,所以是的,我敢打赌这是针对7或者也可能是Vista。

这是一个显示问题的GIF动画,上面的项目。您可以看到,只要按钮启用,设置了中途标记后1秒,进度条就会激活最高100%,按钮启用后

如上所示,将按钮设置为启用并将进度条设置为100是“同时”完成的。基本上,我不希望逐步累积进度条,我希望它在按钮启用的同时直接跳到50%然后再跳到100%。

LINQPad demo


编辑2:为了回应David Heffernan的回答,这就是我改变上述代码的方式:

bt.BeginInvoke(new Action(() => { pb.Value = 51; pb.Value = 50; }));
Thread.Sleep(1000);
bt.BeginInvoke(new Action(() => { pb.Maximum = 101; pb.Value = 101;
                                  pb.Maximum = 100; pb.Value = 100; }));

5 个答案:

答案 0 :(得分:31)

此动画功能是在Vista中引入的Aero主题。

虽然有一种解决方法。如果向后移动进度,则不显示动画。因此,如果您希望它立即提前50,将值增加51,然后立即减1。

当接近100%时你会陷入冲突,因为你不能将Value设置为101(我假设Maximum设置为100)。而是将Maximum设置为1000,例如,增加到1000,减少到999,然后再回到1000。

无论如何,它有点奇怪,但它确实有益于给你想要的效果!

答案 1 :(得分:15)

以下是我的扩展程序,基于David Heffernanrecommendation

  

将它包起来,将其隐藏起来,并假装它不在那里!

public static class ExtensionMethods
{
    /// <summary>
    /// Sets the progress bar value, without using Windows Aero animation
    /// </summary>
    public static void SetProgressNoAnimation(this ProgressBar pb, int value)
    {   
        // To get around this animation, we need to move the progress bar backwards.
        if (value == pb.Maximum) {
            // Special case (can't set value > Maximum).
            pb.Value = value;           // Set the value
            pb.Value = value - 1;       // Move it backwards
        }
        else {
            pb.Value = value + 1;       // Move past
        }
        pb.Value = value;               // Move to correct value
    }
}

答案 2 :(得分:2)

还有另一种跳过vista风格进度条动画的方法: 只需SetState()控件PBST_PAUSED,然后设置值,最后将其设置回PBST_NORMAL

答案 3 :(得分:0)

现在遵循Jonathan Reinharts方法SetProgressNoAnimation的VB.Net 2.0和更高版本。我希望这会对其他VB开发人员有所帮助。 函数setProgressBarValue几乎可以防止崩溃。硬件故障可能会导致故障。

''' <summary>
''' In VB.Net, the value of a progress bar can be set without animation.
''' Set the minimum and the maximum value beforehand.
''' This VB version has been written by EAHMK (Evert Kuijpers) in Tilburg in The Netherlands.
''' See SetProgressNoAnimation in
''' https://stackoverflow.com/questions/5332616/disabling-net-progressbar-animation-when-changing-value/5332770
''' by Jonathan Reinhart, based on the suggestion of David Heffernan.
''' </summary>
''' <param name="progressBar">
''' The progress bar that is to present the new value.
''' </param>
''' <param name="newValue">
''' The new value to present in the progress bar.
''' </param>
Public Function setProgressBarValue(progressBar As ProgressBar,
                                    newValue As Integer) As Exception
  Try
    ' Extremes are not supported.
    If newValue < progressBar.Minimum _
     Or newValue > progressBar.Maximum _
     Or progressBar.Maximum = progressBar.Minimum _
     Or progressBar.Maximum = Integer.MaxValue Then
      Return New ArgumentException("The value " & CStr(newValue) & " for" _
                & " the progress bar '" & progressBar.Name & "' is out of bounds.")
    End If

    ' By field maximumReached also progress bar value progressBar.Maximum is supported.
    Dim maximumReached As Boolean = newValue = progressBar.Maximum
    If maximumReached Then
      progressBar.Maximum += 1
    End If
    progressBar.Value = newValue + 1

    progressBar.Value = newValue
    If maximumReached Then
      progressBar.Maximum -= 1
    End If
    ' The value has been presented succesfully in the progress bar progressBar.
    Return Nothing
  Catch ex As Exception
    ' Returns an exception but does not crash on it.
    Return ex
  End Try
End Function

答案 4 :(得分:-3)

我在VB中解决这个问题的绝对解决方案......

Sub FileSaving()

    With barProgress
        .Minimum = 0
        .Maximum = 100000000
        .Value = 100000
    End With

    For
        ...
        saving_codes
        ...
        With barProgress
            .Maximum = .Value * (TotalFilesCount / SavedFilesCount)
        End With
    Next

End Sub