This article shows how to activate an MDI child form maximized, without the fireworks that erupt when you activate an MDI child form using the
Select() methods of the child form.
If you've used MDI in WinForms or Win32, you've probably come across this very annoying issue, where MDI child forms that are activated through code, paint themselves in the restored window state they always have when they are non-active, just before they are activated and maximized (this happens only when the current MDI child form is maximized).
Because this issue was so annoying, and resulted in a very unprofessional 'look and feel', I became determined to find a workaround. The one I found to work best involves no subclassing or message handling. I discovered this when I noticed that if I activate the next MDI child form via Ctrl+F6 or the MDI system menu, there was none of the usual fireworks that I was seeing when a child form is activated by calling its
That lead me to the
WM_MDINEXT Windows message which, at first glance, seemed only useful for activating the next MDI child form in the sequence. However, it can be used to activate any MDI child form by passing the handle of the next or previous MDI child in the Z-order along with a flag telling it whether to activate the next or previous MDI child in the Z-order.
Using the code
The following sample MDI parent
Form class implements the workaround via a method that can be called and passed the MDI child form to be activated:
public partial class MyMDIParent : Form
public void ActivateMdiChild( Form childToActivate )
if( this.ActiveMdiChild != childToActivate )
MdiClient mdiClient = GetMDIClient();
int count = this.MdiChildren.Length;
Control form = null;
int pos = mdiClient.Controls.IndexOf( childToActivate );
if( pos < 0 )
throw new InvalidOperationException( "MDIChild form not found" );
if( pos == 0 )
form = mdiClient.Controls;
form = mdiClient.Controls[pos - 1];
IntPtr direction = new IntPtr( pos == 0 ? 1 : 0 );
SendMessage( mdiClient.Handle, WM_MDINEXT, form.Handle, direction );
public MdiClient GetMDIClient()
foreach( Control c in this.Controls )
if( c is MdiClient )
return (MdiClient) c;
throw new InvalidOperationException( "No MDIClient !!!" );
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
public static extern IntPtr SendMessage( IntPtr hWnd, int msg,
IntPtr wParam, IntPtr lParam );
public const int WM_MDINEXT = 0x224;
Points of interest
This solution works fine for me, when I need to activate a child window via code, but I haven't looked at how to get the MDI child form menu entries inserted into the menu by the framework, to use it. Any insight or advice on that would be welcome.
- Initial submission - 7/09/07.