我有一个.net应用程序,我用c#编写。在某些形式上,我经常更新显示字段。在某些情况下,表单上的每个字段(文本框,标签,图片框等)都会更改其值。此外,变化的频率可能是每秒。但是,目前每次更新表单时都会出现可怕的闪烁现象。怎么能阻止闪烁?有没有办法可能加倍缓冲?请帮忙!
答案 0 :(得分:7)
简短的回答是
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
只是为了好玩,尝试在每个元素更新后调用Application.DoEvents(),看看问题是好还是坏; - )
答案 1 :(得分:5)
这对我有用。
http://www.syncfusion.com/faq/windowsforms/search/558.aspx
基本上它涉及从所需的控件派生并设置以下样式。
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
答案 2 :(得分:4)
您可以尝试在开始更新之前调用 this.SuspendLayout(); ,并在完成设置所有值后 this.ResumeLayout(false); 这样就可以防止表单一次写一个值。
答案 3 :(得分:3)
我知道这个问题已经过时了,但未来其他人可能会搜索它。
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;
}
答案 4 :(得分:2)
您可以将原始控件替换为具有受保护DoubleBuffered属性的自定义控件。例如。对于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文件不需要更改。
答案 5 :(得分:2)
它也可能是由您的编码引起的,而不是没有双重缓冲。我刚才带着类似的问题来到这里,但意识到这是因为:
换句话说:
那么解决方案是什么? How to avoid thousands of needless ListView.SelectedIndexChanged events?
答案 6 :(得分:1)
你没有好好研究这个问题。每个表单中都有一个DoubleBuffered属性。尝试将其设置为true。如果你没有在表格绘画上重载任何东西,那么一切都应该有效。
答案 7 :(得分:1)
您可以double buffer几乎每个窗体都可以控制,但大多数情况下它需要您从所需的控件继承并覆盖受保护的属性。但要注意的是,我在相同的问题上花了很多时间,而且我还没有完全消除更复杂形式的闪烁。
如果您想要真正无闪烁的窗口,我建议您查看WPF。
答案 8 :(得分:0)
重影通常是因为你在单个线程中运行而且它被字段更新阻止,所以paint事件不会触发。解决这个问题的一种方法是将繁重的工作放在异步方法中。这将允许表单重新绘制自己并更新异步方法回调时所需的内容。
答案 9 :(得分:0)
我遇到了与OpenGLES相同的问题,这就是我发现这个帖子的方法。 当然我意识到你没有使用ogl,但也许这对你有帮助;)
protected override void OnPaintBackground(PaintEventArgs e)
{
}