2. When the app executes, another compiler (known as the just-in-time compiler
15.12 Multiple Document Interface (MDI) Windows
In previous chapters, we have built onlysingle document interface (SDI)apps. Such pro- grams (including Microsoft’s Notepad and Paint) can support only one open window or document at a time. SDI apps usually have limited abilities—Paint and Notepad, for ex- ample, have limited image- and text-editing features. To editmultipledocuments, the user must execute another instance of the SDI app.
Many complex apps aremultiple 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 theparent window, and each window inside the app is referred to as achild window. Although an MDI app can have many child windows, each 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 MDIForm, create a newFormand set itsIsMdiContainerproperty to
true. TheFormchanges appearance, as in Fig. 15.38. Next, create a childFormclass 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 theFormas you like. To add the child Form to the parent, we must create a new child Form object, set its MdiParent property to the parentFormand call the childForm’sShowmethod. In general, to add a childFormto a parent, write
Fig. 15.37 | MDI parent window and MDI child windows.
ChildFormClass childForm = New ChildFormClass();
childForm.MdiParent = parentForm;
childForm.Show();
MDI parent
MDI child MDI child
15.12 Multiple Document Interface (MDI) Windows 615
In most cases, the parentFormcreates the child, so theparentFormreference isthis. 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 asFile, followed by a submenu option ofNew,followed by a submenu option ofWindow) are common techniques for creating new child windows.
ClassFormpropertyMdiChildrenreturns an array of child Formreferences. 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). PropertyActiveMdiChildreturns a reference to the active child window; it returnsnullif there are no active child windows.
Other features of MDI windows are described in Fig. 15.39.
Fig. 15.38 | SDI and MDI forms.
MDIFormproperties, a method and an
event Description
Common MDI Child Properties
IsMdiChild Indicates whether theFormis an MDI child. Iftrue,Formis an MDI child (read-only property).
MdiParent Specifies the MDI parentFormof the child.
Common MDI Parent Properties
ActiveMdiChild Returns theFormthat’s the currently active MDI child (returns
nullif no children are active).
IsMdiContainer Indicates whether aFormcan be an MDI parent. Iftrue, theForm can be an MDI parent. The default value isfalse.
MdiChildren Returns the MDI children as an array ofForms. Common Method
LayoutMdi Determines the display of child forms on an MDI parent. The method takes as a parameter anMdiLayoutenumeration with possible valuesArrangeIcons,Cascade,TileHorizontaland
TileVertical. Figure 15.42 depicts the effects of these values.
Common Event
MdiChildActivate Generated when an MDI child is closed or activated.
Fig. 15.39 | MDI parent and MDI child properties, a method and an event.
Single Document Interface (SDI) Multiple Document Interface (MDI)
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. Notice that the title bar in Fig. 15.40(b) isForm1 - [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 maxi- mized, 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. PropertyMdiWindowListItemof classMenuStripspecifies 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 optionMore Windows..., which allows the user to select a window from a list in a dialog.
MDI containers allow you to organize the placement of its child windows. The child windows in an MDI app can be arranged by calling methodLayoutMdiof the parentForm. MethodLayoutMditakes anMdiLayoutenumeration, which can have valuesArrangeIcons,
Cascade,TileHorizontaland TileVertical.Tiled windows completely fill the parent and donotoverlap; such windows can be arranged horizontally (valueTileHorizontal) or vertically (valueTileVertical).Cascaded windows(valueCascade) overlap—each is the same size and displays a visible title bar, if possible. ValueArrangeIconsarranges the icons for any minimized child windows. If minimized windows are scattered around the parent window, valueArrangeIconsorders them neatly at the bottom-left corner of the parent window. Figure 15.42 illustrates the values of theMdiLayoutenumeration.
Fig. 15.40 | Minimized and maximized child windows.
Good Programming Practice 15.1
When creating MDI apps, include a menu that displays a list of the open child windows.
This helps the user select a child window quickly, rather than having to search for it in the parent window.
Parent window icons:
minimize, maximize and close
Maximized child window icons:
minimize, restore and close
Minimized child window icons:
restore, maximize and close
Parent title bar indicates maximized child
a) b)
15.12 Multiple Document Interface (MDI) Windows 617
ClassUsingMDIForm(Fig. 15.43) demonstrates MDI windows. ClassUsingMDIForm
uses three instances of childForm ChildForm(Fig. 15.44), each containing aPictureBox
that displays an image. The parent MDIFormcontains a menu enabling users to create and arrange childForms.
Fig. 15.41 | MenuStrippropertyMdiWindowListItemexample.
Fig. 15.42 | MdiLayoutenumeration values.
Ten or more child windows enables theMore Windows…option Child windows list
a)ArrangeIcons b)Cascade
c)TileHorizontal d)TileVertical
MDI ParentForm
Figure 15.43 presents classUsingMDIForm—the app’s MDI parentForm. ThisForm, which is created first, contains two top-level menus. The first of these menus,File(fileTool-
StripMenuItem), contains both anExititem (exitToolStripMenuItem) and aNewsub- menu (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.
1 // Fig. 15.43: UsingMDIForm.cs
2 // Demonstrating use of MDI parent and child windows.
3 using System;
4 using System.Windows.Forms;
5
6 namespace UsingMDI 7 {
8 // Form demonstrates the use of MDI parent and child windows 9 public partial class UsingMDIForm : Form
10 {
11 // constructor
12 public UsingMDIForm()
13 {
14 InitializeComponent();
15 } // end constructor 16
17 // create Lavender Flowers image window 18 private void lavenderToolStripMenuItem_Click(
19 object sender, EventArgs e )
20 {
21 // create new child 22
23 24 25
26 } // end method lavenderToolStripMenuItem_Click 27
28 // create Purple Flowers image window 29 private void purpleToolStripMenuItem_Click(
30 object sender, EventArgs e )
31 {
32 // create new child 33
34 35 36
37 } // end method purpleToolStripMenuItem_Click 38
39 // create Yellow Flowers image window 40 private void yellowToolStripMenuItem_Click(
41 object sender, EventArgs e )
42 {
Fig. 15.43 | MDI parent-window class. (Part 1 of 3.)
ChildForm child = new ChildForm(
"Lavender Flowers", "lavenderflowers" );
child.MdiParent = this; // set parent child.Show(); // display child
ChildForm child = new ChildForm(
"Purple Flowers", "purpleflowers" );
child.MdiParent = this; // set parent child.Show(); // display child
15.12 Multiple Document Interface (MDI) Windows 619
43 // create new child 44
45 46 47
48 } // end method yellowToolStripMenuItem_Click 49
50 // exit app
51 private void exitToolStripMenuItem_Click(
52 object sender, EventArgs e )
53 {
54 Application.Exit();
55 } // end method exitToolStripMenuItem_Click 56
57 // set Cascade layout
58 private void cascadeToolStripMenuItem_Click(
59 object sender, EventArgs e )
60 {
61
62 } // end method cascadeToolStripMenuItem_Click 63
64 // set TileHorizontal layout
65 private void tileHorizontalToolStripMenuItem_Click(
66 object sender, EventArgs e )
67 {
68
69 } // end method tileHorizontalToolStripMenuItem 70
71 // set TileVertical layout
72 private void tileVerticalToolStripMenuItem_Click(
73 object sender, EventArgs e )
74 {
75
76 } // end method tileVerticalToolStripMenuItem_Click 77 } // end class UsingMDIForm
78 } // end namespace UsingMDI
Fig. 15.43 | MDI parent-window class. (Part 2 of 3.)
Child child = new ChildForm(
"Yellow Flowers", "yellowflowers" );
child.MdiParent = this; // set parent child.Show(); // display child
this.LayoutMdi( MdiLayout.Cascade );
this.LayoutMdi( MdiLayout.TileHorizontal );
this.LayoutMdi( MdiLayout.TileVertical );
a) Selecting theLavender Flowersmenu item b)Lavender FlowersChildFormwindow displayed
In the Properties window, we set the Form’s IsMdiContainer property to true, making theForman MDI parent. In addition, we set theMenuStrip’sMdiWindowListItem
property towindowToolStripMenuItem. This enables theWindowmenu 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 methodLayoutMdiwith the argumentCascade from theMdiLayoutenumeration (line 61).
TheTile Horizontalmenu 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 LayoutMdiwith the argumentTileHorizontalfrom theMdiLayoutenumeration (line 68).
Finally, theTile Verticalmenu item (tileVerticalToolStripMenuItem) has an event handler (tileVerticalToolStripMenuItem_Click, lines 72–76) that arranges the child windows in a vertical manner. The event handler calls methodLayoutMdiwith the argu- mentTileVerticalfrom theMdiLayoutenumeration (line 75).
MDI ChildForm
At this point, the app is still incomplete—we must define the MDI child class. To do this, right click the project in theSolution Explorerand select Add > Windows Form…. Then name the new class in the dialog asChildForm(Fig. 15.44). Next, we add aPictureBox (displayPictureBox) toChildForm. InChildForm’s constructor, line 16 sets the title-bar text. Lines 19–21 retrieve the appropriate image resource, cast it to anImageand set dis-
playPictureBox’sImageproperty. The images that are used can be found in theImages
subfolder of this chapter’s examples directory.
After the MDI child class is defined, the parent MDIForm(Fig. 15.43) can create new child windows. The event handlers in lines 18–48 create a new childFormcorresponding to the menu item clicked. Lines 22–23, 33–34 and 44–45 create new instances ofChild-
Form. Lines 24, 35 and 46 set eachChild’sMdiParentproperty to the parentForm. Lines 25, 36 and 47 call methodShowto display each childForm.
Fig. 15.43 | MDI parent-window class. (Part 3 of 3.)
c) Selecting theCascademenu item d) Cascaded child windows in an MDI window