1

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?

Ray
  • 7,940
  • 7
  • 58
  • 90

2 Answers2

0

Have you tried using DwmEnableComposition and/or DwmEnableBlurBehindWindow? However, this does appear to disable Aero completely until the application exits or changes it back...

Also there's an answer here on SO that makes it look like you can switch to SW rendering per windows in .net 3.5 SP1 and up.

Community
  • 1
  • 1
Forest Kunecke
  • 2,160
  • 15
  • 32
  • The Aero dwmapi methods are not helping here as they just extend glass into the client area. Also, EnableComposition has no effect anymore since Win8, and it would also disable the whole Aero interface system-wide, which is not what I want. The hardware acceleration you mentioned has to do with WPF, not WinForms and GDI. – Ray Jun 12 '14 at 16:31
  • Oh, you had mentioned windows 8 in your question but I did not realize that was what you were using. If that's the case then I do not believe it is possible. – Forest Kunecke Jun 12 '14 at 17:29
  • Yeah, I didn't like the apps disabling Aero in Windows 7 / Vista from the beginning though :D – Ray Jun 12 '14 at 19:08
0

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:

Ray
  • 7,940
  • 7
  • 58
  • 90