visual c#form update导致闪烁

我有一个.net应用程序,我用c#编写。 在某些forms上,我经常更新显示字段。 在某些情况下,表单上的每个字段(文本框,标签,图片框等)都会更改其值。 此外,变化的频率可能是每秒。 但是,目前每次更新表单时都会出现可怕的闪烁现象。 我怎么能停止闪烁? 有没有办法可能加倍缓冲? 请帮忙!

简短的回答是

SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 

答案很长:请参阅MSDN或谷歌

只是为了好玩,尝试在每个元素更新后调用Application.DoEvents(),看看问题是好还是坏;-)

这对我有用。

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

基本上它涉及从所需的控件派生并设置以下样式。

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

你可以尝试调用this.SuspendLayout(); 在你开始更新和this.ResumeLayout(false)之前; 当您以这种方式设置完所有值后,它应该阻止表单一次写入一个值。

我知道这个问题已经过时了,但未来其他人可能会搜索它。

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文件,并用此文件替换所有本机控件的提及。

PS除了从控件inheritance之外,您还可以通过reflection设置此属性:

 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事件?

你没有好好研究这个问题。 每个表单都有一个DoubleBuffered属性。 尝试将其设置为true。 如果你没有在表格绘画上重载任何东西,那么一切都应该有效。

您可以对几乎每个窗体控件进行双缓冲 ,尽管大多数情况下它需要您从所需的控件inheritance并覆盖受保护的属性。 但要注意的是,我在相同的问题上花了很多时间,而且我还没有完全删除更复杂forms的闪烁。

如果你想要真正无闪烁的窗口,我建议看看WPF。

重影通常是因为你在单个线程中运行而且它被字段更新所阻止,所以paint事件不会触发。 解决这个问题的一种方法是将繁重的工作放在异步方法中。 这将允许表单重新绘制自己并更新异步方法回调时所需的内容。

我有与OpenGLES相同的问题,这就是我发现这个线程的方式。 当然我知道你没有使用ogl,但也许这对你有帮助;)

protected override void OnPaintBackground(PaintEventArgs e) { }