WinForms FAQ - MDI

Find answers for the most frequently asked questions
Expand All Collapse All

The default behavior is to make the client container use the Control color from the Control panel. You can change this behavior by making the
MDI Client container use the form’s BackColor and Image. To do this, after the call to InitializeComponents(), add the code below. You can
also download a working MDI Client project that has this code in it.

//set back color
foreach(Control c in this.Controls)
{
  if(c is MdiClient)
  {
    c.BackColor = this.BackColor;
    c.BackgroundImage = this.BackgroundImage;
  }
}
Permalink

Here is how it can be done. This takes into account all docked controls (including menus) in the mdi parent form.


[C#]
		private void FillActiveChildFormToClient()
		{
			Form child = this.ActiveMdiChild;
			Rectangle mdiClientArea = Rectangle.Empty;
			foreach(Control c in this.Controls)
			{
				if(c is MdiClient)
					mdiClientArea = c.ClientRectangle;
			}
			child.Bounds = mdiClientArea;
		}

[VB.Net]
		Private  Sub FillActiveChildFormToClient()
			Dim child As Form =  Me.ActiveMdiChild 
			Dim mdiClientArea As Rectangle =  Rectangle.Empty 
			Dim c As Control
			For Each c In Me.Controls
				If TypeOf c Is MdiClient Then
					mdiClientArea = c.ClientRectangle
				End If
			Next
			child.Bounds = mdiClientArea
		End Sub
Permalink

It appears that this behavior is a bug that will be corrected in a future .NET release.

You can control the size of your child form by adding a Layout event handler for it. Here is a code snippet that imposes the minimum size that you set in its properties. You can also handle it by overriding the form’s WndProc method as explained in this Microsoft KB article.

[C#]
	private void Document_Layout(object sender, System.Windows.Forms.LayoutEventArgs e)
	{
		if(this.Bounds.Width < this.MinimumSize.Width)
			this.Size = new Size(this.MinimumSize.Width, this.Size.Height);

		if(this.Bounds.Height < this.MinimumSize.Height)
			this.Size = new Size(this.Size.Width, this.MinimumSize.Height);
	}

[VB.NET]
	Private Sub Document_Layout(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LayoutEventArgs) Handles MyBase.Layout

		If (Me.Bounds.Width < Me.MinimumSize.Width) Then
			Me.Size = New Size(Me.MinimumSize.Width, Me.Size.Height)
		End If

		If (Me.Bounds.Height < Me.MinimumSize.Height) Then
			Me.Size = New Size(Me.Size.Width, Me.MinimumSize.Height)
		End If
	End Sub
Permalink

MDIContainer forms have an MDIClient child window and it is to this MDIClient window that MDI child forms are parented. The MDIClient’s ControlAdded/ControlRemoved events will be fired whenever a child form is added or removed. You can subscribe to these events and add the required processing code from within the handlers.


// From within the MDIContainer form, subscribe to the MDIClient’s ControlAdded/ControlRemoved events 
foreach(Control ctrl in this.Controls) 
{ 
	if(ctrl.GetType() == typeof(MdiClient)) 
	{ 
		ctrl.ControlAdded += new ControlEventHandler(this.MDIClient_ControlAdded); 
		ctrl.ControlRemoved += new ControlEventHandler(this.MDIClient_ControlRemoved); 
		break;
	} 
} 

protected void MDIClient_ControlAdded(object sender, ControlEventArgs e) 
{ 
	Form childform = e.Control as Form;
	Trace.WriteLine(String.Concat(childform.Text, ' - MDI child form was added.'));
} 

protected void MDIClient_ControlRemoved(object sender, ControlEventArgs e) 
{ 
	Trace.WriteLine(String.Concat(e.Control.Text, ' - MDI child form was removed.'));
} 
Permalink

Here are two ways you can do this.

i)
Within the parent MDI form, use code such as this:

	// MyChildForm is the one I’m looking for
	MyChildForm childForm = null;
	foreach(Form f in this.MdiChildren) 
	{
		if(f is MyChildForm) 
		{
			// found it
			childForm = (MyChildForm) f;
			break;
		}
	}

	if( childForm != null)
	{
		childForm.Show();
		childForm.Focus();
	}
	else
	{
		childForm = new MyChildForm();
		childForm.MdiParent = this;
		childForm.Show();
		childForm.Focus();
	}

ii) Here is a second solution suggested by John Conwell that implements a singleton pattern on the child form.

In the MDI Child form put this code in (where frmChildForm is the MDI child form you want to control)

	//Used for singleton pattern
	static frmChildForm childForm;
	public static ChildForm GetInstance
	{
		if (childForm == null)
			childForm = new frmChildForm;
		return childForm;
	}

In the Parent MDI form use the following code to call the child MDI form

	frmChildForm childForm = frmChildForm.GetInstance();
	childForm.MdiParent = this;
	childForm.Show();
	childForm.BringToFront();

The first time this code is called, the static GetInstance method will create and return an instance of the child form. Every other time this code is called, the GetInstance method will return the existing instance of the child from, stored in the static field childForm. If the child form instance is ever destroyed, the next time you call GetInstance, a new instance will be created and then used for its lifetime.

Also, if you need constructors or even overloaded constructors for your MDI Child Form, just add the needed parameters to the GetInstance function and pass them along to the class constructor.

Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.