обновление формы Visual C # приводит к мерцанию - PullRequest
9 голосов
/ 08 октября 2008

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

Ответы [ 10 ]

7 голосов
/ 08 октября 2008

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

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

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

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

5 голосов
/ 17 октября 2008

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

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

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

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true); 
4 голосов
/ 08 октября 2008

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

3 голосов
/ 28 июня 2011

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

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;
}
2 голосов
/ 10 августа 2011

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

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

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

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

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

2 голосов
/ 17 июля 2011

Вы можете просто заменить оригинальный элемент управления на пользовательский элемент управления, у которого свойство 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 голос
/ 08 октября 2008

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

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

1 голос
/ 08 октября 2008

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

0 голосов
/ 22 июня 2009

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

protected override void OnPaintBackground(PaintEventArgs e) { }

0 голосов
/ 08 октября 2008

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

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