Académique Documents
Professionnel Documents
Culture Documents
• Menu Bar
• Tool Bar
• Project Explorer
• Properties window
• Form Layout Window
• Toolbox
• Form Designer
• Object Browser
In previous versions of Visual Basic, the IDE was designed as a Single Document Interface (SDI).
In a Single Document Interface, each window is a free-floating window that is contained within a
main window and can move anywhere on the screen as long as Visual Basic is the current
application. But, in Visual Basic 6.0, the IDE is in a Multiple Document Interface (MDI) format. In
this format, the windows associated with the project will stay within a single container known as
the parent. Code and form-based windows will stay within the main container form.
Toolbox
The Toolbox contains a set of controls that are used to place on a Form at design time thereby
creating the user interface area. Additional controls can be included in the toolbox by using the
Components menu item on the Project menu. A Toolbox is represented in figure 2 shown below.
Control Description
Pointer Provides a way to move and resize the controls form
Displays icons/bitmaps and metafiles. It displays text or acts as a
PictureBox
visual container for other controls.
TextBox Used to display message and enter text.
Frame Serves as a visual and functional container for controls
CommandButton Used to carry out the specified action when the user chooses it.
CheckBox Displays a True/False or Yes/No option.
OptionButton control which is a part of an option group allows the
OptionButton
user to select only one option even it displays mulitiple choices.
ListBox Displays a list of items from which a user can select one.
ComboBox Contains a TextBox and a ListBox. This allows the user to select an
ietm from the dropdown ListBox, or to type in a selection in the
TextBox.
HScrollBar and These controls allow the user to select a value within the specified
VScrollBar range of values
Timer Executes the timer events at specified intervals of time
Displays the valid disk drives and allows the user to select one of
DriveListBox
them.
Allows the user to select the directories and paths, which are
DirListBox
displayed.
FileListBox Displays a set of files from which a user can select the desired one.
Shape Used to add shape (rectangle, square or circle) to a Form
Line Used to draw straight line to the Form
used to display images such as icons, bitmaps and metafiles. But
Image
less capability than the PictureBox
Enables the use to connect to an existing database and display
Data
information from it.
Used to link or embed an object, display and manipulate data from
OLE
other windows based applications.
Label Displays a text that the user cannot modify or interact with.
Project Explorer
Docked on the right side of the screen, just under the tollbar, is the Project Explorer window. The
Project Explorer as shown in in figure servres as a quick reference to the various elements of a
project namely form, classes and modules. All of the object that make up the application are
packed in a project. A simple project will typically contain one form, which is a window that is
designed as part of a program's interface. It is possible to develop any number of forms for use in
a program, although a program may consist of a single form. In addition to forms, the Project
Explorer window also lists code modules and classes.
Properties Window
The Properties Window is docked under the Project Explorer window. The Properties Window
exposes the various characteristics of selected objects. Each and every form in an application is
considered an object. Now, each object in Visual Basic has characteristics such as color and
size. Other characteristics affect not just the appearance of the object but the way it behaves too.
All these characteristics of an object are called its properties. Thus, a form has properties and any
controls placed on it will have propeties too. All of these properties are displayed in the Properties
Window.
Object Browser
The Object Browser allows us to browse through the various properties, events and methods that
are made available to us. It is accessed by selecting Object Browser from the View menu or
pressing the key F2. The left column of the Object Browser lists the objects and classes that are
available in the projects that are opened and the controls that have been referenced in them. It is
possible for us to scroll through the list and select the object or class that we wish to inspect. After
an object is picked up from the Classes list, we can see its members (properties, methods and
events) in the right column.
A property is represented by a small icon that has a hand holding a piece of paper. Methods are
denoted by little green blocks, while events are denoted by yellow lightning bolt icon.
Form -frm
Label-lbl
TextBox-txt
CommandButton-cmd
CheckBox -chk
OptionButton -opt
ComboBox -cbo
ListBox-lst
Frame-fme
PictureBox -pic
Image-img
Shape-shp
Line -lin
HScrollBar -hsb
VScrollBar -vsb
Related Topic
Visual Basic uses building blocks such as Variables, Data Types, Procedures, Functions and
Control Structures in its programming environment. This section concentrates on the
programming fundamentals of Visual Basic with the blocks specified.
Modules
Code in Visual Basic is stored in the form of modules. The three kind of modules are Form
Modules, Standard Modules and Class Modules. A simple application may contain a single Form,
and the code resides in that Form module itself. As the application grows, additional Forms are
added and there may be a common code to be executed in several Forms. To avoid the
duplication of code, a separate module containing a procedure is created that implements the
common code. This is a standard Module.
Class module (.CLS filename extension) are the foundation of the object oriented programming in
Visual Basic. New objects can be created by writing code in class modules. Each module can
contain:
Declarations : May include constant, type, variable and DLL procedure declarations.
Procedures : A sub function, or property procedure that contain pieces of code that can be
executed as a unit.
These are the rules to follow when naming elements in VB - variables, constants, controls,
procedures, and so on:
1. Numeric
2. String
Use to store alphanumeric values. A variable length string can store approximately 4 billion
characters
3. Date
Use to store date and time values. A variable declared as date type can store both date and time
values and it can store date values 01/01/0100 up to 12/31/9999
4. Boolean
Boolean data types hold either a true or false value. These are not stored as numeric values and
cannot be used as such. Values are internally stored as -1 (True) and 0 (False) and any non-zero
value is considered as true.
5. Variant
Stores any type of data and is the default Visual Basic data type. In Visual Basic if we declare a
variable without any data type by default the data type is assigned as default.
+ Add 5+5 10
- Substract 10-5 5
/ Divide 25/5 5
* Multiply 5*4 20
Relational Operators
Operators Description
AND Operation will be true only if both the operands are true
Related Topics
Variables are the memory locations which are used to store values temporarily. A defined naming
strategy has to be followed while naming a variable. A variable name must begin with an alphabet
letter and should not exceed 255 characters. It must be unique within the same scope. It should
not contain any special character like %, &, !, #, @ or $.
There are many ways of declaring variables in Visual Basic. Depending on where the variables
are declared and how they are declared, we can determine how they can be used by our
application. The different ways of declaring variables in Visual Basic are listed below and
elucidated in this section.
• Explicit Declaration
• Using Option Explicit statement
• Scope of Variables
Explicit Declaration
Declaring a variable tells Visual Basic to reserve space in memory. It is not must that a variable
should be declared before using it. Automatically whenever Visual Basic encounters a new
variable, it assigns the default variable type and value. This is called implicit declaration. Though
this type of declaration is easier for the user, to have more control over the variables, it is
advisable to declare them explicitly. The variables are declared with a Dim statement to name the
variable and its type. The As type clause in the Dim statement allows to define the data type or
object type of the variable. This is called explicit declaration.
Syntax
For example,
Intcount = Intcount + 1
This calculation will result in intcount yielding a value of 1 as intcount would have been initialized
to zero. This is because the intcount variable has been mityped as incont in the right hand side of
the second variable. But Visual Basic does not see this as a mistake and considers it to be new
variable and therefore gives a wrong result.
In Visual Basic, to prevent errors of this nature, we can declare a variable by adding the following
statement to the general declaration section of the Form.
Option Explicit
This forces the user to declare all the variables. The Option Explicit statement checks in the
module for usage of any undeclared variables and reports an error to the user. The user can thus
rectify the error on seeing this error message.
The Option Explicit statement can be explicitly placed in the general declaration section of each
module using the following steps.
Scope of variables
A variable is scoped to a procedure-level (local) or module-level variable depending on how it is
declared. The scope of a variable, procedure or object determines which part of the code in our
application are aware of the variable's existence. A variable is declared in general declaration
section of e Form, and hence is available to all the procedures. Local variables are recognized
only in the procedure in which they are declared. They can be declared
with Dim and Static keywords. If we want a variable to be available to all of the procedures within
the same module, or to all the procedures in an application, a variable is declared with broader
scope.
Local Variables
A local variable is one that is declared inside a procedure. This variable is only available to the
code inside the procedure and can be declared using the Dim statements as given below.
The local variables exist as long as the procedure in which they are declared, is executing. Once
a procedure is executed, the values of its local variables are lost and the memory used by these
variables is freed and can be reclaimed. Variables that are declared with keyword Dim exist only
as long as the procedure is being executed.
Static Variables
Static variables are not reinitialized each time Visual Invokes a procedure and therefore retains or
preserves value even when a procedure ends. In case we need to keep track of the number of
times a command button in an application is clicked, a static counter variable has to be declared.
These static variables are also ideal for making controls alternately visible or invisible. A static
variable is declared as given below.
Variables have a lifetime in addition to scope. The values in a module-level and public variables
are preserved for the lifetime of an application whereas local variables declared with Dim exist
only while the procedure in which they are declared is still being executed. The value of a local
variable can be preserved using the Static keyword. The follwoing procedure calculates the
running total by adding new values to the previous values stored in the static variable value.
Function RunningTotal ( )
Static Accumulate
Accumulate = Accumulate + num
RunningTotal = Accumulate
End Function
If the variable Accumulate was declared with Dim instead of static, the previously accumulated
values would not be preserved accross calls to the procedure, and the procedure would return
the same value with which it was called. To make all variables in a procedure static, the Static
keyword is placed at the beginning of the procedure heading as given in the below statement.
Example
The following is an example of an event procedure for a CommandButton that counts and
displays the number of clicks made.
The first time we click the CommandButton, the Counter starts with its default value of zero.
Visual Basic then adds 1 to it and prints the result.
A module level variable is available to all the procedures in the module. They are declared using
the Public or the Privatekeyword. If you declare a variable using a Private or a Dim statement in
the declaration section of a module—a standard BAS module, a form module, a class module,
and so on—you're creating a private module-level variable. Such variables are visible only from
within the module they belong to and can't be accessed from the outside. In general, these
variables are useful for sharing data among procedures in the same module:
' In the declarative section of any module
Private LoginTime As Date ' A private module-level variable
Dim LoginPassword As String ' Another private module-level variable
You can also use the Public attribute for module-level variables, for all module types except BAS
modules. (Public variables in BAS modules are global variables.) In this case, you're creating a
strange beast: a Public module-level variable that can be accessed by all procedures in the
module to share data and that also can be accessed from outside the module. In this case,
however, it's more appropriate to describe such a variable as a property:
You can access a module property as a regular variable from inside the module and as a custom
property from the outside:
The lifetime of a module-level variable coincides with the lifetime of the module itself. Private
variables in standard BAS modules live for the entire life of the application, even if they can be
accessed only while Visual Basic is executing code in that module. Variables in form and class
modules exist only when that module is loaded in memory. In other words, while a form is active
(but not necessarily visible to the user) all its variables take some memory, and this memory is
released only when the form is completely unloaded from memory. The next time the form is re-
created, Visual Basic reallocates memory for all variables and resets them to their default values
(0 for numeric values, "" for strings, Nothing for object variables).
It is easier to debug a program a program with procedures, which breaks a program into discrete
logical limits.
Procedures used in one program can act as building blocks for other programs with slight
modifications.
Sub Procedures
A sub procedure can be placed in standard, class and form modules. Each time the procedure is
called, the statements between Sub and End Sub are executed. The syntax for a sub procedure
is as follows:
[Private | Public] [Static] Sub Procedurename [( arglist)]
[ statements]
End Sub
arglist is a list of argument names separated by commas. Each argument acts like a variable in
the procedure. There are two types of Sub Procedures namely general procedures and event
procedures.
Event Procedures
An event procedure is a procedure block that contains the control's actual name, an
underscore(_), and the event name. The following syntax represents the event procedure for a
Form_Load event.
General Procedures
A general procedure is declared when several event procedures perform the same actions. It is a
good programming practice to write common statements in a separate procedure (general
procedure) and then call them in the event procedure.
• The Code window is opened for the module to which the procedure is to be added.
• The Add Procedure option is chosen from the Tools menu, which opens an Add
Procedure dialog box as shown in the figure given below.
• The name of the procedure is typed in the Name textbox
• Under Type, Sub is selected to create a Sub procedure, Function to create a Function
procedure or Property to create a Property procedure.
• Under Scope, Public is selected to create a procedure that can be invoked outside the
module, or Private to create a procedure that can be invoked only from within the module.
We can also create a new procedure in the current module by typing Sub ProcedureName,
Function ProcedureName, or Property ProcedureName in the Code window. A Function
procedure returns a value and a Sub Procedure does not return a value.
Function Procedures
Functions are like sub procedures, except they return a value to the calling procedure. They are
especially useful for taking one or more pieces of data, called arguments and performing some
tasks with them. Then the functions returns a value that indicates the results of the tasks
complete within the function.
The following function procedure calculates the third side or hypotenuse of a right triangle, where
A and B are the other two sides. It takes two arguments A and B (of data type Double) and finally
returns the results.
The above function procedure is written in the general declarations section of the Code window.
A function can also be written by selecting the Add Procedure dialog box from the Tools menu
and by choosing the required scope and type.
Property Procedures
A property procedure is used to create and manipulate custom properties. It is used to create
read only properties for Forms, Standard modules and Class modules.Visual Basic provides three
kind of property procedures-Property Let procedure that sets the value of a property, Property
Get procedure that returns the value of a property, and Property Set procedure that sets the
references to an object.
Control Statements are used to control the flow of program's execution. Visual Basic supports
control structures such as if... Then, if...Then ...Else, Select...Case, and Loop structures such as
Do While...Loop, While...Wend, For...Next etc method.
If <condition> Then
statement
End If
Method 1
Method 2
e.g.: Assume you have to find the grade using select...case and display in the text box
average = txtAverage.Text
Select Case average
Case 100 To 75
txtGrade.Text ="A"
Case 74 To 65
txtGrade.Text ="B"
Case 64 To 55
txtGrade.Text ="C"
Case 54 To 45
txtGrade.Text ="S"
Case 44 To 0
txtGrade.Text ="F"
Case Else
MsgBox "Invalid average marks"
End Select
Note: In this example I have used a message box function. In later lessons you will learn
how to use message Do While... Loop Statement
The Do While...Loop is used to execute statements until a certain condition is met. The following
Do Loop counts from 1 to 100.
A variable number is initialized to 1 and then the Do While Loop starts. First, the condition is
tested; if condition is True, then the statements are executed. When it gets to the Loop it goes
back to the Do and tests condition again. If condition is False on the first pass, the statements are
never executed.
number = 1
While number <=100
number = number + 1
Wend
Do Until...Loop Statement
Unlike the Do While...Loop and While...Wend repetition structures, the Do Until...
Loop structure tests a condition for falsity. Statements in the body of a Do Until...Loop are
executed repeatedly as long as the loop-continuation test evaluates to False.
An example for Do Until...Loop statement. The coding is typed inside the click event of the
command button
Numbers between 1 to 1000 will be displayed on the form as soon as you click on the command
button.
Dim x As Integer
For x = 1 To 50
Print x
Next
In order to count the numbers from 1 yo 50 in steps of 2, the following loop can be used
For x = 1 To 50 Step 2
Print x
Next
The above coding will display numbers vertically on the form. In order to display numbers
horizontally the following method can be used.
For x = 1 To 50
Print x & Space$ (2);
Next
To increase the space between the numbers increase the value inside the brackets after the &
Space$.
Following example is a For...Next repetition structure which is with the If condition used.
In the output instead of number 4 you will get the "This is number 4".
box functions. For...Next loop condition can be terminated by an Exit Forstatement. Consider
the following statement block.
Dim x As Integer
For x = 1 To 10
Print x
If x = 5 Then
Print "The program exited at x=5"
Exit For
End If
Next
The preceding code increments the value of x by 1 until it reaches the condition x = 5. The Exit
For statement is executed and it terminates the For...Next loop. The Following statement block
containing Do...While loop is terminated using Exit Do statement.
Dim x As Integer
Do While x < 10
Print x
x = x + 1
If x = 5 Then
Print "The program is exited at x=5"
Exit Do
End If
Loop
With Text1
.Font.Size = 14
.Font.Bold = True
.ForeColor = vbRed
.Height = 230
.Text = "Hello World"
End With
In the above coding, the object Text1, which is a text box is evaluated only once instead of every
associated property or method. This makes the coding simpler and efficient.
An array is a consecutive group of memory locations that all have the same name and the same
type. To refer to a particular location or element in the array, we specify the array name and the
array element position number.
The Individual elements of an array are identified using an index. Arrays have upper and lower
bounds and the elements have to lie within those bounds. Each index number in an array is
allocated individual memory space and therefore users must evade declaring arrays of larger size
than required. We can declare an array of any of the basic data types including variant, user-
defined types and object variables. The individual elements of an array are all of the same data
type.
Declaring arrays
Arrays occupy space in memory. The programmer specifies the array type and the number of
elements required by the array so that the compiler may reserve the appropriate amount of
memory. Arrays may be declared as Public (in a code module), module or local. Module arrays
are declared in the general declarations using keyword Dim or Private. Local arrays are declared
in a procedure using Dim or Static. Array must be declared explicitly with keyword "As".
Fixed-size array : The size of array always remains the same-size doesn't change during the
program execution.
Dynamic array : The size of the array can be changed at the run time- size changes during the
program execution.
Fixed-sized Arrays
When an upper bound is specified in the declaration, a Fixed-array is created. The upper limit
should always be within the range of long data type.
Declaring a fixed-array
In the above illustration, numbers is the name of the array, and the number 6 included in the
parentheses is the upper limit of the array. The above declaration creates an array with 6
elements, with index numbers running from 0 to 5.
If we want to specify the lower limit, then the parentheses should include both the lower and
upper limit along with the To keyword. An example for this is given below.
In the above statement, an array of 10 elements is declared but with indexes running from 1 to 6.
A public array can be declared using the keyword Public instead of Dim as shown below.
Public numbers(5) As Integer
Multidimensional Arrays
Arrays can have multiple dimensions. A common use of multidimensional arrays is to represent
tables of values consisting of information arranged in rows and columns. To identify a particular
table element, we must specify two indexes: The first (by convention) identifies the element's row
and the second (by convention) identifies the element's column.
Tables or arrays that require two indexes to identify a particular element are called two
dimensional arrays. Note that multidimensional arrays can have more than two dimensions.
Visual Basic supports at least 60 array dimensions, but most people will need to use more than
two or three dimensional-arrays.
It is also possible to define the lower limits for one or both the dimensions as for fixed size arrays.
An example for this is given here.
An example for three dimensional-array with defined lower limits is given below.
Visual Basic starts indexing the array with 0. Therefore, the preceding array actually holds 101
items.
Most programs don't use static arrays because programmers rarely know at compile time how
many items you need and also because static arrays can't be resized during execution. Both
these issues are solved by dynamic arrays. You declare and create dynamic arrays in two distinct
steps. In general, you declare the array to account for its visibility (for example, at the beginning
of a module if you want to make it visible by all the procedures of the module) using a Dim
command with an empty pair of brackets. Then you create the array when you actually need it,
using a ReDim statement:
If you're creating an array that's local to a procedure, you can do everything with a single ReDim
statement:
Sub PrintReport()
' This array is visible only to the procedure.
ReDim Customers(1000) As String
' ...
End Sub
If you don't specify the lower index of an array, Visual Basic assumes it to be 0, unless an Option
Base 1 statement is placed at the beginning of the module. My suggestion is this: Never use an
Option Base statement because it makes code reuse more difficult. (You can't cut and paste
routines without worrying about the current Option Base.) If you want to explicitly use a lower
index different from 0, use this syntax instead:
Dynamic arrays can be re-created at will, each time with a different number of items. When you
re-create a dynamic array, its contents are reset to 0 (or to an empty string) and you lose the data
it contains. If you want to resize an array without losing its contents, use the ReDim Preserve
command:
When you're resizing an array, you can't change the number of its dimensions nor the type of the
values it contains. Moreover, when you're using ReDim Preserve on a multidimensional array,
you can resize only its last dimension:
Finally, you can destroy an array using the Erase statement. If the array is dynamic, Visual Basic
releases the memory allocated for its elements (and you can't read or write them any longer); if
the array is static, its elements are set to 0 or to empty strings.
You can use the LBound and UBound functions to retrieve the lower and upper indices. If the
array has two or more dimensions, you need to pass a second argument to these functions to
specify the dimension you need:
Type MyUDT
StaticArr(100) As Long
DynamicArr() As Long
End Type
...
Dim udt As MyUDT
' You must DIMension the dynamic array before using it.
ReDim udt.DynamicArr(100) As Long
' You don't have to do that with static arrays.
udt.StaticArr(1) = 1234
The memory needed by a static array is allocated within the UDT structure; for example, the
StaticArr array in the preceding code snippet takes exactly 400 bytes. Conversely, a dynamic
array in a UDT takes only 4 bytes, which form a pointer to the memory area where the actual data
is stored. Dynamic arrays are advantageous when each individual UDT variable might host a
different number of array items. As with all dynamic arrays, if you don't dimension a dynamic
array within a UDT before accessing its items, you get an error 9—"Subscript out of
range."
Visual Basic lets you store arrays in Variant variables and then access the array items using the
Variant variable as if it were an array:
You can even create an array of Variant elements on the fly using the Array function and store it
in a Variant variable:
Likewise, you can pass an array to a procedure that expects a Variant parameter and then
access the elements of the array through that parameter:
The most interesting feature of the preceding routine is that it works correctly with any type of
numeric one-dimensional array. It even works with String arrays, but in that case you get the
concatenation of all items, not their sum. This procedure is extremely powerful and reduces the
amount of code you have to write to deal with different kinds of arrays. But you should be aware
that accessing array items through a Variant parameter noticeably slows down the execution. If
you need the best performance, write specific routines that process specific types of arrays.
You can also pass a multidimensional array to a routine that expects a Variant parameter. In this
case, you can still access the array elements through the Variants, but if you don't know at
compile time how many dimensions the array has, your routine has to determine that number
before proceeding. You can get this value using a trial-and-error approach:
It's perfectly legal to use the function name inside a function's code as if it were a local variable,
as the previous code snippet does. Often this technique lets you save a local variable and a final
assignment before exiting the routine, which indirectly makes your code run slightly faster.
Here's a modified ArraySum routine that uses NumberOfDims and works with both one- and two-
dimensional arrays:
Often, if a Variant contains an array, you don't know the basic type of that array in advance. The
VarType function returns the sum of the vbArray constant (decimal 8192), plus the VarType of the
data included in the array. This lets you test that the array passed to a routine is of a given type:
You can also test whether a Variant holds an array using the IsArray function. When a Variant
variable holds an array, the TypeName function appends a pair of empty parentheses to its result:
As I've explained, you can either assign an array to a Variant variable or you can pass an array
as a Variant parameter of a procedure. While the two operations look very similar, they're
substantially different. To execute an assignment, Visual Basic makes a physical copy of the
array. As a result, the Variant variable doesn't point to the original data but to the copy; from this
point on, all the manipulations you do through the Variant variable don't affect the original array.
Conversely, if you call a procedure and pass an array as a Variant parameter, no data is
physically copied and the Variant simply works as an alias of the array. You can reorder array
items or modify their values, and your changes are immediately reflected in the original array
Visual Basic 6 adds two important features to arrays. First, you can perform assignments
between arrays. Second, you can write procedures that return arrays. You can assign arrays only
of the same type and only if the target is a dynamic array. (The latter condition is necessary
because Visual Basic might need to resize the target array.)
It's no surprise that native assignment commands are always faster than the corresponding For…
Next loops that copy one item at a time. The actual increment in speed heavily depends on the
data type of the arrays and can vary from 20 percent to 10 times faster. A native assignment
between arrays also works if the source array is held in a Variant. Under Visual Basic 4 and 5,
you could store an array in a Variant, but you couldn't do the opposite—that is, retrieve an array
stored in a Variant variable and store it back in an array of a specific type. This flaw has been
fixed in Visual Basic 6:
You often use the capacity to assign arrays to build functions that return arrays. Notice that pair of
brackets at the end of the first line in the following procedure:
te arrays are somewhat special because Visual Basic lets you directly assign strings to them. In
this case, Visual Basic performs a direct memory copy of the contents of the string. Because all
Visual Basic 5 and 6 strings are Unicode strings (two bytes per character), the target array is
redimensioned to account for the actual string length in bytes (which you can determine using the
LenB function). If the string contains only characters whose code is in the range 0 through 255
(the case if you work with Latin alphabets), every other byte in the array will be 0:
Text = b()
This special treatment reserved for Byte arrays is meant to ease the conversion from old Visual
Basic 3 applications that use strings to hold binary data, as I explained in "The Byte Data Type"
section, earlier in this chapter. You can exploit this feature to create blindingly fast string routines
when you have to process each individual character in a string. For example, see how quickly you
can count all the spaces in a string:
' NOTE: this function might not work with non-Latin alphabets.
Function CountSpaces(Text As String) As Long
Dim b() As Byte, i As Long
b() = Text
For i = 0 To UBound(b) Step 2
' Consider only even-numbered items.
' Save time and code using the function name as a local variable.
If b(i) = 32 Then CountSpaces = CountSpaces + 1
Next
End Function
The preceding routine is about three times faster than a regular routine, which uses Asc and Mid$
functions to process all the characters in the argument, and even faster if you turn on the Remove
Array Bounds Check compiler optimization. The only drawback of this technique is that it isn't
Unicode-friendly because it considers only the least significant byte in each 2-byte character. If
you plan to convert your application to some language that relies on Unicode—Japanese, for
example—you should stay clear of this optimization technique.
Some of the most common operations you perform on arrays are inserting and deleting items,
shifting all the remaining elements toward higher indices to make room or toward lower indices to
fill the "hole" a deletion has left. You usually do this with a For…Next loop, and you can even
write generic array procedures that work with any type of array (with the usual restrictions about
arrays of UDTs and fixed-length strings that can't be passed to a Variant parameter):
If your application works intensively with arrays, you might find that an approach based on For…
Next loops is too slow. In some cases, you can considerably speed up these operations by using
the RtlMoveMemory API function, which many Visual Basic programmers know under its popular
alias name, CopyMemory.1 This function lets you move a block of bytes from one memory
address to another memory address and works correctly even if the two areas partially overlap.
Here's the code that inserts a new item in an array of Longs:
IMPORTANT NOTE: The prerequisite for using the CopyMemory API function is that data must
be stored in contiguous memory locations, so you absolutely can't use it to insert or remove
elements in String and Object arrays, nor in arrays of UDTs that contain conventional strings,
object references, or dynamic arrays. (Fixed-length strings and static arrays in UDTs are OK,
though.)
Note that while you can't use the preceding routines for arrays other than Long arrays, the
statements in the procedure body can be recycled for another data type without any change,
thanks to the use of the LenB function. Therefore, you can derive new array functions that work
for other data types by simply modifying the procedure's name and its parameter list. For
example, you can create a new function that deletes an item in a Double array by editing just the
first line of code (shown in boldface):
Sorting is an operation that you often perform on arrays. As you probably know, there are dozens
of different sort algorithms, each one with its strengths and weaknesses. I found that the Shell
Sort algorithm works well in most cases, and I've prepared a generic routine that sorts any one-
dimensional array of a data type compatible with the Variant type, either in ascending or
descending order:
While you can create two-dimensional arrays in Visual Basic, their structure isn't really flexible for
at least two reasons: All rows in the array must have the same number of elements, and you can
use ReDim Preserve to change the number of columns but you can't add new rows. The first
point is especially important because it often leads you to declare an array that's far too large for
your needs, thus allocating a lot of memory that in most cases remains largely unused. You can
solve both problems using a structure known as an array of arrays.
The technique is conceptually simple: Since you can store an array in a Variant variable, you can
build an array of Variants, where each item holds an array. Each subarray—a row of this pseudo-
array—can hold a different number of elements, and you don't need to use more memory than is
strictly necessary.
Here's an example, based on an imaginary PIM (Personal Information Manager) program. In this
program, you need to keep track of a list of appointments for each day of the year. The simplest
solution would be to use an array in which each row corresponds to a day in the year and each
column to a possible appointment. (For the sake of simplicity, let's assume that each
appointment's data can be held in a string.)
Of course, you now have the problem of setting a reasonable value for the
MAX_APPOINTMENTS symbolic constant. It should be high enough to account for all possible
appointments in a day but not too high because you might be wasting a lot of memory without any
real reason. Let's see how the array of arrays technique can help us save memory without posing
any artificial limit to your application:
In this example, I kept the code as simple as possible and used an array of Variant arrays. You
could save even more memory if each row of this array were built using an array of a more
specific data type (String, in this case). Note the special syntax used to address an item in an
array of arrays:
Nothing keeps you from extending this concept further, introducing an array of arrays of arrays,
and so on. If you're dealing with arrays in which each row can vary considerably in length, this
approach is going to save you a lot of memory and, in most cases, improve your overall
performance too. A key feature of an array of arrays is that you can process entire rows of your
pseudo-array as if they were single entities. For example, you can swap them, replace them, add
and delete them, and so on.
Finally, an important advantage of this technique is that you can add new rows without losing the
current contents of the array. (Remember that you can use ReDim Preserve on regular arrays
only to modify the number of columns, not the number of rows.)
Variables of different data types when combined as a single variable to hold several related
informations is called a User-Defined data type.
A Type statement is used to define a user-defined type in the General declaration section of a
form or module. User-defined data types can only be private in form while in standard modules
can be public or private. An example for a user defined data type to hold the product details is as
given below.
The user defined data type can be declared with a variable using the Dim statement as in any
other variable declaration statement. An array of these user-defined data types can also be
declared. An example to consolidate these two features is given below.
A User-Defined data type can be referenced in an application by using the variable name in the
procedure along with the item name in the Type block. Say, for example if the text property of a
TextBox namely text1 is to be assigned the name of the electronic good, the statement can be
written as given below.
Text1.Text = ElectronicGoods.ProdName
Text1.Text = ElectronicGoods(i).ProdName
User-defined data types can also be passed to procedures to allow many related items as one
argument.
Constants
Constants are named storage locations in memory, the value of which does not change during
program Execution. They remain the same throughout the program execution. When the user
wants to use a value that never changes, a constant can be declared and created. The Const
statement is used to create a constant. Constants can be declared in local, form, module or
global scope and can be public or private as for variables. Constants can be declared as
illustrated below.
For example consider a statement that will set the window state of a form to be maximized.
Form1.Windowstate = 2
Conversion To Function
Boolean Cbool
Byte Cbyte
Currency Ccur
Date Cdate
Decimals Cdec
Double CDbl
Integer Cint
Long CLng
Single CSng
String CStr
Variant Cvar
Error CVErr
A conversion function should always be placed at the right hand side of the calculation statement.
Not only does Visual Basic let you store date and time information in the specific Date data type,
it also provides a lot of date- and time-related functions. These functions are very important in all
business applications and deserve an in-depth look. Date and Time are internally stored as
numbers in Visual Basic. The decimal points represents the time between 0:00:00 and 23:59:59
hours inclusive.
The system's current date and time can be retrieved using the Now, Date and Time functions in
Visual Basic. The Now function retrieves the date and time, while Date function retrieves only
date and Time function retrieves only the time.
To display both the date and time together a message box is displayed use the statement given
below.
MsgBox "The current date and time of the system is" & Now
Here & is used as a concatenation operator to concentrate the string and the Now function.
Selective portions of the date and time value can be extracted using the below listed functions.
The calculation and conversion functions related to date and time functions are listed below.
Function Description
DateAdd ( ) Returns a date to which a specific interval has been added
DateDiff ( ) Returns a Long data type value specifying the interval between
the two values
DatePart ( ) Returns an Integer containing the specified part of a given date
DateValue ( ) Converts a string to a Date
TimeValue ( ) Converts a string to a time
DateSerial ( ) Returns a date for specified year, month and day
DateDiff Function
The DateDiff function returns the intervals between two dates in terms of years, months or days.
The syntax for this is given below.
Format Function
The format function accepts a numeric value and converts it to a string in the format specified by
the format argument. The syntax for this is given below.
Part Description
Expression Required any valid expression
format Optional. A valid named or user-defined format expression.
firstdayofweek Optional. A contant that specifies the first day of the week.
firstweekofyear Optional. A contant that specifies the first week of the year
Strictly speaking, Date and Time aren't functions: They're properties. In fact, you can use them to
either retrieve the current date and time (as Date values) or assign new values to them to modify
the system settings:
Print Date & " " & Time ' Displays "8/14/98 8:35:48 P.M.".
' Set a new system date using any valid date format.
Date = "10/14/98"
Date = "October 14, 1998"
To help you compare the outcome of all date and time functions, all the examples in this section
assume that they're executed at the date and time shown in the preceding code snippet: October
17, 2008, 9:25:33 p.m.
The outdated Date$ and Time$ properties can also be used for the same task. They're String
properties, however, and therefore recognize only the mm/dd/yy or mm/dd/yyyy formats and the
hh:mm:ss and hh:mm formats, respectively. For this reason, it's usually better to use the new $-
less functions.
The Now function returns a Date value that contains the current date and time:
But the time-honored Timer function returns the number of seconds elapsed from midnight and is
more accurate than Now because the Timer function includes fractional parts of seconds. (The
actual accuracy depends on the system.) This function is often used for benchmarking a portion
of code:
StartTime = Timer
' Insert the code to be benchmarked here.
Print Timer - StartTime
The preceding code suffers from some inaccuracy: The StartTime variable might be assigned
when the system tick is about to expire, so your routine could appear to take longer than it
actually does. Here's a slightly better approach:
StartTime = NextTimerTick
' Insert the code to be benchmarked here.
Print Timer _ StartTime
The bug manifests itself very rarely—for example, if the program asks for a 2-second pause at
11:59:59 p.m. Even if this probability is small, the effect of this minor bug is devastating and you'll
have to press Ctrl+Alt+Del to kill your compiled application. Here's a way to work around this
issue:
There are many ways to assemble a Date value. For example, you can use a Date constant, such
as the following:
but more often you'll build a Date value using one of the many functions that VBA gives you. The
DateSerial function builds a Date value from its year/month/day components; similarly, the
TimeSerial function builds a Time value from its hour/minute/second components:
The DateSerial function is also useful for determining indirectly whether a particular year is a leap
year:
The DateValue and TimeValue functions return the date or time portions of their argument, which
can be a string or a Date expression:
The Weekday function returns a number in the range 1 through 7, which corresponds to the day
of the week of a given Date argument:
The Weekday function returns 1 when the date is the first day of the week. This function is locale
aware, which means that under different localizations of Microsoft Windows it could consider the
first day of the week to be different from vbSunday. In most cases, this condition doesn't affect
the structure of your code. But if you want to be sure that 1 means Sunday, 2 means Monday,
and so on, you can force the function to return a consistent value under all Windows systems, as
follows:
Although using the optional second argument forces the function to return the correct value, it
doesn't change the system localization. If you next call the Weekday function without the second
argument, it will still consider the first day of the week to be what it was before.
Finally you can extract any date and time information from a Date value or expression using the
DatePart function, for which the syntax is
You'll rarely need to resort to this function because you can do most of your calculations using the
other functions I've shown you so far. In two cases, however, this function is really useful:
The first argument can be one of the String constants listed in the following table. For more
information about the two optional arguments, see the description of the DateAdd function in the
next section.
Possible values for the interval argument in DatePart, DateAdd, and DateDiff functions.
Setting Description
"yyyy" Year
"q" Quarter
"m" Month
"y" Day of the year (same as d)
"d" Day
"w" Weekday
"ww" Week
"h" Hour
"n" Minute
"s" Second
In most cases, you don't need any special functions to perform date arithmetic. All you need to
know is that the integer part in a Date variable holds the date information, and the fractional part
holds the time information:
For more sophisticated date math, you can use the DateAdd function, for which the syntax is the
following:
The interval is a string that indicates a date or time unit (see table below), number is the number
of units you are adding, and date is the starting date. You can use this function to add and
subtract date and time values:
When you have two dates and you want to evaluate the difference between them—that is, the
time elapsed between one date and the next—you should use the DateDiff function, for which the
syntax is
where interval has the meaning shown in the previous page Building and Extracting Date and
Time Values's table,FirstDayOfWeek is an optional argument that you can use to specify which
weekday should be considered as the first day of the week (you can use the constants vbSunday,
vbMonday, and so on), and FirstWeekOfYear is another optional argument that lets you specify
which week should be considered as the first week of the year.
A control is an object that can be drawn on a Form object to enable or enhance user interaction
with an application. Controls have properties that define aspects their appearance, such as
position, size and colour, and aspects of their behavior, such as their response to the user input.
They can respond to events initiated by the user or set off by the system. For instance, a code
could be written in a CommandButton control's click event procedure that would load a file or
display a result.
In addition to properties and events, methods can also be used to manipulate controls from code.
For instance, the move method can be used with some controls to change their location and size.
Most of the controls provide choices to users that can be in the form of OptionButton or
CheckBox controls, ListBox entries or ScrollBars to select a value. Let us discuss these controls
by means of a few simple applications in the following lessons.
Classification of Controls
Visual Basic cojntrols are broadly classified as standard controls, ActiveX controls and insertable
objects. Standard controls such as CommandButton, Label and Frame controls are contained
inside .EXE file and are always included in the ToolBox which cannot be removed. ActiveX
controls exist as separate files with either .VBX or .OCX extension. They include specialized
controls such as;
• MSChart control
• The Communications control
• The Animation control
• The ListView control
• An ImageList control
• The Multimedia control
• The Internet Transfer control
• The WinSock control
• The TreeView control
• The SysInfo control
• The Picture Clip control
Some of these objects support OLE Automation, which allow programming another application's
object from within Visual Basic application.
I would like to stress that knowing how and when to set the objects' properties is very important
as it can help you to write a good program or you may fail to write a good program. So, I advice
you to spend a lot of time playing with the objects' properties
• You should set the Caption Property of a control clearly so that a user knows what to do
with that command. For example, in the calculator program, all the captions of the
command buttons such as +, - , MC, MR are commonly found in an ordinary calculator, a
user should have no problem in manipulating the buttons.
• A lot of programmers like to use a meaningful name for the Name Property may be
because it is easier for them to write and read the event procedure and easier to debug
or modify the programs later. However, it is not a must to do that as long as you label
your objects clearly and use comments in the program whenever you feel necessary
• One more important property is whether the control is enabled or not
• Finally, you must also considering making the control visible or invisible at runtime, or
when should it become visible or invisible
By default, Visual Basic assigns a tab order to control as we draw the controls on the Form,
except for Menu, Timer, Data, Image, Line and Shape controls, which are not included in tab
order. At run time, invisible or disabled controls also cannot receive the focus although a
TabIndex value is given. Setting the TabIndex property of controls is compulsory in development
environment.
TextBox controls offer a natural way for users to enter a value in your program. For this reason,
they tend to be the most frequently used controls in the majority of Windows applications.
TextBox controls, which have a great many properties and events, are also among the most
complex intrinsic controls. In this section, I guide you through the most useful properties of
TextBox controls and show how to solve some of the problems that you're likely to encounter.
• The SelStart property sets or returns the position of the blinking caret (the insertion
point where the text you type appears). Note that the blinking cursor inside TextBox and
other controls is named caret, to distinguish it from the cursor (which is implicitly the
mouse cursor). When the caret is at the beginning of the contents of the TextBox control,
SelStart returns 0; when it's at the end of the string typed by the user, SelStart returns the
value Len(Text). You can modify the SelStart property to programmatically move the
caret.
• The SelLength property returns the number of characters in the portion of text that has
been highlighted by the user, or it returns 0 if there's no highlighted text. You can assign
a nonzero value to this property to programmatically select text from code. Interestingly,
you can assign to this property a value larger than the current text's length without raising
a run-time error.
• The SelText property sets or returns the portion of the text that's currently selected, or it
returns an empty string if no text is highlighted. Use it to directly retrieve the highlighted
text without having to query Text, SelStart, and SelLength properties. What's even more
interesting is that you can assign a new value to this property, thus replacing the current
selection with your own. If no text is currently selected, your string is simply inserted at
the current caret position.
When you want to append text to a TextBox control, you should use the following code (instead of
using the concatenation operator) to reduce flickering and improve performance:
Text1.SelStart = Len(Text1.Text)
Text1.SelText = StringToBeAdded
One of the typical operations you could find yourself performing with these properties is selecting
the entire contents of a TextBox control. You often do it when the caret enters the field so that the
user can quickly override the existing value with a new one, or start editing it by pressing any
arrow key:
In the above syntax, text is the text that has to be placed into the Clipboard, and format has three
possible values.
We can get text from the clipboard using the GetText() function this way:
Clipboard.GetText ([format])
The following Figure summarizes the common TextBox control's properties and methods.
Properties
Enabled specifies whether user can interact with this control or not
Index Specifies the control array index
If this control is set to True user can use it else if this control is set to
Locked
false the control cannot be used
Specifies the maximum number of characters to be input. Default value
MaxLength
is set to 0 that means user can input any number of characters
Using this we can set the shape of the mouse pointer when over a
MousePointer
TextBox
By setting this property to True user can have more than one line in the
Multiline
TextBox
PasswordChar This is to specify mask character to be displayed in the TextBox
ScrollBars This to set either the vertical scrollbars or horizontal scrollbars to make
appear in the TextBox. User can also set it to both vertical and
horizontal. This property is used with the Multiline property.
Text Specifies the text to be displayed in the TextBox at runtime
ToolTipIndex This is used to display what text is displayed or in the control
By setting this user can make the Textbox control visible or invisible at
Visible
runtime
Method
SetFocus Transfers focus to the TextBox
Event procedures
Change Action happens when the TextBox changes
Click Action happens when the TextBox is clicked
GotFocus Action happens when the TextBox receives the active focus
LostFocus Action happens when the TextBox loses it focus
KeyDown Called when a key is pressed while the TextBox has the focus
KeyUp Called when a key is released while the TextBox has the focus
TextBox controls support KeyDown, KeyPress, and KeyUp standard events. One thing that you
will often do is prevent the user from entering invalid keys. A typical example of where this
safeguard is needed is a numeric field, for which you need to filter out all nondigit keys:
You should never reject keys whose ANSI code is less than 32, a group that includes important
keys such as Backspace, Escape, Tab, and Enter. Also note that a few control keys will make
your TextBox beep if it doesn't know what to do with them—for example, a single-line TextBox
control doesn't know what to do with an Enter key.
Don't assume that the KeyPress event will trap all control keys under all conditions. For example,
the KeyPress event can process the Enter key only if there's no CommandButton control on the
form whose Default property is set to True. If the form has a default push button, the effect of
pressing the Enter key is clicking on that button. Similarly, no Escape key goes through this event
if there's a Cancel button on the form. Finally, the Tab control key is trapped by a KeyPress event
only if there isn't any other control on the form whose TabStop property is True.
You can use the KeyDown event procedure to allow users to increase and decrease the current
value using Up and Down arrow keys, as you see here:
There's a bug in the implementation of TextBox ready-only controls. When the Locked property is
set to True, the Ctrl+C key combination doesn't correctly copy the selected text to the Clipboard,
and you must manually implement this capability by writing code in the KeyPress event procedure
Although trapping invalid keys in the KeyPress or KeyDown event procedures seems a great idea
at first, when you throw your application to inexperienced users you soon realize that there are
many ways for them to enter invalid data. Depending on what you do with this data, your
application can come to an abrupt end with a run-time error or—much worse—it can appear to
work correctly while it delivers bogus results. What you really need is a bullet-proof method to
trap invalid values.
Before I offer you a decent solution to the problem, let me explain why you can't rely solely on
trapping invalid keys for your validation chores. What if the user pastes an invalid value from the
clipboard? Well, you might say, let's trap the Ctrl+V and Shift+Ins key combinations to prevent the
user from doing that! Unfortunately, Visual Basic's TextBox controls offer a default edit menu that
lets users perform any clipboard operation by simply right-clicking on them. Fortunately, there's a
way around this problem: Instead of trapping a key before it gets to the TextBox control, you trap
its effect in the Change event and reject it if it doesn't pass your test. But this makes the structure
of the code a little more complex than you might anticipate:
If the control's value doesn't pass your tests in the Change event procedure, you must restore its
previous valid value; this action recursively fires a Change event, and you must prepare yourself
to neutralize this nested call. You might wonder why you also need to trap the KeyUp,
MouseDown, and MouseMove events: The reason is that you always need to keep track of the
last valid position for the insertion point because the end user could move it using arrow keys or
the mouse.
The preceding code snippet uses the IsNumeric function to trap invalid data. You should be
aware that this function isn't robust enough for most real-world applications. For example, the
IsNumeric function incorrectly considers these strings as valid numbers:
123,,,123
345-
$1234 ' What if it isn't a currency field?
2.4E10 ' What if I don't want to support scientific notation?
To cope with this issue, I have prepared an alternative function, which you can modify for your
particular purposes. (For instance, you can add support for a currency symbol or the comma as
the decimal separator.) Note that this function always returns True when it's passed a null string,
so you might need to perform additional tests if the user isn't allowed to leave the field blank:
If your TextBox controls are expected to contain other types of data, you might be tempted to
reuse the same validation framework I showed you previously—including all the code in the
GotFocus, Change, KeyUp, MouseDown, and MouseMove event procedures—and replace only
the call to IsNumeric with a call to your custom validation routine. Things aren't as simple as they
appear at first, however. Say that you have a date field: Can you use the IsDate function to
validate it from within the Change event? The answer is, of course, no. In fact, as you enter the
first digit of your date value, IsDate returns False and the routine therefore prevents you from
entering the remaining characters, and so preventing you from entering any value.
This example explains why a key-level validation isn't always the best answer to your validation
needs. For this reason, most Visual Basic programmers prefer to rely on field-level validation and
test the values only when the user moves the input focus to another field in the form. I explain
field-level validation in the next section.
isual Basic 6 has finally come up with a solution for most of the validation issues that have
afflicted Visual Basic developers for years. As you'll see in a moment, the Visual Basic 6
approach is simple and clean; it really astonishes me that it took six language versions to deliver
such a lifesaver. The keys to the new validation features are the Validate event and the
CausesValidation property. They work together as follows: When the input focus leaves a control,
Visual Basic checks the CausesValidation property of the control that is about to receive the
focus. If this property is True, Visual Basic fires the Validate event in the control that's about to
lose the focus, thus giving the programmer a chance to validate its contents and, if necessary,
cancel the focus shift.
Let's try a practical example. Imagine that you have five controls on a form: a required field (a
TextBox control, txtRequired, that can't contain an empty string), a numeric field, txtNumeric, that
expects a value in the range 1 through 1000, and three push buttons: OK, Cancel, and Help. (See
the figure below.) You don't want to perform validation if the user presses the Cancel or Help
buttons, so you set their CausesValidation properties to False. The default value for this property
is True, so you don't have to modify it for the other controls. Run the sample program on the
companion CD, type something in the required TextBox, and then move to the second field.
Because the second field's CausesValidation property is True, Visual Basic fires a Validate event
in the first TextBox control:
If the Cancel parameter is set to True, Visual Basic cancels the user's action and takes the input
focus back on the txtRequired control: No other GotFocus and LostFocus events are generated.
On the other hand, if you typed something in the required field, the focus will now be on the
second field (the numeric text box). Try clicking on the Help or Cancel buttons: No Validate event
will fire this time because you set the CausesValidation property for each of these controls to
False. Instead, click on the OK button to execute the Validate event of the numeric field, where
you can check it for invalid characters and valid range.
A demonstration program that lets you experiment with the new Visual Basic Validate features
In some circumstances, you might want to programmatically validate the control that has the
focus without waiting for the user to move the input focus. You can do it with the form's
ValidateControls method, which forces the Validate event of the control that has the input focus.
Typically, you do it when the user closes the form:
Checking the UnloadMode parameter is important; otherwise, your application will mistakenly
execute a ValidateControls method when the user clicks on the Cancel button. Note that
ValidateControls returns an error 380 if Cancel was set in the Validate event procedure of the
control that had the focus.
Visual Basic 6's validation scheme has two flaws, though. If your form has a CommandButton
whose Default property is set to True, pressing the Enter key while the input focus is on another
control results in a click on the CommandButton control but doesn't fire a Validate event, even if
the CausesValidation property of the CommandButton control is set to True. The only way to
solve this problem is to invoke the ValidateControls method from within the default
CommandButton control's Click event procedure.
The second flaw is that the Validate event doesn't fire when you're moving the focus from a
control whose CausesValidation property is False, even if the control that receives the focus has
its CausesValidation property set to True.
The new Visual Basic 6 validation mechanism is simple and can be implemented with little effort.
But it isn't the magic answer to all your validation needs. In fact, this technique can only enforce
field-level validation; it does nothing for record-level validation. In other words, it ensures that one
particular field is correct, not that all fields in the form contain valid data. To see what I mean, run
the demonstration program, enter a string in the first field, and press Alt+F4 to close the form.
Your code won't raise an error, even if the second field doesn't contain a valid number!
Fortunately, it doesn't take much to create a generic routine that forces each control on the form
to validate itself:
The CausesValidation property and the Validate event are shared by all the intrinsic controls that
are able to get the focus as well as by most external ActiveX controls, even those not specifically
written for Visual Basic. This is possible because they are extender features, provided by the
Visual Basic runtime to all the controls placed on a form's surface.
One Visual Basic operator has great potential when it comes time to validate complex strings but
is neglected by most Visual Basic developers. Let's say you have a product code that consists of
two uppercase characters followed by exactly three digits. You might think that you need some
complex string functions to validate such a string until you try the Like operator, as follows:
Auto-Tabbing Fields
Users aren't usually delighted to spend all their time at the keyboard. Your job as a programmer is
to make their jobs easier, and so you should strive to streamline their everyday work as much as
possible. One way to apply this concept is to provide them with auto-tabbing fields, which are
fields that automatically advance users to the next field in the Tab order as soon as they enter a
valid value. Most often, auto-tabbing fields are those TextBox controls whose MaxLength property
has been assigned a non-null value. Implementing such an auto-tabbing field in Visual Basic is
straightforward:
The trick, as you see, is to have your program provide the Tab key on behalf of your user. In
some cases, this simple approach doesn't work—for example, when you paste a long string into
the field. You might want to write code that works around this and other shortcomings. Auto-
tabbing is a nice feature but not vital to the application, so whether you write a workaround or not
isn't a real problem in most cases.
Formatting Text
Many business applications let you enter data in one format and then display it in another. For
example, numeric values can be formatted with thousand separators and a fixed number of
decimal digits. Currency values might have a $ symbol (or whatever your national currency
symbol is) automatically inserted. Phone numbers can be formatted with dashes to split into
groups of digits. Credit-card numbers can be made more readable with embedded spaces. Dates
can be shown in long-date format ("July 22, 2007"). And so on.
The LostFocus event is an ideal occasion to format the contents of a TextBox control as soon as
the input focus leaves it. In most cases, you can perform all your formatting chores using the
Format function. For example, you can add thousand separators to a numeric value in the
txtNumber control using this code:
When the field regains the focus, you'll want to get rid of those thousand separators. You can do
it easily using the CDbl function:
In some cases, however, formatting and unformatting a value isn't that simple. For example, you
can format a Currency value to add parentheses around negative numbers, but there's no built-in
Visual Basic function able to return a string formatted in that way to its original condition. Fear
not, because nothing prevents you from creating your own formatting and unformatting routines. I
have built two general-purpose routines for you to consider.
FilterNumber builds on FilterString to strip down all formatting characters in a number and can
also trim trailing decimal zeros:
The feature I like most in FilterNumber is that it's locale-independent. It works equally well on both
sides of the Atlantic ocean (and on other continents, as well.) Instead of hard-coding the decimal
separator character in the code, the routine determines it on the fly, using the Visual Basic for
Applications (VBA) Format function. Start thinking internationally now, and you won't have a
nervous breakdown when you have to localize your applications in German, French, and
Japanese.
You can also determine whether the system uses dates in "mm/dd/yy" (U.S.) format or
"dd/mm/yy" (European) format, using this code:
End If
There's no direct way to determine the currency symbol, but you can derive it by analyzing the
result of this function:
It isn't difficult to write a routine that internally uses the information I've just given you to extract
the currency symbol as well as its default position (before or after the number) and the default
number of decimal digits in currency values. Remember, in some countries the currency symbol
is actually a string of two or more characters.
To illustrate these concepts in action, I've built a simple demonstration program that shows how
you can format numbers, currency values, dates, phone numbers, and credit-card numbers when
exiting a field, and how you can remove that formatting from the result when the input focus
reenters the TextBox control. Follwoing figure shows the formatted results.
Formatting and unformatting the contents of TextBox controls makes for more professional-
looking applications
Instead of inserting the code that formats phone numbers and credit-card numbers right in the
LostFocus event procedures, I built two distinct routines, which can be more easily reused in
other applications, as shown in the code below.
Unfortunately, there isn't any way to create locale-independent routines that can format any
phone number anywhere in the world. But by grouping all your formatting routines in one module,
you can considerably speed up your work if and when it's time to convert your code for another
locale.
Label and Frame controls have a few features in common, so it makes sense to explain them
together. First they're mostly "decorative" controls that contribute to the user interface but are
seldom used as programmable objects. In other words, you often place them on the form and
arrange their properties as your user interface needs dictate, but you rarely write code to serve
their events, generally, or manipulate their properties at run time.
Label Controls
Most people use Label controls to provide a descriptive caption and possibly an associated hot
key for other controls, such as TextBox, ListBox, and ComboBox, that don't expose the Caption
property. In most cases, you just place a Label control where you need it, set its Caption property
to a suitable string (embedding an ampersand character in front of the hot key you want to
assign), and you're done. Caption is the default property for Label controls. Be careful to set the
Label's TabIndex property so that it's 1 minus the TabIndex property of the companion control.
Other useful properties are BorderStyle(if you want the Label control to appear inside a 3D
border) and Alignment (if you want to align the caption to the right or center it on the control). In
most cases, the alignment depends on how the Label control relates to its companion control: for
example, if the Label control is placed to the left of its companion field, you might want to set its
Alignment property to 1-Right Justify. The value 2-Center is especially useful for stand-alone
Label controls.
Different settings for the Alignment property of Label controls.
You can insert a literal & character in a Label control's Caption property by doubling it. For
example, to see Research & Development you have to type &Research && Development. Note
that if you have multiple but isolated &s, the one that selects the hot key is the last one and all
others are ignored. This tip applies to all the controls that expose a Caption property. (The & has
no special meaning in forms' Caption properties, however.)
If the caption string is a long one, you might want to set the Label's WordWrap property to True
so that it will extend for multiple lines instead of being truncated by the right border of the control.
Alternatively, you might decide to set the AutoSize property to True and let the control
automatically resize itself to accommodate longer caption strings.
You sometimes need to modify the default value of a Label's BackStyle property. Label controls
usually cover what's already on the form's surface (other lightweight controls, output from graphic
methods, and so on) because their background is considered to be opaque. If you want to show a
character string somewhere on the form but at the same time you don't want to obscure
underlying objects, set the BackStyle property to 0-Transparent.
If you're using the Label control to display data read from elsewhere—for example, a database
field or a text file—you should set its UseMnemonics property to False. In this case, & characters
have no special meaning to the control, and so you indirectly turn off the control's hot key
capability. I mention this property because in older versions of Visual Basic, you had to manually
double each & character to make the ampersand appear in text. I don't think all developers are
aware that you can now treat ampersands like regular characters.
As I said before, you don't usually write code in Label control event procedures. This control
exposes only a subset of the events supported by other controls. For example, because Label
controls can never get the input focus, they don't support GotFocus, LostFocus, or any keyboard-
related events. In practice, you can take advantage only of their mouse events: Click, DblClick,
MouseDown, MouseMove, and MouseUp. If you're using a Label control to display data read from
a database, you might sometimes find it useful to write code in its Change event. A Label control
doesn't expose a specific event that tells programmers when users press its hot keys.
You can do some interesting tricks with Label controls. For example, you can use them to provide
rectangular hot spots for images loaded onto the form. To create that context-sensitive ToolTip, I
loaded the image on the form using the form's Picture property and then I placed a Label control
over the Microsoft BackOffice logo, setting its Caption property to an empty string and the
BackStyle property to 0-Transparent. These properties make the Label invisible, but it correctly
shows its ToolTip when necessary. And because it still receives all mouse events, you can use its
Click event to react to users' actions.
Frame Controls
Frame controls are similar to Label controls in that they can serve as captions for those controls
that don't have their own. Moreover, Frame controls can also (and often do) behave as containers
and host other controls. In most cases, you only need to drop a Frame control on a form and set
its Caption property. If you want to create a borderless frame, you can set its BorderStyle
property to 0-None.
Controls that are contained in the Frame control are said to be child controls. Moving a control at
design time over a Frame control—or over any other container, for that matter—doesn't
automatically make that control a child of the Frame control. After you create a Frame control,
you can create a child control by selecting the child control's icon in the Toolbox and drawing a
new instance inside the Frame's border. Alternatively, to make an existing control a child of a
Frame control, you must select the control, press Ctrl+X to cut it to the Clipboard, select the
Frame control, and press Ctrl+V to paste the control inside the Frame. If you don't follow this
procedure and you simply move the control over the Frame, the two controls remain completely
independent of each other, even if the other control appears in front of the Frame control.
Frame controls, like all container controls, have two interesting features. If you move a Frame
control, all the child controls go with it. If you make a container control disabled or invisible, all its
child controls also become disabled or invisible. You can exploit these features to quickly change
the state of a group of related controls.
You can use two other properties at design time to modify the behavior of a CommandButton
control. You can set the Default property to True if it's the default push button for the form (the
button that receives a click when the user presses the Enter key—usually the OK or Save button).
Similarly, you can set the Cancel property to True if you want to associate the button with the
Escape key.
The only relevant CommandButton's run-time property is Value, which sets or returns the state of
the control (True if pressed, False otherwise). Value is also the default property for this type of
control. In most cases, you don't need to query this property because if you're inside a button's
Click event you can be sure that the button is being activated. The Value property is useful only
for programmatically clicking a button:
The CommandButton control supports the usual set of keyboard and mouse events (KeyDown,
KeyPress, KeyUp, MouseDown, MouseMove, MouseUp, but not the DblClick event) and also the
GotFocus and LostFocus events, but you'll rarely have to write code in the corresponding event
procedures.
Preliminary operations for an OptionButton control are similar to those already described for
CheckBox controls. You set an OptionButton control's Caption property to a meaningful string,
and if you want you can change its Alignment property to make the control right aligned. If the
control is the one in its group that's in the selected state, you also set its Valueproperty to True.
(The OptionButton's Value property is a Boolean value because only two states are possible.)
Value is the default property for this control.
At run time, you typically query the control's Value property to learn which button in its group has
been selected. Let's say you have three OptionButton controls, named optWeekly, optMonthly,
and optYearly. You can test which one has been selected by the user as follows:
If optWeekly.Value Then
' User prefers weekly frequency.
ElseIf optMonthly.Value Then
' User prefers monthly frequency.
ElseIf optYearly.Value Then
' User prefers yearly frequency.
End If
Strictly speaking, you can avoid the test for the last OptionButton control in its group because all
choices are supposed to be mutually exclusive. But the approach I just showed you increases the
code's readability.
A group of OptionButton controls is often hosted in a Frame control. This is necessary when there
are other groups of OptionButton controls on the form. As far as Visual Basic is concerned, all the
OptionButton controls on a form's surface belong to the same group of mutually exclusive
selections, even if the controls are placed at the opposite corners of the window. The only way to
tell Visual Basic which controls belong to which group is by gathering them inside a Frame
control. Actually, you can group your controls within any control that can work as a container—
PictureBox, for example—but Frame controls are often the most reasonable choice.
Example
Open a new Standard EXE project and the save the Form as Option.frm and save the project as
Option.vbp.
• The change event of the TextBox reads the value and stores it in a form-level numeric
variable.
• The click event of optOct button returns curretval in octal.
• The click event of the optHex button curerntval in hexadecimal
• The click event of the optDec button returns the decimal equivalent of the value held
currentval.
The following code is entered in the general declarations section of the Form.
Dim currentval as variant
The variable is initialized to 0 by default. The change event procedure checks to ascertain the
number system (Octal, Hexadecimal) that is in effect and then reads in the number.
The Val function is used to translate string to a number and can recognize Octal and
Hexadecimal strings. The LTrim function trims the leading blanks in the text. The following code is
entered in the click events of the OptionButton controls.
The follwoing code is entered in the click event of teh Close button.
The Application is run by pressing F5 or clicking on the Run icon in the tool bar. By pressing the
Exit button the program is terminated.
Once you place a PictureBox on a form, you might want to load an image in it, which you do by
setting the Picture property in the Properties window. You can load images in many different
graphic formats, including bitmaps (BMP), device independent bitmaps (DIB), metafiles (WMF),
enhanced metafiles (EMF), GIF and JPEG compressed files, and icons (ICO and CUR). You can
decide whether a control should display a border, resetting the BorderStyle to 0-None if
necessary. Another property that comes handy in this phase is AutoSize: Set it to True and let the
control automatically resize itself to fit the assigned image.
You might want to set the Align property of a PictureBox control to something other than the 0-
None value. By doing that, you attach the control to one of the four form borders and have Visual
Basic automatically move and resize the PictureBox control when the form is resized. PictureBox
controls expose a Resize event, so you can trap it if you need to move and resize its child
controls too.
You can do more interesting things at run time. To begin with, you can programmatically load any
image in the control using the LoadPicture function:
Picture1.Picture = LoadPicture("c:\windows\setup.bmp")
and you can clear the current image using either one of the following statements:
The LoadPicture function has been extended in Visual Basic 6 to support icon files containing
multiple icons. The new syntax is the following:
where values in square brackets are optional. If filename is an icon file, you can select a
particular icon using the size or colordepth arguments. Valid sizes are 0-vbLPSmall, 1-vbLPLarge
(system icons whose sizes depend on the video driver), 2-vbLPSmallShell, 3-vbLPLargeShell
(shell icons whose dimensions are affected by the Caption Button property as set in the
Appearance tab in the screen's Properties dialog box), and 4-vbLPCustom (size is determined by
x and y). Valid color depths are 0-vbLPDefault (the icon in the file that best matches current
screen settings), 1-vbLPMonochrome, 2-vbLPVGAColor (16 colors), and 3-vbLPColor (256
colors).
You can copy an image from one PictureBox control to another by assigning the target control's
Picture property:
Picture2.Picture = Picture1.Picture
PictureBox controls are equipped with a very powerful method that enables the programmer to
perform a wide variety of graphic effects, including zooming, scrolling, panning, tiling, flipping, and
many fading effects: This is the PaintPicture method. (This method is also exposed by form
objects, but it's most often used with PictureBox controls.) In a nutshell, this method performs a
pixel-by-pixel copy from a source control to a destination control. The complete syntax of this
method is complex and rather confusing:
The only required arguments are the source PictureBox control's Picture property and the
coordinates inside the destination control where the image must be copied. The destX / destY
arguments are expressed in the ScaleMode of the destination control; by varying them, you can
make the image appear exactly where you want. For example, if the source PictureBox control
contains a bitmap 3000 twips wide and 2000 twips tall, you can center this image on the
destination control with this command:
In general, Visual Basic doesn't provide a way to determine the size of a bitmap loaded into a
PictureBox control. But you can derive this information if you set the control's AutoSize property
to True and then read the control's ScaleWidth and ScaleHeight properties. If you don't want to
resize a visible control just to learn the dimensions of a bitmap, you can load it into an invisible
control, or you can use this trick, based on the fact that the Picture property returns an StdPicture
object, which in turn exposes the Height and Width properties:
By the way, in all subsequent code examples I assume that the source PictureBox control's
ScaleWidth and ScaleHeight properties match the actual bitmap's size. By default, the
PaintPicture method copies the entire source bitmap. But you can copy just a portion of it,
passing a value for srcWidth and srcHeight:
If you're copying just a portion of the source image, you probably want to pass a specific value for
the srcX and srcY values as well, which correspond to the coordinates of the top-left corner of the
area that will be copied from the source control:
You can use this method to tile a target PictureBox control (or form) with multiple copies of an
image stored in another control:
' Start with the leftmost column.
x = 0
Do While x < picDest.ScaleWidth
y = 0
' For each column, start at the top and work downward.
Do While y < picDest.ScaleHeight
picDest.PaintPicture picSource.Picture, x, y, , , 0, 0
' Next row
y = y + picSource.ScaleHeight
Loop
' Next column
x = x + picSource.ScaleWidth
Loop
Another great feature of the PaintPicture method lets you resize the image while you transfer it,
and you can even specify different zoom-in and zoom-out factors for the x- and y-axes
independently. You just have to pass a value to the destWidth and destHeight arguments: If these
values are greater than the source image's corresponding dimensions, you achieve a zoom-in
effect, and if they are less you get a zoom-out effect. For example, see how you can double the
size of the original image:
picDest.PaintPicture picSource.Picture, 0, 0, _
picSource.ScaleWidth * 2, picSource.ScaleHeight * 2
As a special case of the syntax of the PaintPicture method, the source image can even be flipped
along its x-axis, y-axis, or both by passing negative values for these arguments:
As you might expect, you can combine all these effects together, magnifying, reducing, or flipping
just a portion of the source image, and have the result appear in any point of the destination
PictureBox control (or form). You should find no problem in reusing all those routines in your own
applications.
As if all these capabilities weren't enough, we haven't covered the last argument of the
PaintPicture method yet. The opcode argument lets you specify which kind of Boolean operation
must be performed on pixel bits as they're transferred from the source image to the destination.
The values you can pass to this argument are the same that you assign to the DrawMode
property. The default value is 13-vbCopyPen, which simply copies the source pixels in the
destination control. By playing with the other settings, you can achieve many interesting graphical
effects, including simple animations.
When you're working with an Image control, you typically load a bitmap into its Picture property
either at design time or at run time using the LoadPicture function. Image controls don't expose
the AutoSize property because by default they resize to display the contained image (as it
happens with PictureBox controls set at AutoSize = True). On the other hand, Image controls
support a Stretch property that, if True, resizes the image (distorting it if necessary) to fit the
control. In a sense, the Stretch property somewhat remedies the lack of the PaintPicture method
for this control. In fact, you can zoom in to or reduce an image by loading it in an Image control
and then setting its Stretch property to True to change its width and height:
Image controls support all the usual mouse events. For this reason, many Visual Basic
developers have used Image controls to simulate graphical buttons and toolbars. Now that Visual
Basic natively supports these controls, you'd probably better use Image controls only for what
they were originally intended.
See Also
Timer controls let you write interesting programs with just a few lines of code. The typical (and
abused) example is a digital clock. Just to make things a bit more compelling, I added flashing
colons:
You must be careful not to write a lot of code in the Timer event procedure because this code will
be executed at every pulse and therefore can easily degrade your application's performance. Just
as important, never execute a DoEvents statement inside a Timer event procedure because you
might cause the procedure to be reentered, especially if the Interval property is set to a small
value and there's a lot of code inside the procedure.
Timer controls are often useful for updating status information on a regular basis. For example,
you might want to display on a status bar a short description of the control that currently has the
input focus. You can achieve that by writing some code in the GotFocus event for all the controls
on the form, but when you have dozens of controls this will require a lot of code (and time).
Instead, at design time load a short description for each control in its Tag property, and then
place a Timer control on the form with an Interval setting of 500. This isn't a time-critical task, so
you can use an even larger value. Finally add two lines of code to the control's Timer event:
In the long run, however, the Embedding term in OLE has lost much of its appeal and importance,
and nowadays programmers are more concerned and thrilled about Automation, a subset of OLE
that lets them control other Windows applications from the outside, manipulating their object
hierarchies through OLE. For this reason, I won't describe the OLE control: It's a rather complex
object, and a thorough description of its many properties, methods, and events (and quirks) would
take too much space. ListBox and ComboBox controls present a set of choices that are displayed
vertically in a column. If the number of items exceed the value that be displayed, scroll bars will
automatically appear on the control. These scroll bars can be scrolled up and down or left to right
through the list.
The following Fig lists some of the common ComboBox properties and methods.
Property/Method Description
Properties
By setting this property to True or False user can decide whether
Enabled
user can interact with this control or not
Index Specifies the Control array index
String array. Contains the strings displayed in the drop-down list.
List
Starting array index is 0.
ListCount Integer. Contains the number of drop-down list items
Integer. Contains the index of the selected ComboBox item. If an
ListIndex
item is not selected, ListIndex is -1
Locked Boolean. Specifies whether user can type or not in the ComboBox
Integer. Specifies the shape of the mouse pointer when over the
MousePointer
area of the ComboBox
Integer. Index of the last item added to the ComboBox. If the
NewIndex
ComboBox does not contain any items , NewIndex is -1
Boolean. Specifies whether the ComboBox's items are sorted or
Sorted
not.
Style Integer. Specifies the style of the ComboBox's appearance
TabStop Boolean. Specifies whether ComboBox receives the focus or not.
Text String. Specifies the selected item in the ComboBox
ToolTipIndex String. Specifies what text is displayed as the ComboBox's tool tip
Visible Boolean. Specifies whether ComboBox is visible or not at run time
Methods
AddItem Add an item to the ComboBox
Clear Removes all items from the ComboBox
RemoveItem Removes the specified item from the ComboBox
SetFocus Transfers focus to the ComboBox
Event Procedures
Change Called when text in ComboBox is changed
DropDown Called when the ComboBox drop-down list is displayed
GotFocus Called when ComboBox receives the focus
LostFocus Called when ComboBox loses it focus
Run Time : The AddItem method is used to add items to a list at run time. The AddItem method
uses the following syntax.
Object.AddItemitem, Index
The item argument is a string that represents the text to add to the list
The index argument is an integer that indicates where in the list to add the new item. Not giving
the index is not a problem, because by default the index is assigned.
Following is an example to add item to a combo box. The code is typed in the Form_Load event
Combo1.AddItem 1
Combo1.AddItem 2
Combo1.AddItem 3
Combo1.AddItem 4
Combo1.AddItem 5
Combo1.AddItem 6
End Sub
Object.RemoveItem index
The following code verifies that an item is selected in the list and then removes the selected item
from the list.
Simple combo
Dropdown combo Dropdown list
The Simple Combo box displays an edit area with an attached list box always visible immediately
below the edit area. A simple combo box displays the contents of its list all the time. The user can
select an item from the list or type an item in the edit box portion of the combo box. A scroll bar is
displayed beside the list if there are too many items to be displayed in the list box area.
The Dropdown Combo box first appears as only an edit area with a down arrow button at the
right. The list portion stays hidden until the user clicks the down-arrow button to drop down the list
portion. The user can either select a value from the list or type a value in the edit area.
The Dropdown list combo box turns the combo box into a Dropdown list box. At run time , the
control looks like the Dropdown combo box. The user could click the down arrow to view the list.
The difference between Dropdown combo & Dropdown list combo is that the edit area in the
Dropdown list combo is disabled. The user can only select an item and cannot type anything in
the edit area. Anyway this area displays the selected item.
Example
This example is to Add , Remove, Clear the list of items and finally close the application.
• Open a new Standard EXE project is opened an named the Form as Listbox.frm and
save the project as Listbox.vbp
• Design the application as shown below.
The following event procedures are entered for the TextBox and CommandButton controls.
End Sub
The click event of the Add button adds the text to the list box that was typed in the Text box. Then
the text box is cleared and the focus is got to the text box. The number of entered values will is
increased according to the number of items added to the listbox.
End If
End Sub
Remove button removes the selected item from the list as soon as you pressed the Remove
button. The number of items is decreased in the listbox and the value is displayed in the label.
The code for the clear button clears the listbox when you press it. And the number of items shown
in the label becomes 0.
The ScrollBar is a commonly used control, which enables the user to select a value by positioning
it at the desired location. It represents a set of values. The Min and Max property represents the
minimum and maximum value. The value property of the ScrollBar represents its current value,
that may be any integer between minimum and maximum values assigned.
The HScrollBar and the VScrollBar controls are perfectly identical, apart from their different
orientation. After you place an instance of such a control on a form, you have to worry about only
a few properties: Min and Max represent the valid range of values, SmallChange is the variation
in value you get when clicking on the scroll bar's arrows, and LargeChange is the variation you
get when you click on either side of the scroll bar indicator. The default initial value for those two
properties is 1, but you'll probably have to change LargeChange to a higher value. For example, if
you have a scroll bar that lets you browse a portion of text, SmallChange should be 1 (you scroll
one line at a time) and LargeChange should be set to match the number of visible text lines in the
window.
The most important run-time property is Value, which always returns the relative position of the
indicator on the scroll bar. By default, the Min value corresponds to the leftmost or upper end of
the control:
' Move the indicator near the top (or left) arrow.
VScroll1.Value = VScroll1.Min
' Move the indicator near the bottom (or right) arrow.
VScroll1.Value = VScroll1.Max
While this setting is almost always OK for horizontal scroll bars, you might sometimes need to
reverse the behavior of vertical scroll bars so that the zero is near the bottom of your form. This
arrangement is often desirable if you want to use a vertical scroll bar as a sort of slider. You
obtain this behavior by simply inverting the values in the Min and Max properties. (In other words,
it's perfectly legal for Min to be greater than Max.)
There are two key events for scrollbar controls: the Change event fires when you click on the
scroll bar arrows or when you drag the indicator; the Scroll event fires while you drag the
indicator. The reason for these two distinct possibilities is mostly historical. First versions of Visual
Basic supported only the Change event, and when developers realized that it wasn't possible to
have continuous feedback when users dragged the indicator, Microsoft engineers added a new
event instead of extending the Change event. In this way, old applications could be recompiled
without unexpected changes in their behavior. At any rate, this means that you must often trap
two distinct events:
The example shown in the following figure uses three VScrollBar controls as sliders to control the
individual RGB (red, green, blue) components of a color. The three scroll bars have their Min
property set to 255 and their Max property set to 0, while their SmallChange is 1 and
LargeChange is 16. This example is also a moderately useful program in itself because you can
select a color and then copy its numeric value to the clipboard and paste it in your application's
code as a decimal value, a hexadecimal value, or an RGB function.
Use scrollbar controls to visually create colors.
Scrollbar controls can receive the input focus, and in fact they support both the TabIndex and
TabStop properties. If you don't want the user to accidentally move the input focus on a scrollbar
control when he or she presses the Tab key, you must explicitly set its TabStop property to False.
When a scrollbar control has the focus, you can move the indicator using the Left, Right, Up,
Down, PgUp, PgDn, Home, and End keys. For example, you can take advantage of this behavior
to create a read-only TextBox control with a numeric value that can be edited only through a tiny
companion scroll bar. This scroll bar appears to the user as a sort of spin button, as you can see
in the figure below. To make the trick work, you need to write just a few lines of code:
You don't need external ActiveX controls to create functional spin buttons
Scrollbar controls are even more useful for building scrolling forms, like the one displayed in
Figure 3-15. To be certain, scrolling forms aren't the most ergonomic type of user interface you
can offer to your customers: If you have that many fields in a form, you should consider using a
Tab control, child forms, or some other custom interface. Sometimes, however, you badly need
scrollable forms, and in this situation you are on your own because Visual Basic forms don't
support scrolling.
Fortunately, it doesn't take long to convert a regular form into a scrollable one. You need a couple
of scrollbar controls, plus a PictureBox control that you use as the container for all the controls on
the form, and a filler control—a CommandButton, for example—that you place in the bottom-right
corner of the form when it displays the two scroll bars. The secret to creating scrollable forms is
that you don't move all the child controls one by one. Instead, you place all the controls in the
PictureBox control (named picCanvas in the following code), and you move it when the user acts
on the scroll bar:
Sub MoveCanvas()
picCanvas.Move -HScroll1.Value, -VScroll1.Value
End Sub
In other words, to uncover the portion of the form near the right border, you assign a negative
value to the PictureBox's Left property, and to display the portion near the form's bottom border
you set its Top property to a negative value. It's really that simple. You do this by calling the
MoveCanvas procedure from within the scroll bars' Change and Scroll events. Of course, it's
critical that you write code in the Form_Resize event, which makes a scroll bar appear and
disappear as the form is resized, and that you assign consistent values to Max properties of the
scrollbar controls:
Working with scrollable forms at design time isn't comfortable. I suggest that you work with a
maximized form and with the PictureBox control sized as large as possible. When you're finished
with the form interface, resize the PictureBox control to the smallest area that contains all the
controls, and then reset the form's WindowState property to 0-Normal.
A control array is a group of controls that share the same name type and the same event
procedures. Adding controls with control arrays uses fewer resources than adding multiple control
of same type at design time.
A control array can be created only at design time, and at the very minimum at least one control
must belong to it. You create a control array following one of these three methods:
• You create a control and then assign a numeric, non-negative value to its Index property;
you have thus created a control array with just one element.
• You create two controls of the same class and assign them an identical Name property.
Visual Basic shows a dialog box warning you that there's already a control with that name
and asks whether you want to create a control array. Click on the Yes button.
• You select a control on the form, press Ctrl+C to copy it to the clipboard, and then press
Ctrl+V to paste a new instance of the control, which has the same Name property as the
original one. Visual Basic shows the warning mentioned in the previous bullet.
Control arrays are one of the most interesting features of the Visual Basic environment, and they
add a lot of flexibility to your programs:
• Controls that belong to the same control array share the same set of event procedures;
this often dramatically reduces the amount of code you have to write to respond to a
user's actions.
• You can dynamically add new elements to a control array at run time; in other words, you
can effectively create new controls that didn't exist at design time.
• Elements of control arrays consume fewer resources than regular controls and tend to
produce smaller executables. Besides, Visual Basic forms can host up to 256 different
control names, but a control array counts as one against this number. In other words,
control arrays let you effectively overcome this limit.
The importance of using control arrays as a means of dynamically creating new controls at run
time is somewhat reduced in Visual Basic 6, which has introduced a new and more powerful
capability.
Don't let the term array lead you to think control array is related to VBA arrays; they're completely
different objects. Control arrays can only be one-dimensional. They don't need to be
dimensioned: Each control you add automatically extends the array. The Index property identifies
the position of each control in the control array it belongs to, but it's possible for a control array to
have holes in the index sequence. The lowest possible value for the Index property is 0. You
reference a control belonging to a control array as you would reference a standard array item:
Text1(0).Text = ""
The fact that multiple controls can share the same set of event procedures is often in itself a good
reason to create a control array. For example, say that you want to change the background color
of each of your TextBox controls to yellow when it receives the input focus and restore its
background color to white when the user clicks on another field:
Control arrays are especially useful with groups of OptionButton controls because you can
remember which element in the group has been activated by adding one line of code to their
shared Click event. This saves code when the program needs to determine which button is the
active one:
Where object is the name of the control to add or delete from the control array. Index % is the
value of the index in the array. The control array to be added must be an element of the existing
array created at design time with an index value of 0. When a new element of a control array is
loaded, most of the property settings are copied from the lowest existing element in the array.
Following example illustrates the use of the control array.
* Open a Standard EXE project and save the Form as Calculator.frm and save the Project as
Calculater.vbp.
Index 0
Caption 2
Index 1
Caption 3
Index 2
Caption 4
Index 3
Caption 5
Index 4
Caption 6
Index 5
Caption 7
Index 6
CommandButton Caption 8
Name
cmd
Index
7
Caption 9
Index 8
Caption 0
Index 10
Caption .
Index 11
Caption AC
CommandButton
Name cmdAC
Caption +
CommandButton
Name cmdPlus
Caption -
CommandButton
Name cmdMinus
Caption *
CommandButton
Name cmdMultiply
Caption /
CommandButton
Name cmdDivide
Caption +/-
CommandButton
Name cmdNeg
Name txtDisplay
TextBox
Text ( empty )
Caption =
CommandButton
Name cmdEqual
The following variables are declared inside the general declaration
The following code is entered in the cmd_Click( ) (Control Array) event procedure
The following code is entered in the click events of the cmdPlus, cmdMinus, cmdMultiply,
cmdDevide controls respectively.
To print the result on the text box, the following code is entered in the cmdEqual_Click ( ) event
procedure.
Case "+"
Result = Previous + Current
txtDisplay.Text = Result
Case "-"
Result = Previous - Current
txtDisplay.Text = Result
Case "*"
Result = Previous * Current
txtDisplay.Text = Result
Case "/"
Result = Previous / Current
txtDisplay.Text = Result
End Select
Current = Result
End Sub
Save and run the project. On clicking digits of user's choice and an operator button, the output
appears.
Here you're using the LBound and UBound methods exposed by the control array object, which is
an intermediate object used by Visual Basic to gather all the controls in the array. In general, you
shouldn't use this approach to iterate over all the items in the array because if the array has holes
in the Index sequence an error will be raised. A better way to loop over all the items of a control
array is using the For Each statement:
A third method exposed by the control array object, Count, returns the number of elements it
contains. It can be useful on several occasions (for example, when removing all the controls that
were added dynamically at run time):
' This code assumes that txtField(0) is the only control that was
' created at design time (you can't unload it at run time).
Do While txtFields.Count > 1
Unload txtFields(txtFields.UBound)
Loop
There are some limitations, though: All the items in an array of menu controls must be adjacent
and must belong to the same menu level, and their Index properties must be in ascending order
(even though holes in the sequence are allowed). This set of requirements severely hinders your
ability to create new menu items at run time. In fact, you can create new menu items in well-
defined positions of your menu hierarchy—namely, where you put a menu item with a nonzero
Index value—but you can't create new submenus or new top-level menus.
Now that you have a thorough understanding of how Visual Basic's forms and controls work,
you're ready to dive into the subtleties of the Visual Basic for Applications (VBA) language.
Three of the controls on the ToolBox let you access the computer's file system. They are
DriveListBox, DirListBox and FileListBox controls (see below figure) , which are the basic blocks
for building dialog boxes that display the host computer's file system. Using these controls, user
can traverse the host computer's file system, locate any folder or files on any hard disk, even on
network drives. The files are controls are independent of one another, and each can exist on it's
own, but they are rarely used separately. The files controls are described next.
In a nutshell, the DriveListBox control is a combobox-like control that's automatically filled with
your drive's letters and volume labels. The DirListBox is a special list box that displays a directory
tree. The FileListBox control is a special-purpose ListBox control that displays all the files in a
given directory, optionally filtering them based on their names, extensions, and attributes.
These controls often work together on the same form; when the user selects a drive in a
DriveListBox, the DirListBox control is updated to show the directory tree on that drive. When the
user selects a path in the DirListBox control, the FileListBox control is filled with the list of files in
that directory. These actions don't happen automatically, however—you must write code to get
the job done.
After you place a DriveListBox and a DirListBox control on a form's surface, you usually don't
have to set any of their properties; in fact, these controls don't expose any special property, not in
the Properties window at least. The FileListBox control, on the other hand, exposes one property
that you can set at design time—the Pattern property. This property indicates which files are to be
shown in the list area: Its default value is *.* (all files), but you can enter whatever specification
you need, and you can also enter multiple specifications using the semicolon as a separator. You
can also set this property at run time, as in the following line of code:
File1.Pattern = "*.txt;*.doc;*.rtf"
Following figure shows three files controls are used in the design of Forms that let users explore
the entire structure of their hard disks.
• DriveListBox : Displays the names of the drives within and connected to the PC. The
basic property of this control is the drive property, which set the drive to be initially
selected in the control or returns the user's selection.
• DirListBox : Displays the folders of current Drive. The basic property of this control is the
Path property, which is the name of the folder whose sub folders are displayed in the
control.
• FileListBox : Displays the files of the current folder. The basic property of this control is
also called Path, and it's the path name of the folder whose files are displayed.
The three File controls are not tied to one another. If you place all three of them on a Form, you
will see the names of all the folders under the current folder, and so on. Each time you select a
folder in the DirlistBox by double clicking its name, its sub folders are displayed. Similarly , the
FileListBox control will display the names of all files in the current folder. Selecting a drive in the
DriveListBox control, however this doesn't affect the contents of the DirListBox.
To connect to the File controls, you must assign the appropriate values to the properties. To
compel the DirListBox to display the folders of the selected drive in the DriveListBox, you must
make sure that each time the user selects another drive, the Path property of the DirListBox
control matches the Drive property of the DriveListBox.
After these preliminary steps, you're ready to set in motion the chain of events. When the user
selects a new drive in the DriveListBox control, it fires a Change event and returns the drive letter
(and volume label) in its Drive property. You trap this event and set the DirListBox control's Path
property to point to the root directory of the selected drive:
When the user double-clicks on a directory name, the DirListBox control raises a Change event;
you trap this event to set the FileListBox's Path property accordingly:
Finally, when the user clicks on a file in the FileListBox control, a Click event is fired (as if it were
a regular ListBox control), and you can query its Filename property to learn which file has been
selected. Note how you build the complete path:
Filename = File1.Path
If Right$(Filename, 1) <> "\" Then Filename = Filename & "\"
Filename = Filename & File1.Filename
The DirListBox and FileListBox controls support most of the properties typical of the control they
derive from—the ListBox control—including the ListCount and the ListIndex properties and the
Scroll event. The FileListBox control supports multiple selection; hence you can set its MultiSelect
property in the Properties window and query the SelCount and Selected properties at run time.
The FileListBox control also exposes a few custom Boolean properties, Normal, Archive, Hidden,
ReadOnly, and System, which permit you to decide whether files with these attributes should be
listed. (By default, the control doesn't display hidden and system files.) This control also supports
a couple of custom events, PathChange and PatternChange, that fire when the corresponding
property is changed through code. In most cases, you don't have to worry about them, and I won't
provide examples of their usage.
The problem with the DriveListBox, DirListBox and FileListBox controls is that they're somewhat
outdated and aren't used by most commercial applications any longer. Moreover, these controls
are known to work incorrectly when listing files on network servers and sometimes even on local
disk drives, especially when long file and directory names are used. For this reason, I discourage
you from using them and suggest instead that you use the Common Dialog controls for your
FileOpen and FileSave dialog boxes. But if you need to ask the user for the name of a directory
rather than a file, you're out of luck because—while Windows does include such a system dialog
box, named BrowseForFolders dialog—Visual Basic still doesn't offer a way to display it (unless
you do some advanced API programming). Fortunately, Visual Basic 6 comes with a new control
—the ImageCombo control—that lets you simulate the appearance of the DriveListBox control. It
also offers you a powerful library—the FileSystemObject library—that completely frees you from
using these three controls, if only as hidden controls that you use just for quickly retrieving
information on the file system.
The CheckBox control is similar to the option button, except that a list of choices can be
made using check boxes where you cannot choose more than one selection using
an OptionButton. By ticking the CheckBox the value is set to True. This control can also be
grayed when the state of the CheckBox is unavailable, but you must manage that state through
code.
When you place a CheckBox control on a form, all you have to do, usually, is set its Caption
property to a descriptive string. You might sometimes want to move the little check box to the
right of its caption, which you do by setting the Alignment property to 1-Right Justify, but in most
cases the default setting is OK. If you want to display the control in a checked state, you set its
Value property to 1-Checked right in the Properties window, and you set a grayed state with 2-
Grayed.
The only important event for CheckBox controls is the Click event, which fires when either the
user or the code changes the state of the control. In many cases, you don't need to write code to
handle this event. Instead, you just query the control's Value property when your code needs to
process user choices. You usually write code in a CheckBox control's Click event when it affects
the state of other controls. For example, if the user clears a check box, you might need to disable
one or more controls on the form and reenable them when the user clicks on the check box
again. This is how you usually do it (here I grouped all the relevant controls in one frame named
Frame1):
Note that Value is the default property for CheckBox controls, so you can omit it in code. I
suggest that you not do that, however, because it would reduce the readability of your code.
* Open a new Project and save the Form as CheckBox.frm and save the Project
as CheckBox.vbp
To terminate the program following code is typed in the Click() event of the Exit button
Run the program by pressing F5. Check the program by clicking on OptionButtons and
CheckBoxes.
The main characteristic of a Form is the title bar on which the Form's caption is displayed. On the
left end of the title bar is the Control Menu icon. Clicking this icon opens the Control Menu.
Maximize, Minimize and Close buttons can be found on the right side of the Form. Clicking on
these buttons performs the associated function.
• Restore : Restores a maximized Form to the size it was before it was maximized;
available only if the Form has been maximized.
• Move : Lets the user moves the Form around with the mouse
• Size : Lets the user resizes the control with the mouse
• Minimize: Minimizes the Form
• Maximize : Maximizes the Form
• Close : Closes the Form
By default, Visual Basic suggests the name of the first Form created when the project started.
Load FormName
Unload FormName
The FormName variable is the name of the Form to be loaded or unloaded. Unlike the Show
method which cares of both loading and displaying the Form, the load statement doesn't show the
Form. You have to call the Form's Show method to display it on the desktop.
FormName.Show mode
The FormName variable is the Form's name, and the optional argument mode determines
whether the Form will be Modal or not. It can have one of the following syntax :
* 0-Modeless (default)
* 1-Modal
Modeless Forms are the normal Forms. Modeless Forms interact with the user and the user
allowed to switch to any other Form of the application. If you do not specify the optional mode
argument, by default the mode is set to modeless.
The Modal Forms takes the total control of the application where user cannot switch to any other
Forms in the application unless the Form is closed. A modal Form, thus, must have a Close
button or some means to close the Form in order to return to the Form where the Modal Form
was loaded.
Hiding Forms
The Hide method is used to hide a Form. The following is the syntax of the Hide Method.
FormName.Hide
To hide a Form from within its own code, the following code can be used.
Me.Hide
You must understand that the Forms that are hidden are not unloaded ; they remains in the
memory and can be displayed instantly with the Show Method. When a Form is hidden, you can
still access its properties and code. For instance, you can change the settings of its Control
Properties or call any Public functions in the Form.
The following is an example illustrates the Show method and Mode statement
Run the application. Clicking on the buttons will display the Forms respectively. But you can see
that in the cmd2_Click( ) event additionally VbModal argument has been added. You can see the
difference after you display the forms by clicking on the command buttons. You can notice that
you cannot switch to any other Forms in the application unless you close the Form3. (Download
the source code)
Me.Hide
Save the project and run the application. Once you click on Hide button you can note that the
Form is invisible but the application is still running. But when you click on Unload button you can
see that the application is terminated.
Windows applications provide groups of related commands in Menus. These commands depends
on the application, but some-such as Open and Save are frequently found in applications. Menus
are intrinsic controls, and as such they deserve a place in this chapter. On the other hand, menus
behave differently from other controls. For example, you don't drop menu items on a form from
the Toolbox; rather, you design them in the Menu Editor window, as you can see in the figur
below. You invoke this tool from the Menu Editor button on the standard toolbar or by pressing
the Ctrl+E shortcut key. There's also a Menu Editor command in the Tools menu, but you
probably won't use it often.
Visual Basic provides an easy way to create menus with the modal Menu Editor dialog. The
below dialog is displayed when the Menu Editor is selected in the Tool Menu. The Menu Editor
command is grayed unless the form is visible. And also you can display the Menu Editor window
by right clicking on the Form and selecting Menu Editor.
Basically, each menu item has a Caption property (possibly with an embedded & character to
create an access key) and a Name. Each item also exposes three Boolean properties, Enabled,
Visible, and Checked, which you can set both at design time and at run time. At design time, you
can assign the menu item a shortcut key so that your end users don't have to go through the
menu system each time they want to execute a frequent command. (Do you really like pulling
down the Edit menu any time you need to clear some text or copy it to the Clipboard?) The
assigned shortcut key can't be queried at run time, much less modified.
Building a menu is a simple, albeit more tedious, job: You enter the item's Caption and Name, set
other properties (or accept the default values for those properties), and press Enter to move to
the next item. When you want to create a submenu, you press the Right Arrow button (or the
Alt+R hot key). When you want to return to work on top-level menus—those items that appear in
the menu bar when the application runs—you click the Left Arrow button (or press Alt+L). You
can move items up and down in the hierarchy by clicking the corresponding buttons or the hot
keys Alt+U and Alt+B, respectively.
You can create up to five levels of submenus (six including the menu bar), which are too many
even for the most patient user. If you find yourself working with more than three menu levels,
think about trashing your specifications and redesigning your application from the ground up.
You can insert a separator bar using the hypen (-) character for the Caption property. But even
these separator items must be assigned a unique value for the Name property, which is a real
nuisance. If you forget to enter a menu item's Name, the Menu Editor complains when you decide
to close it. The convention used in this book is that all menu names begin with the three letters
mnu.
One of the most annoying defects of the Menu Editor tool is that it doesn't permit you to reuse the
menus you have already written in other applications. It would be great if you could open another
instance of the Visual Basic IDE, copy one or more menu items to the clipboard, and then paste
those menu items in the application under development. You can do that with controls and with
pieces of code, but not with menus! The best thing you can do in Visual Basic is load the FRM file
using an editor such as Notepad, find the portion in the file that corresponds to the menu you're
interested in, load the FRM file you're developing (still in Notepad), and paste the code there. This
isn't the easiest operation, and it's also moderately dangerous: If you paste the menu definition in
the wrong place, you could make your FRM form completely unreadable. Therefore, always
remember to make backup copies of your forms before trying this operation.
Better news is that you can add a finished menu to a form in your application with just a few
mouse clicks. All you have to do is activate the Add-In Manager from the Add-Ins menu, choose
the VB 6 Template Manager, and tick the Loaded/Unloaded check box. After you do that, you'll
find three new commands in the Tools menu: Add Code Snippet, Add Menu, and Add Control
Set. Visual Basic 6 comes with a few menu templates, as you can see in the following figure, that
you might find useful as a starting point for building your own templates. To create your menu
templates, you only have to create a form with the complete menu and all the related code and
then store this form in the \Templates\Menus directory. (The complete path, typically c:\Program
Files\Microsoft Visual Studio\VB98\Template, can be found in the Environment tab of the Options
dialog box on the Tools menu. The Template Manager was already available with Visual Basic 5,
but it had to be installed manually and relatively few programmers were aware of its existence.
The Template Manager in action
The programmer can create menu control arrays. The Index TextBox specifies the menu's index
in the control array.
The Menu Editor dialog also provides several CheckBoxes to control the appearance of the
Menu.
Checked : This is unchecked by default and allows the programmer the option of creating a
checked menu item( a menu item that act as a toggle and displays a check mark when selected.
The following is a Check Menu items.
Enabled : specifies whether a menu is disabled or not. If you see a disabled command in a menu
that means that feature is not available. The Visible checkbox specifies whether the menu is
visible or not.
To add commands to the Form's menu bar, enter a caption and a name for each command. As
soon as you start typing the command's caption, it also appears in a new line in the list at the
bottom of the Menu Editor window. To add more commands click Enter and type the Caption and
the Name.
Creating Menus
Open a new Project and save the form as menu.frm and save the project as menu.vbp.
Choose Tools ››› Menu Editor and type the menu items as shown below.
Caption Name
File mnuFile
Open mnuOpen
Save mnuSave
Exit mnuExit
Edit mnuEdit
Copy mnuCopy
Cut mnuCut
Paste mnuPaste
Run the application by pressing F5. You can see that you can select a menu.
Menu controls expose only one event, Click. As you expect, this event fires when the user clicks
on the menu:
You can manipulate menu items at run time through their Checked, Visible, and Enabled
properties. For example, you can easily implement a menu item that acts as a switch and
displays or hides a status bar:
While menu items can be responsible for their own Checked status, you usually set their Visible
and Enabled properties in another region of the code. You make a menu item invisible or disabled
when you want to make the corresponding command unavailable to the user. You can choose
from two different strategies to achieve this goal: You can set the menu properties as soon as
something happens that affects that menu command, or you can set them one instant before the
menu is dropped down. Let me explain these strategies with two examples.
Let's say that the Save command from the File menu should look disabled if your application has
loaded a read-only file. In this case, the most obvious place in code to set the menu Enabled
property to False is in the procedure that loads the file, as shown in the code below.
This solution makes sense because the menu state doesn't change often. By comparison, the
state of most of the commands in a typical Edit menu (Copy, Cut, Clear, Undo, and so on)
depends on whether any text is currently selected in the active control. In this case, changing the
menu state any time a condition changes (because the user selects or deselects text in the active
control, for example) is a waste of time, and it also requires a lot of code. Therefore, it's
preferable to set the state of those menu commands in the parent menu's Click event just before
displaying the menu:
Visual Basic also supports pop-up menus, those context-sensitive menus that most commercial
applications show when you right-click on an user interface object. In Visual Basic, you can
display a pop-up menu by calling the form's PopupMenu method, typically from within the
MouseDown event procedure of the object:
The argument you pass to the PopupMenu method is the name of a menu that you have defined
using the Menu Editor. This might be either a submenu that you can reach using the regular
menu structure or a submenu that's intended to work only as a pop-up menu. In the latter case,
you should create it as a top-level menu in the Menu Editor and then set its Visible attribute to
False. If your program includes many pop-up menus, you might find it convenient to add one
invisible top-level entry and then add all the pop-up menus below it. (In this case, you don't need
to make each individual item invisible.) The complete syntax of the PopupMenu method is quite
complex:
By default, pop-up menus appear left aligned on the mouse cursor, and even if you use a right-
click to invoke the menu you can select a command only with the left button. You can change
these defaults using the Flags argument. The following constants control the alignment: 0-
vbPopupMenuLeftAlign (default), 4-vbPopupMenuCenterAlign, and 8-vbPopupMenuRightAlign.
The following constants determine which buttons are active during menu operations: 0-
vbPopupMenuLeftButton (default) and 2-vbPopupMenuRightButton. For example, I always use
the latter because I find it natural to select a command with the right button since it's already
pressed when the menu appears:
The x and y arguments, if specified, make the menu appear in a particular position on the form,
rather than at mouse coordinates. The last optional argument is the name of the menu that's the
default item for the pop-up menu. This item will be displayed in boldface. This argument has only
a visual effect; If you want to offer a default menu item, you must write code in the MouseDown
event procedure to trap double-clicks with the right button.
You can take advantage of the x and y arguments in a PopupMenu method to make your
program more Windows compliant, and show your pop-up menus over the control that has the
focus when the user presses the Application key (the key beside the Windows key on the right
side of a typical extended keyboard, such as the Microsoft Natural Keyboard). But remember that
Visual Basic doesn't define any key-code constant for this key. Here's how you must proceed:
Visual Basic's implementation of pop-up menus has a serious flaw. All Visual Basic TextBox
controls react to right-clicks by showing the standard Edit pop-up menu (with the usual
commands, such as Undo, Copy, Cut, and so on). The problem is that if you invoke a
PopupMenu method from within the TextBox control's MouseDown event, your custom pop-up
menu will be displayed only after the standard one, which is obviously undesirable. You can solve
it only by resorting to the unorthodox and undocumented technique shown below.
You almost certainly use Windows applications that can open multiple documents at the same
time and allow the user to switch among them with a mouse-click. Multiple Word is a typical
example, although most people use it in single document mode. Each document is displayed in
its own window, and all document windows have the same behavior. The main Form, or MDI
Form, isn't duplicated, but it acts as a container for all the windows, and it is called the parent
window. The windows in which the individual documents are displayed are called Child windows.
An MDI application must have at least two Form, the parent Form and one or more child Forms.
Each of these Forms has certain properties. There can be many child forms contained within the
parent Form, but there can be only one parent Form.
The parent Form may not contain any controls. While the parent Form is open in design mode,
the icons on the ToolBox are not displayed, but you can't place any controls on the Form. The
parent Form can, and usually has its own menu.
1. Start a new project and then choose Project >>> Add MDI Form to add the parent Form.
2. Set the Form's caption to MDI Window
3. Choose Project >>> Add Form to add a SDI Form.
4. Make this Form as child of MDI Form by setting the MDI Child property of the SDI Form
to True. Set the caption property to MDI Child window.
Visual Basic automatically associates this new Form with the parent Form. This child Form can't
exist outside the parent Form; in the words, it can only be opened within the parent Form.
MDI Form cannot contain objects other than child Forms, but MDI Forms can have their own
menus. However, because most of the operations of the application have meaning only if there is
at least one child Form open, there's a peculiarity about the MDI Forms. The MDI Form usually
has a menu with two commands to load a new child Form and to quit the application. The child
Form can have any number of commands in its menu, according to the application. When the
child Form is loaded, the child Form's menu replaces the original menu on the MDI Form
Following example illustrates the above explanation.
* Open a new Project and name the Form as Menu.frm and save the Project as Menu.vbp
At design time double click on MDI Open and add the following code in the click event of the open
menu.
Form1.Show
And so double click on MDI Exit and add the following code in the click event
End
Double click on Child Close and enter the following code in the click event
Unload Me
Before run the application in the project properties set MDI Form as the start-up Form. Save and
run the application. Following output will be displayed.
And as soon as you click MDI Open you can notice that the main menu of the MDI Form is
replaced with the Menu of the Child Form. The reason for this behavior should be obvious. The
operation available through the MDI Form are quite different from the operations of the child
window. Moreover, each child Form shouldn't have it's own menu.
Displays a prompt in a dialog box, waits for the user to input text or click a button, and returns a
String containing the contents of the text box.
Syntax :
memory_variable is a variant data type but typically it is declared as string, which accept the
message input by the users. The arguments are explained as follows:
• Prompt - String expression displayed as the message in the dialog box. If prompt
consists of more than one line, you can separate the lines using the vbCrLf constant
• Title - String expression displayed in the title bar of the dialog box. If you omit the title,
the application name is displayed in the title bar
• default-text - The default text that appears in the input field where users can use it as his
intended input or he may change to the message he wish to key in.
• x-position and y-position - the position or the coordinate of the input box.
* Open a new project and save the Form as InputBox.frm and save the Project as InputBox.vbp
Name frmInputBox
Label Caption You entered
Name lbl1
Caption ( empty)
Label
Name lbl2
Name cmdOK
Following code is entered in cmdOK_Click ( ) event
Save and run the application. As soon as you click the OK button you will get the following
InputBox
Here I have entered "Hello World" in text field. As soon as you click OK the output is shown as
shown below
Displays a message in a dialog box and wait for the user to click a button, and returns an integer
indicating which button the user clicked.
Syntax :
Prompt : String expressions displayed as the message in the dialog box. If prompt consist of
more than one line, you can separate the lines using the vbrCrLf constant.
Icons + Buttons : Numeric expression that is the sum of values specifying the number and type
of buttons and icon to display.
Title : String expression displayed in the title bar of the dialog box. If you omit title, the application
name is placed in the title bar.
Icons
Buttons
Constant Value Description
vbOkOnly 0 Display OK button only
vbOkCancel 1 Display OK and Cancel buttons
Display Abort, Retry and Ignore
vbAbortRetryIgnore 2
buttons
Display Yes, No and Cancel
vbYesNoCancel 3
buttons
vbYesNo 4 Display Yes and No buttons
Display Retry and Cancel
vbRetryCancel 5
buttons
Return Values
* Open a new Project and save the Form as messageboxdemo.frm and save the Project as
messageboxdemo.vbp
Name frmMessageBoxDemo
Label Caption lblName
Name Name
TextBox Name txtName
Text ( empty )
ListBox Name lstName
CommandButton Caption Add
Name cmdAdd
CommandButton Caption Delete
Name cmdDelete
CommandButton Caption Exit
Name cmdExit
End If
End If
End If
End Sub
Save and run the application. You can notice the different type of message box types are used to
perform an action
Visual Basic responds to various mouse events, which are recognized by most of the controls.
The main events areMouseDown, MouseUp and MouseMove. MouseDown occurs when the
user presses any mouse button and MouseUp occurs when the user releases any mouse button.
These events use the arguments button, Shift, X, Y and they contain information about the
mouse's condition when the button is clicked.
The first argument is an integer called Button. The value of the argument indicates whether the
left, right or middle mouse button was clicked. The second argument in an integer called shift.
The value of this argumnet indicates whether the mouse button was clicked simultaneously with
the Shift key, Ctrl key or Alt key. The third and fourth arguments X and Y are the coordinates of
the mouse location at the time the mouse button was clicked. As theForm_MouseDown( ) is
executed automatically whenever the mouse button is clicked inside the Form's area the X, Y co-
ordinates are referenced to the form.
Positioning a control
MouseDown is the commonly used event and it is combined wiyth the move method to move an
Image control to different locations in a Form. The following application illustrates the movement
of objects responding to move events. it makes use of two OptionButton Controls, two image
controls and a CommandButton. The application is designed in such a way that when an
OptionButton is selected, the corresponding image control is placed anywhere in the form
whenever it is clicked.
Open a new standard EXE project and save the Form as Move.frm and save the project
as Move.vbp Design the Form as shown below.
Name frmMouseDown
Name optCredit
Value True
Name optCash
Image Name imgCredit
Picture c:/credit.jpg
Image Name imgCash
Picture c:/cash.jpg
The follwoing code is entered in the general declarations section of the Form.
Option Explicit
Run the application by keying in F5. You can notice that when the mouse is clicked on the form
somewhere, the selected image moves to that clicked location. This is shown in the below figure.
The mouse events can be combined with graphics methods and any number of customized
drawing or paint applications can be created. The following application combines MouseMove
and MouseDown events, and illustrates a drawing program.
Open a new Standard EXE project and save the Form as Draw.frm and save the Project as
Draw.vbp. Name the caption of the as Drawing. Add command button control and name the
caption of it as Clear
Button value 1 indicates that the left mouse button is clicked. The code written in the MouseDown
event changes the CurrentX and CurrentY to the coordinates where the mouse button was just
clicked.
Run the application. You can notice that when the mouse is clicked and moved in the Form a line
is drawn corresponding to the mouse movement. Following figure illustrates the combined action
of MouseDown and MouseMove.
The program uses two graphics related Visual Basic concepts, the Line method and the CurrentX
and CurrentY properties. Line method is preferred to draw a line in a Form. The following
statement draws a line from the coordinates X = 2500, Y = 2000, X = 5000, Y = 5500
MouseMove application
Visual Basic does not generate a MouseMove event for every pixel the mouse moves over and
a limited number of mouse messages are generated per second by the operating environment.
The following application illustrates how often the Form_MouseMove ( ) event is executed.
Open a new standard EXE project and save the form as MouseMove.frm and save the Project as
MouseMOve.vbp. Place a CommandButton control and name the caption as Clear and set the
name as cmdClear.
The above procedure simply draws small circles at the mouse's current location using the Circle
method. The parameter x, y represent the centre of the circle, and the second parameter
represents the radius of the circle.
Save the application and run. You can notice that when the mouse is moved inside the Form,
circles are drwan along the path of the mouse movement as shown in below figure. And also you
can notice the circles are widely spaced when the mouse is moved quickly. Each small circle is
an indication that the MouseMove event occured and theForm_MouseMove ( ) procedure was
executed.
( Download the source code )
Error Handling enables programmers to write clearer, more robust, more fault-tolerant programs.
Error handling enables the programmer to attempt to recover (i.e., continue executing) from
infrequent fatal errors rather than letting them occur and suffering the consequences (such as
loss of application data). If an error is severe and recovery is not possible, the program can be
exited "gracefully"-all files can be closed and notification can be given that the program is
terminating. The recovery code is called an error handler.
Error handling is designed for dealing with synchronous errors such as an attempt to divide by 0
(that occurs as the program executes the divide instruction). Other common examples of
synchronous errors are memory exhaustion, an out-of-bound array index, and arithmetic
overflow. Error handling provides the programmer with a disciplined set of capabilities for dealing
with these types of errors.
Error-handling code varies in nature and amount among software systems depending on the
application and whether or not the software is a product for release. Products tend to contain
much more error-handling code than is contained in "casual" software.
Usually, error-handling code is interspersed throughout a program's code. Errors are dealt with
the places in the code where errors are likely to occur. The advantage of this approach is that a
programmer reading the code can see the error handling in the immediate vicinity of the code and
determine if the proper error handling has been implemented.
The problem with the scheme is that code in a sense becomes "polluted" with error handling. It
becomes difficult for a programmer concerned with the application itself to read the code and
determine if the code is working is correctly. Error handling often makes the code more difficult to
understand and maintain.
Contents
Error Types
Debugging Strategies
Sequential Files
User-Defined Variables
• No matter how hard we try, errors do creep into our programs. These errors can be grouped into
three categories:
1. Syntax errors
2. Run-time errors
3. Logic errors
• Syntax errors occur when you mistype a command or leave out an expected phrase or
argument. Visual Basic detects these errors as they occur and even provides help in correcting
them. You cannot run a Visual Basic program until all syntax errors have been corrected.
• Run-time errors are usually beyond your program's control. Examples include: when a variable
takes on an unexpected value (divide by zero), when a drive door is left open, or when a file is not
found. Visual Basic allows you to trap such errors and make attempts to correct them.
• Logic errors are the most difficult to find. With logic errors, the program will usually run, but will
produce incorrect or unexpected results. The Visual Basic debugger is an aid in detecting logic
errors.
• Design your application carefully. More design time means less debugging time.
• Use comments where applicable to help you remember what you were trying to do.
• Use consistent and meaningful naming conventions for your variables, objects, and
procedures.
• Run-time errors are trappable. That is, Visual Basic recognizes an error has occurred and
enables you to trap it and take corrective action. If an error occurs and is not trapped, your
program will usually end in a rather unceremonious manner.
Yes, this uses the dreaded GoTo statement! Any time a run-time error occurs following this line,
program control is transferred to the line labeled errlabel. Recall a labeled line is simply a line with
the label followed by a colon (:).
• The best way to explain how to use error trapping is to look at an outline of an example
procedure with error trapping.
Sub SubExample()
[Procedure code]
Exit Sub
HandleErrors:
End Sub
Once you have set up the variable declarations, constant definitions, and any other procedure
preliminaries, the On Error statement is executed to enable error trapping. Your normal procedure
code follows this statement. The error handling code goes at the end of the procedure, following
the HandleErrors statement label. This is the code that is executed if an error is encountered
anywhere in the Sub procedure. Note you must exit (with Exit Sub) from the code before reaching
the HandleErrors line to avoid inadvertent execution of the error handling code.
• Since the error handling code is in the same procedure where an error occurs, all variables in
that procedure are available for possible corrective action. If at some time in your procedure, you
want to turn off error trapping, that is done with the following statement:
On Error GoTo 0
• Once a run-time error occurs, we would like to know what the error is and attempt to fix it. This
is done in the error handling code.
• Visual Basic offers help in identifying run-time errors. The Err object returns, in its Number
property (Err.Number), the number associated with the current error condition. (The Err function
has other useful properties that we won’t cover here - consult on-line help for further information.)
The Error() function takes this error number as its argument and returns a string description of the
error. Consult on-line help for Visual Basic run-time error numbers and their descriptions.
• Once an error has been trapped and some action taken, control must be returned to your
application. That control is returned via the Resume statement. There are three options:
Resume Lets you retry the operation that caused the error. That is, control is returned to the line
where the error occurred. This could be dangerous in that, if the error has not been corrected (via
code or by the user), an infinite loop between the error handler and the procedure code may
result.
Resume Next Program control is returned to the line immediately following the line where the
error occurred.
Resume label Program control is returned to the line labeled label.
• Be careful with the Resume statement. When executing the error handling portion of the code
and the end of the procedure is encountered before a Resume, an error occurs. Likewise, if a
Resume is encountered outside of the error handling portion of the code, an error occurs.
• What we develop here is a generic framework for an error handling procedure. It simply informs
the user that an error has occurred, provides a description of the error, and allows the user to
Abort, Retry, or Ignore. This framework is a good starting point for designing custom error
handling for your applications.
HandleErrors:
Select Case MsgBox(Error(Err.Number), vbCritical + vbAbortRetryIgnore,
"Error Number" + Str(Err.Number))
Case vbAbort
Resume ExitLine
Case vbRetry
Resume
Case vbIgnore
Resume Next
End Select
ExitLine:
Exit Sub
Let’s look at what goes on here. First, this routine is only executed when an error occurs. A
message box is displayed, using the Visual Basic provided error description [Error(Err.Number)]
as the message, uses a critical icon along with the Abort, Retry, and Ignore buttons, and uses the
error number [Err.Number] as the title. This message box returns a response indicating which
button was selected by the user.
If Abort is selected, we simply exit the procedure. (This is done using a Resume to the line
labeled ExitLine. Recall all error trapping must be terminated with a Resume statement of some
kind.)
If Retry is selected, the offending program line is retried (in a real application, you or the user
would have to change something here to correct the condition causing the error).
If Ignore is selected, program operation continues with the line following the error causing line.
• To use this generic code in an existing procedure, you need to do three things:
1.
1.
1. Copy and paste the error handling code into the end of your procedure.
2.
3. Place an Exit Sub line immediately preceding the HandleErrors labeled line.
4.
5. Place the line, On Error GoTo HandleErrors, at the beginning of your procedure.
For example, if your procedure is the SubExample seen earlier, the modified code will look like
this:
Sub SubExample()
.
. [Declare variables, ...]
.
On Error GoTo HandleErrors
.
. [Procedure code]
.
Exit Sub
HandleErrors:
Select Case MsgBox(Error(Err.Number), vbCritical + vbAbortRetryIgnore,
"Error Number" + Str(Err.Number))
Case vbAbort
Resume ExitLine
Case vbRetry
Resume
Case vbIgnore
Resume Next
End Select
ExitLine:
Exit Sub
End Sub
Again, this is a very basic error-handling routine. You must determine its utility in your
applications and make any modifications necessary. Specifically, you need code to clear error
conditions before using the Retry option.
• One last thing. Once you've written an error handling routine, you need to test it to make sure it
works properly. But, creating run-time errors is sometimes difficult and perhaps dangerous. Visual
Basic comes to the rescue! The Visual Basic Err object has a method (Raise) associated with it
that simulates the occurrence of a run-time error. To cause an error with value Number, use:
Err.Raise Number
• We can use this function to completely test the operation of any error handler we write. Don’t
forget to remove the Raise statement once testing is completed, though! And, to really get fancy,
you can also use Raise to generate your own ‘application-defined’ errors. There are errors
specific to your application that you want to trap.
• To clear an error condition (any error, not just ones generated with the Raise method), use the
method Clear:
Err.Clear
Form1:
BorderStyle - 1-Fixed Single
Caption - Error Generator
Name frmError
Command1:
Caption - Generate Error
Default - True
Name - cmdGenError
Text1:
Name - txtError
Text - [Blank]
HandleErrors:
Select Case MsgBox(Error(Err.Number), vbCritical + vbAbortRetryIgnore,
"Error Number" + Str(Err.Number))
Case vbAbort
Resume ExitLine
Case vbRetry
Resume
Case vbIgnore
Resume Next
End Select
ExitLine:
Exit Sub
End Sub
In this code, we simply generate an error using the number input in the text box. The generic
error handler then displays a message box which you can respond to in one of three ways.
4. Save your application. Try it out using some of these typical error numbers (or use numbers
found with on-line help). Notice how program control changes depending on which button is
clicked.
6 Overflow
9 Subscript out of range
11 Division by zero
13 Type mismatch
16 Expression too complex
20 Resume without error
52 Bad file name or number
53 File not found
55 File already open
61 Disk full
70 Permission denied
92 For loop not initialized
• We now consider the search for, and elimination of, logic errors. These are errors that don’t
prevent an application from running, but cause incorrect or unexpected results. Visual Basic
provides an excellent set of debugging tools to aid in this search.
• Debugging a code is an art, not a science. There are no prescribed processes that you can
follow to eliminate all logic errors in your program. The usual approach is to eliminate them as
they are discovered.
• What we’ll do here is present the debugging tools available in the Visual Basic environment
(several of which appear as buttons on the toolbar) and describe their use with an example. You,
as the program designer, should select the debugging approach and tools you feel most
comfortable with.
• The interface between your application and the debugging tools is via three different debug
windows: the Immediate Window, the Locals Window, and the Watch Window. These windows
can be accessed from the View menu (the Immediate Window can be accessed by pressing
Ctrl+G). Or, they can be selected from the Debug Toolbar (accessed using the Toolbars option
under the View menu):
• All debugging using the debug windows is done when your application is in break mode. You
can enter break mode by setting breakpoints, pressing Ctrl+Break, or the program will go into
break mode if it encounters an untrapped error or a Stop statement.
• Once in break mode, the debug windows and other tools can be used to:
Example - Debugging
1. Unlike other examples, we’ll do this one as a group. It will be used to demonstrate use of the
debugging tools.
2. The example simply has a form with a single command button. The button is used to execute
some code. We won’t be real careful about proper naming conventions and such in this example.
3. The code attached to this button’s Click event is a simple loop that evaluates a function at
several values.
This code begins with an X value of 0 and computes the Y value using the general integer
function Fcn. It then increments X by 1 and repeats the Loop. It continues looping While X is less
than or equal to 20. The function Fcn is computed using:
Admittedly, this code doesn’t do much, especially without any output, but it makes a good
example for looking at debugger use. Set up the application and get ready to try debugging.
• There are several debugging tools available for use in Visual Basic. Access to these tools is
provided with both menu options and buttons on the Debug toolbar. These tools include
breakpoints, watch points, calls, step
• The simplest tool is the use of direct prints to the immediate window.
You can print directly to the immediate window while an application is running. Sometimes, this is
all the debugging you may need. A few carefully placed print statements can sometimes clear up
all logic errors, especially in small applications.
• Debug.Print Example:
1. Place the following statement in the Command1_Click procedure after the line calling the
general procedure Fcn:
Debug.Print X; Y
• Breakpoints:
In the above examples, the program ran to completion before we could look at the debug window.
In many applications, we want to stop the application while it is running, examine variables and
then continue running. This can be done with breakpoints.
A breakpoint is a line in the code where you want to stop (temporarily) the execution of the
program, that is force the program into break mode. To set a breakpoint, put the cursor in the line
of code you want to break on. Then, press <F9> or click the Breakpoint button on the toolbar or
select Toggle Breakpoint from the Debug menu. The line will be highlighted.
When you run your program, Visual Basic will stop when it reaches lines with breakpoints and
allow you to use the immediate window to check variables and expressions. To continue program
operation after a breakpoint, press <F5>, click the Run button on the toolbar, or choose Start from
the Run menu.
You can also change variable values using the immediate window. Simply type a valid Basic
expression. This can sometimes be dangerous, though, as it may change program operation
completely.
• Breakpoint Example:
1. Set a breakpoint on the X = X + 1 line in the sample program. Run the program.
2. When the program stops, display the immediate window and type the following line:
Print X;Y
3. The values of these two variables will appear in the debug window. You can use a
question mark (?) as shorthand for the command Print, if you’d like. Restart the
application. Print the new variable values.
4. Try other breakpoints if you have time. Once done, all breakpoints can be cleared by
Ctrl+Shift+<F9> or by choosing Clear All Breakpoints from the Debug menu. Individual
breakpoints can be toggled using <F9> or the Breakpoint button on the toolbar.
• Watch Expressions:
The Add Watch option on the Debug menu allows you to establish watch expressions for your
application. Watch expressions can be variable values or logical expressions you want to view or
test. Values of watch expressions are displayed in the watch window.
In break mode, you can use the Quick Watch button on the toolbar to add watch expressions you
need. Simply put the cursor on the variable or expression you want to add to the watch list and
click the Quick Watch button.
Watch expressions can be edited using the Edit Watch option on the Debug menu.
• Call Stack:
Selecting the Call Stack button from the toolbar (or pressing Ctrl+L or selecting Call Stack from
the View menu) will display all active procedures, that is those that have not been exited.
Call Stack helps you unravel situations with nested procedure calls to give you some idea of
where you are in the application.
1. Set a breakpoint on the Fcn = Cint() line in the general function procedure. Run the
application. It will break at this line.
2. Press the Call Stack button. It will indicate you are currently in the Fcn procedure which
was called from the Command1_Click procedure. Clear the breakpoint.
This process is single stepping. It allows you to watch how variables change (in the locals
window) or how your form changes, one step at a time.
You may step through several lines at a time by using Run To Cursor option. With this option,
click on a line below your current point of execution. Then press Ctrl+<F8> (or choose Run To
Cursor in the Debug menu). the program will run through every line up to the cursor location, then
stop.
While single stepping your program, if you come to a procedure call you know functions properly,
you can perform procedure stepping. This simply executes the entire procedure at once, rather
than one step at a time.
To move through a procedure in this manner, press Shift+<F8>, choose Step Over from the
Debug menu, or press the Step Over button on the toolbar.
While stepping through your program, if you wish to complete the execution of a function you are
in, without stepping through it line-by-line, choose the Step Out option. The function will be
completed and you will be returned to the procedure accessing that function.
To perform this step out, press Ctrl+Shift+<F8>, choose Step Out from the Debug menu, or press
the Step Out button on the toolbar. Try this on the previous example
All business applications need to store large volumes of data organized in a format so that
information can be retrieved efficiently and quickly as and when required. With the help of a
DBMS (Database Management System), managing the data becomes easy. A DBMS is a system
that manages the storage and retrieval of data in a database.
Further Microsoft Visual Basic provides tools for creating and accessing a variety of RDBMS
(Relational Database Management System). An RDBMS stores and retrieves information
according to the relationship defined. In a RDBMS, the data is the container of the tables in which
all data is stored in the relationships is formed by data values.
A database is a collection of data that is related one to another to support a common application.
For example Employee details - Name, Address, etc. Each of these collections of data continue a
database.
Contents
Database Structure and Terminology
Data Links
Assigning Tables
Data Manager
Example - Phone Directory - Creating the Database
Database Management
Example - Phone Directory - Managing the Database
• The rows in a database table are used to describe similar items. The rows are referred to as
database records. In general, no two rows in a database table will be alike.
• The columns in a database table provide characteristics of the records. These characteristics
are called database fields. Each field contains one specific piece of information. In defining a
database field, you specify the data type, assign a length, and describe other attributes.
In this database table, each record represents a single individual. The fields (descriptors of the
individuals) include an identification number (ID No), Name, Date of Birth, Height, and Weight.
• Most databases use indexes to allow faster access to the information in the database. Indexes
are sorted lists that point to a particular row in a table. In the example just seen, the ID No field
could be used as an index.
• A database using a single table is called a flat database. Most databases are made up of many
tables. When using multiple tables within a database, these tables must have some common
fields to allow cross-referencing of the tables. The referral of one table to another via a common
field is called a relation. Such groupings of tables are called relational databases.
• In our first example, we will use a sample database that comes with Visual Basic. This database
(BIBLIO.MDB) is found in the main Visual Basic directory (try c:\Program Files\Microsoft Visual
Studio\VB98). It is a database of books about computers. Let’s look at its relational structure. The
BIBLIO.MDB database is made up of four tables:
Note each table has two types of information: source data and relational data. Source data is
actual information, such as titles and author names. Relational data are references to data in
other tables, such as Au_ID and PubID. In the Authors, Publishers and Title Author tables, the
first column is used as the table index. In the Titles table, the ISBN value is the index.
• Using the relational data in the four tables, we should be able to obtain a complete description of
any book title in the database. Let’s look at one example:
Here, the book in the Titles table, entitled “Step-by-step dBase IV,” has an ISBN of 0-0280095-2-
5 and a PubID of 52. Taking the PubID into the Publishers table, determines the book is
published by McGraw-Hill and also allows us to access all other information concerning the
publisher. Using the ISBN in the Title Author table provides us with the author identification
(Au_ID) of 171, which, when used in the Authors table, tells us the book’s author is Toby Wraye.
• We can form alternate tables from a database’s inherent tables. Such virtual tables, or logical
views, are made using queries of the database. A query is simply a request for information from
the database tables. As an example with the BIBLIO.MDB database, using pre-defined query
languages, we could ‘ask’ the database to form a table of all authors and books published after
1992, or provide all author names starting with B. We’ll look briefly at queries.
The ADO (ActiveX Data Object) data control is the primary interface between a Visual Basic
application and a database. It can be used without writing any code at all! Or, it can be a central
part of a complex database management system. This icon may not appear in your Visual Basic
toolbox. If it doesn’t, select Project from the main menu, then click Components. The
Components window will appear. Select Microsoft ADO Data Control, then click OK. The control
will be added to your toolbox.
• As mentioned in Review and Preview, previous versions of Visual Basic used another data
control. That control is still included with Visual Basic 6.0 (for backward compatibility) and has as
its icon:
Make sure you are not using this data control for the work in this class. This control is suitable for
small databases. You might like to study it on your own.
• The data control (or tool) can access databases created by several other programs besides
Visual Basic (or Microsoft Access). Some other formats supported include Btrieve, dBase,
FoxPro, and Paradox databases.
• The data control can be used to perform the following tasks:
1. Connect to a database.
4. Pass database fields to other Visual Basic tools, for display or editing. Such tools are bound
tools (controls), or data aware.
LockType Indicates the type of locks placed on records during editing (default
setting makes databases read-only).
RecordSource Determines the table (or virtual table) the data control is attached to.
• As a rule, you need one data control for every database table, or virtual table, you need access
to. One row of a table is accessible to each data control at any one time. This is referred to as the
current record.
• When a data control is placed on a form, it appears with the assigned caption and four arrow
buttons:
The arrows are used to navigate through the table rows (records). As indicated, the buttons can
be used to move to the beginning of the table, the end of the table, or from record to record.
• After placing a data control on a form, you set theConnectionString property. The ADO data
control can connect to a variety of database types. There are three ways to connect to a
database: using a data link, using an ODBC data source, or using a connection string. In this
lesson, we will look only at connection to a Microsoft Access database using a data link. A data
link is a file with a UDL extension that contains information on database type.
• If your database does not have a data link, you need to create one. This process is best
illustrated by example. We will be using the BIBLIO.MDB database in our first example, so these
steps show you how to create its data link:
• If a data link has been created and exists for your database, click the ellipsis that appears next
to theConnectionString property. Choose Use Data Link File. Then, click Browse and find the
file. Click Open. The data link is now assigned to the property. Click OK.
• Once the ADO data control is connected to a database, we need to assign a table to that
control. Recall each data control is attached to a single table, whether it is a table inherent to the
database or the virtual table we discussed. Assigning a table is done via
the RecordSource property.
• Tables are assigned by making queries of the database. The language used to make a query
is SQL (pronounced ‘sequel,’ meaning structured query language). SQL is an English-like
language that has evolved into the most widely used database query language. You use SQL to
formulate a question to ask of the database. The data base ‘answers’ that question with a new
table of records and fields that match your criteria.
• Click on the ellipsis next to RecordSource in the property box. A Property Pages dialog box
will appear. In the box marked Command Text (SQL), type this line:
This will select all fields (the * is a wildcard) from a table named TableName in the database.
Click OK.
• Setting the RecordSource property also establishes the Recordset property, which we will see
later is a very important property.
• In summary, the relationship between the data control and its two primary properties
(ConnectionString andRecordSource) is:
• Most of the Visual Basic tools we’ve studied can be used as bound, or data-aware, tools (or
controls). That means, certain tool properties can be tied to a particular database field. To use a
bound control, one or more data controls must be on the form.
Label - Can be used to provide display-only access to a specified text data field.
Text Box - Can be used to provide read/write access to a specified text data field. Probably, the
most widely used data bound tool.
Combo Box - Can be used to provide read/write access to a text data field.
List Box - Can be used to provide read/write access to a text data field.
Picture Box - Used to display a graphical image from a bitmap, icon, or metafile on your form.
Provides read/write access to a image/binary data field.
Image Box - Used to display a graphical image from a bitmap, icon, or metafile on your form
(uses fewer resources than a picture box). Provides read/write access to a image/binary data
field.
• There are also three ‘custom’ data aware tools, the DataCombo (better than using the bound
combo box), DataList(better than the bound list box), and DataGrid tools, we will look at later.
DataField - Specifies the name of a field in the table pointed to by the respective data control.
If the data in a data-aware control is changed and then the user changes focus to another control
or tool, the database will automatically be updated with the new data (assuming LockType is set
to allow an update).
• To make using bound controls easy, follow these steps (in order listed) in placing the controls on
a form:
1. Draw the bound control on the same form as the data control to which it will be bound.
2. Set the DataSource property. Click on the drop-down arrow to list the data controls on
your form. Choose one.
3. Set the DataField property. Click on the drop-down arrow to list the fields associated with
the selected data control records. Make your choice.
4. Set all other properties, as required.
• The relationships between the bound data control and the data control are:
1. Start a new application. We’ll develop a form where we can skim through the books database,
examining titles and ISBN values. Place an ADO data control, two label boxes, and two text
boxes on the form.
2. If you haven’t done so, create a data link for the BIBLIO.MDB database following the steps
given under Data Links in these notes.
3. Set the following properties for each control. For the data control and the two text boxes, make
sure you set the properties in the order given.
Form1:
BorderStyle - 1-Fixed Single
Caption - Books Database
Name - frmBooks
Adodc1:
Caption - Book Titles
ConnectionString - BIBLIO.UDL (in whatever folder you saved it in - select, don’t type)
RecordSource - SELECT * FROM Titles
Name - dtaTitles
Label1:
Caption - Title
Label2:
Caption - ISBN
Text1:
DataSource - dtaTitles (select, don’t type)
DataField - Title (select, don’t type)
Locked - True
MultiLine - True
Name - txtTitle
Text - [Blank]
Text2:
DataSource - dtaTitles (select, don’t type)
DataField - ISBN (select, don’t type)
Locked - True
Name - txtISBN
Text - [Blank]
When done, the form will look something like this (try to space your controls as shown; we’ll use
all the blank space as we continue with this example):
4. Save the application. Run the application. Cycle through the various book titles using the data
control. Did you notice something? You didn’t have to write one line of Visual Basic code! This
indicates the power behind the data tool and bound tools.
Many times, a database table has more information than we want to display. Or, perhaps a table
does not have all the information we want to display. For instance, in Example 8-1, seeing the
Title and ISBN of a book is not real informative - we would also like to see the Author, but that
information is not provided by the Titles table. In these cases, we can build our own virtual table,
displaying only the information we want the user to see.
• We need to form a different SQL statement in the RecordSource property. Again, we won’t be
learning SQL here. We will just give you the proper statement.
1. We’ll use the results of Example 8-1 to add the Author name to the form. Replace the
RecordSource property of the dtaTitles control with the following SQL statement:
This must be typed as a single line in the Command Text (SQL) area that appears when you click
the ellipsis by the RecordSource property. Make sure it is typed in exactly as shown. Make sure
there are spaces after ‘SELECT’, after ‘Author,Titles.ISBN,Title’, after ‘FROM’, after ‘Authors,[Title
Author],Titles’, after ‘WHERE’, after ‘Authors.Au_ID=[Title Author].Au_ID’, after ‘AND’, after
‘Titles.ISBN=[Title Author].ISBN’, and separating the final three words ‘ORDER BY Author’. The
program will tell you if you have a syntax error in the SQL statement, but will give you little or no
help in telling you what’s wrong.
Here’s what this statement does: It selects the Author, Titles.ISBN, and Title fields from the
Authors, Title Author, and Titles tables, where the respective Au_ID and ISBN fields match. It
then orders the resulting virtual table, using authors as an index.
2. Add a label box and text box to the form, for displaying the author name. Set the control
properties.
Label3:
Caption - Author
Text1:
DataSource - dtaTitles (select, don’t type)
DataField - Author (select, don’t type)
Locked - True
Name - txtAuthor
Text - [Blank]
3. Save, then rerun the application. The author’s names will now appear with the book titles and
ISBN values. Did you notice you still haven’t written any code?
I know you had to type out that long SQL statement, but that’s not code, technically speaking.
Notice how the books are now ordered based on an alphabetical listing of authors’ last names
In addition to using the data control to move through database records, we can write Visual Basic
code to accomplish the same, and other, tasks. This is referred to as programmatic control. In
fact, many times the data control Visible property is set to Falseand all data manipulations are
performed in code. We can also use programmatic control to find certain records.
• There are four methods used for moving in a database. These methods replicate the capabilities
of the four arrow buttons on the data control:
• When moving about the database programmatically, we need to test the BOF (beginning of
file) and EOF (end of file) properties. The BOF property is True when the current record is
positioned before any data. The EOF property is True when the current record has been
positioned past the end of the data. If either property is True, the current record is invalid. If both
properties are True, then there is no data in the database table at all.
• These properties, and the programmatic control methods, operate on the Recordset property of
the data control. Hence, to move to the first record in a table attached to a data control
named dtaExample, the syntax is:
dtaExample.Recordset.MoveFirst
This method also operates on the Recordset property and has three arguments we will be
concerned with. To use Find with a data control named dtaExample:
dtaExample.Recordset.Find Criteria,NumberSkipped,SearchDirection
• The search Criteria is a string expression like a WHERE clause in SQL. We won’t go into much
detail on such criteria here. Simply put, the criteria describes what particular records it wants to
look at. For example, using our book database, if we want to look at books with titles
(the Title field) beginning with S, we would use:
Note the use of single quotes around the search letter. Single quotes are used to enclose strings
in Criteria statements. Three logical operators can be used: equals (=), greater than (>), and less
than (<).
• The NumberSkipped argument tells how many records to skip before beginning the Find. This
can be used to exclude the current record by setting NumberSkipped to 1.
• If a search fails to find a record that matches the criteria, the Recordset’s EOF or BOF property
is set to True(depending on search direction). Another property used in searches is
the Bookmark property. This allows you to save the current record pointer in case you want to
ret1. We expand the book database application to allow searching for certain author names. We’ll
use a ‘rolodex’ approach where, by pressing a particular letter button, books with author last
names corresponding to that button appear on the form.
2. We want a row of buttons starting at ‘A’ and ending at ‘Z’ to appear on the lower part of our
form. Drawing each one individually would be a big pain, so we’ll let Visual Basic do all the work
in the Form_Load procedure. What we’ll do is create one command button (the ‘A’), make it a
control array, and then dynamically create 25 new control array elements at run-time, filling each
with a different letter. We’ll even let the code decide on proper spacing.
So, add one command button to the previous form. Name it cmdLetter and give it a Caption of A.
Set its Index property to 0 to make it a control array element. On my form, things at this point look
like this:
3. Attach this code to the Form_Load procedure. This code sets up the rolodex control array and
draws the additional 25 letter buttons on the form. (Sorry, you have to type some code now!)
At this point, even though all the code is not in place, you could run your application to check how
the letter buttons look. My finished form (at run-time) looks like this:
Notice how Visual Basic adjusted the button widths to fit nicely on the form.
4. Attach this code to the cmdLetter_Click procedure. In this procedure, we use a search criteria
that finds the first occurrence of an author name that begins with the selected letter command
button. If the search fails, the record displayed prior to the search is retained (using the Bookmark
property).
dtaTitles.Recordset.MoveFirst
dtaTitles.Recordset.Find "Author >= '" + cmdLetter(Index).Caption +
"'", 0, adSearchForward
If dtaTitles.Recordset.EOF = True Then
dtaTitles.Recordset.Bookmark = BookMark1
End If
txtAuthor.SetFocus
End Sub
Let’s look at the search a little closer. We move to the top of the database using MoveFirst. Then,
the Find is executed (notice the selected letter is surrounded by single quotes). If EOF is True
after the Find, it means we didn’t find a match to the Criteria and Bookmark is returned to its
saved value.
5. Save your application. Test its operation. Note once the program finds the first occurrence of
an author name beginning with the selected letter (or next highest letter if there is no author with
the pressed letter), you can use the data control navigation buttons (namely the right arrow
button) to find other author names beginning with that letter.
• At this point, we know how to use the data control and associated data bound tools to access a
database. The power of Visual Basic lies in its ability to manipulate records in code. Such tasks
as determining the values of particular fields, adding records, deleting records, and moving from
record to record are easily done. This allows us to build a complete database management
system (DBMS).
• We don’t want to change the example database, BIBLIO.MDB. Let’s create our own database to
change. Fortunately, Visual Basic helps us out here. The Visual Data Manager is a Visual Basic
Add-In that allows the creation and management of databases. It is simple to use and can create
a database compatible with the Microsoft Jet (or Access) database engine.
• To examine an existing database using the Data Manager, follow these steps:
1. Select Visual Data Manager from Visual Basic’s Add-In menu (you may be asked if you
want to add SYSTEM.MDA to the .INI file - answer No.)
2. Select Open Database from the Data Manager File menu.
3. Select the database type and name you want to examine.
Once the database is opened, you can do many things. You can simply look through the various
tables. You can search for particular records. You can apply SQL queries. You can add/delete
records. The Data Manager is a DBMS in itself. You might try using the Data Manager to look
through the BIBLIO.MDB example database.
1. Select Visual Data Manager from Visual Basic’s Add-In menu (you may be asked if you
want to add SYSTEM.MDA to the .INI file - answer No.)
2. Select New from the Data Manager File menu. Choose database type (Microsoft Access,
Version 7.0), then select a directory and enter a name for your database file. Click OK.
3. The Database window will open. Right click the window and select New Table. In
the Name box, enter the name of your table. Then define the table’s fields, one at a time,
by clicking Add Field, then entering a field name, selecting a data type, and specifying
the size of the field, if required. Once the field is defined, click the OK button to add it to
the field box. Once all fields are defined, click the Build the Table button to save your
table.
1. With this example, we begin the development of a simple phone directory. In the directory, we
will keep track of names and phone numbers. We’ll be able to edit, add and delete names and
numbers from the directory. And, we’ll be able to search the directory for certain names. In this
first step, we’ll establish the structure for the database we’ll use. The directory will use a single
table, with three fields: Name, Description, and Phone. Name will contain the name of the
person or company, Description will contain a descriptive phrase (if desired) of who the person or
company is, and Phone will hold the phone number.
2. Start the Data Manager. Use the previously defined steps to establish a new database .
Use PhoneList as a Name for your database table. Define the three fields. Each should be a
Text data type. Assign a size of 40 to the Name and Description fields, a size of 15 to the Phone
field. When all fields have been defined, the screen should look like this:
When done with the field definitions, click Build the Table to save your new table. You will be
returned to the Database Tables window.
3. We’re now ready to enter some data in our database. From the Database Tables window, right
click the PhoneList table and select Open. The following window will appear:
At this point, add several (at least five - make them up or whatever) records to your database.
The steps for each record are: (1) click Add to add a record, (2) fill in the three fields (or, at least
the Name and Phone fields), and (3) click Update to save the contents.
You can also Delete records and Find records, if desired. You can move through the records
using the scroll bar at the bottom of the screen. When done entering records, click Close to save
your work. Select Exit from the Data Manager File menu. Your database has been created.
• The Data Manager is a versatile utility for creating and viewing databases. However, its
interface is not that pretty and its use is somewhat cumbersome. We would not want to use it as a
database management system (DBMS). Nor, would we expect users of our programs to have the
Data Manager available for their use. The next step in our development of our database skills is
to use Visual Basic to manage our databases, that is develop a DBMS.
• We will develop a simple DBMS. It will allow us to view records in an existing database. We will
be able to edit records, add records, and delete records. Such advanced tasks as adding tables
and fields to a database and creating a new database can be done with Visual Basic, but are far
beyond the scope of the discussion here.
• To create our DBMS, we need to define a few more programmatic control methods associated
with the data control Recordset property. These methods are:
AddNew - A new record is added to the table. All fields are set to Null and this record is made the
current record.
Delete - The current record is deleted from the table. This method must be immediately followed
by one of the Move methods because the current record is invalid after a Delete.
• To edit an existing record, you simply display the record and make any required changes. The
LockType property should be set to adLockPessimistic (locks each record as it is edited). Then,
when you move off of that record, either with a navigation button or through some other action,
Visual Basic will automatically update the record. If desired, or needed, you may invoke the
Update method to force an update (use LockType = asLockOptimistic). For a data control named
dtaExample, the syntax for this statement is:
dtaExample.Recordset.Update
• To add a record to the database, we invoke the AddNew method. The syntax for our example
data control is:
dtaExample.Recordset.AddNew
This statement will blank out any bound data tools and move the current record to the end of the
database. At this point, you enter the new values. When you move off of this record, the changes
are automatically made to the database. Another way to update the database with the changes is
via the Update method.
After adding a record to a database, you should invoke the Refresh property of the data control to
insure proper sorting (established by RecordSource SQL statement) of the new entry. The format
is:
dtaExample.Refresh
• To delete a record from the database, make sure the record to delete is the current record.
Then, we use the Delete method. The syntax for the example data control is:
dtaExample.Recordset.Delete
Once we execute a Delete, we must move (using one of the ‘Move’ methods) off of the current
record because it no longer exists and an error will occur if we don’t move. This gets particularly
tricky if deleting the last record (check the EOF property). If EOF is true, you must move to the
top of the database (MoveFirst). You then must make sure there is a valid record there (check the
BOF property). The example code demonstrates proper movement.
1. Before starting, make a copy of your phone database file using the Windows Explorer. That
way, in case we mess up, you still have a good copy. And, create a data link to the database.
Here, we develop a simple DBMS for our phone number database. We will be able to display
individual records and edit them. And, we will be able to add or delete records. Note this is a
simple system and many of the fancy ‘bells and whistles’ (for example, asking if you really want to
delete a record) that should really be here are not. Adding such amenities is left as an exercise to
the student.
2. Load your last Books Database application (Example 8-2 - the one with the ‘Rolodex’ search).
We will modify this application to fit the phone number DBMS. Resave your form and project with
different names. Add three command buttons to the upper right corner of the form. Modify/set the
following properties for each tool. For the data control and text boxes, make sure you follow the
order shown.
*Label1:
Caption - Description
*Label2:
Caption - Phone
*Label3:
Caption - Name
*Command1:
Caption - &Add
Name - cmdAdd
*Command2:
Caption - &Save
Enabled - False
Name - cmdSave
*Command3:
Caption - &Delete
Name - cmdDelete
At this point, you can run your application and you should be able to navigate through your phone
database using the data control. Don’t try any other options, though. We need to do some coding.
3. In Form_Load, replace the word frmBooks with frmPhone. This will allow the letter keys to
be displayed properly.
5. Attach this code to the cmdAdd_Click procedure. This code invokes the code needed to add a
record to the database. The Add and Delete buttons are disabled. Click the Save button when
done adding a new record.
6. Add this code to the cmdSave_Click procedure. When done entering a new record, the
command button status’s are toggled, the Recordset updated, and the data
control Refresh method invoked to insure proper record sorting.
7. Attach this code to the cmdDelete_Click procedure. This deletes the current record and
moves to the next record. If we bump into the end of file, we need to check if there are no records
remaining. If no records remain in the table, we display a message box. If records remain, we
move around to the first record.
8. Save the application. Try running it. Add records, delete records, edit records. If you’re really
adventurous, you could add a button that dials your phone (via modem) for you! Look at the
custom communications control.
• As mentioned earlier, there are three custom data aware tools, in addition to the standard Visual
Basic tools: the DataList, DataCombo, and DataGrid ADO tools. We’ll present each of these,
giving their suggested use, some properties and some events. If the icons for these tools are not
in the toolbox, select Project from the main menu, then click Components. Select Microsoft
DataList Controls 6.0 (OLEDB) and Microsoft DataGrid 6.0 (OLEDB) in the Components window.
Click OK - the controls will appear.
• Like the data control, previous versions of Visual Basic used DAO versions of the list, combo,
and grid controls, named DBList, DBCombo, and DBGrid. Make sure you are not using these
tools.
• DataList Box:
The first bound data custom tool is the DataList Box. The list box is automatically filled with a field
from a specified data control. Selections from the list box can then be used to update another
field from the same data control or, optionally, used to update a field from another data control.
ListField - Name of field in Recordset specified by RowSource used to fill list box.
BoundText - Text value of BoundColumn field. This is the value passed to DataField property.
Text - Text value of selected item in list. Usually the same as BoundText.
The most prevalent use of the DataList box is to fill the list from the database, then allow
selections. The selection can be used to fill any tool on a form, whether it is data aware or not.
As a quick example, here is a DataList box filled with the Title (ListField) field from the
dtaExample (RowSource) data control. The data control is bound to the Titles table in the
BIBLIO.MDB database.
• DataCombo Box:
The DataCombo Box is nearly identical to the DataList box, hence we won’t look at a separate set
of properties. The only differences between the two tools is that, with the DataCombo box, the list
portion appears as a drop-down box and the user is given the opportunity to change the contents
of the returned Text property.
• DataGrid Tool:
The DataGrid tool is, by far, the most useful of the custom data bound tools. It can display an
entire database table, referenced by a data control. The table can then be edited as desired.
The DataGrid control is in a class by itself, when considering its capabilities. It is essentially a
separate, highly functional program. The only property we’ll be concerned with is
the DataSource property, which, as always, identifies the table associated with the respective
data control. Refer to the Visual Basic Programmer’s Guide and other references for complete
details on using the DataGrid control.
As an example of the power of the DataGrid control, here’s what is obtained by simply setting
the DataSource property to the dtaExample data control, which is bound to the Titles table in
the BIBLIO.MDB database:
At this point, we can scroll through the table and edit any values we choose. Any changes are
automatically reflected in the underlying database. Column widths can be changed at run-time!
Multiple row and column selections are possible! Like we said, a very powerful tool.
Once you have gone to all the trouble of developing and managing a database, it is nice to have
the ability to obtain printed or displayed information from your data. The process of obtaining such
information is known as creating a data report.
• There are two steps to creating a data report. First, we need to create a Data Environment. This
is designed within Visual Basic and is used to tell the data report what is in the database. Second,
we create the Data Report itself. This, too, is done within Visual Basic. The Data Environment
and Data Report files then become part of the Visual Basic project developed as a database
management system.
• The Visual Basic 6.0 data report capabilities are vast and using them is a detailed process. The
use of these capabilities is best demonstrated by example. We will look at the rudiments of report
creation by building a tabular report for our phone database.
We will build a data report that lists all the names and phone numbers in our phone database. We
will do this by first creating a Data Environment, then a Data Report. We will then reopen the
phone database management project and add data reporting capabilities.
2. On the Project menu, click Add Data Environment. If this item is not on the menu,
click Components. Click theDesigners tab, and choose Data Environment and click OK to add
the designer to your menu.
5. Click OK. All this was needed just to connect the environment to our database.
6. Display the properties window and give the data environment a name property of denPhone.
Click File and SavedenPhone As. Save the environment in an appropriate folder. We will
eventually add this file to our phone database management system. At this point, my data
environment window looks like this (I expanded the PhoneList tab by clicking the + sign):
Once the Data Environment has been created, we can create a Data Report. We will drag things
out of the Data Environment onto a form created for the Data Report, so make sure your Data
Environment window is still available.
1. On the Project menu, click Add Data Report and one will be added to your project. If this item
is not on the menu, click Components. Click the Designers tab, and choose Data Report and click
OK to add the designer to your menu.
Name - rptPhone
Caption - Phone Directory
DataSource - denPhone (your phone data environment - choose, don’t type)
DataMember - PhoneList (the table name - choose don’t type)
3. Right-click the Data Report and click Retrieve Structure. This establishes a report format
based on the Data Environment.
4. Note there are five sections to the data report: a Report Header, a Page Header, a Detail
section, a Page Footer, and a Report Footer. The headers and footers contain information you
want printed in the report and on each page. To place information in one of these regions, right-
click the selected region, click Add Control, then choose the control you wish to place. These
controls are called data report controls and properties are established just like you do for usual
controls. Try adding some headers.
5. The Detail section is used to layout the information you want printed for each record in your
database. We will place two field listings (Name, Phone) there. Click on the Name tab in the Data
Environment window and drag it to the Detail section of the Data Report. Two items should
appear: a text box Name and a text box Name (PhoneList). The first text box is heading
information. Move this text box into the Page Header section. The second text box is the actual
value for Name from the PhoneList table. Line this text box up under the Name header. Now,
drag the Phone tab from the Data Environment to the Data Report. Adjust the text boxes in the
same manner. Our data report will have page headers Name and Phone. Under these headers,
these fields for each record in our database will be displayed. When done, the form should look
something like this:
In this form, I’ve resized the labels a bit and added a Report Header. Also, make sure you close
up the Detail section to a single line. Any space left in this section will be inserted after each
entry.
6. Click File and Save rptPhone As. Save the environment in an appropriate folder. We will now
reopen our phone database manager and attach this and the data environment to that project and
add capabilities to display the report.
1. Reopen the phone directory project. Add a command button named cmdReport and give it a
Caption of Show Report. (There may be two tabs in your toolbox, one named General and one
named DataReport. Make sure you select from the General tools.)
2. We will now add the data environment and data report files to the project. Click the Project
menu item, then click Add File. Choose denPhone and click OK. Also add rptPhone. Look at your
Project Window. Those files should be listed under Designers.
5. Save the application and run it. Click the Show Report button and this should appear:
You now have a printable copy of the phone directory. Just click the Printer icon. Notice the
relationship with this displayed report and the sections available in the Data Report designer.
Design and develop an application that manages a home inventory database. Add the option of
obtaining a printed list of your inventoried property.
My Solution:
Database Design:
The first step is to design a database using Data Manager (or Access). My database is a single
table (named MYSTUFF). Its specifications are:
This database is saved as file HomeInv.mdb. Create a data link to your database. The link is
saved as HomeInv.udl.
Report Design:
The second step is to use the Data Environment and Data Report designers to setup how you
want the printed home inventory to appear. Use your discretion here. My final report design is
saved in denHomeInv and rptHomeInv. We will access this report from our Visual Basic
application. My Data Report design looks like this:
Project Design:
Form:
Properties:
Form frmHome:
BorderStyle = 1 - Fixed Single
Caption = Home Inventory
CommandButton cmdExit:
Caption = E&xit
ADO Data Control dtaHome:
Caption = Book Titles
ConnectionString = HomeInv.udl (in whatever folder you saved it in -
select, don’t type)
RecordSource = SELECT * FROM MyStuff
Visible = False
CommandButton cmdShow:
Caption = Show &Report
CommandButton cmdPrevious:
Caption = &Previous Item
CommandButton cmdNext:
Caption = &Next Item
CommandButton cmdDelete:
Caption = &Delete Item
CommandButton cmdAdd:
Caption = &Add Item
TextBox txtLocation:
DataField = Location
DataSource = dtaHome
FontName = MS Sans Serif
FontSize = 9.75
MaxLength = 40
TextBox txtValue:
DataField = New Value
DataSource = dtaHome
FontName = MS Sans Serif
FontSize = 9.75
TextBox txtDate:
DataField = Date Purchased
DataSource = dtaHome
FontName = MS Sans Serif
FontSize = 9.75
MaxLength = 20
TextBox txtSerial:
DataField = Serial Number
DataSource = dtaHome
FontName = MS Sans Serif
FontSize = 9.75
MaxLength = 20
TextBox txtItem:
DataField = Item
DataSource = dtaHome
FontName = MS Sans Serif
FontSize = 9.75
MaxLength = 40
Label Label5:
Caption = Location
FontName = Times New Roman
FontSize = 12
Label Label4:
Caption = New Value
FontName = Times New Roman
FontSize = 12
Label Label3:
Caption = Purchase Date
FontName = Times New Roman
FontSize = 12
Label Label2:
Caption = Serial Number
FontName = Times New Roman
FontSize = 12
Label Label1:
Caption = Item
FontName = Times New Roman
FontSize = 12
Code:
General Declarations:
Option Explicit
n our last (VB - Database Access Management), we saw how using the data control and bound data
tools allowed us to develop a simple database management system. Most of the work done by
that DBMS, though, was done by the underlying Jet database engine, not Visual Basic. In this
lesson, we learn how to interact with another underlying set of code by programming the
Windows applications interface (API) using dynamic link libraries (DLL).
Contents
Dynamic Link Libraries (DLL)
Drawing Ellipses
Quick Example 3: Drawing Ellipses
Drawing Lines
Quick Example 4: Drawing Lines
Drawing Polygons
Quick Example 5: Drawing Polygons
A Bit of Multimedia
Quick Example 12: Multimedia Sound and Video