Enough Talk: Press F5 and Run Your Program

Enough Talk: Press F5 and Run Your Program

Just as I said, press F5 and run your program. The Visual Basic .NET compiler builds your project, and the form is displayed. While we have a button on the form, we didn't program any of the button's events (assuming you deleted the code inside the Button1_Click event handler). Because we don't have any code in the Click event handler, when you click the button, there's nothing for it to do; the event handler is immediately exited without a trace. You could press the button shown in Figure 2-7 until the sun turns cold and nothing would happen.

Figure 2-7

An uneventful button.

Even though not much is going on at this point, we did set the Text property of the form to "Mirror Image" for a reason. As you've learned, each Visual Basic .NET object inherits a common set of characteristics and capabilities (properties, methods, and events) that are defined by the base class. However, each instance of an object you create with Sub New is an individual object with its own name. Each object can be separately enabled and disabled, placed in a different location on the form, and so on. Click the form's Close button to dismiss the form, and let's have some fun with our simple program while at the same time looking at the principles of object-oriented programming in action.

The Doppelganger Program: Creating Clones of the Form1 Class

Let's put this theory of object inheritance into practice. Let's create several identical objects from the same class.

  1. Double-click the form in the Designer to bring up the code window. Between the Class declaration and Sub New, add the two lines of code highlighted below.

    Public Class Form1     Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code "     Dim myform As Form1     Shared iFormCounter As Integer = 0    Public Sub New()         MyBase.New()         'This call is required by the Windows Form Designer         InitializeComponent()         'Add any initialization after the         ' InitializeComponent() call     End Sub

  2. Add the following code to the Click event handler of Button1. With it, you are going to create a new object from the Form1 class each time you click the button. And, to tell each new form apart, you'll add a number to the form's Text property.

    Private Sub Button1_Click(ByVal sender As Object,_     ByVal e As System.EventArgs)     myform = New Form1()     iFormCounter += 1     myform.Text = "Doppelganger - Number " & _         iFormCounter.ToString     myform.Show()End Sub

    With this code we change the Text caption to "Doppelganger" and assign a number to the instance. Notice how to use the ToString method of the iFormCounter object variable. Because everything in .NET is an object, including integers, each object has built-in methods and properties. And since the Text property requires a string, we simply create a string from an integer, leaving the underlying value unchanged. In this example, we are creating new instances of our original class, all within the class itself.

  3. Press F5 again to run the program. The first form will be displayed with the caption "Mirror Image". Click the Clone Me! button several times to create additional forms from the Form1 class, as shown in Figure 2-8. With the exception of the Text property, each new form is an identical copy of the original Form1 class.

    Figure 2-8

    Clicking Clone Me! instantiates identical copies of the Form1 class.

If you glance at the taskbar, you will see that each form has its own icon. Each form is a self-contained unit with the same capabilities as the original. We simply instantiated multiple copies of the Form1 class, each with its own identity. Select one of the clones and try its Control menu and Minimize button. You'll see that they work as advertised on each form. Each copy knows how to do everything the base class knows how to do. Reusability, the Holy Grail of modern programming, is a reality with Visual Basic .NET objects.

Important Object Concepts from the Doppelganger Program

We wanted to create several copies of our object, so the first variable we put into scope with a Dim statement was that of type Form1. We also used a counter to display which form is which, using the variable iFormCounter to keep track for us.

Another new Visual Basic .NET keyword you'll become familiar with is Shared.

Dim myform As Form1 Shared iFormCounter As Integer = 0

You'll want to understand the use of Shared right away. Shared members are properties, procedures, or fields (such as iFormCounter) that are available to all instances of a class. (If you are familiar with other object-oriented languages, shared items are sometimes called static or class members.) The Shared keyword is useful in Visual Basic applications that use inheritance. Shared data members such as iFormCounter exist independently of any particular instance of a class, so shared items are not implicitly passed to instances of the class. For this reason, no unqualified references are permitted in your code. In upcoming chapters, I'll cover various uses of shared data members and inheritance in more detail.

Take a look at the Click event of Button1. Each time the user clicks the button, a new Form1 object is created.

Private Sub Button1_Click(ByVal sender As Object, _     ByVal e As System.EventArgs)     myform = New Form1()     iFormCounter += 1     myform.Text = "Doppelganger - Number " & _         iFormCounter.ToString     myform.Show()End Sub

The New keyword calls the constructor Sub New of Form1 and creates a new object. That object is assigned to the object variable myform. You can access the newly minted Form1 object by referring to its object variable. If our simple sample were a production program, you would have either created an array or a collection of new forms or given each a unique name. But for now, we want to focus on classes. We'll get to everything else in due time.

Recall that our form inherits from Windows.Forms.Form. When you create a new form, the form's constructor is called immediately and this creates a new form. Sub New is always called first and is called only once.

Public Sub New()     MyBase.New()

Notice, however, that the first line of Sub New is a call to the inherited class, which calls its constructor. Before any work is performed, the parent class's constructor is called. If a parent class is derived from yet another class, that class's constructor is called first, and so on up the chain. Constructor code gets called from the top of the inheritance chain down, with your derived class's constructor code called last. This sequence makes perfect sense because the base class has to be instantiated first so that the rest of the inherited classes can be derived from it. Deriving a new form from the base class form permits you to immediately access all the functionality of that parent form. You can simply build on what is already provided.

note

One of the ways in which C++ programmers would often shoot themselves in the foot was inheriting from multiple classes incorrectly. In all .NET-compliant languages, you can inherit only from one base class. This "best of breed" approach will go a long way toward making programs more understandable and bug free.

After the new Form1 object is created, we want to count how many new forms are floating around. We increment the shared variable iFormCounter by 1 each time the button is clicked. Because a shared variable is just that—a variable shared by each instance of the class—we know our variable will provide an accurate count.

iFormCounter += 1

The incrementing syntax might look strange to a classic Visual Basic programmer. You would usually have to write something like

iFormCounter = iFormCounter + 1.

You can still use this syntax if you want, but in Visual Basic .NET, you can use the new method I've shown, and it has its advantages. One of the elegant and clean features of the C language that I always missed when working with Visual Basic was this way of incrementing or decrementing values. Since I'm lazy, I like the new method because it requires less typing and has less potential for typos. (I'm getting better at typing; I'm down to one mistake per word.) However, this notation is also more streamlined and intuitive. Visual Basic .NET provides a streamlined operator set, shown in Table 2-3. If you come from C or C++, these operators will be familiar to you.

I suggest that you use these operators instead of the longhand assignment from classic Visual Basic. These operators are not only more streamlined, but using them will permit you to move to other .NET languages down the road.

tip

Recall that we explicitly initialized iFormCounter to 0 in the class. If we had left out = 0, our program would still have worked because the default behavior of the language initializes numeric variables to 0. However, professional programmers should never rely on the default behavior of the language. Initializing a value to 0 makes the code more readable and leaves no room for ambiguity, which makes your programs easier to debug. Also, the underlying default behavior of the language could change in later versions of Visual Basic .NET. Being explicit shows a precise thought process; you are telling the language exactly what you want, leaving no room for errors.

The last two lines of code are pretty straightforward. We are assigning some verbiage to the Text property of the new form and then calling its Show method to display it. Because our variable iFormCounter is now an object (what isn't?), it knows how to convert itself to a string. When we call the built-in ToString method of our object variable iFormCounter, a string of the value is returned and displayed as part of the text string.

myform.Text = "Doppelganger - Number " & _     iFormCounter.ToString myform.Show()

Table 2-3  New Operators You Can Use in Visual Basic .NET

Operator

Example

Description

+=

Variable += Expression

Adds the value of an expression to the value of a variable and assigns the result to the variable.

- =

Variable -= Expression

Subtracts the value of an expression from the value of a variable and assigns the result to the variable.

&=

Variable &= Expression

Concatenates a string expression to a string variable and assigns the result to the variable.

*=

Variable *= Expression

Multiplies the value of a variable by the value of an expression and assigns the result to the variable.

/=

Variable /= Expression

Divides the value of a variable by the floating point value of an expression and assigns the result to the variable.

\=

Variable \= Expression

Divides the value of a variable by the value of an expression and assigns the integer result to the variable.

^=

Variable ^= Expression

Raises the value of a variable to the power of an exponent and assigns the result back to the variable.

If you have any lingering doubt that each new form is its own object, add the following message box code right after the myform.Show statement. This code will display a unique number (a handle) that Windows uses to track each visible object. It will be different for each form and different each time you run the program. Handles are referred to as "magic cookies" by grizzled programmers because they are unique and there is no way to know in advance what they will be. The only guarantee is that they will be unique. (They're magic.) Again, this code is for illustration only.

myform = New Form1() iFormCounter += 1 myform.Text = "Doppelganger - Number " & _     iFormCounter.ToString myform.Show() MessageBox.Show(myform.Text & " has a handle of " & _     myform.Handle.ToString, "Doppelganger", _     MessageBoxButtons.OK, MessageBoxIcon.Information)

Whenever you click the button to display a new form, you will see the sort of magic cookie that Windows uses to track this and other visible components, as shown in Figure 2-9.

Figure 2-9

One of our form objects showing off its Windows handle.

More About Handles

While beginners usually think of a form as a window, to the Windows operating system everything is a window: forms, buttons, option boxes, text boxes, and so on. Windows has an internal table that tracks each of these visible items. In Visual Basic .NET, several controls, such as the line control, were removed. In classic Visual Basic, line controls and labels were known as lightweight controls because they didn't have a handle. This means that they couldn't receive focus. Line controls were removed and the label control was buffed up in Visual Basic .NET so that it would have its own handle.

Never use a handle for tracking items because Windows changes them often as it automatically compacts memory internally and shifts things around for optimization. As such, a handle for the same object can and will change as the program runs. Advanced classic Visual Basic programmers passed form and control handles as parameters for API functions. Another beauty of Visual Basic .NET is that you never have to do this. In short, you don't need to be concerned with handles anymore.



Coding Techniques for Microsoft Visual Basic. NET
Coding Techniques for Microsoft Visual Basic .NET
ISBN: 0735612544
EAN: 2147483647
Year: 2002
Pages: 123
Authors: John Connell

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