Sams Teach Yourself Visual Studio .NET 2003 in 21 Days

Sams Teach Yourself .Net in 21 Days

By Jason Beres

Using Menus and MDI Forms

One of the worst interfaces ever created was the Menu Editor in Visual Basic 6 and earlier. It was a top complaint of developers; Microsoft heard their screams and provided an amazing, easy-to-use Menu Editor in Windows Forms. In addition to the editor being great, because items added to a menu are derived from a Menu class, you can easily create menu items dynamically at runtime, which was almost possible in Visual Basic 6. To test the new Menu Editor's features, you're going to create a Multiple Document Interface (MDI) application. The flexibility of MDI applications in .NET has also improved dramatically, as you'll see when you're done with the following exercise.

To get started, add three new forms to the HelloNET application by right-clicking the HelloNET project name in the Solution Explorer and selecting Add, New Windows Form. Name the new forms as follows:

You'll notice that there is no MDI form template. This is now just a property on a form. After the three new forms are added, your Solution Explorer should look something like Figure 3.11.

03fig11.jpg

Figure 3.11 The HelloNET application after adding three new forms.

From the Solution Explorer, double-click the parentForm form so that it's in the Forms Designer. In the Properties window, change the IsMdiContainer property to True. You'll notice that the form now has a dark gray background color, which is the indication that it's a MDI parent form.

Next, drag a MainMenu control from the Toolbox to the form. The MainMenu control is a nonvisual control, which means it doesn't appear as part of the form. When nonvisual controls are added to a form, the screen splits and the controls are added to the bottom portion of the Forms Designer. This makes it very easy to see what nonvisual controls have been added to a form. At this point, your application should look something like Figure 3.12.

03fig12.jpg

Figure 3.12 The parentForm after adding a MainMenu control.

Adding menu items to the MainMenu is very intuitive: You simply type the name that you want the menu to display, and it shows up. Notice that you can go as many levels deep into a menu as you want—you just keep typing where the arrow is in the editor, and that's where the menu item appears. Use the up-, down-, right-, and left-arrow keys on your keyboard to navigate the menu levels. Figure 3.13 demonstrates the addition of items to a MainMenu.

03fig13.jpg

Figure 3.13 Adding items to a MainMenu.

Add the following five menu items to the MainMenu control:

While adding items to the menu, you can right-click on the menu itself to get the contextual menu with available options for the MainMenu control. One of the most useful items is the EditNames toggle. If you click EditNames, you can change the name of the menu item directly from the Menu Editor. You can also do this via the Properties window. From the Properties window, some of the individual properties that can be set are the Shortcut, RadioCheck, and Visible properties.

After you've added the new menu items, you'll add some code that brings up the child1 and child2 forms, gets a count of open forms, and exits the application.

To do this, add the code in Listing 3.5 to the click events for their corresponding controls.

Example 3.5. The Code-Behind for the MDI Application

vbnet_icon.gif
Private Sub MenuItem2_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles showChild1.Click

      Dim f As New child1()
      f.MdiParent = Me
      f.Show()

   End Sub

Private Sub showChild2_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles showChild2.Click

      Dim f As New child2()
      f.MdiParent = Me
      f.Show()

   End Sub

Private Sub formsCount_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles formsCount.Click

      ' Get the number of children
      MessageBox.Show(Me.MdiChildren.Length)

      ' Declare a Form object to get object properties
      Dim f As Form
      For Each f In Me.MdiChildren
         MessageBox.Show(f.Name.ToString)
      Next

End Sub

Private Sub closeAllForms_Click(ByVal sender As System.Object, _
     ByVal e As System.EventArgs) Handles closeAllForms.Click

      ' Declare a Form object and call the Close event
      Dim f As Form
      For Each f In Me.MdiChildren
         f.Close()
      Next

End Sub

Private Sub exitApplication_Click(ByVal sender As System.Object, _
     ByVal e As System.EventArgs) Handles exitApplication.Click

      ' Exit the Application
      Application.Exit()

End Sub

c_icon.gif
private void showChild2_Click(object sender, System.EventArgs e)
{
   Form f = new child1();
   f.MdiParent = this;
   f.Show();
}

private void showChild1_Click(object sender, System.EventArgs e)
{
   Form f = new child2();
   f.MdiParent = this;
   f.Show();
}

private void formsCount_Click(object sender, System.EventArgs e)
{
   MessageBox.Show(this.MdiChildren.Length.ToString());
   foreach (Form f in this.MdiChildren)
   {
      MessageBox.Show(f.Name.ToString());
   }
}

private void closeAllForms_Click(object sender, System.EventArgs e)
{
   foreach (Form f in this.MdiChildren)
   {
      f.Close();
   }
}

private void exitApplication_Click(object sender, System.EventArgs e)
{
   Application.Exit();
}
}

Now press the F5 key to run the application. You should change the StartUp form in the parent form before starting. When the application is running, click the Show Child1 and Show Child2 menu items a few times each. You should see something like Figure 3.14.

03fig14.gif

Figure 3.14 Multiple MDIChildren open in an MDIParent form.

Each time you set the variable f to a new instance of a form, you're setting the MdiParent property to the current form. This makes it an MdiChild. The code for determining the number of MdiChildren open is simply the Length property of the MdiChildren class. Because the form is an object, you can use the For Each method to iterate through its collection to retrieve properties, methods, and events. So, by using the For Each method and calling the form's Close method, you're firing the Form_Closing method of each active form.

To exit the application, you called the Application.Exit() method. The Application object is similar to the App object in Visual Basic 6; it contains information about the current running application. It's important to note that the Closing event won't fire when you call the Application.Exit() method. So, make sure that you gracefully close your windows, and then call Application.Exit(). The code in the closeAllForms click event demonstrates the correct way to accomplish that.

Table 3.3 has some common properties of the Application object, and Table 3.4 has some common methods of the Application object that you'll find useful.

Table 3.3. Useful Application Object Properties

Property

Description

AllowQuit

Gets a value indicating whether the caller can quit this application

CommonAppDataPath

Gets the path for the application data that's shared among all users

CommonAppDataRegistry

Gets the Registry key for the application data that's shared among all users

CompanyName

Gets the company name associated with the application

CurrentCulture

Gets or sets the culture information for the current thread

ExecutablePath

Gets the path for the executable file that started the application

LocalUserAppDataPath

Gets the path for the application data of a local, nonroaming user

ProductName

Gets the product name associated with this application

ProductVersion

Gets the product version associated with this application

StartupPath

Gets the path for the executable file that started the application

UserAppDataPath

Gets the path for the application data of a roaming user

UserAppDataRegistry

Gets the Registry key of the application data specific to the roaming user

Table 3.4. Useful Methods of the Application Object

Method

Description

AddMessageFilter

Adds a message filter to monitor Windows messages as they're routed to their destinations

DoEvents

Processes all Windows messages currently in the message queue

Exit

Informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed

ExitThread

Exits the message loop on the current thread and closes all windows on the thread

OnThreadException

Raises the ThreadException event

RemoveMessageFilter

Removes a message filter from the message pump of the application

Run

Overloaded; begins running a standard application message loop on the current thread

Share ThisShare This

Informit Network