Windows Forms MDI
FAQ Home
1.
How can I create an MDI application in the .NET framework with C#?
2. I have an MDI application with several child forms. The
child form's Activated event is not being fired consistently as different
child forms are activated. What's wrong?
3. In an MDI application, the MDI child's MaximumSize and
MinimumSize properties don't seem to take effect. How can I restrict the
size of my MDI child?
4. How do I check to see if a child form is already displayed
so I don't have two instances showing?
5. I need to perform certain custom processing whenever an MDI
child form is added to/removed from the MDIContainer form. How do I
determine this?
6. How do I paint in my mdi container, a logo, for example?
7. How do I make my child Form fill the entire mdi client
without being maximized?
8. How can I change the background of my MDI Client container?
1 How can I create an MDI application in the .NET
framework with C#?
This is one of the Quick Start Samples that ships with VS.Net.
2 I have an MDI application with several child forms.
The child form's Activated event is not being fired consistently as
different child forms are activated. What's wrong?
The child forms do not get the Form.Activated event (only the parent MDI).
To catch MDI children being activated, listen to the Enter/Leave events of
that child Form or listen to the Form.MdiChildActivate event in the parent
Form.
3 In an MDI application, the MDI child's MaximumSize and
MinimumSize properties don't seem to take effect. How can I restrict the
size of my MDI child?
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
4 How do I check to see if a child form is already
displayed so I don't have two instances showing?
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.
5 I need to perform certain custom processing whenever
an MDI child form is added to/removed from the MDIContainer form. How do I
determine this?
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."));
}
6 How do I paint in my mdi container, a logo, for
example?
You should not try listening to your MDI container Form's Paint event,
instead listen to the Paint event of the MDIClient control that is a child
of the mdi container form. This article provides you a detailed example:
Painting in the MDI Client Area
7 How do I make my child Form fill the entire mdi client
without being maximized?
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
8 How can I change the background of my MDI Client
container?
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.
//set back color
foreach(Control c in this.Controls)
{
if(c is MdiClient)
{
c.BackColor = this.BackColor;
c.BackgroundImage = this.BackgroundImage;
}
}
|