SDI and MDI


A single-document interface (SDI) application displays a single document in each form. Here, a document can be an actual disk file, or it can be a group of related items such as those on an order, employee record, or architectural drawing. For example, Microsoft Paint and Notepad are both SDI applications. Figure 10-7 shows an SDI application showing three files in separate forms.

image from book
Figure 10-7: An SDI application displays separate documents in separate forms.

In contrast, a multiple-document interface (MDI) application displays its documents in their own forms, but then places the forms inside a container form. For example, Visual Studio can act either as an MDI application or it can display its child forms (form designers, code editors, and so forth) using tabs. The individual document windows are called MDI child forms and the container form is called the MDI container or MDI parent form. Figure 10-8 shows an MDI application with three MDI child forms.

image from book
Figure 10-8: An MDI application displays documents in forms contained within an MDI container form.

The following sections describe some of the features provided by MDI forms and discuss reasons you might want to use an MDI or SDI application style.

MDI Features

The MDI container form provides several services for its child forms. It contains the forms and keeps them all together so that they are easy to find. If you move a form so that it won’t fit within the container, the container automatically displays scroll bars so you can view it.

The program displays an icon in the taskbar and Task Manager for the MDI container, but not for the child forms. If you minimize the MDI container, all of the forms it contains are hidden with it. If you minimize a child form, its icon is displayed within the container, not separately in the taskbar. If you maximize an MDI child, it fills the parent form and its caption becomes part of the parent’s. For example, if the MDI parent form’s caption is Parent and the child’s caption is Child, then when you maximize the child, the parent’s caption becomes Parent - [Child].

The MDI container also provides some methods for arranging its child forms. The following code shows how an MDI container’s code can cascade the children so that they overlap nicely, tile the children vertically or horizontally, and arrange the icons of any minimized child forms.

  Private Sub CascadeToolStripMenuItem_Click(ByVal sender As Object, _  ByVal e As EventArgs) Handles CascadeToolStripMenuItem.Click     Me.LayoutMdi(MdiLayout.Cascade) End Sub Private Sub TileVerticleToolStripMenuItem_Click(ByVal sender As Object, _  ByVal e As EventArgs) Handles TileVerticalToolStripMenuItem.Click     Me.LayoutMdi(MdiLayout.TileVertical) End Sub Private Sub TileHorizontalToolStripMenuItem_Click(ByVal sender As Object, _  ByVal e As EventArgs) Handles TileHorizontalToolStripMenuItem.Click     Me.LayoutMdi(MdiLayout.TileHorizontal) End Sub Private Sub ArrangeIconsToolStripMenuItem_Click(ByVal sender As Object, _  ByVal e As EventArgs) Handles ArrangeIconsToolStripMenuItem.Click     Me.LayoutMdi(MdiLayout.ArrangeIcons) End Sub  

Some other useful commands that you can add to an MDI application include Minimize All, Restore All, Maximize All, and Close All. You can implement these commands by looping through the MDI container’s MdiChildren collection, as shown in the following code:

  Private Sub MinimizeAllToolStripMenuItem_Click(ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles MinimizeAllToolStripMenuItem.Click     For Each frm As Form In Me.MdiChildren         frm.WindowState = FormWindowState.Minimized     Next frm End Sub Private Sub RestoreAllToolStripMenuItem_Click(ByVal sender As System.Object, _  ByVal e As System.EventArgs) Handles RestoreAllToolStripMenuItem.Click      For Each frm As Form In Me.MdiChildren          frm.WindowState = FormWindowState.Normal      Next frm  End Sub    Private Sub MaximizeAllToolStripMenuItem_Click(ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles MaximizeAllToolStripMenuItem.Click      For Each frm As Form In Me.MdiChildren          frm.WindowState = FormWindowState.Maximized      Next frm  End Sub    Private Sub CloseAllToolStripMenuItem_Click(ByVal sender As Object, _   ByVal e As EventArgs) Handles CloseAllToolStripMenuItem.Click      For Each frm As Form In Me.MdiChildren          frm.Close()      Next  End Sub  

Depending on your application, you might also provide commands that operate on subsets of the child forms. Suppose that a program displays a main order record and its many related order items in MDI child forms. You might want to let the user close all the order items, while keeping the main order form open.

Many MDI programs include a Window menu that displays a list of the MDI child forms that are open. You can select one of these menu items to move that form to the top of the others.

Building an MDI child list is easy in Visual Basic. Select the main MenuStrip control. Then in the Properties window, set the control’s MdiWindowListItem property to the menu that you want to hold the child list. When you open and close child windows, Visual Basic automatically updates the list.

Figure 10-9 shows a menu displaying an MDI child list. The form with the caption MDIEdit.sln (behind the menu) currently has the focus, so the list displays a check mark next to that form’s entry.

image from book
Figure 10-9: The MenuStrip’s MdiWindowListItem property determines which menu item displays an MDI child list.

Most regular Visual Basic applications use SDI and when you create a new application, you get SDI by default. To build an MDI application, start a new application as usual. Then set the startup form’s IsMdiContainer property to True. In the Form Designer, this form will change appearance, so it’s obvious that it is an MDI parent form.

Alternatively you can select the Project menu’s Add Windows Form command. In the new form dialog, select MDI Parent Form, give the form a reasonable name, and click Add. Visual Basic adds a new MDI parent form and gives it an assortment of standard controls that you might like it to have including a menu strip containing standard menus (File, Edit, View, and so forth) and a toolbar with standard tools (new, open, save, and so forth).

At design time, an MDI child form looks just like any other form. To make the child form sit inside the MDI container, you must set its MdiParent property to the MDI container form at runtime.

The following code shows how the MDI parent form in Figure 10-8 creates new MDI children. When the user selects the File menu’s Open command or the toolbar’s Open tool, this event handler executes and displays a file open dialog. If the user selects a file and clicks OK, the code creates a new Form1 object. It loads the selected file into the form’s txtContents TextBox, sets the form’s caption to the file’s name (without the path), sets the form’s MdiParent property to Me (the MDI parent form), and displays the form. The form is automatically shown in the MDI container and added to the MDI child list.

  Private Sub OpenFile(ByVal sender As Object, ByVal e As EventArgs) Handles _  OpenToolStripMenuItem.Click, OpenToolStripButton.Click     Dim dlgOpen As New OpenFileDialog     If dlgOpen.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then         Dim frm As New Form1         frm.txtContents.Text = File.ReadAllText(dlgOpen.FileName)         frm.txtContents.Select(0, 0)         frm.Text = New FileInfo(dlgOpen.FileName).Name         frm.MdiParent = Me         frm.Show()     End If End Sub  

Normally, the system menu in the left of a form’s title area includes a Close command with the shortcut Alt-F4. This command closes the form. An MDI child’s system menu also contains a Close command, but this one’s shortcut is Ctrl+F4. If you select this command or invoke its shortcut, the application closes the MDI child form but not the MDI container.

The MDI child’s system menu also includes a Next command that moves the focus to the MDI container’s next MDI child. The menu shows this command’s shortcut as Ctrl+F6. However, Ctrl+Tab works as well. Ctrl+Tab may be a bit easier to remember because it is more similar to the Alt+Tab shortcut that moves to the next application on the desktop. This is also more consistent with the shortcuts for closing forms: Alt-F4 closes a top-level form, whereas Ctrl+F4 closes an MDI child; Alt+Tab moves to the next desktop application, whereas Ctrl+Tab moves to the next MDI child form.

MDI Events

Events for an MDI child form generally occur before the corresponding MDI parent’s events. For example, if you try to close an MDI form, the child forms all receive FormClosing events before the MDI parent receives its FormClosing event. Next, the MDI child forms receive FormClosed events, and finally the MDI parent receives its FormClosed event.

Note that MDI child forms also receive these events if only the child form is closing. If the user closes an MDI child form, it receives a FormClosing event followed by its FormClosed event.

If a form’s FormClosing event handler sets its e.Cancel parameter to True, the close is canceled and the form remains open. The form can use this to guarantee that its data is consistent and has been saved.

For example, the following code checks the m_IsDirty variable to see if the form’s data has been modified since it was loaded. If m_IsDirty is True, the program displays a message box to the user asking if it should save the changes.

When the user clicks the Yes button, the code calls subroutine SaveFile to save the changes. This routine saves the data and sets m_IsDirty to False if it is successful. If SaveFile fails (for example, if the data file is locked), it leaves m_IsDirty set to True. When the user clicks No to indicate that the program should discard the changes, the FormClosing event handler leaves e.Cancel equal to False so the form closes normally. If the user clicks the Cancel button to indicate that the form should not be closed after all, the event handler sets e.Cancel to True to keep the form open.

  ' See if it's safe to close the form. Private Sub mdiChild_FormClosing(ByVal sender As Object, _  ByVal e As System.Windows.Forms.FormClosingEventArgs) _  Handles Me.FormClosing     If m_IsDirty Then         ' There are unsaved changes.         ' Ask the user if we should save them.         Select Case MessageBox.Show( _                "The data has changed. Save the changes?", _                "Save Changes?", _                MessageBoxButtons.YesNoCancel, _                MessageBoxIcon.Question)             Case Windows.Forms.DialogResult.Yes                ' Save the changes.                SaveFile()                ' See if we succeeded.                e.Cancel = m_IsDirty             Case Windows.Forms.DialogResult.No                ' Discard the changes.                ' Leave e.Cancel = False.             Case Windows.Forms.DialogResult.Cancel                ' Cancel the close.                e.Cancel = True         End Select     End If End Sub  

If the user tries to close the MDI container and any of the MDI child forms’ FormClosing event handlers sets e.Cancel to True, the close is canceled for all the child forms. Any child forms that have not yet received a FormClosing event do not get one. All of the children remain open, even those that set e.Cancel = False.

After the children process their FormClosing events, the MDI parent form still gets the final word. It receives a FormClosing event with its e.Cancel value set to True if any of the child forms set it to True. The value e.Cancel value is False if all of the child forms left it False.

The MDI parent can leave the e.Cancel alone to accept whatever value the child forms selected, or it can override the value and force the program to exit or not as it desires.

The child forms still have one chance to save their data in their FormClosed events. At this point, they will close, however, so they had better take action if they need to save their data.

MDI Versus SDI

MDI and SDI applications both have their advantages. In an SDI application, building and understanding the menus is simpler. A menu applies to exactly one form, and there is no merging and swapping of menus as the user changes MDI child forms.

SDI applications work particularly well when the program works with only one document at a time. Notepad, Microsoft Paint, and similar applications that only let the user work with one file at a time are SDI applications. These programs are light enough in weight that the user can easily run more than one instance of the program to view more than one file at a time if necessary.

MDI applications help the user display many related files at once without cluttering up the desktop. For example, Visual Studio can use an MDI interface to let you examine all of the files in a project side by side. Displaying all of a project’s form designers, code editors, resource editors, and other files in separate windows might bury the desktop under forms and fill the taskbar with icons. Putting all of these forms inside an MDI container makes using the application easier. It lets the system represent the Visual Studio program with a single container form and a single icon. The Windows menu provides an MDI child list that makes it easier to find a particular form.

You can also build a hybrid application that displays several MDI containers, each holding any number of MDI child forms. For example, each MDI container might hold all the forms related to a particular order: customer data, order items, and so forth. This would keep these related items together. It would also enable the user to display information about more than one order at a time in separate MDI containers.

In practice, examples of this kind of hybrid application are often cumbersome and poorly designed. It would generally be simpler to build this application as a standard MDI application and let the user launch multiple instances to display more than one order’s data at once, but there may be times when it is easier to build a single multiple-MDI application. For example, if the program must work with a password-protected database, the program would need only to prompt the user for a username and password once, and all the MDI containers could share the same database connection. Often, you can avoid the need for multiple forms (and hence an MDI format) by using other controls to fit more information on a single form. For example, ComboBox, ListBox, TreeView, SplitterContainer, and many other controls can display large amounts of data in a limited space, providing scroll bars as necessary.

The TabControl lets an application display many pages of data on a single form. For example, you might use different tabs to display the different pages that are relevant to an order: customer data, the order itself, order items, shipping and billing addresses, and so forth. This type of tabbed form placed inside an MDI container can make a very powerful application that enables the user to easily manage and understand huge amounts of information.

One drawback to many of these controls is that they make it more difficult to perform side-by-side comparisons of values. For example, suppose that a single form displays different addresses (billing, shipping, contact, and so forth) on different tabs. Then it would be difficult for the user to compare two addresses to see if they are identical. If you know that the user may want to compare two pieces of data, try to arrange them so they can both be visible at the same time.




Visual Basic 2005 with  .NET 3.0 Programmer's Reference
Visual Basic 2005 with .NET 3.0 Programmer's Reference
ISBN: 470137053
EAN: N/A
Year: 2007
Pages: 417

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net