Multiple Document Interface (MDI) Windows
In previous chapters, we have built only single document interface (SDI) applications. Such programs (including Microsoft's Notepad and Paint) can support only one open window or document at a time. SDI applications usually have limited abilitiesPaint and Notepad, for example, have limited image- and text-editing features. To edit multiple documents, the user must execute another instance of the SDI application.
Most recent applications 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 complexPaintShop Pro and Photoshop have a greater number of image-editing features than does Paint.
The main application window of an MDI program is called the parent window, and each window inside the application is referred to as a child window. Although an MDI application 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, etc.). A child window's functionality can be different from the functionality 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 14.37 depicts a sample MDI application.
Figure 14.37. MDI parent window and MDI child windows.
(This item is displayed on page 696 in the print version)
To create an MDI Form, create a new Form and set its IsMdiContainer property to TRue. The Form changes appearance, as in Fig. 14.38.
Figure 14.38. SDI and MDI forms.
(This item is displayed on page 696 in the print version)
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 Nothing if there are no active child windows. Other features of MDI windows are described in Fig. 14.39.
MDI Form 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 is 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 14.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 each other and the parent window. Figure 14.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. 14.40(b) is Form1 - [Child2]. 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).
Figure 14.40. Minimized and maximized child windows.
(This item is displayed on page 698 in the print version)
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. When a new child window is opened, an entry is added to the list (as in the first screen of Figure 14.41). If nine 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.
Figure 14.41. MenuItem property MdiList example.
(This item is displayed on page 698 in the print version)
MDI containers allow you to organize the placement ofs child windows. The child windows in an MDI application can be arranged by calling method LayoutMdi of the parent Form. Method LayoutMdi takes a 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) overlapeach 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 14.42 illustrates the values of the MdiLayout enumeration.
Figure 14.42. MdiLayout enumeration values.
(a) ArrangeIcons
(b) Cascade
(c) TileHorizontal
(d) TileVertical
Class UsingMDIForm (Fig. 14.43) demonstrates MDI windows. Class UsingMDIForm uses three instances of child Form ChildForm (Fig. 14.44), each containing a PictureBox that displays an image. The parent MDI Form contains a menu enabling users to create and arrange child Forms.
Figure 14.43. MDI parent-window class.
1 // Fig. 14.43: UsingMDIForm.cs 2 // Demonstrating use of MDI parent and child windows. 3 using System; 4 using System.Windows.Forms; 5 6 // Form demonstrates the use of MDI parent and child windows 7 public partial class UsingMDIForm : Form 8 { 9 // default constructor 10 public UsingMDIForm() 11 { 12 InitializeComponent(); 13 } // end constructor 14 15 // create Child 1 window when child1ToolStrip MenuItem is clicked 16 private void child1ToolStripMenuItem_Click( 17 object sender, EventArgs e ) 18 { 19 // create new child 20 ChildForm formChild = 21 new ChildForm( "Child 1", @"imagescsharphtp1.jpg" ); 22 formChild.MdiParent = this; // set parent 23 formChild.Show(); // display child 24 } // end method child1ToolStripMenuItem_Click 25 26 // create Child 2 window when child2ToolStripMenuItem is clicked 27 private void child2ToolStripMenuItem_Click( 28 object sender, EventArgs e ) 29 { 30 // create new child 31 ChildForm formChild = 32 new ChildForm( "Child 2", @"imagesvbnethtp2.jpg" ); 33 formChild.MdiParent = this; // set parent 34 formChild.Show(); // display child 35 } // end method child2ToolStripMenuItem_Click 36 37 // create Child 3 window when child3ToolStripMenuItem is clicked 38 private void child3ToolStripMenuItem_Click( 39 object sender, EventArgs e ) 40 { 41 // create new child 42 Child formChild = 43 new Child( "Child 3", @"imagespythonhtp1.jpg" ); 44 formChild.MdiParent = this; // set parent 45 formChild.Show(); // display child 46 } // end method child3ToolStripMenuItem_Click 47 48 // exit application 49 private void exitToolStripMenuItem_Click( object sender, EventArgs e ) 50 { 51 Application.Exit(); 52 } // end method exitToolStripMenuItem_Click 53 54 // set Cascade layout 55 private void cascadeToolStripMenuItem_Click( 56 object sender, EventArgs e ) 57 { 58 this.LayoutMdi( MdiLayout.Cascade ); 59 } // end method cascadeToolStripMenuItem_Click 60 61 // set TileHorizontal layout 62 private void tileHorizontalToolStripMenuItem_Click( 63 object sender, EventArgs e ) 64 { 65 this.LayoutMdi( MdiLayout.TileHorizontal ); 66 } // end method tileHorizontalToolStripMenuItem 67 68 // set TileVertical layout 69 private void tileVerticalToolStripMenuItem_Click( 70 object sender, EventArgs e ) 71 { 72 this.LayoutMdi( MdiLayout.TileVertical ); 73 } // end method tileVerticalToolStripMenuItem_Click 74 } // end class UsingMDIForm (a) (b) (c) (d) |
Figure 14.44. MDI child ChildForm.
(This item is displayed on pages 702 - 703 in the print version)
1 // Fig. 14.44: ChildForm.cs 2 // Child window of MDI parent. 3 using System; 4 using System.Drawing; 5 using System.Windows.Forms; 6 using System.IO; 7 8 public partial class ChildForm : Form 9 { 10 public ChildForm( string title, string fileName ) 11 { 12 // Required for Windows Form Designer support 13 InitializeComponent(); 14 15 Text = title; // set title text 16 17 // set image to display in pictureBox 18 picDisplay.Image = Image.FromFile( 19 Directory.GetCurrentDirectory() + fileName ); 20 } // end constructor 21 } // end class ChildForm |
The program in Fig. 14.43 is the application. The MDI parent 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 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 5559) that arranges the child windows in a cascading manner. The event handler calls method LayoutMdi with the argument Cascade from the MdiLayout enumeration (line 58).
The Tile Horizontal menu item (tileHorizontalToolStripMenuItem) has an event handler (tileHorizontalToolStripMenuItem_Click, lines 6266) that arranges the child windows in a horizontal manner. The event handler calls method LayoutMdi with the argument TileHorizontal from the MdiLayout enumeration (line 65).
Finally, the Tile Vertical menu item (tileVerticalToolStripMenuItem) has an event handler (tileVerticalToolStripMenuItem_Click, lines 6973) that arranges the child windows in a vertical manner. The event handler calls method LayoutMdi with the argument TileVertical from the MdiLayout enumeration (line 72).
At this point, the application is still incompletewe 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. 14.44). Next, we add a PictureBox (picDisplay) to ChildForm. In the constructor, line 15 sets the title bar text. Lines 1819 set ChildForm's Image property to an Image, using method FromFile.
After the MDI child class is defined, the parent MDI Form (Fig. 14.43) can create new child windows. The event handlers in lines 1646 create a new child Form corresponding to the menu item clicked. Lines 2021, 3132 and 4243 create new instances of ChildForm. Lines 22, 33 and 44 set each Child's MdiParent property to the parent Form. Lines 23, 34 and 45 call method Show to display each child Form.