Wednesday 24 June 2009

Working with projects and controls in VB6

A VB project contains one or more forms and/or modules which make up a complete VB application. By default, VB names the project "Project1", but you can rename the project by going to Project à Project1 Properties on the VB menu, which will open the following dialog box:
On the General tab of the Project Properties dialog box, let's change the name from "Project1" to prjFirst. When you are done, click OK to dismiss the dialog box.

Now that we have the IDE just the way we want it and a proper project name to work under, let's explore the basic windows that comprise the VB IDE.

The Form

The form is the heart of your VB application; it is the "screen" or "window" that your users will interact with. You can think of the form as a "canvas" on which you will place the various objects that make up your application. When you start a new project, VB automatically supplies you with one form to work with; more forms can be added as needed (the first few examples in this manual will only use one form). Before we start adding objects to the form, let's set some of its properties, using the Properties window.

The Properties Window

The Properties window lets you change the characteristics, or property settings, of the form itself and of visual interface elements on the form. The Properties window consists of two columns: the first is the name of the property, which you cannot change; the second column, which is the property setting that you can change.

Make sure the form is the active window (click on its title bar if necessary), then locate the Properties window. On the Properties window, change the (Name) property to frmFirst, as shown below:


VB objects are automatically given a "numeric name" (like "Form1", "Form2", etc.). It is good programming practice to rename these objects to something more meaningful.

Change the Caption property to My First Program:


Note that the title bar of the form changes accordingly:



The Toolbox

The toolbox (shown below), consists of the various objects that you will use to design your application. These objects, called controls, are objects that you see in all standard Windows applications, such as textboxes, command buttons, option (radio) buttons, checkboxes, etc.


Understanding the MsgBox command in Visual Basic

NOTE: This tutorial uses The VB Test Harness. If you have not already created this test harness please do so first. It will make this tutorial a lot easier to follow.
This VB6 tutorial explains how to use the MsgBox function in Visual Basic. The MsgBox function displays a message in a dialog box, waits for the user to click a button, and returns an Integer indicating which button the user clicked.

Syntax:
MsgBox(prompt[, buttons] [, title] [, helpfile, context])

The MsgBox function syntax has these parts:

Part
Description
prompt
Required. String expression displayed as the message in the dialog box. The maximum length of prompt is approximately 1024 characters, depending on the width of the characters used.
buttons
Optional. Numeric expression that is the sum of values specifying the number and type of buttons to display, the icon style to use, the identity of the default button, and the modality of the message box. If omitted, the default value for buttons is 0 (which causes only an OK button to be displayed with no icon). The buttons argument is explained in more detail below.
title
Optional. String expression displayed in the title bar of the dialog box. If you omit title, the application name is placed in the title bar.
helpfile and context
Both optional. These arguments are only applicable when a Help file has been set up to work with the application.

The buttons argument
The first group of values (0–5) describes the number and type of buttons displayed in the dialog box; the second group (16, 32, 48, 64) describes the icon style; the third group (0, 256, 512, 768) determines which button is the default; and the fourth group (0, 4096) determines the modality of the message box. When adding numbers to create a final value for the buttons argument, use only one number from each group.

First Group - Determines which buttons to display:

Constant
Value
Description
vbOKOnly
0
Display OK button only.
vbOKCancel
1
Display OK and Cancel buttons.
vbAbortRetryIgnore
2
Display Abort, Retry, and Ignore buttons.
vbYesNoCancel
3
Display Yes, No, and Cancel buttons.
vbYesNo
4
Display Yes and No buttons.
vbRetryCancel
5
Display Retry and Cancel buttons.

Second Group - Determines which icon to display:

Constant
Value
Description
Icon
vbCritical
16
Display Critical Message icon.
vbQuestion
32
Display Warning Query (question mark) icon.
vbExclamation
48
Display Warning Message icon.
vbInformation
64
Display Information Message icon.

Third Group - Determines which button is the default:

Constant
Value
Description
vbDefaultButton1
0
First button is default.
vbDefaultButton2
256
Second button is default.
vbDefaultButton3
512
Third button is default.
vbDefaultButton4
768
Fourth button is default (applicable only if a Help button has been added).

Fourth Group Determines the modality of the message box. Note – generally, you would not need to use a constant from this group, as you would want to use the default (application modal). If you specified "system modal", you would be "hogging" Windows – i.e., if a user had another app open, like Word or Excel, they would not be able to get back to it until they responded to your app's message box.

Constant
Value
Description
vbApplicationModal
0
Application modal; the user must respond to the message box before continuing work in the current application.
vbSystemModal
4096
System modal; all applications are suspended until the user responds to the message box.

There is a fifth group of constants that can be used for the buttons argument which would only be used under special circumstances:

Constant
Value
Description
vbMsgBoxHelpButton
16384
Adds Help button to the message box
VbMsgBoxSetForeground
65536
Specifies the message box window as the foreground window
vbMsgBoxRight
524288
Text is right aligned
vbMsgBoxRtlReading
1048576
Specifies text should appear as right-to-left reading on Hebrew and Arabic systems

When you use MsgBox to with the option to display more than one button (i.e., from the first group, anything other than "vbOKOnly"), you can test which button the user clicked by comparing the return value of the Msgbox function with one of these values:

Constant
Value
Description
vbOK
1
The OK button was pressed
vbCancel
2
The Cancel button was pressed
vbAbort
3
The Abort button was pressed
vbRetry
4
The Retry button was pressed
vbIgnore
5
The Ignore button was pressed
vbYes
6
The Yes button was pressed
vbNo
7
The No button was pressed
Note: To try any of the MsgBox examples, you can simply start a new project, double-click on the form, and place the code in the Form_Load event.

There are two basic ways to use MsgBox, depending on whether or not you need to know which button the user clicked.

· If you do NOT need to test which button the user clicked (i.e., you displayed a message box with only an OK button), then you can use MsgBox as if you were calling a Sub. You can use the following syntax:

Msgbox arguments
-or-
Call MsgBox(arguments)

Examples:

o The statement

MsgBox "Hello there!"
causes the following box to be displayed
This is the simplest use of MsgBox: it uses only the required prompt argument. Since the buttons argument was omitted, the default (OK button with no icons) was used; and since the title argument was omitted, the default title (the project name) was displayed in the title bar.

o The statement

MsgBox "The Last Name field must not be blank.", _
vbExclamation, _
"Last Name"
causes the following box to be displayed:


This is how a data entry error might be displayed. Note that vbExclamation was specified for the buttons argument to specify what icon should be displayed – the fact that we did not add a value from the first group still causes only the OK button to be displayed. If you wanted to explicitly indicate that only the OK button should be displayed along with the exclamation icon, you could have coded the second argument as

vbExclamation + vbOKOnly
making the full statement read:

MsgBox "The Last Name field must not be blank.", _
vbExclamation + vbOKOnly, _
"Last Name"

Remember, for the buttons argument, you can add one value from each of the four groups.

An alternative (not recommended) is to use the hard-coded number for the buttons argument, as in:

MsgBox "The Last Name field must not be blank.", 48, "Last Name"

Note also that this example provided a value for the title argument ("Last Name"), which causes that text to be displayed in the box's title bar.

The format of the MsgBox statement used in this example could also be used for more critical errors (such as a database problem) by using the vbCritical icon. You may also want to use the name of the Sub or Function in which the error occurred for your title argument.

Example:

MsgBox "A bad database error has occurred.", _
vbCritical, _
"UpdateCustomerTable"

Result:


· If you DO need to test which button the user clicked (i.e., you displayed a message box with more than one button), then you must use MsgBox as a function, using the following syntax:

IntegerVariable = Msgbox (arguments)

One of the more common uses of MsgBox is to ask a Yes/No question of the user and perform processing based on their response, as in the following example:

Dim intResponse As Integer

intResponse = MsgBox("Are you sure you want to quit?", _
vbYesNo + vbQuestion, _
"Quit")

If intResponse = vbYes Then
End
End If

The following message box would be displayed:


After the user clicks a button, you would test the return variable (intResponse) for a value of vbYes or vbNo (6 or 7).

Note that the use of the built-in constants makes the code more readable. The statement

intResponse = MsgBox("Are you sure you want to quit?", _
vbYesNo + vbQuestion, _
"Quit")
is more readable than

intResponse = MsgBox("Are you sure you want to quit?", 36, "Quit")
and

If intResponse = vbYes Then

is more readable than

If intResponse = 6 Then


In that you can use a function anywhere a variable can be used, you could use the MsgBox function directly in an if statement without using a separate variable to hold the result ("intResponse" in this case). For example, the above example could have been coded as:

If MsgBox("Are you sure you want to quit?", _
vbYesNo + vbQuestion, _
"Quit")= vbYes Then
End
End If

Note: If desired you could place the code for this example in the cmdExit_Click event of any of the "Try It" projects.

Following is an example using the vbDefaultButton2 constant:

Dim intResponse As Integer

intResponse = MsgBox("Are you sure you want to delete all of the rows " _
& "in the Customer table?", _
vbYesNo + vbQuestion + vbDefaultButton2, _
"Delete")

If intResponse = vbYes Then
' delete the rows ...
End If

The message box displayed by this example would look like this:

he sample project for this topic contains a command button for each MsgBox example given above.


Introducing the VB6 IDE

Once you click "Open" on the New Project dialog box, the IDE will look something like the screen-shot shown below. You'll notice that the IDE contains a main menu bar and several windows (toolbox, form, project explorer, and properties). You can customize the IDE to some degree to work according to your preferences, which I will address in the next section.
The VB6 IDE (which was first introduced in VB5, and has not significantly changed in VB6) is by default, an MDI (Multiple Document Interface) application, where the various windows are "docked" at certain locations of the screen and can interlock with each other (for example, the project explorer and the properties window are initially interlocked with each other). This arrangement looks nice and organized upon first glance, and many people do prefer working with VB using this default setup, or are not aware of the alternatives.

In earlier versions of VB, the IDE was an SDI (Single Document Interface), where each of these windows (toolbox, form, project explorer, and properties window) would float "independently" on the Windows desktop. I found it easy to move from window to window to get to what I needed, and it was particularly easy to design the forms. With the VB5/VB6 default setup, I feel "boxed in" when designing a form, and if you move one of the other windows (like the Properties window), you may find that it will "re-dock" itself in an area of the screen that you didn't expect, re-arranging all of the other windows – this I find frustrating. Fortunately, the IDE can be customized to use an SDI arrangement as well as to set other preferences.

VB6 Variable Scope

The syntax for declaring a variable in VB is as follows:

[Dim Private Public Static Global] variablename [As datatype]

Note that you use one of five keywords to declare a variable; which one you use depends on the scope you want the variable to have. There are three levels of scope:
· project-level (also called "global" or "application" scope; the variable is accessible to all procedures in all modules of the project)
· module-level (the variable is accessible to all procedures in the module in which it is declared)
· local-level (the variable is accessible only to the procedure in which it is declared)

In addition to the keyword used to declare the variable, the location of the variable declaration also affects its scope. A variable may be declared in one of two places:

· The General Declarations Section of a form or standard module. This section of a module is not labeled as such; it simply exists at the beginning of a code module, after the "Option Explicit" statement but prior to the first Sub or Function procedure. Declaring a variable here makes it a project-level variable (if the Public or Global keyword is used) or a module-level variable (if the Private or Dim keyword is used).

· Within a Sub or Function procedure. Declaring a variable here makes it a local-level variable; only the Dim or Static keyword can be used here. The recommended practice is to declare all local variables within a procedure immediately following the Sub or Function header and prior to any executable statements (although VB will allow you to declare variables anywhere within the procedure).

The following table shows how the five different declarative keywords and the location of their declaration affects the scope:

Keyword Used to Declare the
Variable:
$
Where Declared
à

General Declarations Section of a Form (.frm) Module

General Declarations Section of a Standard (.bas) Module

Sub or Function procedure of a Form or Standard Module
Dim (preferred keyword for local-, but not module-level variables)
module-level scope
module-level scope
local-level scope (value of the variable is NOT preserved between calls
Static
not allowed
not allowed
local-level scope (value of the variable is preserved between calls)
Private (preferred keyword for module-level variables)
module-level scope
module-level scope
not allowed


Public
project-level scope (but references to the variable must be qualified with the form name; also there are some minor restrictions on the types of variables that can be declared as public in a form)

project-level scope

not allowed
Global (the use of this keyword is discouraged; it remains only for compatibility with older versions of VB)

not allowed

project-level scope

not allowed

If the "As datatype" clause is omitted in a variable declaration, the variable type defaults to Variant, unless a type declaration character is used. For example, the following two statements both declare an integer called "intCounter" (the "As" version is preferred):

Dim intCounter As Integer
Dim intCounter%

The following two statements both declare a Variant variable called "vntWhatever":

Dim vntWhatever As Variant
Dim vntWhatever

String variables can be either variable-length or fixed-length. The difference in declaring them is shown below:

'Variable-length string, length changes depending upon length of whatever is assigned to it:
Dim strPlayerName As String

'Fixed-length string, always 2 bytes. Pads or truncates accordingly.
Dim strStateAbbrev As String * 2


Multiple Declarations on One Line

VB allows you to declare any number of variables on one line – but there is a caveat: you must explicitly provide the data type of each variable, even if all the variables are the same data type. For example, you may write the following statement with the intention of declaring three integer variables:

Dim intA, intB, intC As Integer

However, the above statement actually declares intA and intB both as Variant; only intC is Integer. The corrected version of the statement would be:

Dim intA As Integer, intB As Integer, intC As Integer

I recommend declaring only one variable per line.

Initialization of Variables

Unlike many other languages, VB does not allow you to initialize variables; this must be done with an executable statement. However, each variable does have a default initialization value. Numeric variable types are initialized to zero, Strings are initialized to "", Booleans are initialized to False, etc.

Statics and Constants in VB6

Statics in Visual Basic
Statics allow you to maintain a variables value even when it goes out of scope. For example:
Suppose you have a Sub in a form called CountThem that looks like this:

Private Sub CountThem()

Dim intI As Integer
Static intJ As Integer
intI = intI + 1
intJ = intJ + 1
Print intI, intJ

End Sub

Suppose you have some other Sub that calls CountThem three times in a row:

Call CountThem
Call CountThem
Call CountThem

The following output would be displayed on the form (by default, the "Print" statement directs its output to the current form):

(values for intI)
(values for intJ)
1
1
1
2
1
3

Note that the "regular" variable, intI, declared with "Dim", does not retain its value between calls, whereas the Static variable, intJ, does.

Note: The keyword "Static" can also be used in the Sub procedure header, which causes all variables in that procedure to be static. Example:

Private Static Sub AllVarsAreStatic()
Dim intCounter As Integer ' as if declared Static
Dim strErrMsg As String ' as if declared Static
. . . ' other statements
End Sub

Constants
VB supports the use of symbolic, or named constants. Constants are similar to variables, except that you provide a value for the constant when you declare it, and its value can never change. The syntax for declaring a constant is:

[Public Global Private] Const constantname [As datatype] = expression

A global (project-level) constant can only be declared in a standard (.bas) module (not a form), using "Public Const" or "Global Const" (the "Public" keyword is preferred). Module-level constants can be declared in the General Declarations Section of either a standard or form code module using "Private Const" (or just "Const"; the default is "Private"). Local-level constants are declared in any procedure of a standard or form module just using the word "Const" (no "Public" or "Private"). If you omit the "As datatype" clause, VB will use its "best guess" as to what the datatype should be, based on the expression.

The following table shows how constants may be declared and the location of their declaration affects the scope:


Keyword Used to Declare the
Constant:
$
Where Declared
à

General Declarations Section of a Form (.frm) Module

General Declarations Section of a Standard (.bas) Module

Sub or Function procedure of a Form or Standard Module
Const
module-level scope
module-level scope
local-level scope

Private Const
module-level scope
module-level scope
not allowed

Public Const
-or –
Global Const

not allowed

project-level scope

not allowed


Sample Constant Declarations:

Public Const gsngTAX_RATE As Single = 0.06

Private Const mdtmCUT_OFF_DATE As Date = #1/1/1980#

Const strERROR_MESSAGE = "Invalid Data" 'String data type assumed

Note that in Const declarations, string literals are delimited with double quotes ("), date literals are delimited with pound signs (#), and numeric literals are not delimited.

Naming Conventions for Constants

Similar to naming variables, use the lowercase three-character datatype prefix ("int", "str", etc.), prefixed by an "m" if a module-level constant or "g" if a global (project-level) constant. However, for the main part of the name, use all capital letters (with underscores to break up individual words within the name).