web-dev-qa-db-fra.com

Comment doubler la mémoire tampon des contrôles .NET sur un formulaire?

Comment puis-je définir la propriété protégée DoubleBuffered des contrôles sur un formulaire qui souffre de scintillement?

47
Ian Boyd

Voici une version plus générique de la solution de Dummy .

Nous pouvons utiliser la réflexion pour accéder à la propriété protégée DoubleBuffered , puis elle peut être définie sur true .

Remarque : vous devez payer vos taxes de développeur et non tiliser la double mise en mémoire tampon si l'utilisateur s'exécute dans un session de services terminaux (par exemple Remote Desktop) Cette méthode d'assistance n'activera pas la double mise en mémoire tampon si la personne s'exécute sur le bureau distant.

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

Vérifiez ce fil

En répétant le cœur de cette réponse, vous pouvez activer l'indicateur de style WS_EX_COMPOSITED dans la fenêtre pour obtenir à la fois le formulaire et tous ses contrôles en double tampon. Le drapeau de style est disponible depuis XP. Cela ne rend pas la peinture plus rapide, mais toute la fenêtre est dessinée dans un tampon hors écran et fusionnée à l'écran en un seul coup. Le rendre instantané aux yeux de l'utilisateur sans artefacts de peinture visibles. Il n'est pas entièrement sans problème, certains rendus de styles visuels peuvent y avoir des problèmes, en particulier TabControl lorsqu'il contient trop d'onglets. YMMV.

Collez ce code dans votre classe de formulaire:

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

La grande différence entre cette technique et la prise en charge de la double mise en mémoire tampon de Winform est que la version de Winform ne fonctionne que sur un seul contrôle à la fois. Vous verrez toujours chaque contrôle individuel Paint lui-même. Ce qui peut également ressembler à un effet de scintillement, en particulier si le rectangle de contrôle non peint contraste mal avec l'arrière-plan de la fenêtre.

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 a plus d'informations sur son utilisation sur un serveur Terminal Server.

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

Une façon consiste à étendre le contrôle spécifique que vous souhaitez doubler la mémoire tampon et définir la propriété DoubleBuffered à l'intérieur du ctor du contrôle.

Par exemple:

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

Méthode d'extension pour activer ou désactiver la double mise en mémoire tampon pour les contrôles

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

Utilisation (par exemple, comment créer DataGridView DoubleBuffered):

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

nobugz obtient le crédit de la méthode dans son lien, je ne fais que republier. Ajoutez ce remplacement au formulaire:

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

Cela fonctionnait mieux pour moi, sur Windows 7, j'obtenais de gros blocs noirs apparaissant lorsque je redimensionnais un formulaire de contrôle lourd. Le contrôle rebondit désormais à la place! Mais c'est mieux.

5
Chris S

Avant d'essayer la double mise en mémoire tampon, voyez si SuspendLayout ()/ResumeLayout () résout votre problème.

4
Joel Coehoorn

Cela m'a causé beaucoup de chagrin pendant deux jours avec un contrôle tiers jusqu'à ce que je le retrouve.

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

J'ai récemment eu beaucoup de trous (excréments) lors du redimensionnement/redessin d'un contrôle contenant plusieurs autres contrôles.

J'ai essayé WS_EX_COMPOSITED et WM_SETREDRAW mais rien n'a fonctionné jusqu'à ce que j'utilise ceci:

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

Je voulais juste le transmettre.

4
dnennis

version vb.net de cette belle solution ....:

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

Vous pouvez également hériter des contrôles dans vos propres classes et y définir la propriété. Cette méthode est également bien si vous avez tendance à faire beaucoup de configuration qui est la même sur tous les contrôles.

1
MagicKat

J'ai constaté que le simple fait de définir le paramètre DoubleBuffered sur le formulaire définit automatiquement toutes les propriétés répertoriées ici.

0
ljs