2010-07-20 57 views
20

Tengo una aplicación que tiene un montón de controles. Y tiene una gran cantidad de parpadeo, especialmente en el arranque.Parpadeo en una aplicación de Windows Forms

Apliqué este fix a él.

protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
      return cp; 
     } 
    } 

Esto funcionó muy bien - el parpadeo se redujo en una cantidad bastante increíble. Sin embargo, el efecto secundario es que los botones Minimizar, Maximizar y Cerrar de la esquina superior derecha de la ventana no se animan cuando muevo el mouse o hago clic en ellos (aunque siguen funcionando). Esto le da a la aplicación una sensación colgada.

¿Cómo mantengo el WS_EX_COMPOSITED sin perder la capacidad de uso de los botones Maximizar, Minimizar y Cerrar?

Esto ocurre en Windows XP. Como señaló @fallenidol, esto no es un problema en Windows 7.

+5

Pregunta perfecta (deseo esta funcionalidad, probé esta resolución, ¿cómo logro esta funcionalidad con esta nueva restricción?). –

+0

Por cierto, probé esta corrección en una aplicación de prueba que se ejecuta en Windows 7 y los botones Maximizar, Minimizar y Cerrar aún parecen animarse. – pmcilreavy

+0

@fallenidol. Es bueno saberlo. Todos mis clientes están en XP. – AngryHacker

Respuesta

11

Me di cuenta. El truco consiste en eliminar el indicador WS_EX_COMPOSITED después de que se muestre el formulario. La explicación completa y el código en mi blog:

How to get rid of flicker on Windows Forms applications

+0

Excelente ... trabajado para mí – Marshal

+0

Buena documentación. Gracias por eso. Upvoted. – C4u

+0

@Hossein Sí, el blog está inactivo por ahora ... con suerte se restablecerá en algún momento de este mes. – AngryHacker

0

Debes probar la propiedad de control de formularios estándar de Windows llamada DoubleBuffered. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

+0

Eso solo funciona por control. El ejemplo que proporcioné fuerza el doble buffer en cada control en el formulario. – AngryHacker

+0

Puede usar la reflexión al inicio de la aplicación para completar esta propiedad de cada control. – Kru

+0

No puedo hacerlo por los controles de terceros que no exponen esta propiedad. – AngryHacker

4

Pruebe el siguiente código. Esto debe ir en la forma principal y cualquier otro control de usuario personalizado que tenga.

 // Enable double duffering to stop flickering. 
     this.SetStyle(ControlStyles.DoubleBuffer, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor, false); 
     this.SetStyle(ControlStyles.Opaque, false); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     this.SetStyle(ControlStyles.ResizeRedraw, true); 
+0

El objetivo del código que publiqué es que lo haga una vez, no para cada control de usuario (que son cientos de controles de terceros). – AngryHacker

+3

Esta es otra opción para otras personas que ven esta página y que quizás no tengan acceso a toda la aplicación y solo están desarrollando un control de usuario de forma aislada. La próxima vez que esté desarrollando un solo control de usuario, puede usar mi fragmento de código anterior. Entonces es posible que no termines en una situación en la que tienes cientos de controles parpadeantes. – pmcilreavy

5

Sé que esta pregunta es un poco viejo, pero mejor tarde que nunca. Usé tu ejemplo original que vinculó para encontrar uno que lo active al cambiar el tamaño, luego lo apaga para dibujar todo lo demás perfectamente. Con suerte, ayuda a otros a buscar una solución a este problema. Como sabe el OP, las propiedades de DoubleBuffering por sí solas no resuelven los problemas de parpadeo.

Aquí es una solución alternativa para detener el parpadeo cuando un usuario cambia el tamaño de un formulario, pero sin estropear el dibujo de controles tales como DataGridView, NumericUpDown, etc. siempre y cuando su nombre del formulario es "Form1":

int intOriginalExStyle = -1; 
bool bEnableAntiFlicker = true; 

public Form1() 
{ 
    ToggleAntiFlicker(false); 
    InitializeComponent(); 
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin); 
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd); 
} 

protected override CreateParams CreateParams 
{ 
    get 
    { 
     if (intOriginalExStyle == -1) 
     { 
      intOriginalExStyle = base.CreateParams.ExStyle; 
     } 
     CreateParams cp = base.CreateParams; 

     if (bEnableAntiFlicker) 
     { 
      cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED 
     } 
     else 
     { 
      cp.ExStyle = intOriginalExStyle; 
     } 

     return cp; 
    } 
} 

private void Form1_ResizeBegin(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(true); 
} 

private void Form1_ResizeEnd(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(false); 
} 

private void ToggleAntiFlicker(bool Enable) 
{ 
    bEnableAntiFlicker = Enable; 
    //hacky, but works 
    this.MaximizeBox = true; 
} 
+0

Buen punto. He tenido este código en mi aplicación, pero olvidé agregarlo a mi entrada de blog. Lo actualizará en un par de días. – AngryHacker

0

Acabo de encontrar esta publicación y darme cuenta de que es un poco vieja. Sin embargo, estoy teniendo el mismo problema con mi formulario y lo descubrí (para XP, de todos modos) una solución poco elegante parece no estar habilitando estilos visuales.

+0

Como seguimiento, parece que no tengo ningún problema con el parpadeo cuando anulo OnPaintBackground. Si no quiero pintar el fondo, llamo a e.Graphics.Clear ([color apropiado]) y lo devuelvo; de lo contrario, se llama al método de evento base. Como dije, esto "parece" aliviar el problema. Sin embargo, me pregunto qué repercusiones imprevistas pueden surgir. – Tebc

+0

Corrección. La anulación anterior parece funcionar siempre que la propiedad de tamaño mínimo del formulario se establezca en el tamaño actual. – Tebc

Cuestiones relacionadas