When you think about it, the SDI as I have shown it here is actually a misnomer. It does, after all, show multiple documents. It just does not show them in a cohesive manner like the MDI interface does.
So what is an MDI program, anyway? An MDI application has a form that acts as a container for any child forms that belong to it. Word 97 is a true MDI application. Excel is also a true MDI application. Figure 3-5 shows you the SDI project you just completed reformulated as an MDI application.
It is actually quite easy to convert the SDI application to an MDI application, and I show you how to do so in this section. Once you have finished with the code, you will see that the .NET Framework supports many nice features of MDI applications that you would normally have to program yourself in an SDI environment.
Start a new C# or VB project. Mine is called "MDIapp." While you have this new project open, start up the SDI project you just finished in a different window. You will need to complete the following steps to generate this project:
Size the existing form to be 800×600. Name it UberForm and change its text to read HR Program.
Make the form start up in the center of the screen.
Change the IsMdiContainer property to true.
Copy and paste the MainMenu control from the SDI project to the form on this project. (I love how copy and paste works between .NET projects.)
Delete the separator bar from the Window menu choices in the main menu (under the Close All choice).
In the Property window for the Window choice, change the MdiList property to true.
Add Tile Horizontally to the Window menu and name it mnuHoriz.
Add Tile Vertically to the Window menu and name it mnuVert.
Add Cascade to the Window menu and name it mnuCascade.
Copy and paste the status bar from the SDI project to the main form on this project.
Create a new form called Employee.
Copy and paste the controls from the Employee form in the SDI application to this Employee form.
Create a new form called Payroll.
Create a new form called Training.
Create a new form called Scheduling.
Add a label on the Payroll form called lblCash. Put a dollar sign ($) in for the Text property. Center the text and set the font at 100 points.
This is it for the visible part of the MDI application. You can now close the SDI project. Listings 3-2a and 3-2b show the code for the MDI application's main form.
![]() |
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace MDIapp_c { /// <summary> /// Summary description for Form1. /// </summary> public class UberForm : System.Windows.Forms.Form { private System.Windows.Forms.MainMenu mainMenu1; private System.Windows.Forms.MenuItem mnuFile; private System.Windows.Forms.MenuItem mnuClose; private System.Windows.Forms.MenuItem mnuEdit; private System.Windows.Forms.MenuItem mnuEmp; private System.Windows.Forms.MenuItem mnuTrain; private System.Windows.Forms.MenuItem mnuPayroll; private System.Windows.Forms.MenuItem mnuSked; private System.Windows.Forms.MenuItem mnuWindow; private System.Windows.Forms.MenuItem mnuHelp; private System.Windows.Forms.StatusBar statusBar1; private System.Windows.Forms.StatusBarPanel statusBarPanel1; private System.Windows.Forms.StatusBarPanel statusBarPanel2; private System.Windows.Forms.StatusBarPanel statusBarPanel3; private System.ComponentModel.Container components = null; private System.Windows.Forms.MenuItem mnuHoriz; private System.Windows.Forms.MenuItem mnuVert; private System.Windows.Forms.MenuItem mnuCascade; private System.Windows.Forms.MenuItem mnuCloseAll; #region Class Local Variables Payroll PayForm; Employee EmpForm; Scheduling SkedForm; Training TrainForm; #endregion public UberForm() { InitializeComponent(); this.Menu = mainMenu1; mnuClose.Click += new EventHandler(this.CloseMe); mnuEmp.Click += new EventHandler(this.OpenWindow); mnuSked.Click += new EventHandler(this.OpenWindow); mnuPayroll.Click += new EventHandler(this.OpenWindow); mnuTrain.Click += new EventHandler(this.OpenWindow); mnuCloseAll.Click += new EventHandler(this.CloseAllWindows); mnuHoriz.Click += new EventHandler(this.ArrangeWindow); mnuVert.Click += new EventHandler(this.ArrangeWindow); mnuCascade.Click += new EventHandler(this.ArrangeWindow); } protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code ... ... ... #endregion [STAThread] static void Main() { Application.Run(new UberForm()); } private void UberForm_Load(object sender, System.EventArgs e) { } #region events private void CloseMe(object sender, EventArgs e) { this.Close(); } private void OpenWindow(object sender, EventArgs e) { MenuItem m; if(sender is MenuItem) m = (MenuItem)sender; else return; if(m == mnuEmp) { if(EmpForm == null) { EmpForm = new Employee(); EmpForm.MdiParent = this; EmpForm.Disposed += new EventHandler(this.ByByWindow); EmpForm.Show(); } else EmpForm.Focus(); } if(m == mnuTrain) { if(TrainForm == null) { TrainForm = new Training(); TrainForm.MdiParent = this; TrainForm.Disposed += new EventHandler(this.ByByWindow); TrainForm.Show(); } else TrainForm.Focus(); } if(m == mnuPayroll) { if(PayForm == null) { PayForm = new Payroll(); PayForm.MdiParent = this; PayForm.Disposed += new EventHandler(this.ByByWindow); PayForm.Show(); } else PayForm.Focus(); } if(m == mnuSked) { if(SkedForm == null) { SkedForm = new Scheduling(); SkedForm.MdiParent = this; SkedForm.Disposed += new EventHandler(this.ByByWindow); SkedForm.Show(); } else SkedForm.Focus(); } } private void CloseAllWindows(object sender, EventArgs e) { if(EmpForm != null) EmpForm.Dispose(); if(PayForm != null) PayForm.Dispose(); if(TrainForm != null) TrainForm.Dispose(); if(SkedForm != null) SkedForm.Dispose(); } private void ByByWindow(object sender, EventArgs e) { if(sender == EmpForm) EmpForm = null; if(sender == PayForm) PayForm = null; if(sender == TrainForm) TrainForm = null; if(sender == SkedForm) SkedForm = null; } private void ArrangeWindow(object sender, EventArgs e) { MenuItem m; if(sender is MenuItem) m = (MenuItem)sender; else return; if(m == mnuHoriz) this.LayoutMdi(MdiLayout.TileHorizontal); if(m == mnuVert) this.LayoutMdi(MdiLayout.TileVertical); if(m == mnuCascade) this.LayoutMdi(MdiLayout.Cascade); } #endregion } }
![]() |
![]() |
Public Class UberForm Inherits System.Windows.Forms.Form #Region "Class Local Variables" Dim PayForm As Payroll Dim EmpForm As Employee Dim SkedForm As Scheduling Dim TrainForm As Training #End Region #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() Me.Menu = mainMenu1 AddHandler mnuClose.Click, New EventHandler(AddressOf Me.CloseMe) AddHandler mnuEmp.Click, New EventHandler(AddressOf Me.OpenWindow) AddHandler mnuSked.Click, New EventHandler(AddressOf Me.OpenWindow) AddHandler mnuPayroll.Click, New EventHandler(AddressOf Me.OpenWindow) AddHandler mnuTrain.Click, New EventHandler(AddressOf Me.OpenWindow) AddHandler mnuCloseAll.Click, New EventHandler(AddressOf Me.CloseAllWindows) AddHandler mnuHoriz.Click, New EventHandler(AddressOf Me.ArrangeWindow) AddHandler mnuVert.Click, New EventHandler(AddressOf Me.ArrangeWindow) AddHandler mnuCascade.Click, New EventHandler(AddressOf Me.ArrangeWindow) End Sub ... ... ... #End Region Private Sub UberForm_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load End Sub #Region "Events" Private Sub CloseMe(ByVal sender As Object, ByVal e As EventArgs) Me.Close() End Sub Private Sub OpenWindow(ByVal sender As Object, ByVal e As EventArgs) Dim m As MenuItem If sender.GetType() Is GetType(MenuItem) Then m = CType(sender, MenuItem) Else Return End If If m Is mnuEmp Then If EmpForm Is Nothing Then EmpForm = New Employee() AddHandler EmpForm.Disposed, AddressOf Me.ByByWindow EmpForm.MdiParent = Me EmpForm.Show() Else EmpForm.Focus() End If End If If m Is mnuTrain Then If TrainForm Is Nothing Then TrainForm = New Training() AddHandler TrainForm.Disposed, AddressOf Me.ByByWindow TrainForm.MdiParent = Me TrainForm.Show() Else TrainForm.Focus() End If End If If m Is mnuPayroll Then If PayForm Is Nothing Then PayForm = New Payroll() AddHandler PayForm.Disposed, AddressOf Me.ByByWindow PayForm.MdiParent = Me PayForm.Show() Else PayForm.Focus() End If End If If m Is mnuSked Then If SkedForm Is Nothing Then SkedForm = New Scheduling() AddHandler SkedForm.Disposed, AddressOf Me.ByByWindow SkedForm.MdiParent = Me SkedForm.Show() Else SkedForm.Focus() End If End If End Sub Private Sub ArrangeWindow(ByVal sender As Object, ByVal e As EventArgs) Dim m As MenuItem If sender.GetType() Is GetType(MenuItem) Then m = CType(sender, MenuItem) Else Return End If If m Is mnuHoriz Then Me.LayoutMdi(MdiLayout.TileHorizontal) End If If m Is mnuVert Then Me.LayoutMdi(MdiLayout.TileVertical) End If If m Is mnuCascade Then Me.LayoutMdi(MdiLayout.Cascade) End If End Sub Private Sub CloseAllWindows(ByVal sender As Object, ByVal e As EventArgs) If Not EmpForm Is Nothing Then EmpForm.Dispose() End If If Not PayForm Is Nothing Then PayForm.Dispose() End If If Not TrainForm Is Nothing Then TrainForm.Dispose() End If If Not SkedForm Is Nothing Then SkedForm.Dispose() End If End Sub Private Sub ByByWindow(ByVal sender As Object, ByVal e As EventArgs) If sender Is EmpForm Then EmpForm = Nothing End If If sender Is PayForm Then PayForm = Nothing End If If sender Is TrainForm Then TrainForm = Nothing End If If sender Is SkedForm Then SkedForm = Nothing End If End Sub #End Region End Class
![]() |
There is not anywhere near as much to this code. I do not have to keep track of the windows for listing purposes anymore. The .NET Framework does that by using just one property in the menu. I had to capture and dissect all kinds of events in the SDI project to accomplish the same thing.
Notice that when I instantiate each form, I make its MdiParent equal to the main form. This is all I need to do to make a form a child. Leave this line of code out and your child form will be an SDI. This is a great enhancement over VB 6.0, where you had to change the form's property at design time to go from being an MDI child to not. It makes it hard to reuse the same form in two projects both ways.
If you think about it, there is not much you have to do to add a menu option to make this project an SDI or an MDI on the fly. You can do all the rearranging in code. As a matter of fact, you can copy the SDI project's main form code over to this one and do just that if you like. Let me know how you get on, OK?