Как удвоить буфер управления .NET на форме? - PullRequest
47 голосов
/ 17 сентября 2008

Как установить защищенное свойство DoubleBuffered элементов управления в форме, которая подвержена мерцанию?

Ответы [ 12 ]

86 голосов
/ 17 сентября 2008

Вот более общая версия решения Dummy .

Мы можем использовать отражение, чтобы получить защищенное свойство DoubleBuffered , а затем его можно установить равным true .

Примечание : вы должны платить налоги с разработчиков , а не использовать двойную буферизацию, если пользователь работает в сеансе служб терминалов (например, удаленный рабочий стол) Этот вспомогательный метод не включает двойную буферизацию, если пользователь работает на удаленном рабочем столе.

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); 
}
65 голосов
/ 18 сентября 2008

Проверить эту тему

Повторяя ядро ​​этого ответа, вы можете включить флаг стиля WS_EX_COMPOSITED в окне, чтобы получить как форму, так и все ее элементы управления с двойной буферизацией. Флаг стиля доступен с XP. Это не делает рисование быстрее, но все окно рисуется в закадровом буфере и перетаскивается на экран одним ударом. Заставить его выглядеть мгновенно для глаз пользователя без видимых артефактов рисования. Это не совсем без проблем, некоторые средства визуализации стилей могут давать сбой, особенно TabControl, когда на нем слишком много вкладок. YMMV.

Вставьте этот код в класс вашей формы:

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

Большая разница между этой техникой и поддержкой двойной буферизации в Winform заключается в том, что версия Winform одновременно работает только на одном элементе управления. Вы все равно увидите каждую отдельную контрольную краску. Это также может выглядеть как эффект мерцания, особенно если неокрашенный контрольный прямоугольник плохо контрастирует с фоном окна.

18 голосов
/ 17 сентября 2008
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control)
    .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Instance);
aProp.SetValue(ListView1, true, null);

Ян имеет дополнительную информацию об использовании этого на терминальном сервере.

12 голосов
/ 17 сентября 2008
public void EnableDoubleBuffering()
{
   this.SetStyle(ControlStyles.DoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.AllPaintingInWmPaint,
      true);
   this.UpdateStyles();
}
8 голосов
/ 17 сентября 2008

Один из способов - расширить определенный элемент управления, который вы хотите удвоить, и установить свойство DoubleBuffered внутри ctor элемента управления.

Например:

class Foo : Panel
{
    public Foo() { DoubleBuffered = true; }
}
5 голосов
/ 11 января 2013

Метод расширения для включения или выключения двойной буферизации для элементов управления

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

Использование (например, как сделать DataGridView DoubleBuffered):

DataGridView _grid = new DataGridView();
//  ...
_grid.MakeDoubleBuffered(true);
5 голосов
/ 29 октября 2009

nobugz получает кредит за метод в своей ссылке, я просто перепост. Добавьте это переопределение в форму:

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

Это сработало для меня лучше всего, в Windows 7 у меня появлялись большие черные блоки при изменении размера тяжелой формы элемента управления. Контроль теперь отказов вместо этого! Но это лучше.

4 голосов
/ 24 июня 2013

Это вызвало у меня много горя в течение двух дней с контролем третьей стороны, пока я не выследил его.

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

У меня недавно было много дырок (помет) при изменении размера / перерисовке элемента управления, содержащего несколько других элементов управления.

Я пробовал WS_EX_COMPOSITED и WM_SETREDRAW, но ничего не получалось, пока я не использовал это:

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

Просто хотел передать это.

4 голосов
/ 17 сентября 2008

Прежде чем попробовать двойную буферизацию, посмотрите, решают ли вашу проблему SuspendLayout () / ResumeLayout ().

2 голосов
/ 06 сентября 2016

vb.net версия этого прекрасного решения ....:

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
...