You are on page 1of 16

Visual Basic 5

Programming - 6
A Specialised Training Course
Contents
APPLICATIONS WITH MULTIPLE FORMS ................................................................................................ 2
LOADING, SHOWING, HIDING AND UNLOADING FORMS .......................................................................................... 2
Load Statement .................................................................................................................................................. 2
Show Method ..................................................................................................................................................... 2
Hide Method ...................................................................................................................................................... 2
Unload Statement............................................................................................................................................... 3
Modal forms....................................................................................................................................................... 3
CHOOSING THE INITIAL FORM .................................................................................................................................. 3
FORM OBJECT VARIABLES ...................................................................................................................................... 3
OBJECTS & INSTANCES.................................................................................................................................. 4
OBJECT VARIABLES................................................................................................................................................. 4
Generic and Specific Types................................................................................................................................ 4
FORM OBJECT VARIABLES (REVISITED) .................................................................................................................. 5
Set Statement...................................................................................................................................................... 5
New keyword...................................................................................................................................................... 6
Lifetimes of Forms and object variables............................................................................................................ 6
Screen.ActiveForm............................................................................................................................................. 6
Me keyword........................................................................................................................................................ 7
Forms collection ................................................................................................................................................ 7
SYSTEM OBJECTS .................................................................................................................................................... 8
App Object ......................................................................................................................................................... 8
Clipboard Object ............................................................................................................................................... 8
Debug Object ..................................................................................................................................................... 8
Printer Object .................................................................................................................................................... 8
Screen Object..................................................................................................................................................... 8
MDI - MULTIPLE DOCUMENT INTERFACE ............................................................................................. 9
COMPONENTS .......................................................................................................................................................... 9
Creating MDI Forms ....................................................................................................................................... 10
Creating MDI Child Forms ............................................................................................................................. 10
DEVELOPING AN MDI APPLICATION ..................................................................................................................... 10
MDI at Design Time ........................................................................................................................................ 10
MDI at Run-Time ............................................................................................................................................. 11
Instances of Forms........................................................................................................................................... 11
Arranging MDIChild Forms ............................................................................................................................ 12
Dirty, Dirty! ..................................................................................................................................................... 12
EXERCISES ....................................................................................................................................................... 13

Visual Basic Book 6 © Mark Collins 1999 Page 1


Applications with multiple forms
So far we have looked at applications that use a single form. Many applications require more
than one form, for example, an application may need forms for each of the following...
• Main application window.
• Application specific dialog boxes.
• An About Box.
To create such an application you need to create a form for each. These forms appear as
individual files in the project window. You often require Code Modules that allow you to
declare common variables and to create general procedures that can be shared by each form
(see previous discussion on scope).
If you require multiple instances of a document form then you need to use MDI forms, see
the section later in this book.

Loading, Showing, Hiding and Unloading Forms


A form can be in one of three states...
• Loaded and showing, i.e. active on screen
• Loaded but hidden, i.e. loaded in memory but not showing on screen
• Not loaded, i.e. not resident in memory and not showing.
To change the state of a window you use a combination of Statements and Methods.
Load Statement
This statement is used with the following syntax...
Load formName
The result is a form that is loaded in memory but not yet showing. This is a useful state for
forms that you do not need constantly but do need frequently as they can be shown quickly.
Activates the form’s Load event-procedure.
Show Method
This is a method for the Form object and is therefore used with the following syntax...
formName.Show [modestyle]
It has the effect of showing a form; if the form is not loaded this method performs that
function too. If however the form has been pre-Loaded it is shown faster. See below for an
explanation of modestyle.
Hide Method
This Form Object method is used with the following syntax...
formName.Hide
This method hides a form (un-shows it) without unloading it from memory. The variable
values remain intact.

Visual Basic Book 6 © Mark Collins 1999 Page 2


Unload Statement
This statement is used with the following syntax...
Unload formName
Unloads the displayed component of a form. The code associated with the form module
remains in memory, but not the variable values.
Modal forms
A modal form is a form that retains the focus until hidden or unloaded. With forms this
means that you can not switch to other windows in the application (with message boxes you
have the option of making them system modal which prevents you from switching to any
applications windows).
To make a form modal you set the modestyle switch to 1 in a Show method line. For
example...
ErrorForm.Show 1
This lasts until released by hiding or unloading the form. You could also remove the modal
behaviour and leave the form on screen as a normal form by setting the switch back to 0...
ErrorForm.Show 0

Choosing the initial form


If you are using multiple forms (not MDI) you need to decide which form to load initially.
This can be done via the Project / Project Properties menu in the application window. One of
the General tab selection in the resulting dialog box is Startup Object. Using this allows you
to select between the forms available in the project and Sub Main.
Sub Main is a general procedure that you can use as the start-up procedure and must be
defined as part of a Code Module included in the project. If a form is selected that form’s
Load event-procedure effectively becomes the start-up procedure.

Form Object Variables


Before we handle this specific subject we need to look at the general concept:

Visual Basic Book 6 © Mark Collins 1999 Page 3


Objects & Instances
In the world of pure objects you define a class of object and then proceed to create instances
of that object. The instances adopt the attributes and functions of the class, but each instance
is completely independent from other instances of that object.
This analogy can be carried forward to Visual Basic. At design-time we create a ‘kind’ of
form and can create multiple instances of that form at run-time. Each instance may appear
identical but its properties, controls and variables can hold different data. You are now
entering the twilight zone of Object Variables.

Object Variables
We are familiar now with the concept of Visual Basic Control Objects. We can have a form
called frmMain on which we have a text box called txtName, another called txtAddress,
two command buttons called cmdOK and cmdCancel. We can also add an array of controls
which share the same name and event-procedures, let’s say a pair of option buttons called
optSex( ). By creating this array we have already begun to treat our objects like data types.
Generic and Specific Types
Generic Object Variables can refer to any object of that kind. Generic types must be one of...
• Form
• Control
• MDIForm
A generic Form object variable can therefore refer to any form in that application. A generic
Control object variable can refer to any control, whether it be a TextBox, Timer or Frame.
We will discuss MDI Forms later.
Specific Object Variables refer to only one type of object.
This must be one of the following...
• A specific Form in your application
• A specific Control Type (TextBox or Timer or Frame etc.)

The possible Control Types are...


• CheckBox • DriveListBox • Label • PictureBox
• ComboBox • FileListBox • Line • Shape
• CommandButton • Grid • ListBox • TextBox
• CommonDialog • Frame • Menu • Timer
• Data • HScrollBar • OptionButton • VScrollBar
• DirListBox • Image • OLE
• Other Custom Control Types, refer to their Documentation.

Visual Basic Book 6 © Mark Collins 1999 Page 4


We can create an object variable or pass an object as an argument to a procedure that changes
a property no matter what object is passed using the Generic Control type...
Dim anyControl as Control
...
Sub disable (objVar As Control)
objVar.Enabled = False
End Sub
If we wanted to be more specific we could create or pass an object variable of a Specific
control type...
Dim varText as TextBox
...
Sub embolden (txtVar As TextBox)
txtVar.Bold = True
End Sub
Object variables of the same type can be assigned or compared as values...
If txtVar1 = txtVar2 Then
...
We can also use them to create multiple instances of a form.

Form Object Variables (revisited)


By far the biggest use of Object Variables is in multiple instances of forms. As already
discussed there are two possibilities...
• Generic (variable that refers to any Form)
• Specific (variable that refers to an instance of a specific Form)
We will rarely need to use Generic Form Variables except for passing them to procedures as
arguments.
Each form you create at design time is available at run-time as a Specific Form Type. We can
then create variables of that type...
Dim frmVar1 As frmMain
There are two possibilities that we want to consider...
• Defining a variable that refers to an existing form
• Creating a new Instance of a form type
Set Statement
The Set statement assigns an object reference to a variable. The variable must have been
declared previously. An Explicit declaration would be as the previous example. It is therefore
possible to explicitly declare several variables that refer to the same object instance.
Visual Basic also Implicitly declares a global form variable for each form automatically with
the same name as the form, and at the same time creating an instance of that form type. In
other words the following code is effectively performed automatically for any form name...
Dim formName As New formName
You may not have realised this before, but whenever you have used a form in code you have
actually been using a form variable that refers to an instance of that form rather than the
actual form directly.

Visual Basic Book 6 © Mark Collins 1999 Page 5


New keyword
This is the vital component of a statement that determines whether the variable is to refer to
an existing form or a new form. To create a new form it can be used in two ways...
Dim frmVar As frmMain ‘ frmMain is Type
...
Set frmVar = New frmMain ‘ create new instance
frmMain.Show ‘ frmMain is variable
frmVar.Show
...
or...
Dim frmVar As New frmMain
frmVar.Show
...
Remember that in both cases the Dim line is creating a new variable of type frmMain. Do not
confuse this with the form instance referred to by the variable name frmMain that is actually
used in the first show statement.
The difference between the two constructs is that when you use Set... New... a new instance is
always created, even if the object variable already refers to an existing form. The previously
referred to form doesn’t disappear because it doesn’t have a variable pointing to it. Any use
of the object variable after it’s declared and before it’s set can cause problems as it does not
yet reference anything.
Using Dim...New... a new instance is created only if there isn’t an existing instance referred to
by the object variable. You guarantee that an instance of the form exists whenever you use
the variable as a new one is created if necessary.
Lifetimes of Forms and object variables
If a new form instance has its object variable declared and created within a procedure then
what happens at the end of the procedure? As with reassigning the variable with the Set
statement the form instance is not lost although the variable is killed off at the end of the
procedure.
We need a mechanism that allows us to access any form, especially if there is no direct object
variable referencing it. There are several options...
• Screen.ActiveForm
• Me keyword
• Forms collection
Screen.ActiveForm
One concept that we haven’t considered so far is the treatment of the Screen as an Object. As
only one window / form can be active at any one time Screen.ActiveForm references the
active form on the screen object. It is possible therefore to use this reference in our code for
forms that may not be referenced by an object variable, but only if there is no possibility that
the form we want to reference is not the active form. One such situation can arise when using
the timer control which may activate a procedure in a non-active form...

Unload Screen.ActiveForm
Screen.ActiveForm.Hide

Visual Basic Book 6 © Mark Collins 1999 Page 6


Me keyword
Another way of referencing the form in its own code is by using the Me keyword...

Unload Me
Me.Hide

This is more satisfactory than Screen.ActiveForm as it is always a ‘personal’ reference.


Forms collection
We have already discussed the possibility of creating arrays of forms or other controls. Visual
Basic automatically maintains a structure similar to an array that references all loaded form
instances. We can refer to any element using the syntax...
Forms.(index)
The collection is zero based (i.e. the first form is index 0) and is also dynamic. As a form
instance is loaded or unloaded the collection is resized (redimensioned) but the size is always
available via...
Forms.Count
This also means that we can’t depend on a form instance maintaining the same position in the
collection. Where it does become useful is when we need to loop through all loaded forms.
This is fine for most operations, but when we are unloading just imagine the likely confusion.
Other tricks, are to create new object variables, or even arrays of the same and Setting them
to the forms in the collection.
Be aware that Forms is not a reserved word, so any declared variable of the same name will
cause confusion.

Visual Basic Book 6 © Mark Collins 1999 Page 7


System Objects
We mentioned the screen object in the last section, perhaps now is a good time to deal with
the concept.
There are five special system objects that you can use to manipulate and reference the system
environment. They are global.
• App, for determining information specific to the application
• Clipboard, for accessing Windows’ clipboard.
• Debug, for printing to the debug window in VB3
• Printer, for printing text and graphics to the printer
• Screen, for determining assorted screen related information
App Object
This object has no methods or events. The properties available relate to the executable file’s
name and path, the help file name, whether a previous instance is loaded and the title to
appear in task lists etc.
Clipboard Object
This object has no properties or events. It has the following methods for cutting, copying and
pasting text or other data to and from the clipboard. We will look at this whole subject in
more detail later in the course.
Debug Object
Has only a single method, Print. It is used to display values in the Immediate window at
runtime, for example...
Debug.Print myVariable
This line has no effect when converted to an EXE file.
Printer Object
The Printer object is used to control text and graphics printed on a page and to send output
directly to the default system printer. For example, you can use this object to manipulate the
appearance of your printed output by changing fonts. We will look at this whole subject later.
Screen Object
This object has a number of properties from which we can get information such as...
• Width & Height of the screen
• Number and names of fonts available
• Active forms and controls
We can also set the mouse pointer globally (e.g. to hourglass) using the MousePointer
property.

Visual Basic Book 6 © Mark Collins 1999 Page 8


MDI - Multiple Document Interface
Many document based applications need the facility to edit or view more than one document
at a time. One way of allowing this would be to run more than one instance of an application.
The alternative is to run a single instance with multiple documents; hence MDI.

Components
An MDI application requires at least two forms...
• MDI Form - a.k.a. parent form or application window
• MDI Child - document form
To allow multiple documents to be active the application launches more than one instance of
the Child form. It is also possible to have several types of MDI Child form (e.g. a text edit
form and picture edit form) available in a single application. It is also possible to have several
forms that are not MDI Child forms, they are treated as you would in a normal application.

An MDI child form appears within the internal area of the MDI Parent. If the parent is not
large enough scroll bars are automatically implemented. An MDI Parent can only contain
controls that have the Align property, usually a picture box. Additional controls can then be
placed inside this control effectively creating a toolbar.
For simplicity we will adopt the terminology of referring to...
• MDI Form - the parent form, as opposed to
• MDIChild Form

Visual Basic Book 6 © Mark Collins 1999 Page 9


Creating MDI Forms
An application can only have a single MDI Form. This can be added to your project by
selecting Project / New MDI Form from the VB application window. The form is opened and
added to the Project window as MDIForm1.frm. You can of course change this.
Creating MDI Child Forms
To create an MDI Child Form you simply change the MDIChild property of a standard form
from False to True. It is possible to have more than one MDI Child form type that can be
displayed in a single MDI Form (e.g. one that displays text, another pictures).

Developing an MDI Application


MDI at Design Time
At design time the MDI child forms can be placed anywhere on the screen, it is only at run-
time that they are restricted to the MDI Form.
You can tell the type of forms included in your project from the icons displayed beside each
entry in the Project Window.

The icons are the same as those automatically assigned to the forms to display if they are
minimised. Although the icons for each window can be changed via their icon property, the
icons on the project window do not change.

Visual Basic Book 6 © Mark Collins 1999 Page 10


MDI at Run-Time
As previously mentioned, MDI Child forms are displayed within the internal area of the MDI
Form. If a MDIChild form is minimised it appears as an icon within the MDI Form. If the
MDI Form is minimised it appears as a single icon on the desktop, restoring it restores the
MDIChild forms to the state they were in previously.
If a MDIChild form is maximised it maximises to fill the MDI form. The MDIChild and
parent captions are merged into a single title bar with the MDIChild name in square brackets.
You will notice two bars at the top, the title bar has control and Min/Max boxes for the MDI
Form. The menu bar line (empty above) includes control and restore boxes for the MDI child.
If both MDI parent and MDIChild forms have menus the parents menu will only display if
there is no active MDIChild. Instantiating a MDIChild form causes the parents menu to be
replaced by the MDIChild menu. If the MDIChild has no menu the parents menu remains. If
the parent has no menu it will adopt the MDIChilds menu.
Whilst on the subject of menus, don’t forget that you can create a menu item that lists the
active MDIChild windows by setting its WindowList property to True. As we will discuss
later this can also let us switch between active forms.

Instances of Forms
Most of what we discussed earlier about multiple instances of standard forms can be applied
to MDI Child forms (form variables, Me keyword, collections and arrays). We do not need to
consider the subject of multiple MDI Parent Forms as we can have only one Form Type that
is an MDI form in an application and only one instance of that type.
We need to consider how to launch MDI Forms however. This can be done in several ways...
• Set the MDI Form to be the start-up form
• Load a new MDIChild form, the MDI form is loaded automatically
• Load it from Sub Main or another procedure using code

Visual Basic Book 6 © Mark Collins 1999 Page 11


Arranging MDIChild Forms
There is a specific method that allows you to arrange your MDIChild windows and icons.
This is the Arrange Method and uses the following syntax...
frmRef.Arrange mode
The mode determines the type of arrangement and takes the following values

Value Constant Effect


0 vbCascade Cascades the non-minimised MDIChild forms
diagonally overlapping
1 vbTileHorizontal The non-minimised MDIChild forms are tiled
across the MDI form Internal area
2 vbTileVertical As 1 except vertically
3 vbArrangeIcons Neatly align minimised form icons

An MDI application will often include a Window menu that includes options for each of the
above as well as a window list for switching active forms.

Dirty, Dirty!
When you have several documents / forms active you should consider placing safeguards that
warn you if you try to unload a form with data that hasn’t been saved.
One recommended technique is to use a state flag, usually implemented as a form level
variable called Dirty. This variable (of type Integer) is set to True when the form data is
altered and to False when the data is saved.
When a form of any type is closed two event procedures are activated...
• QueryUnload - before the Unload is carried out
• Unload - when actually unloaded
In QueryUnload we can check on the value of Dirty and if True allow the user to proceed
without saving, or save then unload or to cancel the unload process.
In the world of MDI we can unload a MDIChild form individually. If we unload the MDI
Form it automatically unloads each MDIChild in turn before unloading itself. The whole
process can be cancelled at any stage by a MDIChild form’s QueryUnload.

Visual Basic Book 6 © Mark Collins 1999 Page 12


Exercises
Preparation
For this session you should prepare project directories called...
• Toggle
• formvars
• MDIvars

Exercise 1
This exercise shows how to pass a specific control type to a procedure, in this case a
Command Button type.
1 Place four command buttons on your form.
2 Name them cmd1 to cmd4 (do not place them in a control array). Give them captions
of "1" to "4"
3 Create a general procedure as follows...
Sub Toggle_Button (PassedButton As CommandButton)
PassedButton.Enabled = Not PassedButton.Enabled
End Sub
4 Add code to each buttons click procedure that calls our Toggle_Button procedure
passing a reference to another button similar to...
Toggle_Button cmd3
So that...
cmd1_click passes a reference to cmd3
cmd2_click passes a reference to cmd1
cmd3_click passes a reference to cmd4
cmd4_click passes a reference to cmd2
5 Run your code. Save it as toggle.frm and toggle.vbp.

Visual Basic Book 6 © Mark Collins 1999 Page 13


Exercise 2
The project we are about to create will load instances of a single form. This is not an MDI
project.
1 Start a new project called formvars.
2 Your first form is going to show a list of active forms. Change the name of the form
to listforms and give it the caption "List of Forms". Place a single list box on it.
3 Create a new code module. In the code module create a general procedure as
follows...

Sub update_list ()
listform!List1.Clear
For n = 0 To Forms.Count - 1
listform!List1.AddItem Forms(n).Caption
Next n
End Sub

4 Now create another form, this will be the one we are going to load multiple instances
of at run-time. Place two command buttons on the new form and use the following
property settings.

Type Name Caption Other...


Form formPrototype blank
Command Button command1 Clone
command2 Kill me
5 Edit various procedures and definitions as follows...
in [general] / [declarations]
Dim spawned As Integer

Sub Form_Load ()
spawned = 0
End Sub

Sub Command1_Click ()
Dim NewForm As formPrototype
Set NewForm = New formPrototype
spawned = spawned + 1
NewForm.Caption = Me.Caption & "." & spawned
NewForm.Move Left + 360, Top + 360
NewForm.Show
update_list
End Sub

Sub Command2_Click ()
Unload Me
update_list
End Sub

Visual Basic Book 6 © Mark Collins 1999 Page 14


6 Return to your first form, formlist and edit the following procedure to load the first
instance of our second form.
Sub Form_Load ()
Dim NewForm As formPrototype
Set NewForm = New formPrototype
NewForm.Caption = "Orig"
NewForm.Show
update_list
End Sub

7 Save your hard work as...


• formlist.frm - the list form
• formvars.frm - the cloning form called formPrototype
• formvars.bas - the code module
• formvars.mak - the project

8 Run your application. Try cloning and killing various combinations of forms. Move
the forms about to ensure you don't lose any.
Exercise 3 - taking it further
MDIvars
For this exercise you should take a copy of the previous example's files and alter it to become
an MDI application where the prototypes are child forms. You will need to create a new
MDIForm and make the prototype form an MDI child form (look for the property).
Try adding a menu that shows the list of active child windows. How about a quit option too.
While you are about it why not get rid of those space consuming buttons and create a menu
option for loading and unloading instances.
Add a text box to your child forms to prove that they are independent and have their own
data. So that you can enter a decent amount of text make it multiline and add the code to
make it fill the child window.
If you've got this far just consider how much you've done. How long would it have taken you
using C, C++ or Pascal?

Visual Basic Book 6 © Mark Collins 1999 Page 15

You might also like