C# 在Windows窗体应用程序中闪烁

C# 在Windows窗体应用程序中闪烁,c#,winforms,flicker,createparams,C#,Winforms,Flicker,Createparams,我有一个应用程序,上面有很多控件。而且它有大量的闪烁,特别是在启动时 我把这个应用于它 这非常有效-闪烁减少了相当难以置信的数量。但是,副作用是,当我将鼠标移到窗口上方或单击窗口右上角的“最小化”、“最大化”和“关闭”按钮时,它们不会产生动画效果(尽管它们仍然有效)。这给应用程序一种挂起的感觉 如何在保持最大化、最小化和关闭按钮可用性的同时保持WS_EX_合成 这在Windows XP上发生。正如@fallenidol指出的,这在Windows 7上不是问题。您应该尝试名为DoubleBuffe

我有一个应用程序,上面有很多控件。而且它有大量的闪烁,特别是在启动时

我把这个应用于它

这非常有效-闪烁减少了相当难以置信的数量。但是,副作用是,当我将鼠标移到窗口上方或单击窗口右上角的“最小化”、“最大化”和“关闭”按钮时,它们不会产生动画效果(尽管它们仍然有效)。这给应用程序一种挂起的感觉

如何在保持最大化、最小化和关闭按钮可用性的同时保持WS_EX_合成


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

您应该尝试名为DoubleBuffered的标准Windows窗体控件属性。
请尝试以下代码。这应该放在主窗体和任何其他自定义用户控件中

        // 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);

我想出来了。诀窍是在显示表单后删除WS_EX_COMPOSITED标志。我的博客上的完整解释和代码:


我知道这个问题有点老了,但迟问总比不问好。我使用了您链接的原始示例,在调整大小时打开它,然后将其关闭,以完美地绘制其他所有内容。希望它能帮助其他人寻找这个问题的解决方案。正如OP所知,仅使用双缓冲属性并不能解决闪烁问题

这里有一个解决方法,可以在用户调整窗体大小时停止闪烁,但不会弄乱控件的绘图,如DataGridView、NumericUpDown等。如果窗体名称为“Form1”:



我刚看到这篇文章,意识到它有点过时了。然而,我的表单也遇到了同样的问题,并且发现(无论如何,对于XP来说)一个不雅观的解决方案似乎无法启用视觉样式。

完美的问题(我想要这个功能,我尝试过这个解决方案,我如何在这个新的约束下实现这个功能)。顺便说一句,我在Windows7上运行的一个测试应用程序中尝试了这个修复程序,最大化、最小化和关闭按钮似乎仍然有动画效果。@fallenidol。很高兴知道。我所有的客户端都在XP上。我知道这是一篇老文章,但当Win 7 SP1上启用WS_EX_COMPOSITED时,最大化、最小化和关闭按钮上的动画消失了。这只适用于每个控件。我提供的示例强制对表单上的每个控件进行双缓冲。您可以在应用程序开始时使用反射来填充每个控件的此属性。对于不公开此属性的第三方控件,我不能这样做。嗯,任何第三方控件都必须从Windows.Forms.control继承。即使此属性已关闭,您也可以使用反射来访问任何私有或受保护的属性。我发布的代码的要点是,您只需执行一次,而不是针对每个用户控件(有数百个以上的第三方控件)。这是其他看到此页面的人的另一个选项,他们可能无法访问整个应用程序,并且正在单独开发用户控件。下次开发单用户控件时,可以使用上面的代码片段。那么,你可能不会在有数百个闪烁控件的情况下结束。这一点很好。我的应用程序中有这个代码,但忽略了将其添加到我的博客条目中。将在几天内更新它。很好,但如果我应用此解决方案,那么当窗体调整大小时,闪烁再次出现。如果我只是像问题中那样使用CreateParams,那么即使调整了窗体的大小,闪烁也会消失。也许,我遗漏了一些东西……作为跟进,当我覆盖OnPaintBackground时,我似乎没有闪烁的问题。如果我不想绘制背景,我调用e.Graphics.Clear([适当的颜色])并返回,否则调用基本事件方法。正如我所说,这“似乎”缓解了问题。然而,我想知道可能会产生什么不可预见的影响。只要表单的“最小大小”属性设置为当前大小,上述覆盖似乎就可以工作。@Hossein是的,博客暂时关闭了……希望能在本月某个时候恢复。@Hossein同时,在这里获取它:Hi@AngryHacker!我尝试了你的建议,但在Win 10中出现了闪烁和MDI形式的问题。在Win7中,最小化、恢复和关闭按钮上的动画仍然不起作用。你能给我一些线索吗?提前谢谢你!
        // 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);
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;
}