在C# Windows窗体中显示MDI子窗体时如何避免闪烁?

3

当连接到 RDC 时,我发现 mdi 子窗体的背景图像出现闪烁问题。如何避免这种情况?

5个回答

2

我知道这是一个非常晚的答案,但由于这里所有的答案(包括被接受的答案)都没有解决闪烁问题,我仍然想发布一下我的解决方法

首先,我必须做到这一点

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;

        // reduce flickering when switching mdi child forms (see also WndProc)
        cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED (which is essentially double buffered)

        return cp;
    }
}

但这还不够,我还得做这个:

protected override void WndProc(ref Message msg)
{
    const int WM_NCPAINT = 0x85;
    const int WM_SIZE = 0x05;

    // reduce flickering when switching mdi child forms (see also CreateParams)
    if (msg.Msg == WM_NCPAINT)
    {
        if (this.WindowState == FormWindowState.Maximized)
            return;
    }

    // reduce flickering when switching mdi child forms (see also CreateParams)
    if (msg.Msg == WM_SIZE)
    {
        if (this.WindowState == FormWindowState.Maximized)
            return;
    }

    base.WndProc(ref msg);
}

我曾在某个地方读到,我可以通过简单地执行这个来实现所有这些:

this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

但是当我这样做时,闪烁只会变得更严重。

总之,通过这个解决方案(至少在我的 mdi 项目中),我已经完全消除了在 mdi 子窗体之间切换时的闪烁。
希望这可以帮助任何寻找此问题的人。


未能在 Windows 10 上测试通过。这个可以工作,但是标题栏图标消失了...至少对我来说是这样的。对我来说完美的解决方案是只添加第一个建议的函数(CreateParams),这可以避免闪烁并正常显示标题栏,但是,当最小化然后最大化窗口时它停止工作。 - user5583316

1

你尝试过以下方法吗?

this.DoubleBuffered = true;

将这个放在InitializeComponent之后的构造函数中。

这个怎么样?http://msdn.microsoft.com/zh-cn/library/dd145208(v=vs.85).aspx 你可以锁定窗口,做你要做的事情,然后再解锁它。 - Alexander Schmidt

1
我正在使用这段代码,完全没有闪烁。
if (!CheckForm(childForm))
        {
            childForm.WindowState = FormWindowState.Minimized; //avoid flickering
            childForm.Show();
            childForm.WindowState = FormWindowState.Normal;
        }
        else
        {
            childForm.BringToFront();
            childForm.WindowState = FormWindowState.Minimized;
            childForm.Activate();
            childForm.WindowState = FormWindowState.Normal;
        }

0

我也长期面临这个问题。最后我找到了解决方法:以填充停靠模式打开表单,而不是最大化。

//childFrm.WindowState = FormWindowState.Maximized;
childFrm.Dock = DockStyle.Fill;

在 MDI 窗体中删除任何背景图像。


0

我也一直在苦恼同样的问题,没有找到任何有效的方法,包括 form.DoubleBuffered = true。所以这是对我有效的方法。

form.WindowState = FormWindowState.Minimized;
form.Show();
form.WindowState = FormWindowState.Maximized;

在设计师端,将表单窗口状态保留为正常状态。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接