2008-09-16 22 views

Respuesta

81

Aquí hay una versión más genérica de Dummy's solution.

Podemos usar el reflejo para llegar a la propiedad DoubleBuffered protegida, y luego se puede establecer en true.

Nota: Debe pay your developer taxes y no use double-buffering if the user is running in a terminal services session (por ejemplo escritorio remoto) Este método de ayuda no se encenderá el doble buffer si la persona que se está ejecutando en el escritorio remoto.

public static void SetDoubleBuffered(System.Windows.Forms.Control c) 
{ 
    //Taxes: Remote Desktop Connection and painting 
    //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx 
    if (System.Windows.Forms.SystemInformation.TerminalServerSession) 
     return; 

    System.Reflection.PropertyInfo aProp = 
     typeof(System.Windows.Forms.Control).GetProperty(
       "DoubleBuffered", 
       System.Reflection.BindingFlags.NonPublic | 
       System.Reflection.BindingFlags.Instance); 

    aProp.SetValue(c, true, null); 
} 
+0

Este código resolvió mi problema sin ninguna modificación. ¡Gracias! – Mykroft

+0

Es curioso, creo que es aún más importante realizar una doble amortiguación cuando se hace de forma remota, para evitar el envío innecesario de un montón de vueltas por el cable. –

+11

Es exactamente lo que no quieres. En una sesión de terminal, el sistema GDI puede enviar comandos (dibujar una línea aquí, dibujar un círculo aquí, rellenar aquí, etc.). El búfer doble se logra al dibujar todo en un mapa de bits y luego usar GDI para pintar todo su formulario como un mapa de bits. El envío de un mapa de bits sin comprimir a través del cable es * MUCHO * más lento que el envío de los comandos Origianl GDI. –

10
public void EnableDoubleBuffering() 
{ 
    this.SetStyle(ControlStyles.DoubleBuffer | 
     ControlStyles.UserPaint | 
     ControlStyles.AllPaintingInWmPaint, 
     true); 
    this.UpdateStyles(); 
} 
18
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control) 
    .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | 
    System.Reflection.BindingFlags.Instance); 
aProp.SetValue(ListView1, true, null); 

Ian tiene algo más de información sobre el uso de este en un servidor terminal.

+0

Esto hace el truco. Lo convertí en una función auxiliar genérica y lo publiqué aquí. –

+0

No es realmente para * on * un servidor de terminal, ya que ninguno de mis clientes ejecuta el software desde una sesión de escritorio remota. Pero deberías pagar los impuestos a tu desarrollador, y no quería publicar un código que no incluyera los impuestos. –

1

También puede heredar los controles en sus propias clases y establecer la propiedad allí. Este método también es bueno si tiende a hacer muchas configuraciones que son iguales en todos los controles.

8

Una forma es ampliar el control específico que desea al doble buffer y establecer la propiedad DoubleBuffered dentro del controlador del control.

Por ejemplo:

class Foo : Panel 
{ 
    public Foo() { DoubleBuffered = true; } 
} 
+0

Estoy trabajando con un ListView dibujado por el propietario en una clase derivada. ¡Esto resolvió el problema perfectamente! –

+0

No sé si hay inconvenientes, pero funcionó a la perfección. Mi control personalizado previamente heredado de "Control", y en cambio lo cambié para heredarlo de "Panel" y establecí DoubleBuffered en verdadero. Un cambio de dos líneas. El movimiento es fluido ... y la velocidad para dibujar una actualización parece mucho más rápida también. –

4

Antes de intentar el doble buffer, a ver si SuspendLayout()/ResumeLayout() resolver su problema.

+3

Suspend/ResumeLayout no resuelve el problema del parpadeo al pintar. –

0

He encontrado que simplemente estableciendo la configuración DoubleBuffered en el formulario establece automáticamente todas las propiedades enumeradas aquí.

Sin embargo; He encontrado que el doble buffer proporcionado por winforms es menos que excelente. This little gem of a code snippetrealmente hace la diferencia, pruébalo en serio. Pasé mucho tiempo en busca de una solución que funcionó y finalmente encontró que :-)

+0

El enlace está muerto ... –

+0

Sí, lo sé ... He perdido ese código y no he podido encontrarlo en ningún otro lugar en Internet ... ¡lo siento! – ljs

54

Comprobar this thread

Repitiendo el núcleo de esta respuesta, se puede activar el indicador de estilo WS_EX_COMPOSITED en la ventana para conseguir tanto la forma como todos sus controles tienen doble buffer. La bandera de estilo está disponible desde XP. No hace que la pintura sea más rápida, pero toda la ventana se dibuja en un búfer fuera de la pantalla y se enfoca en la pantalla de una sola vez. Hacer que se vea instantáneamente a los ojos del usuario sin artefactos de pintura visibles. No es completamente libre de problemas, algunos visualizadores de estilos visuales pueden fallar, particularmente TabControl cuando tiene demasiadas pestañas. YMMV.

Pega este código en tu clase formulario:

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

La gran diferencia entre esta técnica y soporte de doble búfer de Winform es que la versión de Winform sólo funciona en un control en en el tiempo. Todavía verá cada pintura de control individual. También puede parecer un efecto de parpadeo, particularmente si el rectángulo de control sin pintar contrasta mal con el fondo de la ventana.

+0

Guau ... habla sobre la noche y el día; gran diferencia para mí usando este método. –

+1

404-ED. –

+4

+1 OMG. Un-be-freakin-lievable. Intenté cualquier otra solución mencionada aquí, y todavía parpadeaba como código morse. Siguió la magia negra simple descrita aquí, y nary un blip en la pantalla. ¡GRACIAS! –

5

nobugz obtiene el crédito por el método en su enlace, solo estoy volviendo a publicar. Añadir esta anulación para la Forma:

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

Esto funcionó mejor para mí, en Windows 7 que estaba recibiendo grandes bloques negros que aparecen cuando se cambio el tamaño de una forma pesada de control. ¡Ahora el control rebota! Pero es mejor

+0

Esto es lo mismo que la respuesta de @Hans Passant, pero +1 para poner el código aquí. –

+6

Nobugz, el nick que utilicé en los foros de MSDN. –

4

método de extensión para encender el doble buffer dentro o fuera de los controles

public static class ControlExtentions 
{ 
    /// <summary> 
    /// Turn on or off control double buffering (Dirty hack!) 
    /// </summary> 
    /// <param name="control">Control to operate</param> 
    /// <param name="setting">true to turn on double buffering</param> 
    public static void MakeDoubleBuffered(this Control control, bool setting) 
    { 
     Type controlType = control.GetType(); 
     PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); 
     pi.SetValue(control, setting, null); 
    } 
} 

uso (por ejemplo, cómo hacer DataGridView DoubleBuffered):

DataGridView _grid = new DataGridView(); 
// ... 
_grid.MakeDoubleBuffered(true); 
4

Esto me causó una gran cantidadde dolor durante dos días con un control de terceros hasta que lo rastreé.

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

Recientemente tuve un montón de agujeros (excrementos) cuando se re-dimensionamiento/volver a dibujar un control que contiene varios otros controles.

me trataron WS_EX_COMPOSITED y WM_SETREDRAW pero nada funcionó hasta que use esto:

private void myPanel_SizeChanged(object sender, EventArgs e) 
{ 
    Application.DoEvents(); 
} 

Sólo quería transmitirlo.

0

versión vb.net de esta solución bien ....:

Protected Overrides ReadOnly Property CreateParams() As CreateParams 
    Get 
     Dim cp As CreateParams = MyBase.CreateParams 
     cp.ExStyle = cp.ExStyle Or &H2000000 
     Return cp 
    End Get 
End Property 
Cuestiones relacionadas