Visual Basic Concepts

Customizing Form Classes

It may surprise you to learn that you've been creating classes for as long as you've been programming in Visual Basic. It's true: Form1, that familiar denizen of every project you've ever started, is really — a class.

To see this, open a new Standard Exe project. Add a button to Form1, and place the following code in its Click event:

Private Sub Command1.Click()
   Dim f As New Form1
   f.Show
End Sub

Press F5 to run the project, and click the button. Holy smokes, there's another instance of Form1! Click its button. There's another! Every instance you create looks the same, and has the same behavior, because they're all instances of the Form1 class.

What's Going On Here?

If you've read "Working with Objects" in "Programming Fundamentals," you know that an object variable declared As New contains Nothing until the first time you refer to it in code. When you use the variable for the first time, Visual Basic notices that it contains the special value Nothing, and creates an instance of the class. (And a good thing it does, too, or f.Show would cause an error.)

Me and My Hidden Global Variable

You may be wondering how it is that you can refer to Form1 in code, as if it were an object variable. There's no magic involved. Visual Basic creates a hidden global object variable for every form class. It's as if Visual Basic had added the following declaration to your project:

Public Form1 As New Form1

When you select Form1 as your startup object, or type Form1.Show in code, you're referring to this hidden global object variable. Because it's declared As New, an instance of the Form1 class is created the first time you use this predeclared variable in code.

The reason this declaration is hidden is that Visual Basic changes it every time you change the Name property of a form. In this way, the hidden variable always has the same name as the form class.

A Very Short Quiz

Which of the instances of Form1 you created in the exercise above was associated with the hidden global variable? If you guessed the first one, you're right. Form1 is the default startup object for the project, and to Visual Basic that's just like using the predeclared global variable Form1 in code.

Tip   After you unload a form, you should always set any references to the form to Nothing in order to free the memory and resources the form was using. The reference most often overlooked is the hidden global form variable.

What About All Those Other Instances of Form1?

In "Programming Fundamentals," you learned that to refer to an object, you need an object variable, and that an object exists only as long as there's at least one object variable containing a reference to it. So what was keeping all those other instances alive?

The second instance of Form1, and all the ones that followed, had an object variable for just as long as it took to call their Show methods. Then that variable went out of scope, and was set to Nothing. But Visual Basic keeps a special collection named Forms, which you can read about in "More About Forms" in "Creating a User Interface." The Forms collection contains a reference to each of the loaded forms in your project, so that you can always find and control them.

Note   As you'll learn, this is not true of all classes. For example, the classes you design won't have hidden global variables or global collections to keep track of them — those are special features of form classes. However, you can declare your own global variables, and you can create your own collections — as described in "Creating Your Own Collection Classes."

Properties, Methods, and Events of Form Classes

The first time you added a property to a form class, you probably did it visually, by dropping a command button (or some other control) on Form1. In doing so, you added a read-only Command1 property to the form class. Thereafter, you invoked this property of Form1 whenever you needed to call a method or property of the command button:

Command1.Caption = "Click Me"

When you changed the Name property of any control on a form, Visual Basic quietly changed the name of the read-only property, so they always matched.

If you still have the project open from the earlier exercise, you can see this Command1 property by pressing F2 to open the Object Browser. In the Project/Library box, select Project1. You'll see Form1 in the Classes pane. In the Members pane, scroll down until you find Command1, and select it.

Command1 has a property symbol beside it, and if you look in the description pane, you'll see that it's a WithEvents property. As you'll learn in "Adding Events to a Class," this means that the property (or object variable) has event procedures associated with it. One of those event procedures, Command1_Click(), may have been the first place you ever wrote Visual Basic code.

But Wait, There's More

Dropping controls on a form is not the only way to add new members to the form class. You can add your own custom properties, methods, and events, as easily as you create new variables and procedures.

To see this, add the following code to the Declarations section of Form1:

' The Comment property of the Form1 class.
Public Comment As String

Add the following code to the Click event of Form1:

Private Sub Form_Click()
   MsgBox Comment, , "My comment is:"
End Sub

Finally, change the code in the Command1_Click() event procedure by adding a line, as follows:

Private Sub Command1.Click()
   Dim f As New Form1
   f.Comment = InputBox("What's my comment?")
   f.Show
End Sub

Press F5 to run the project. Click Command1, and when the input box appears, type in some racy comment and click OK. When the new instance of Form1 appears, click on it to play back its Comment property.

Click on the first instance of Form1, and notice that its Comment property is blank. Because Visual Basic created this instance as the Startup Object, you never got a chance to set its Comment property.

Forms Can Call Each Other's Methods

If you were watching closely, you may have noticed that the code you added to the Form1 class didn't set the object's own Comment property — it set the Comment property of the new instance of Form1 it was creating.

This ability of forms to set each other's properties and call each other's methods is a very useful technique. For example, when an MDIForm is opening a new child window, it can initialize the new window by setting its properties and calling its methods.

You can also use this technique to pass information between forms.

Tip   You can create custom events for forms. "Adding an Event to a Form" later in this chapter, provides a step by step procedure.

Other Kinds of Modules

You add properties, methods, and events to form classes by putting code in their code modules. In the same way, you can add properties, methods, and events to class modules and — if you have the Professional or Enterprise Edition of Visual Basic — to UserControl and UserDocument code modules.

As you read "Adding Properties and Methods to a Class" and "Adding Events to a Class," remember that everything you read applies to form classes as well as to class modules.

For More Information   What the heck is a class module? "Class Module Step by Step" shows how to define a class and illustrates the life cycle of the objects you create from that class.