it-swarm-es.com

¿Cómo duplicar los controles de buffer .NET en un formulario?

¿Cómo puedo configurar la propiedad protegida DoubleBuffered de los controles en un formulario que sufre parpadeo?

47
Ian Boyd

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

Podemos usar la reflexión para llegar a la propiedad protegida DoubleBuffered , y luego se puede establecer en verdadero .

Nota : Debería pagar sus impuestos de desarrollador y no se doble búfer si el usuario se está ejecutando en un sesión de servicios de terminal (por ejemplo, Escritorio remoto) Este método auxiliar no activará el almacenamiento en búfer doble si la persona 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); 
}
85
Ian Boyd

Compruebe este hilo

Repitiendo el núcleo de esa respuesta, puede activar el indicador de estilo WS_EX_COMPOSITED en la ventana para obtener tanto el formulario como todos sus controles con doble búfer. 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 borra a la pantalla de un golpe. Hacer que parezca instantáneo a los ojos del usuario sin artefactos de pintura visibles. No está completamente libre de problemas, algunos renderizadores de estilos visuales pueden fallar, particularmente TabControl cuando tiene demasiadas pestañas. YMMV.

Pegue este código en su clase de 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 el soporte de doble búfer de Winform es que la versión de Winform solo funciona en un control a la vez. Aún verá cada control individual Paint en sí. Lo que también puede parecer un efecto de parpadeo, especialmente si el rectángulo de control sin pintar contrasta mal con el fondo de la ventana.

65
Hans Passant
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 más información sobre el uso de esto en un servidor terminal.

18
dummy
public void EnableDoubleBuffering()
{
   this.SetStyle(ControlStyles.DoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.AllPaintingInWmPaint,
      true);
   this.UpdateStyles();
}
12
Arno

Una forma es extender el control específico que desea duplicar el búfer y establecer la propiedad DoubleBuffered dentro del ctor del control.

Por ejemplo:

class Foo : Panel
{
    public Foo() { DoubleBuffered = true; }
}
8
Jeff Hubbard

Método de extensión para activar o desactivar el doble búfer para 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 que DataGridView DoubleBuffered):

DataGridView _grid = new DataGridView();
//  ...
_grid.MakeDoubleBuffered(true);
5
MajesticRa

nobugz obtiene el crédito por el método en su enlace, solo estoy volviendo a publicar. Agregue esta anulación al formulario:

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

Esto funcionó mejor para mí, en Windows 7 estaba apareciendo grandes bloques negros cuando cambio el tamaño de una forma pesada de control. ¡El control ahora rebota en su lugar! Pero es mejor.

5
Chris S

Antes de intentar el doble búfer, vea si SuspendLayout ()/ResumeLayout () resuelve su problema.

4
Joel Coehoorn

Esto me causó un lote de 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 muchos agujeros (excrementos) al redimensionar/volver a dibujar un control que contiene varios otros controles.

Intenté WS_EX_COMPOSITED y WM_SETREDRAW pero nada funcionó hasta que usé esto:

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

Solo quería transmitirlo.

4
dnennis

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

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

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

1
MagicKat

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

0
ljs