Visual Basic 2005 Guide
Making The MDI

What Is An MDI?

MDI stands for Multiple Document Interface. Notepad is an example of an SDI (Single), you can only edit one document at a time in each application window. If you want to have two documents open at the same time, you would need to create a new instance of the application - taking up more memory etc.

This examples is based on making an HTML editor. If you have never done any HTML, don't worry - if you are doing this project you are more than capable of picking up the basics in a few hours. You will most probably understand enough by the end of this project to be able to make simple web pages. If it concerns you, spend a few hours with the HTML section of this site or learn from a decent book.

Step 1 - Making The Container

Visual Basic has a built-in template for MDI containers. Create a new project called HTML Editor or something more snappy if you are feeling precious.

Step 2 - Creating The Parent Form

Go to the Project menu and choose to add a Windows Form. Name the form, frmMain as in the screenshot below.

parent form

When you do this, VB generates a form with the toolbars and menus that you would expect with an MDI. We will have to do quite a bit of tidying to make this work for us.

Step 3 - Creating The Child Form

A form was automatically created when you created the project. Go to that form and rename it to frmChild. Add a RichTextBox control to this form and set its Dock property to Fill.

Step 3 - Getting The Parent To Use The Child Form

Go to the Code Window of the Parent form. Locate the subroutine called ShowNewForm(). We will need to change the following line,

Dim ChildForm As New System.Windows.Forms.Form

The line needs to read,

Dim ChildForm As New frmChild

Also, change the code so that the word Document is used for the title bar of the new forms.

Now to make sure that the parent form loads first. Double click on the Project name in the solution explorer, this should bring up a window of settings. Choose to make the StartUp object the MDI parent form, frmMain.

Run the program and check that clicking on File, New or the toolbar button now creates a new form with a big text box.

Step 4 - Opening & Saving Files

Now that we have a child form that can be used to write a text file, we need to make sure that we can save work and reopen previously saved files. In the code window, you should see that some of the automatically generated subroutines contain comments. Look for the subroutine named OpenFile and locate the line which reads,

' TODO: Add code here to open the file.

Add the following lines of code immediately after the comment,

ShowNewForm(sender, e)
Dim theBox As New RichTextBox
theBox = ActiveMdiChild.Controls(0)
ActiveMdiChild.Text = OpenFileDialog.FileName
theBox.LoadFile(ActiveMdiChild.Text, RichTextBoxStreamType.PlainText)

Study this code carefully. One important aspect is how we obtain a reference to the text box on the active form.

No go to the SaveAsToolStripMenuItem_Click subroutine. Add the following line as the first line in the subroutine - if the user hasn't got a form loaded, then we have nothing to save.

If ActiveMdiChild Is Nothing Then Exit Sub

Just below the comment, we need the following code to save a file,

Dim sFile As String
Dim theBox As New RichTextBox
theBox = ActiveMdiChild.Controls(0)
If SaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
   sFile = SaveFileDialog.FileName
   theBox.SaveFile(sFile, RichTextBoxStreamType.PlainText)
   ActiveMdiChild.Text = sFile
Else
   Exit Sub
End If

Run the project and test that you can create a text file, save, close and reopen the file using your program.

Our final basic feature is the ability to save a previously saved file. The user does this by clicking either the menu item or the toolbar item. We want to create one event handler to do this. Double click on the toolbar save button, it should bring up a subroutine called, SaveToolStripButton_Click. Change the end of the line so that it reads, Handles SaveToolStripButton.Click, SaveToolStripMenuItem.Click. Then add the following code,

If ActiveMdiChild Is Nothing Then Exit Sub
Dim sFile As String, uFile As String
uFile = ActiveMdiChild.Text
Dim theBox As New RichTextBox
theBox = ActiveMdiChild.Controls(0)
If Microsoft.VisualBasic.Left(uFile, 8) = "Document" Then
   Dim SaveFileDialog As New SaveFileDialog
   SaveFileDialog.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
   SaveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
   If SaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
      sFile = SaveFileDialog.FileName
      theBox.SaveFile(sFile, RichTextBoxStreamType.PlainText)
      ActiveMdiChild.Text = sFile
   Else
      Exit Sub
   End If
Else
   sFile = uFile
   theBox.SaveFile(sFile, RichTextBoxStreamType.PlainText)
End If

Save and test your application again.

Adding More Of The Basic Features

There are many more basic application features that you should try to add at this stage. Use the MSDN to find out how to sort out the following issues,

  • Dialog Box Filters - make it so that the dialog box defaults to opening and saving web page files (.htm and any other file types you expect to create).
  • Tidy Menus - there are some menu items that don't really need programming. There may be a need to print code, print preview and set up are not likely to be needed for this application - these items can be deleted from the main menu and toolbars. You could also delete the Tools and Help menu items. You can put recreate them later if you find the need.
  • Edit Functions - there are some simple features on the edit menu that need programming. The comments include a few tips and, using the MSDN, you should be able to work out how to do this.

Anything that you choose not to develop should be removed from the menus or toolbar.

One More Issue

It is normal for applications to prompt users before discarding changes that they have made to a file. This means asking if they want to save a file before they close down either the file or the application. To make it easier on them, it makes sense not to do this for a file that has no changes.

To work out whether or not a file has been altered, add the following code to the declarations section of the child form.

Private changeTxt As Boolean
Public Property isChanged() As Boolean
   Get
      Return changeTxt
   End Get
   Set(ByVal Value As Boolean)
      changeTxt = Value
   End Set
End Property

The Property structure may come in useful later in this project or in other projects that you undertake. It is worth spending a few minutes reading the explanations in the MSDN.

In the form's load event, write the following line of code,

Me.isChanged = False

In the TextChanged event of the richtextbox, write the following line of code,

Me.isChanged = True

The following code should now be placed in the frmChild_FormClosing event handler,

If Me.isChanged = True Then
   Select Case MsgBox("Wanna save " + Me.Text + "?", vbYesNoCancel, "Emergency Exit Procedure")
      Case 6
         Dim sFile As String
         If Microsoft.VisualBasic.Left(Me.Text, 8) = "Document" Then
            Dim SaveFileDialog As New SaveFileDialog
            SaveFileDialog.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
            SaveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
            If SaveFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
               sFile = SaveFileDialog.FileName
               RichTextBox1.SaveFile(sFile, RichTextBoxStreamType.PlainText)
               ActiveMdiChild.Text = sFile
            Else
               Exit Sub
            End If
         Else
            sFile = Me.Text
            RichTextBox1.SaveFile(sFile, RichTextBoxStreamType.PlainText)
         End If
      Case 2
         e.Cancel = True
      Case 7
         'form unloads
   End Select
End If