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





Вы плохо это исследовали. В каждой форме есть свойство DoubleBuffered. Попробуйте установить для него значение true. Если вы ничего не перегружали при рисовании формы, то все должно работать.
краткий ответ
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
длинный ответ: см. MSDN или Google
просто для удовольствия попробуйте вызвать Application.DoEvents () после обновления каждого элемента и посмотрите, станет ли проблема лучше или хуже ;-)
Не уверен, что это поможет. Похоже, проблема в том, что стандартные элементы управления мерцают, а OptimizedDoubleBuffer поможет только с настраиваемыми элементами управления.
Призрак обычно возникает из-за того, что вы работаете в одном потоке, и он задерживается обновлениями поля, поэтому событие рисования не запускается. Один из способов исправить это - переложить тяжелую работу на асинхронные методы. Это позволит форме перерисовывать себя и обновлять все, что необходимо, когда асинхронный метод выполняет обратный вызов.
Вы можете попытаться вызвать this.SuspendLayout (); перед тем, как начать обновление, и this.ResumeLayout (ложь);, когда вы закончите установку всех значений таким образом, это должно помешать форме записывать значения по одному.
suspendlayout / resumelayout предназначены для подавления событий, связанных с добавлением и перемещением элементов управления
Верно, события только предотвращают многократный вызов функций макета при обновлении больших групп элементов управления. Таким образом, эти функции ускорят разметку, но не предотвратят мерцание. Использование их вместе с двойной буферизацией даст наилучшие результаты.
Вы можете двойной буфер почти для каждого элемента управления Windows Forms, хотя в большинстве случаев это требует, чтобы вы унаследовали от желаемого элемента управления и переопределили защищенное свойство. Однако имейте в виду, что я потратил довольно много времени на ту же проблему, и мне еще не удалось полностью удалить мерцание на моих более сложных формах.
Если вам нужны окна без мерцания, я предлагаю взглянуть на WPF.
Это сработало для меня.
http://www.syncfusion.com/faq/windowsforms/search/558.aspx
В основном это включает получение желаемого элемента управления и установку следующих стилей.
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
Это должен быть ответ!
У меня была такая же проблема с 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;
}
Это лучший и, на мой взгляд, однозначный ответ.
Вы можете просто заменить исходный элемент управления на пользовательский, для которого свойство 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.
Это также может быть вызвано вашим кодированием, а не отсутствием двойной буферизации. Я пришел сюда только сейчас с похожей проблемой, но понял, что это потому, что:
Другими словами:
Так в чем же выход? Как избежать тысяч ненужных событий ListView.SelectedIndexChanged?
Спасибо! Я потратил много лет на поиски этого, и он все время лежал передо мной.