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?
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: