it-swarm-pt.tech

Como duplicar buffer .NET controles em um formulário?

Como posso definir a propriedade DoubleBuffered protegida dos controles em um formulário que está sofrendo de cintilação?

47
Ian Boyd

Aqui está uma versão mais genérica de solução da Dummy .

Podemos usar a reflexão para obter a propriedade --- DoubleBuffered e, em seguida, ela pode ser definida como true .

Nota : você deve pagar os impostos do desenvolvedor e não sar buffer duplo se o usuário estiver executando um sessão de serviços de terminal (por exemplo, Área de Trabalho Remota) Este método auxiliar não ativará o buffer duplo se a pessoa estiver executando na área de trabalho remota.

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

Marque este tópico

Repetindo o núcleo dessa resposta, você pode ativar o sinalizador de estilo WS_EX_COMPOSITED na janela para obter o formulário e todos os seus controles com buffer duplo. O sinalizador de estilo está disponível desde o XP. Não torna a pintura mais rápida, mas a janela inteira é desenhada em um buffer fora da tela e combinada com a tela de uma só vez. Fazendo com que pareça instantâneo aos olhos do usuário, sem artefatos de pintura visíveis. Não é totalmente livre de problemas, alguns estilos visuais que os renderizadores podem apresentar, particularmente o TabControl quando há muitas guias. YMMV.

Cole este código na sua classe de formulário:

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

A grande diferença entre essa técnica e o suporte a buffer duplo do Winform é que a versão do Winform funciona apenas em um controle por vez. Você ainda verá cada controle individual Paint em si. O que também pode parecer um efeito de tremulação, principalmente se o retângulo de controle sem pintura contrasta muito com o plano de fundo da janela.

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 tem mais algumas informações sobre como usá-lo em um servidor de terminal.

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

Uma maneira é estender o controle específico que você deseja armazenar em buffer duplo e definir a propriedade DoubleBuffered dentro do controlador do controle.

Por exemplo:

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

Método de extensão para ativar ou desativar o buffer duplo para 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 exemplo, como criar o DataGridView DoubleBuffered):

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

nobugz recebe o crédito pelo método em seu link, estou apenas repostando. Adicione esta substituição ao formulário:

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

Isso funcionou melhor para mim, no Windows 7 eu estava aparecendo grandes blocos pretos quando redimensionava um formulário pesado de controle. O controle agora salta agora! Mas é melhor.

5
Chris S

Antes de tentar o buffer duplo, verifique se SuspendLayout ()/ResumeLayout () resolve seu problema.

4
Joel Coehoorn

Isso me causou lote de luto por dois dias com um controle de terceiros até que eu o localizei.

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

Recentemente, tive muitos buracos (excrementos) ao redimensionar/redesenhar um controle contendo vários outros controles.

Eu tentei WS_EX_COMPOSITED e WM_SETREDRAW, mas nada funcionou até que eu usei isso:

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

Só queria passar adiante.

4
dnennis

versão vb.net desta solução fina ....:

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

Você também pode herdar os controles em suas próprias classes e definir a propriedade lá. Esse método também é bom se você costuma fazer muitas configurações iguais em todos os controles.

1
MagicKat

Eu descobri que simplesmente definir a configuração DoubleBuffered no formulário define automaticamente todas as propriedades listadas aqui.

0
ljs