2011-05-20 148 views
13

我正在使用Windows Vista和Visual Studio 2010.創建一個.Net 4 Windows窗體應用程序。在默認窗體上放置一個進度條,添加代碼以處理表單加載事件並在那裏執行progressBar1.Value = 100;ProgressBar在Windows窗體中速度很慢

開始調試,你看到一個動畫移動進度條到100半秒左右。

我需要在我的項目2的進度條。一個是「全球進步」,第二個是「當前步驟進展」,所以第二個從0到100,在下一個步驟回到0。問題在於,進度條對於某些快速步驟來說很慢,因此它從未達到100,看起來很奇怪。

有沒有擺脫該動畫的一種方式?在WPF中沒問題,但我寧願留在Windows窗體中。

+0

嘗試調用Application.DoEvents()方法 – 2011-05-20 12:13:24

+0

我不認爲這是Windows窗體的問題。我多次使用進度條,並且總是很快。檢查其他內容是否會降低應用程序的性能。 – Vale 2011-05-20 12:13:58

+0

只有進度條纔有問題。我正在使用一個背景工作,報告進度在0到100之間循環,每個值之間都有一個System.Threading.Thread.Sleep(10)。報告進度的事件處理程序在文本框和進度條中顯示進度的值。文本框從0到100,進度條從0到大約70. – user755327 2011-05-20 12:16:32

回答

14

這是Vista/7的進度條是如何設計的。當您更改進度欄的值時,該欄會逐漸變爲該值。

我知道避免這個問題的唯一辦法就是倒退更新進度條時,如下:

progressBar1.Value = n; 
if (n>0) 
    progressBar1.Value = n-1; 

更完整的討論,請參閱Disabling .NET progressbar animation when changing value?

+0

我必須檢查但我認爲進度條比Windows XP中的文本框慢。所以WPF或應付它,好的。 – user755327 2011-05-20 13:15:53

+0

@用戶我100%確定他是答案。 WPF繪製所有自己的控件並且不使用Win32控件。 WinForms包裝了Win32控件。請參閱http://stackoverflow.com/questions/5332616/disabling-net-progressbar-animation-when-changing-value – 2011-05-20 13:17:10

+0

沒關係。我的意思是我必須檢查Windows XP,我記得進度條比文本框「慢」。 – user755327 2011-05-20 13:21:56

2

您可以輕鬆地編寫自定義進度條無需動畫即可顯示其價值。下面是一個簡單的實現,顯示從0進度,100和恢復到0

public class ProgressBarDirectRender : UserControl 
{ 
    private int _value; 
    public int Value 
    { 
     get { return _value; } 
     set 
     { 
      if (value < 0 || value > 100) 
       throw new ArgumentOutOfRangeException("value"); 
      _value = value; 
      const int margin = 1; 
      using (var g = CreateGraphics()) 
      { 
       if (_value == 0) 
        ProgressBarRenderer.DrawHorizontalBar(g, ClientRectangle); 
       else 
       { 
        var rectangle = new Rectangle(ClientRectangle.X + margin, 
                ClientRectangle.Y + margin, 
                ClientRectangle.Width * _value/100 - margin * 2, 
                ClientRectangle.Height - margin * 2); 
        ProgressBarRenderer.DrawHorizontalChunks(g, rectangle); 
       } 
      } 
     } 
    } 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     ProgressBarRenderer.DrawHorizontalBar(e.Graphics, ClientRectangle); 
    } 
} 
+0

好主意,但如果您想要去「向後「(也許是因爲這個問題不需要)建議啓用doublebuffering,將所有繪圖移動到OnPaint並在setter中失效。但是這對我來說是一個很好的提示,現在一切都完美無缺了:) – drvolcano 2015-11-29 11:56:22

9

大廈關閉的Heffernan's tip上在一個相關的問題的進度條和Reinhart's extension method approach倒退,我想到了我自己解。

的解決方案是相當無縫和成功處理當值處於Maximum你會遇到的問題。 ProgressBar的這種擴展方法減輕了滯後,這是由於在Windows Vista和7(我尚未在Windows 8上測試過)上運行時,存在於漸進式動畫風格中的漸進式動畫風格導致的。

public static class ExtensionMethods 
{ 
    /// <summary> 
    /// Sets the progress bar value, without using 'Windows Aero' animation. 
    /// This is to work around a known WinForms issue where the progress bar 
    /// is slow to update. 
    /// </summary> 
    public static void SetProgressNoAnimation(this ProgressBar pb, int value) 
    { 
     // To get around the progressive animation, we need to move the 
     // progress bar backwards. 
     if (value == pb.Maximum) 
     { 
      // Special case as value can't be set greater than Maximum. 
      pb.Maximum = value + 1;  // Temporarily Increase Maximum 
      pb.Value = value + 1;  // Move past 
      pb.Maximum = value;   // Reset maximum 
     } 
     else 
     { 
      pb.Value = value + 1;  // Move past 
     } 
     pb.Value = value;    // Move to correct value 
    } 
} 

使用範例:

private void backgroundWorker_ProgressChanged(object sender, 
                ProgressChangedEventArgs e) 
{ 
    progressBar.SetProgressNoAnimation(e.ProgressPercentage); 
} 
+0

老實說,最後的'pb.Value = value;'可以放在'else'裏面。無論如何,在最大值時減小最大值會自動降低值。 – Nyerguds 2014-08-27 10:41:37