2008-09-16 3 views

ответ

81

Вот более общая версия Dummy's solution.

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

Примечание: Вы должны pay your developer taxes и не use double-buffering if the user is running in a terminal services session (например, Remote Desktop) Этот вспомогательный метод не получится двойной буферизации, если человек работает в удаленном рабочем столе.

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

Этот код решил мою проблему без каких-либо изменений. Благодаря! – Mykroft 2009-04-24 15:18:58

+0

Забавно, я думаю, что еще более важно удваивать буфер при удалении, чтобы избежать ненужной отправки кучу ретрансляций по проводу? – 2009-06-11 14:50:52

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 имеет больше информации об использовании этого на сервере терминалов.

+0

Это делает трюк. я сделал его общей вспомогательной функцией и разместил его здесь. – 2008-09-17 14:23:12

+0

Это не действительно для * на * терминальном сервере, так как ни один из моих клиентов не запускает программное обеспечение с сеанса удаленного рабочего стола. Но вы должны платить налоги с вашего разработчика, и я не хотел выпускать код, который еще не включал налоги. – 2008-09-19 19:38:45

1

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

8

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

Например:

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

Я работаю с владельцем, нарисованным ListView в производном классе. Это решило проблему отлично! – 2010-02-27 12:00:51

+0

Я не знаю, есть ли какие-то недостатки, но это сработало отлично. Мой пользовательский элемент управления ранее унаследовал от «Control», и я просто изменил его, чтобы наследовать от «Panel» вместо этого, и установите DoubleBuffered в true. Изменение двух строк. Движение плавное ... и скорость рисования одного обновления кажется намного быстрее. – 2017-07-07 05:57:31

4

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

+3

Suspend/ResumeLayout не решает проблему мерцания при рисовании. – 2009-10-29 17:20:48

0

Я обнаружил, что просто установка параметра DoubleBuffered в форме автоматически устанавливает все перечисленные здесь свойства.

Однако; Я обнаружил, что двойная буферизация, предоставляемая winforms, будет меньше, чем велика. This little gem of a code snippetдействительно имеет значение, серьезно попробуйте. Я провел долго ищет решения, которые работали и, наконец, нашли, что :-)

54

Проверить this thread

Повторяя ядро ​​этого ответа, вы можете включить флаг 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 работает только на одном элементе управления в момент времени. Вы по-прежнему будете видеть каждую отдельную контрольную краску. Который может выглядеть как эффект мерцания, особенно если неокрашенный прямоугольник управления плохо контрастирует с фоном окна.

5

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

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

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

4

метод Extension превратить двойную буферизацию включения или выключения для управления

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

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

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

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

0

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 
Смежные вопросы