¿Desactivar la animación de la barra de progreso de .NET al cambiar el valor?

Me doy cuenta de que hay otras preguntas sobre SO con respecto a las animaciones y barras de progreso, pero parecen girar en torno a deshacerse de la animación dibujada en la parte superior de la barra de progreso, es decir. lo más destacado que viaja sobre él.

Lo que quiero hacer es deshacerme de la animación que se usa cuando establezco el nuevo valor de la barra de progreso. El problema que tengo ahora es que la acción que se está ejecutando se completa y luego la barra de progreso continúa aumentando hasta su posición máxima después de que la acción se haya completado.

En otras palabras, si configuro la propiedad Value de la barra de progreso en 50, quiero que pase a la posición intermedia (si max es 100) de inmediato, no construya lentamente la barra de progreso en esa posición como lo hace ahora.

Si de hecho hay una pregunta sobre SO que ya se refiere a esto, simplemente ciérrelo como duplicado y lo eliminaré felizmente, pero no pude encontrar ninguno.

Este es el que encontré: deshabilitar la animación WinForms ProgressBar , y se trata del resaltado que está animado, y eso no es de lo que estoy hablando.

Aquí hay una demostración LINQPad simple que muestra el problema:

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(); } } 

Edición 1: este es Windows 7, tema de vidrio, así que sí, apuesto a que esto es específico para 7 o posiblemente también para Vista.

Aquí hay una animación GIF que muestra el problema, el proyecto desde arriba. Puede ver que tan pronto como se habilita el botón, 1 segundo después de que se ha establecido la marca de la mitad, la barra de progreso se anima hasta el 100%, después de que el botón se habilite.

Como puede ver arriba, volver a establecer el botón en “enabled” y configurar la barra de progreso en 100 se hace “al mismo tiempo”. Básicamente, no quiero la acumulación progresiva de la barra de progreso, quiero que salte directamente al 50% y luego al 100% al mismo tiempo que se habilita el botón.

Demostración LINQPad


Editar 2: En respuesta a la respuesta de David Heffernan, así es como cambié el código anterior:

 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; })); 

Esta característica de animación se introdujo en Vista con el tema Aero.

Sin embargo, hay una solución. Si mueve el progreso hacia atrás, la animación no se muestra. Entonces, si desea que avance 50 al instante, incremente el valor en 51, luego disminuya inmediatamente en 1.

Te metes en conflicto cuando estás cerca del 100% porque no puedes establecer el Valor en 101 (supongo que el Máximo está establecido en 100). En su lugar, establezca Máximo a 1000, por ejemplo, aumente a 1000, disminuya a 999, y luego regrese a 1000.

De todos modos, es un poco raro, pero tiene el beneficio de darle el efecto deseado.

Aquí está mi método de extensión, basado en la recomendación de David Heffernan :

¡Abrácelo, escóndalo de la vista y pretenda que no está allí!

 public static class ExtensionMethods { ///  /// Sets the progress bar value, without using Windows Aero animation ///  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 } } 

Hay otra manera de omitir la animación de una barra de progreso de estilo vista: simplemente SetState() el control en PBST_PAUSED , luego establezca el valor y finalmente vuelva a PBST_NORMAL en PBST_NORMAL .

Mi solución absoluta para este problema en 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