2010-07-20 49 views
20

我有一个应用程序,它有一吨的控件。而且它有大量的闪烁,特别是在启动时。在Windows窗体应用程序中闪烁

我将此fix加到它。

protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
      return cp; 
     } 
    } 

这很好 - 闪烁减少了一个相当不可思议的数额。但是,副作用是当我将鼠标移到或点击它们(它们仍然可以工作)时,窗口右上角的最小化,最大化和关闭按钮不会生成动画。这给了应用程序一个悬挂的感觉。

如何保留WS_EX_COMPOSITED,同时仍保留最大化,最小化和关闭按钮的可用性?

这发生在Windows XP上。正如@fallenidol指出的,这在Windows 7上不是问题。

+5

完美的问题(我想要这个功能,我试过这个解决方案,我如何用这个新的约束来实现这个功能)。 – 2010-07-20 01:34:32

+0

顺便说一句,我试着在Windows 7上运行的测试应用程序中进行修复,最大化,最小化和关闭按钮似乎仍然具有动画效果。 – pmcilreavy 2010-07-21 07:21:53

+0

@fallenidol。这很好。我所有的客户都在XP上。 – AngryHacker 2010-07-21 16:37:27

回答

11

我想通了。诀窍是在显示表单后删除WS_EX_COMPOSITED标志。在我的博客的完整说明和代码:

How to get rid of flicker on Windows Forms applications

+0

非常棒..为我工作 – Marshal 2011-03-31 07:00:14

+0

很好的文档。感谢那。 Upvoted。 – C4u 2014-11-26 10:52:47

+0

@Hossein是的,博客现在停下来......希望这个月会在某个时候恢复。 – AngryHacker 2016-08-07 19:02:07

0

您应该尝试标准的Windows窗体控件属性,名为DoubleBuffered。 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

+0

这只适用于每个控件。我提供的示例强制在表单上的每个控件上进行双缓冲。 – AngryHacker 2010-07-20 07:43:37

+0

您可以在应用程序的开始处使用反射来填充每个控件的此属性。 – Kru 2010-07-20 07:51:14

+0

我不能为不公开此属性的第三方控件执行此操作。 – AngryHacker 2010-07-21 16:32:59

4

请尝试下面的代码。这应该在主窗体以及您拥有的任何其他自定义用户控件中进行。

 // Enable double duffering to stop flickering. 
     this.SetStyle(ControlStyles.DoubleBuffer, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor, false); 
     this.SetStyle(ControlStyles.Opaque, false); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     this.SetStyle(ControlStyles.ResizeRedraw, true); 
+0

我发布的代码的全部内容是,您只需执行一次,而不是针对每个用户控件(其中有数百个+第三方控件)。 – AngryHacker 2010-07-20 15:53:33

+3

这是其他人看到此页面的另一种选择,他们可能无法访问整个应用程序,而只是单独开发用户控件。 下次您正在开发单个用户控件时,您可以使用上面的代码片段。那么你可能不会在有数百个闪烁控制的情况下结束。 – pmcilreavy 2010-07-21 07:18:25

5

我知道这个问题是有点老了,但迟到总比不到好。我使用了你链接的原始示例来创建一个在调整大小时切换它的示例,然后将其切换回来以便完美地绘制其他所有内容。希望它可以帮助其他人寻找解决这个问题的方法。正如OP所知道的,DoubleBuffering单独的属性不能解决闪烁的问题。

这里有一个变通停止闪烁时,用户改变形式,但没有搞乱如的DataGridView,的NumericUpDown等控制绘图前提是你的窗体名称是“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; 
} 
+0

好点。我在我的应用中使用过这些代码,但忽略将其添加到我的博客条目中。将在几天内更新。 – AngryHacker 2011-06-29 16:45:33

0

我刚刚遇到这个帖子,意识到它有点老了。然而,我的表单与我的表单有相同的问题,并且发现(对于XP,无论如何),一个不雅的解决方案似乎并没有启用视觉样式。

+0

作为一个后续行动,当我重写OnPaintBackground时,我似乎没有闪烁问题。如果我不想绘制背景,我将调用e.Graphics.Clear([适当的颜色])并返回,否则调用基本事件方法。正如我所说,这似乎是为了缓解这个问题。但是,我想知道可能会产生什么样的不可预见的后果。 – Tebc 2012-12-10 15:01:45

+0

正确。只要表单的最小大小属性设置为当前大小,上述覆盖似乎就会起作用。 – Tebc 2012-12-10 15:11:37