使用Aero在WinForms MDI中禁用GDI“硬件加速”以加快速度

时间:2014-06-06 11:17:56

标签: winforms gdi mdi hardware-acceleration aero

如果启用Aero,则自Windows Vista以来,MDI应用程序速度非常慢。移动MDI窗口似乎明显滞后,重新绘制非常缓慢。

自Windows Vista起,GDI不再是硬件加速,以简化新的图形驱动程序模型。如果您禁用Aero(在Windows 8中已不再使用),它的速度与Windows XP一样快。

使用Microsoft应用程序兼容性管理员,可以设置" NoGdiHwAcceleration"即使启用了Aero,也会恢复MDI应用程序速度的标志。

但是,没有提供如何以编程方式禁用此加速或如果代码可以触发此兼容性标志的说明。

任何人都知道怎么做?

2 个答案:

答案 0 :(得分:0)

您是否尝试过使用DwmEnableComposition和/或DwmEnableBlurBehindWindow?但是,这确实会在应用程序退出或更改之前完全禁用Aero ...

还有一个answer here on SO,看起来你可以在.net 3.5 SP1及更高版本的每个窗口切换到SW渲染。

答案 1 :(得分:0)

我实际上可以使用另一种更直接的.NET方法来解决缓慢的MDI性能,而不需要任何兼容性标记。

诀窍是强制双重缓冲到MdiClient控件(托管MDI窗口的容器)。

可以通过遍历其所有控件并检查其类型来检索父窗体上的MdiClient实例。

// Retrieve the MDI client control on this parent window.
MdiClient mdiClient = null;
foreach (Control control in Controls)
{
    mdiClient = control as MdiClient;
    if (mdiClient != null)
    {
        break;
    }
}

强制双缓冲实际上只能通过调用受保护的方法SetStyle来实现,因此我们必须使用反射从外部调用它。这看起来非常安全,因为自.NET 1.1以来SetStyle可用,并且从那以后没有改变。

// Force double buffering on it by calling the protected SetStyle method via reflection.
MethodInfo setStyleMethod = typeof(MdiClient).GetMethod("SetStyle",
    BindingFlags.NonPublic | BindingFlags.Instance)
setStyleMethod.Invoke(mdiClient, object[] {
    ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw,
    true });

现在,性能与没有任何自定义绘图一样好。

由于ControlStyles.ResizeRedraw参数,整个背景在表单大小更改时重新绘制,如果您计划绘制渐变背景,则非常有用。只需使用Paint实例上的MdiClient事件,然后在那里进行绘制。

这也使得首先在一个不需要的位图上绘制所有内容的方法,因为双缓冲已经在内部完成了 - 在此过程中消除了闪烁。

您可能想要解决的唯一问题是在滚动MdiClient时(当Windows在可见区域之外时)重绘背景。这不会导致Paint事件。这需要更多代码,请参考以下答案:How to detect when an MDIClient window has been scrolledWinForms Layered Controls with Background images cause tearing while scrolling