Как удвоить буферизацию элементов управления .NET в форме?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
51
0
65 551
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

хороший....! Но мне интересно, почему он все еще мерцает, когда я пытался сделать видимым форму, которая стала ложной?

gumuruh 26.06.2020 02:46

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 Boyd 19.09.2008 23:38

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

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

Например:

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

Я работаю с владельцем, нарисованным ListView в производном классе. Это отлично решило проблему!

Brad Bruce 27.02.2010 15:00

Не знаю, есть ли недостатки, но это сработало отлично. Мой настраиваемый элемент управления ранее унаследован от «Control», и я просто изменил его, чтобы вместо этого унаследовать от «Panel», и установил для DoubleBuffered значение true. Смена двух строк. Движение плавное ... и скорость рисования одного обновления тоже кажется намного выше.

Mark T 07.07.2017 08:57

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

Suspend / ResumeLayout не решает проблему мерцания при рисовании.

Ian Boyd 29.10.2009 20:20
Ответ принят как подходящий

Вот более общая версия Решение пустышки.

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

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

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

Забавно, я думаю, что еще важнее использовать двойную буферизацию при удаленном взаимодействии, чтобы избежать ненужной отправки кучи перерисовок по сети?

Robert Jeppesen 11.06.2009 18:50

Это именно то, чего вы не хотите. В терминальном сеансе система GDI может отправлять команды (нарисовать линию здесь, нарисовать круг здесь, заполнить здесь и т. д.). Двойная буферизация достигается за счет того, что вы рисуете все на растровом изображении, а затем используете GDI для рисования всей вашей формы как растрового изображения. Отправка несжатого растрового изображения по сети на МНОГО медленнее, чем отправка исходных команд GDI.

Ian Boyd 12.06.2009 22:50

Не помогает предотвратить мерцание TextBox с автоматическим размером при изменении размера ... На самом деле ничего из того, что я пробовал до сих пор, не помогает.

Roman Starkov 26.08.2009 12:57

@Boris Это потому, что Windows TEXTBOX контролирует законы рисования не подчиняется никакому.

Ian Boyd 30.11.2012 22:51

@romkyns, Если вам нужен TextBox с двойной буферизацией, используйте RichTextBox с DetectUrls, установленным на False. Если вы хотите, чтобы его можно было редактировать, удалите форматирование с помощью сообщений EM_SETCHARFORMAT и EM_SETPARAFORMAT (пример кода это здесь).

alldayremix 28.06.2013 02:16

@IanBoyd Я знаю, что это очень старый вопрос, но подумал, что все равно попробую. У меня была такая же проблема с моим приложением, поэтому я преобразовал приведенный выше код в VB.NET и добавил его в свой основной класс формы. Затем я добавил SetDoubleBuffered(SplashScreen) непосредственно перед SplashScreen.Show() в свой DisplaySplashSub. Оно работает! Однако я совершенно новичок в подобных вещах, и я не уверен, правильный ли это способ реализовать это?

Aaron Wright 30.12.2020 02:03

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

да, я знаю ... Я потерял этот код и не смог найти его нигде в Интернете ... извините!

ljs 03.01.2010 19:54

Проверить эта ветка

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

Однако это решение замедляет прокрутку.

MatanKri 23.10.2014 17:42

Это решение вызывает проблемы с элементами управления WPF, размещенными внутри ElementHost. Элемент управления не будет правильно нарисован.

PeterB 21.06.2018 16:03

Если у вас есть форма с контейнером-разделителем, НЕ используйте WS_EX_COMPOSITED!

Elmue 26.10.2019 16:01

Ты мой герой. Спасибо

il Giovine 08.02.2021 19:42

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

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

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

Это то же самое, что и ответ @Hans Passant, но +1 за размещение кода здесь.

Shaul Behr 24.02.2011 20:39

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

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

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

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

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

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

применимо ли это для двойной буферизации всех элементов управления только в этом кадре?

gumuruh 26.06.2020 02:41

Другие вопросы по теме