15.12 Multiple Document Interface (MDI) Windows

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.

Fig. 15.37 MDI parent window and MDI 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();

Fig. 15.38 SDI and MDI forms.

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.

Fig. 15.39 MDI parent and MDI child properties, a method and an event.

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.

Fig. 15.40 Minimized and maximized child windows.

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.

Good Programming Practice 15.1

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.

Fig. 15.41 MenuStrip property MdiWindowListItem example.

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 Forms.

Fig. 15.42 MdiLayout enumeration values.

MDI Parent 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.

Fig. 15.43 Demonstrating use of MDI parent and child windows.

Alternate View

  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          }
 16
 17          // create Lavender Flowers image window
 18          private void lavenderToolStripMenuItem_Click(
 19             object sender, EventArgs e)
 20          {
 21             // create new child
 22             var child = new ChildForm(
 23                 "Lavender Flowers", "lavenderflowers");
 24             child.MdiParent = this; // set parent
 25             child.Show(); // display child
 26          }
 27
 28          // create Purple Flowers image window
 29          private void purpleToolStripMenuItem_Click(
 30             object sender, EventArgs e)
 31          {
 32             // create new child
 33             var child = new ChildForm(
 34                 "Purple Flowers", "purpleflowers");
 35             child.MdiParent = this; // set parent
 36             child.Show(); // display child
 37          }
 38
 39          // create Yellow Flowers image window
 40          private void yellowToolStripMenuItem_Click(
 41             object sender, EventArgs e)
 42          {
 43             // create new child
 44             var child = new ChildForm(
 45                 "Yellow Flowers", "yellowflowers");
 46             child.MdiParent = this; // set parent
 47             child.Show(); // display child
 48          }
 49
 50          // exit app
 51          private void exitToolStripMenuItem_Click(
 52             object sender, EventArgs e)
 53          {
 54             Application.Exit();
 55          }
 56
 57          // set Cascade layout
 58          private void cascadeToolStripMenuItem_Click(
 59             object sender, EventArgs e)
 60          {
 61             this.LayoutMdi(MdiLayout.Cascade);
 62          }
 63
 64          // set TileHorizontal layout
 65          private void tileHorizontalToolStripMenuItem_Click(
 66             object sender, EventArgs e)
 67          {
 68             this.LayoutMdi(MdiLayout.TileHorizontal);
 69          }
 70
 71          // set TileVertical layout
 72          private void tileVerticalToolStripMenuItem_Click(
 73             object sender, EventArgs e)
 74          {
 75             this.LayoutMdi(MdiLayout.TileVertical);
 76          }
 77       }
 78   }

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).

MDI Child 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.

Fig. 15.44 Child window of MDI parent.

Alternate View

  1    // Fig. 15.44: ChildForm.cs
  2    // Child window of MDI parent.
  3
  4    using System.Drawing;
  5    using System.Windows.Forms;
  6
  7    namespace UsingMDI
  8    {
  9       public partial class ChildForm : Form
 10       {
 11          public ChildForm(string title, string resourceName)
 12          {
 13             // Required for Windows Form Designer support
 14             InitializeComponent();
 15
 16             Text = title; // set title text
 17
 18             // set image to display in PictureBox
 19             displayPictureBox.Image =
 20               (Image) (Properties.Resources.ResourceManager.GetObject(
 21                  resourceName));
 22           }
 23        }
 24    }

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset