Обновление формы Visual C# приводит к мерцанию
У меня есть приложение.net, которое я написал на C#. В некоторых формах я часто обновляю поля отображения. В некоторых случаях каждое поле в форме (текстовые поля, метки, графическое окно и т. Д.) Меняет свое значение. Плюс частота изменений может быть каждую секунду. Однако в настоящее время происходит ужасное мерцание при каждом обновлении формы. Как я могу остановить мерцание? Есть ли способ удвоить буфер? Пожалуйста помоги!
10 ответов
Это сработало для меня.
http://www.syncfusion.com/faq/windowsforms/search/558.aspx
В основном это включает в себя получение от желаемого элемента управления и установку следующих стилей.
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
Я знаю, что этот вопрос старый, но, возможно, в будущем его будут искать другие.
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;
}
Вы можете попытаться вызвать это. SuspendLayout (); перед началом обновления и this.ResumeLayout(false); когда вы закончите установку всех значений таким образом, это не позволит форме записывать значения по одному.
Это также может быть вызвано вашей кодировкой, а не отсутствием двойной буферизации. Я пришел сюда только сейчас с похожей проблемой, но понял, что это потому, что:
- Я установил рамку невидимым, когда элемент не выбран.
- Между выборами пользователя индекс очищается элементом управления ListView.
- Я связан с событием SelectedIndexChanged
Другими словами:
- Пользователь нажимает кнопку 1
~ SelectedIndexChanged (1) - Пользователь щелкает пункт 2
~ SelectedIndexChanged (-1) <---- Это вызывает мерцание
~ SelectedIndexChanged (2)
Так в чем же решение? Как избежать тысяч ненужных событий ListView.SelectedIndexChanged?
Вы можете просто заменить оригинальный элемент управления на пользовательский элемент управления, для которого свойство DoubleBuffered имеет значение true. Например, для ListView это будет примерно так:
internal class DoubleBufferedListView : ListView {
public DoubleBufferedListView()
: base() {
this.DoubleBuffered = true;
}
}
После этого вы просто посещаете файл *.Designer.cs и заменяете все упоминания о нативном контроле этим.
PS Вместо того, чтобы наследовать от контроля, вы также можете установить это свойство с помощью отражения:
listView1.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(lsvReport, true, null);
Это не чисто и не рекомендуется, но не требует никаких изменений в файлах *.Designer.cs.
Вы можете создать двойной буфер почти для каждого элемента управления формы Windows, хотя в большинстве случаев требуется, чтобы вы унаследовали от требуемого элемента управления и переопределили защищенное свойство. Однако, будьте осторожны, я потратил довольно много времени на ту же проблему, и мне еще предстоит полностью устранить мерцание на моих более сложных формах.
Если вы хотите по-настоящему свободные от мерцания окна, советую посмотреть на WPF.
Вы не исследовали это хорошо. В каждой форме есть свойство DoubleBuffered. Попробуйте установить это в true. Если вы ничего не перегружали при рисовании формы, то все должно работать.
Побочное действие обычно вызывается тем, что вы работаете в одном потоке, и оно задерживается обновлениями поля, поэтому событие рисования не запускается. Один из способов исправить это - поместить тяжелую работу в асинхронные методы. Это позволит форме перерисовывать себя и обновлять все, что необходимо, когда они вызывают асинхронный вызов метода.
У меня была такая же проблема с OpenGLES, как я нашел эту тему. конечно, я понимаю, что вы не используете OGL, но, возможно, это поможет вам в любом случае;)
protected override void OnPaintBackground(PaintEventArgs e)
{
}