ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Introduction to VB.NET Windows Forms

by Budi Kurniawan
08/27/2001

In VB.NET, Windows forms have changed completely. Now a Windows form is a representation of the System.Windows.Forms.Form class in the .NET Framework. This article offers an introduction to the new underlying technology by giving examples of how to do the basic tasks of writing a Windows application. This includes creating a form, adding controls, and responding to events. It also gives the object-oriented analysis of a WinForm, concluding with the most powerful new feature that enables code reuse: inheritance.

The new version of VB adds a new feature that entitles it to be called an object-oriented programming language: inheritance. Now, no one can argue that VB is not a purely OOP language. But what does this mean to VB programmers worldwide? Does it mean that every VB programmer must now learn OOP? Well, the answer is not that straightforward. The previous versions of VB have been known for their ease of use. Everyone remembers how easy it was to drag and drop controls and create a Windows application without any understanding of OOP. The half-OOP features in those versions were probably not often used by the majority of programmers. The ease of use continues with the current version; with Visual Studio.NET, creating a VB Windows application is as easy as it used to be. However, this article will show you why you should master OOP to really take advantage of the full power of VB.NET.

A Brief Theory of Inheritance

Everything is an object and there are three main principles of OOP: encapsulation, inheritance and polymorphism. That's how a typical OOP book would teach you. However, this article has no pretension of teaching OOP; it's a broad topic that takes a whole book to explain. This section only gives you a small dose of inheritance, just to make sure that you can still enjoy this article without being an OOP guru. Those who know OOP as well as they know their bodies can skip this section entirely.

Related Reading

VB .NET Language in a NutshellVB .NET Language in a Nutshell
By Steven Roman, Ron Petrusha & Paul Lomax
Table of Contents
Index
Full Description
Read Online -- Safari

Let's begin.

If you have a class named ClassA with a number of methods, you can extend ClassA into another class. This new class is a child class of ClassA, and it inherits methods and variables from ClassA. In the child class, you can use inherited methods and variables of the parent class and/or create your own methods. The advantage is clear: if you want to build a software program and someone else has already written something similar, you can borrow or buy his/her program and extend it. Instead of writing 100% of the application, you can probably release the program with 20% of the work. Imagine how much time and money you can save.

Listing 1 shows three VB.NET classes named ClassA, ClassB,and ClassC. ClassB inherits ClassA and ClassC inherits ClassB. The code shows that ClassB can use the SendMessage method from ClassA,as well as its own SendPersonalMessage. ClassC can use the SendMessage method from ClassA and the SendPersonalMessage from ClassB, as well as its own SendPrivateMessage method.


Listing 1: Simple inheritance in VB.NET

Imports System

Class ClassA

 Public Sub SendMessage()
  Console.WriteLine("From SendMessage in ClassA")  
 End Sub

End Class

Class ClassB
 Inherits ClassA

 Public Sub SendPersonalMessage()
  Console.WriteLine("From SendPersonalMessage in ClassB")
 End Sub

End Class

Class ClassC
 Inherits ClassB

 Public Sub SendPrivateMessage()
  Console.WriteLine("From SendPrivateMessage in ClassC")
 End Sub

End Class

Module Module1
 Sub Main()

  Dim a As ClassA = New ClassA()
  Dim b As ClassB = New ClassB()
  Dim c As ClassC = New ClassC()

  a.SendMessage()
  b.SendMessage()
  b.SendPersonalMessage()
  c.SendMessage()
  c.SendPersonalMessage()
  c.SendPrivateMessage()

 End Sub
End Module

Now, let's see what it takes to create a form in VB.NET.

Creating a VB.NET Form

VB.NET programmers can use the .NET Framework base type library to rapidly build a Windows application. The System.Windows.Forms namespace provide types that you need to build a Windows form. To create a form, you simply need to create a new class that inherits the System.WinForms.Form class. The following code creates a new class named Form1 that inherits System.Windows.Forms.Form:

Public Class Form1 : Inherits System.Windows.Forms.Form
End Class

Note that if you put the Inherits part on a separate line, you don't need a colon that separates the class name and the Inherits keyword.

Public Class Form1 
  Inherits System.Windows.Forms.Form
End Class

Because when working with forms you will be using classes from the System.Windows.Forms namespace, you can import the namespace to avoid having to type the namespace in front of every class you use.

Imports System.Windows.Forms
Public Class Form1
  Inherits System.WinForms.Form
End Class

If you use Visual Studio.NET, it will write some initial code. This might be confusing if you don't know which is which. After creating a new VB.NET Windows application, go to the code window of the first form and delete everything and type in the code above. Run the application by pressing F5 and you will see a blank form. Easy, isn't it? How is it possible? Because our Form1 class inherits the System.Windows.Forms.Form class, a rich class on its own. The Form class itself is the seventh in the hierarchy. It inherits ContainerControl that inherits ScrollableControl, and so on.

See Figure 1 below.

Object
  MarshalByRefObject
    Component
      Control
        ScrollableControl
          ContainerControl
            Form

Figure 1: The System.Windows.Forms.Form class hierarcy

However, you might still wonder how it is possible to display a form without a single line of code. The Visual Studio.NET actually takes care of a few things. First, in the .vbproj file, it specifies the first class to run. This is like having a hidden Sub Main. By default, the first form (Form1, in our example) should be the first class to create. Also, when you create a class without a constructor, the VB.NET compiler will assume a no-argument constructor, such as this:

Public Sub New()
End Sub

So, our Form1 class actually has a constructor. Explicitly creating the constructor is not a bad idea at all.

Imports System.Windows.Forms
Public Class Form1
  Inherits System.Windows.Forms.Form

  Public Sub New()

  End Sub

End Class

Comment on this articleWhat are your experiences with the new VB.NET WinForms?
Post your comments

When you instantiate an object with the New keyword, one of the class's constructors will be called. In the constructor, you usually write some initialization code. If you have a large number of lines for the initialization code, you may want to create a private sub that takes care of the initialization, to make your code more readable. For example, by default the Visual Studio.NET creates a sub called InitializeComponent and calls it from inside the constructor.


Bringing this to the previous code, we now have:

Imports System.Windows.Forms
Public Class Form1
  Inherits System.Windows.Forms.Form
  
  Public Sub New()
    InitializeComponent
  End Sub

  Private Sub InitializeComponent()
    '
    ' write your initialization code here
    '
  End Sub

End Class

Initialization code includes, for example, setting the form title or resizing the form. In VB.NET a Form's title is represented by its Text property. This property is inherited from the System.Windows.Forms.Control class. For the size, the Form class also has the Width and Height properties, which are also inherited from the System.Windows.Forms.Control class.

Bearing in mind that you refer to the instance of the current class using the keyword Me, you will have the following InitializeComponent sub that writes the form's title and resizes the form.

Private Sub InitializeComponent()
  Me.Text = "Developer Form"
  Me.Width = 400
  Me.Height = 300
End Sub
When you press F5 again this time, you will see a form with a width of 400 pixels and a height of 300 pixels. Still a blank form, but this time its title is changed to "Developer Form." (See Figure 2.)

Screen shot.
Figure 2: A Blank Form with Width=400 and Height=300

Adding Controls

Your form is not really useful without controls. The .NET Framework base type library provides controls that are ready to use. You have button, checkbox, textbox, label... you name it. If you are new to the .NET Framework, you might want to have a look at their object hierarchies. For instance, the Button control hierarchy is given in Figure 3.

Object
  MarshalByRefObject
    Component
      Control
        ButtonBase
          Button

Figure 3: The Button class hierarcy

All controls are indirectly derived from the Control class. Adding a control to a form requires three steps:

Because VB.NET variables have different scopes, it now does matter where a variable is declared. A variable declared inside a function is only visible from the function. If you want your control to be visible from the whole class, declare it in the class level.

Instantiating a control is like instantiating any other object; you use the New keyword. Once you have an instance of the control, you can add that object to the form. You can't add a control directly to a form, because the Form class has no such a method as Add(Control). However, the Form class inherits the Controls property from the Control class. In the Form class, you use this property to obtain the System.Windows.Forms.Form.ControlCollection object of the form. The Form.ControlCollection class represents the collection of controls contained within a form. You can use its Add method to add a control to the form and its Remove method to remove a control from the form. Understanding these three steps, adding a Button control to a form will involve code like the following:

'Declare the button
Dim Button1 As System.Windows.Forms.Button
'Instantiate the button
Button1 = New System.Windows.Forms.Button()
'Add the button to the form
Me.Controls.Add(Button1)

Of course, you can set the control's many properties to get a control that you want. You can set these properties before or after adding it to the form, but after the control is instantiated. A control has properties such as Left, Top, Width and Height for its size and position. A Button control also has the Text property that will appear as the text for the button object.

The code in Listing 2 brings a form to life and adds two controls, a Button and a TextBox, to the control.


Listing 2: Adding controls to a form.

Imports System.Windows.Forms
Public Class Form1
  Inherits Form
   
  ' Control declaration: a Button and a TextBox
  Private Button1 As Button
  Private TextBox1 As TextBox
    
  Public Sub New()
        InitializeComponent()
  End Sub
    
    
  Private Sub InitializeComponent()
        
        
    Me.Text = "Developer Form"
    Me.Width = 400
    Me.Height = 300
    
    Button1 = New Button()
    TextBox1 = New TextBox()
        
    Button1.Left = 200
    Button1.Top = 200
    Button1.Width = 100
    Button1.Height = 40
    Button1.TabIndex = 0
    Button1.Text = "Click Me"
        
    TextBox1.Left = 200
    TextBox1.Top = 30
    TextBox1.Width = 150
    TextBox1.Height = 40
        
    Me.Controls.Add(Button1)
    Me.Controls.Add(TextBox1)
        
  End Sub

End Class

Event Handling

The previous versions of VB are event-driven; you can write code that responds to an event easily. For instance, if you want a button called Button1 to respond to the user click, all you need to do is to create an event procedure called Button1_Click. (Well, actually the VB IDE does this for you.) In VB.NET it's business as usual, in regard to event handling. Once you draw your control in the Design mode, you can click it to tell Visual Studio.NET that you want to write an event procedure. Here you will be shown how to write it manually, though, so you get the picture of how events really work in VB.NET.

If you want your object to respond to an event, you use the keyword WithEvents when you declare it. For example, if you want your button to be able to respond to events, instead of saying

Private Button1 As Button

you add the keyword WithEvents before the variable name:

Private WithEvents Button1 As Button

Then, you need to create an event procedure for each event that your object should respond to. For Button1 to respond to a click event, you need a Button1_Click sub, followed by Handles Control.Event.

Private Sub Button1_Click(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles Button1.Click
  'Write your code here
End Sub

The Form class and all the control classes inherit the events from the Control class. If you look up the .NET Framework reference for the System.Windows.Forms.Control class, you will see that this class has 58 events, including the Disposed event, inherited from Component. To name a few more: Click, DoubleClick, GotFocus, LostFocus, KeyUp, KeyDown, etc.

The code in Listing 3 creates a form and adds two controls, a Button and a TextBox, to it. The Button is declared with the WithEvents keyword. For this control, two event procedures are created: Button1_Click and Button1_GotFocus.


Listing 3: Event Handling in a Windows Form

Imports System.Windows.Forms

Public Class Form1
  Inherits Form
  
  Private WithEvents Button1 As Button
  Private TextBox1 As TextBox
    
  Public Sub New()
    InitializeComponent()
  End Sub
    
    
  Private Sub InitializeComponent()
    Me.Text = "Developer Form"
    Me.Width = 400
    Me.Height = 300
        
        
    Button1 = New Button()
    TextBox1 = New TextBox()
        
    Button1.Left = 200
    Button1.Top = 200
    Button1.Width = 100
    Button1.Height = 40
    Button1.TabIndex = 0
    Button1.Text = "Click Me"
      
    TextBox1.Left = 200
    TextBox1.Top = 30
    TextBox1.Width = 150
    TextBox1.Height = 40
        
    Me.Controls.Add(Button1)
    Me.Controls.Add(TextBox1)
        
 
  End Sub
 
  Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    TextBox1.Text = "Ooops.... you clicked me."
        
  End Sub
    
  Private Sub Button1_GotFocus(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.GotFocus
    TextBox1.Text = "Button got focus."
        
  End Sub
    
End Class

Form Inheritance

Now, this is the most important part of this article. This section explains a very powerful feature of inheritance. When you create a new form, you extend the System.WinForms.Form class. Now that VB.NET supports inheritance, you can also extend your own form. This way, if you want to create a form that is similar to a form you have created before, you can just extend it and save time. You may have guessed that it would be something like this:

Public Class NewForm
    Inherits WindowsApplication1.ExistingForm

The following example shows form inheritance. You have created an Employee form that has two labels, two textboxes, and two buttons. (See Figure 4; you basically need an employee's first name and last name.)

Screen shot.
Figure 4: The Employee Form

Now you need to create a form for all contractors in your company. Contractors are like normal employees. They come to the office everyday and, like the rest of us, use the office microwave to warm their lunch. The only difference is that they are not directly paid by your company. Your company pays an external company for their service.

Now, rather than create a new form for the contractors, you can extend the existing Employee form. A contractor has a first name and last name just like an employee, but in addition, a contractor has an external company field. The code for the existing Employee form is given in Listing 4. Note that the code is generated by Visual Studio.NET. By now, however, you should not have a problem understanding it.


Listing 4: The Employee Form

Imports System.Drawing
Imports System.Windows.Forms
Imports System.ComponentModel

Public Class Form2
  Inherits Form

  Public Sub New()
    MyBase.New()
    'This call is required by the Win Form Designer.
    InitializeComponent()
  End Sub

#Region " Windows Form Designer generated code "

  'Required by the Windows Form Designer
  Private components As System.ComponentModel.Container
  Protected cancel As System.Windows.Forms.Button
  Private LastName As System.Windows.Forms.TextBox
  Private FirstName As System.Windows.Forms.TextBox
  Private Label2 As System.Windows.Forms.Label
  Private Label1 As System.Windows.Forms.Label
  Protected ok As System.Windows.Forms.Button

  Dim Form2 As System.Windows.Forms.Form

  Private Sub InitializeComponent()
    Me.Label1 = New System.Windows.Forms.Label()
    Me.FirstName = New System.Windows.Forms.TextBox()
    Me.ok = New System.Windows.Forms.Button()
    Me.Label2 = New System.Windows.Forms.Label()
    Me.LastName = New System.Windows.Forms.TextBox()
    Me.cancel = New System.Windows.Forms.Button()
    Me.SuspendLayout()
    '
    'Label1
    '
    Me.Label1.Location = New System.Drawing.Point(8, 24)
    Me.Label1.Name = "Label1"
    Me.Label1.TabIndex = 1
    Me.Label1.Text = "First Name"
    '
    'FirstName
    '
    Me.FirstName.Location = New System.Drawing.Point(120, 16)
    Me.FirstName.Name = "FirstName"
    Me.FirstName.Size = New System.Drawing.Size(136, 20)
    Me.FirstName.TabIndex = 3
    Me.FirstName.Text = ""
    '
    'ok
    '
    Me.ok.Location = New System.Drawing.Point(8, 128)
    Me.ok.Name = "ok"
    Me.ok.Size = New System.Drawing.Size(112, 32)
    Me.ok.TabIndex = 0
    Me.ok.Text = "OK"
    '
    'Label2
    '
    Me.Label2.Location = New System.Drawing.Point(8, 48)
    Me.Label2.Name = "Label2"
    Me.Label2.Size = New System.Drawing.Size(88, 16)
    Me.Label2.TabIndex = 2
    Me.Label2.Text = "Last Name"
    '
    'LastName
    '
    Me.LastName.Location = New System.Drawing.Point(120, 40)
    Me.LastName.Name = "LastName"
    Me.LastName.Size = New System.Drawing.Size(136, 20)
    Me.LastName.TabIndex = 4
    Me.LastName.Text = ""
    '
    'cancel
    '
    Me.cancel.Location = New System.Drawing.Point(144, 128)
    Me.cancel.Name = "cancel"
    Me.cancel.Size = New System.Drawing.Size(112, 32)
    Me.cancel.TabIndex = 5
    Me.cancel.Text = "Cancel"
    '
    'Form2
    '
    Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
    Me.ClientSize = New System.Drawing.Size(272, 181)
    Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.cancel, Me.LastName, Me.FirstName, Me.Label2, Me.Label1, Me.ok})
    Me.Name = "Form2"
    Me.Text = "Employee Form"
    Me.ResumeLayout(False)

  End Sub

#End Region

End Class

Note that all controls are declared Private except the OK and Cancel Button controls that are declared Protected. By declaring a control Protected, you have access to it from any class that inherits the Employee Form. The code in Listing 5 is the Contractor form that extends the Employee form. What it does is inherit the Employee form and add two more controls (Label3 and ExternalCompany). Note also that we change the OK button position a bit, to show that we have access to this button.


Listing 5: The Contractor form

Imports System.Windows.Forms
Public Class Form1
  Inherits WindowsApplication1.Form2
  Private Label3 As Label
  Private ExternalCompany As TextBox
  
  Public Sub New()
    InitializeComponent()
    
  End Sub
  Private Sub InitializeComponent()
    Label3 = New Label()
    ExternalCompany = New TextBox()
    
    Label3.Location = New System.Drawing.Point(8, 72)
    Label3.Size = New System.Drawing.Size(88, 16)
    Label3.Text = "Ext Company"
    
    ExternalCompany.Location = New System.Drawing.Point(120, 62)
ExternalCompany.Size = New System.Drawing.Size(136, 20)

' Change the ok button position
ok.Location = New System.Drawing.Point(8, 140)

Me.Text = "Contractor Form"
Me.Controls.Add(Label3)
Me.Controls.Add(ExternalCompany)

End Sub

End Class


Figure 5 shows the Contractor form.

Screen shot.
Figure 5: The Contractor form

Summary

You have seen the new Windows form in VB.NET. It's as easy as in the previous versions of VB. However, it's now fully OOP, and understanding OOP will give you access to the full power of VB.NET. For instance, understanding inheritance enables you to extend a form and maximize code reuse. See my next article for details.

Budi Kurniawan is a senior J2EE architect and author.


Return to the .NET DevCenter.

Copyright © 2009 O'Reilly Media, Inc.