2011-03-16 12 views
20

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.¿Desactivar la animación de la barra de progreso de .NET al cambiar el valor?

Lo que quiero hacer es deshacerme de la animación que se utiliza 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 haya completado la acción.

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) inmediatamente, 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érrela como duplicada y lo eliminaré felizmente, pero no pude encontrar ninguna.

Este es el que encontré: Disabling WinForms ProgressBar animation, y se trata de lo más destacado que está animado, y eso no es de lo que estoy hablando.

Aquí es un simple LINQPad demostración 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 es específica a 7 o posiblemente también Vista.

Aquí hay una animación GIF que muestra el problema, el proyecto de 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 100%, después de el botón se ha habilitado.

Como puede ver arriba, al volver a configurar el botón y configurar la barra de progreso en 100 se realiza "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.

LINQPad demo


Edición 2: En respuesta a la respuesta de David Heffernan, así es como he cambiado 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; })); 
+0

Esto va inmediatamente a la marca a mitad de camino; no hay acumulación. En XP; puede ser específico del sistema operativo ¿estás en Vista/7? –

+0

Esto es Windows 7, de 64 bits, déjame editar la pregunta y publicar una muestra de video. Además, gracias por agregar esa etiqueta :) –

+0

Es gracioso, me encontré con este problema pensando que había una demora en mi código, ya que toma aproximadamente 100ms para que comience la animación. –

Respuesta

30

Esta animación funció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 quiere que avance 50 al instante, incremente el Valor en 51, luego disminuya inmediatamente en 1.

Se mete en una disputa cuando está cerca del 100% porque no puede establecer el Valor en 101 (estoy asumiendo el Máximo está configurado a 100). En cambio, configure Máximo a 1000, por ejemplo, aumente a 1000, disminuya a 999 y luego vuelva a 1000.

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

+1

Ok, puedo vivir con eso, supongo :) –

+1

@Lasse ¡Abrácelo, ocultelo y pretenda que no está allí! –

+1

He editado un cambio en el código de LINQPad en la parte inferior de mi pregunta. ¿Es esto lo que quieres decir? De hecho, funciona como se describe, simplemente me hace sentir un poco asqueroso, pero sí, pretendo que no está allí :) –

2

Hay otra forma de omitir la animación de una barra de progreso al estilo Vista: Sólo SetState() el control de PBST_PAUSED, a continuación, establezca el valor y finalmente la pusieron de nuevo a PBST_NORMAL.

+0

¿Puedes dar un ejemplo de cómo se hace eso? ProgressBar no parece tener un método SetState(). – Daniel

+1

Esta respuesta es incorrecta. SetState() no existe. Supongo que estás hablando de SendMessage (PBM_SETSTATE, ...) pero esto NO afecta la animación de la barra de progreso. – Elmue

14

Aquí es mi método de extensión, basado en David Heffernan 's recommendation:

envolverlo, ocultarlo de la vista, y pretender que no está allí!

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

¿No hay amor? Esta es una gran sugerencia. – nathanchere

+0

Me encanta la idea de una solución de método de extensión, pero esto no solucionó completamente el caso de borde especial para mí. –

+0

Usando su enfoque como inspiración, se me ocurrió esto y se logró el efecto deseado: http://stackoverflow.com/questions/6071626/progressbar-is-slow-in-windows-forms/22941217#22941217 –

-3

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 
+2

Esto no hace nada para abordar el problema que se le preguntó. –

Cuestiones relacionadas