Search code examples
winformsgdimdihardware-accelerationaero

Disabling GDI "hardware acceleration" in WinForms MDI with Aero for speed up


MDI applications are horribly slow since Windows Vista if Aero is turned on. Moving MDI windows around seems to lag noticably and the repainting is very slow.

Since Windows Vista, GDI is not hardware accelerated anymore to simplify the new graphic driver model. If you disable Aero (which you can't anymore in Windows 8), it's as fast as in Windows XP again.

With the Microsoft Application Compatibility Administrator, it is possible to set the "NoGdiHwAcceleration" flag which restores the MDI application speed even with Aero enabled.

However, no description was provided how to disable this acceleration programmatically or if this compatibility flag can be triggered by code.

Anyone knows how to?


Solution

  • I solved this issue without requiring any compatibility flags. The idea is to force double buffering on the MdiClient control available on the parent form, which is the container hosting the MDI windows. Its instance can be retrieved with:

    MdiClient mdiClient = Controls.OfType<MdiClient>().First();
    

    Forcing double buffering requires to call the protected SetStyle method, so we have to use reflection to invoke it from outside. This is safe as SetStyle is available since .NET 1.1 and has not changed since then:

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

    Now, simply use the Paint event on the MdiClient instance and do your drawing there. There is no need for any intermediate bitmaps.

    If you need to redraw all of the background if the form size changes (like gradients that need to be scaled over the whole container), you want to add the ControlStyles.ResizeRedraw flag.

    Note that scrolling the MdiClient (e.g. when child windows are placed outside the visible bounds), the Paint event is not raised. Refer to these answers if you want to redraw during a scroll: