Визуальное обновление формы C# приводит к мерцанию

У меня есть приложение .net, которое я написал на C#. В некоторых формах я часто обновляю поля отображения. В некоторых случаях каждое поле в форме (текстовые поля, метки, графические поля и т. д.) Изменяет свое значение. К тому же частота изменений может быть каждую секунду. Однако в настоящее время каждый раз при обновлении формы происходит ужасное мерцание. Как мне перестать мерцать? Есть ли способ, возможно, удвоить буфер? Пожалуйста помоги!

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
15 594
10

Ответы 10

Вы плохо это исследовали. В каждой форме есть свойство DoubleBuffered. Попробуйте установить для него значение true. Если вы ничего не перегружали при рисовании формы, то все должно работать.

Спасибо! Я потратил много лет на поиски этого, и он все время лежал передо мной.

GrandMasterFlush 16.09.2011 18:17

краткий ответ

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

длинный ответ: см. MSDN или Google

просто для удовольствия попробуйте вызвать Application.DoEvents () после обновления каждого элемента и посмотрите, станет ли проблема лучше или хуже ;-)

Не уверен, что это поможет. Похоже, проблема в том, что стандартные элементы управления мерцают, а OptimizedDoubleBuffer поможет только с настраиваемыми элементами управления.

Cameron MacFarland 08.10.2008 09:03

Призрак обычно возникает из-за того, что вы работаете в одном потоке, и он задерживается обновлениями поля, поэтому событие рисования не запускается. Один из способов исправить это - переложить тяжелую работу на асинхронные методы. Это позволит форме перерисовывать себя и обновлять все, что необходимо, когда асинхронный метод выполняет обратный вызов.

Вы можете попытаться вызвать this.SuspendLayout (); перед тем, как начать обновление, и this.ResumeLayout (ложь);, когда вы закончите установку всех значений таким образом, это должно помешать форме записывать значения по одному.

suspendlayout / resumelayout предназначены для подавления событий, связанных с добавлением и перемещением элементов управления

Steven A. Lowe 08.10.2008 09:13

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

Toji 08.10.2008 17:01

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

Если вам нужны окна без мерцания, я предлагаю взглянуть на WPF.

Это сработало для меня.

http://www.syncfusion.com/faq/windowsforms/search/558.aspx

В основном это включает получение желаемого элемента управления и установку следующих стилей.

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true); 

Это должен быть ответ!

RendoJack 09.06.2019 13:24

У меня была такая же проблема с OpenGLES, именно так я нашел эту ветку. конечно, я понимаю, что вы не используете ogl, но, возможно, это все равно вам поможет;)

protected override void OnPaintBackground(PaintEventArgs e) { }

Я знаю, что это старый вопрос, но, возможно, в будущем его будут искать другие.

DoubleBuffering не всегда работает хорошо. Чтобы форма вообще никогда не мерцала (но иногда вызывает проблемы с отрисовкой):

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

Чтобы прекратить мерцание, когда пользователь изменяет размер формы, но без нарушения рисования элементов управления (при условии, что имя вашей формы - «Form1»):

int intOriginalExStyle = -1;
bool bEnableAntiFlicker = true;

public Form1()
{
    ToggleAntiFlicker(false);
    InitializeComponent();
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin);
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd);
}

protected override CreateParams CreateParams
{
    get
    {
        if (intOriginalExStyle == -1)
        {
            intOriginalExStyle = base.CreateParams.ExStyle;
        }
        CreateParams cp = base.CreateParams;

        if (bEnableAntiFlicker)
        {
            cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED
        }
        else
        {
            cp.ExStyle = intOriginalExStyle;
        }

        return cp;
    }
} 

private void Form1_ResizeBegin(object sender, EventArgs e)
{
    ToggleAntiFlicker(true);
}

private void Form1_ResizeEnd(object sender, EventArgs e)
{
    ToggleAntiFlicker(false);
}

private void ToggleAntiFlicker(bool Enable)
{
    bEnableAntiFlicker = Enable;
    //hacky, but works
    this.MaximizeBox = true;
}

Это лучший и, на мой взгляд, однозначный ответ.

HydroPowerDeveloper 26.09.2017 17:35

Вы можете просто заменить исходный элемент управления на пользовательский, для которого свойство DoubleBuffered имеет значение true. Например. для ListView это будет примерно так:

internal class DoubleBufferedListView : ListView {

    public DoubleBufferedListView()
        : base() {
        this.DoubleBuffered = true;
    }

}

После этого вы просто посетите файл * .Designer.cs и замените все упоминания о собственном элементе управления этим.

P.S. Вместо наследования от элемента управления вы также можете установить это свойство через отражение:

listView1.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(lsvReport, true, null);

Это не чисто и не рекомендуется, но не требует изменений в файлах * .Designer.cs.

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

  1. Я устанавливаю невидимую рамку, когда элемент не выбран.
  2. Между выборками пользователя индекс очищается элементом управления ListView.
  3. Я привязан к событию SelectedIndexChanged

Другими словами:

  • Пользователь нажимает на элемент 1
    ~ SelectedIndexChanged (1)
  • Пользователь нажимает на элемент 2
    ~ SelectedIndexChanged (-1) <---- Это вызывает мерцание
    ~ SelectedIndexChanged (2)

Так в чем же выход? Как избежать тысяч ненужных событий ListView.SelectedIndexChanged?

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