In previous chapters, we have built only single document interface (SDI) apps. Such programs (including Microsoft’s Notepad and Paint) typically have one window that displays a single document at a time. To edit multiple documents, you must execute separate instances of the app.
Many complex apps are multiple document interface (MDI) programs, which allow users to edit multiple documents at once (e.g., Microsoft Office products). MDI programs also tend to be more complex—Paint Shop Pro and Photoshop have a greater number of image-editing features than does Paint.
An MDI program’s main window is called the parent window, and each window inside the app is referred to as a child window. Although an MDI app can have many child windows, each child has only one parent window. Furthermore, a maximum of one child window can be active at once. Child windows cannot be parents themselves and cannot be moved outside their parent. Otherwise, a child window behaves like any other window (with regard to closing, minimizing, resizing, and so on). A child window’s functionality can differ from that of other child windows of the parent. For example, one child window might allow the user to edit images, another might allow the user to edit text and a third might display network traffic graphically, but all could belong to the same MDI parent. Figure 15.37 depicts a sample MDI app with two child windows.
To create an MDI Form
, set a Form
’s IsMdiContainer
property to true
. The Form
changes appearance, as in Fig. 15.38. Next, create a child Form
class to be added to the Form
. To do this, right click the project in the Solution Explorer, select Project > Add Windows Form… and name the file. Edit the Form
as you like. To add the child Form
to the parent, we must create a new child Form
object, set its MdiParent
property to the parent Form
and call the child Form
’s Show
method. In general, to add a child Form
to a parent, write
ChildFormClass childForm = New ChildFormClass();
childForm.MdiParent = parentForm;
childForm.Show();
In most cases, the parent Form
creates the child, so the parentForm reference is this
. The code to create a child usually lies inside an event handler, which creates a new window in response to a user action. Menu selections (such as File, followed by a submenu option of New, followed by a submenu option of Window) are common techniques for creating new child windows.
Class Form
property MdiChildren
returns an array of child Form
references. This is useful if the parent window wants to check the status of all its children (for example, ensuring that all are saved before the parent closes). Property ActiveMdiChild
returns a reference to the active child window; it returns null
if there are no active child windows. Other features of MDI windows are described in Fig. 15.39.
MDI parent and MDI child properties, a method and an event | Description |
---|---|
Common MDI Child Properties | |
IsMdiChild |
Indicates whether the Form is an MDI child. If true , Form is an MDI child (read-only property). |
MdiParent |
Specifies the MDI parent Form of the child. |
Common MDI Parent Properties | |
ActiveMdiChild |
Returns the Form that’s the currently active MDI child (returns null if no children are active). |
IsMdiContainer |
Indicates whether a Form can be an MDI parent. If true , the Form can be an MDI parent. The default value is false . |
MdiChildren |
Returns the MDI children as an array of Forms . |
Common Method | |
LayoutMdi |
Determines the display of child forms on an MDI parent. The method takes as a parameter an MdiLayout enumeration with possible values ArrangeIcons , Cascade , TileHorizontal and TileVertical . Figure. 15.42 depicts the effects of these values. |
Common Event | |
MdiChildActivate |
Generated when an MDI child is closed or activated. |
Child windows can be minimized, maximized and closed independently of the parent window. Figure. 15.40 shows two images: one containing two minimized child windows and a second containing a maximized child window. When the parent is minimized or closed, the child windows are minimized or closed as well.
Note the title bar in Fig. 15.40(b) is Form1 - [Child1]. When a child window is maximized, its title-bar text is inserted into the parent window’s title bar. When a child window is minimized or maximized, its title bar displays a restore icon, which can be used to return the child window to its previous size (its size before it was minimized or maximized).
C# provides a property that helps track which child windows are open in an MDI container. Property MdiWindowListItem
of class MenuStrip
specifies which menu, if any, displays a list of open child windows that the user can select to bring the corresponding window to the foreground. When a new child window is opened, an entry is added to the end of the list (Fig. 15.41). If ten or more child windows are open, the list includes the option More Windows..., which allows the user to select a window from a list in a dialog.
In an MDI app, include a menu that displays a list of the open child windows. This helps the user select a child window quickly.
MDI containers allow you to organize the placement of its child windows. The child windows in an MDI app can be arranged by calling method LayoutMdi
of the parent Form
. Method LayoutMdi
takes an MdiLayout
enumeration, which can have values ArrangeIcons
, Cascade
, TileHorizontal
and TileVertical
. Tiled windows completely fill the parent and do not overlap; such windows can be arranged horizontally (value TileHorizontal
) or vertically (value TileVertical
). Cascaded windows (value Cascade
) overlap—each is the same size and displays a visible title bar, if possible. Value ArrangeIcons
arranges the icons for any minimized child windows. If minimized windows are scattered around the parent window, value ArrangeIcons
orders them neatly at the bottom-left corner of the parent window. Figure 15.42 illustrates the values of the MdiLayout
enumeration.
Class UsingMDIForm
(Fig 15.43) demonstrates MDI windows. Class UsingMDIForm
uses three instances of child Form
ChildForm
(Fig. 15.44), each containing a PictureBox
that displays an image. The parent MDI Form
contains a menu enabling users to create and arrange child Form
s.
Form
Figure 15.43 presents class UsingMDIForm
—the app’s MDI parent Form
. This Form
, which is created first, contains two top-level menus. The first of these menus, File (fileToolStripMenuItem
), contains both an Exit item (exitToolStripMenuItem
) and a New submenu (newToolStripMenuItem
) consisting of items for each type of child window. The second menu, Window (windowToolStripMenuItem
), provides options for laying out the MDI children, plus a list of the active MDI children.
In the Properties window, we set the Form
’s IsMdiContainer
property to true
, making the Form
an MDI parent. In addition, we set the MenuStrip
’s MdiWindowListItem
property to windowToolStripMenuItem
. This enables the Window menu to contain the list of child MDI windows.
The Cascade menu item (cascadeToolStripMenuItem
) has an event handler (cascadeToolStripMenuItem_Click
, lines 58–62) that arranges the child windows in a cascading manner. The event handler calls method LayoutMdi
with the argument Cascade
from the MdiLayout
enumeration (line 61).
The Tile Horizontal menu item (tileHorizontalToolStripMenuItem
) has an event handler (tileHorizontalToolStripMenuItem_Click
, lines 65–69) that arranges the child windows in a horizontal manner. The event handler calls method LayoutMdi
with the argument TileHorizontal
from the MdiLayout
enumeration (line 68).
Finally, the Tile Vertical menu item (tileVerticalToolStripMenuItem
) has an event handler (tileVerticalToolStripMenuItem_Click
, lines 72–76) that arranges the child windows in a vertical manner. The event handler calls method LayoutMdi
with the argument TileVertical
from the MdiLayout
enumeration (line 75).
Form
At this point, the app is still incomplete—we must define the MDI child class. To do this, right click the project in the Solution Explorer and select Add > Windows Form…. Then name the new class in the dialog as ChildForm
(Fig. 15.44). Next, we add a PictureBox
(displayPictureBox
) to ChildForm
. In ChildForm
’s constructor, line 16 sets the title-bar text. Lines 19–21 retrieve the appropriate image resource, cast it to an Image
and set displayPictureBox
’s Image
property. The images that are used can be found in the Images
subfolder of this chapter’s examples directory.
After the MDI child class is defined, the parent MDI Form
(Fig. 15.43) can create new child windows. The event handlers in lines 18–48 create a new child Form
corresponding to the menu item clicked. Lines 22–23, 33–34 and 44–45 create new instances of Child-Form
. Lines 24, 35 and 46 set each Child
’s MdiParent
property to the parent Form
. Lines 25, 36 and 47 call method Show
to display each child Form
.