Top Banner
Visual Basic is initiated by using the Programs option > Microsoft Visual Basic 6.0 > Visual Basic 6.0. Clicking the Visual Basic icon, we can view a copyright screen enlisting the details of the license holder of the copy of Visual Basic 6.0. Then it opens in to a new screen as shown in figure 1 below, with the interface elements Such as MenuBar, ToolBar, The New Project dialog box. These elements permit the user to buid different types of Visual Basic applications. The Integrated Development Environment One of the most significant changes in Visual Basic 6.0 is the Integrated Development Environment (IDE). IDE is a term commonly used in the programming world to describe the interface and environment that we use to create our applications. It is called integrated because we can access virtually all of the development tools that we need from one screen called an interface. The IDE is also commonly referred to as the design environment, or the program. Tha Visual Basic IDE is made up of a number of components 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. Figure 1 The Visual Basic startup dialog box
211
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: vb6

Visual Basic is initiated by using the Programs option > Microsoft Visual Basic 6.0 > Visual Basic 6.0. Clicking the Visual Basic icon, we can view a copyright screen enlisting the details of the license holder of the copy of Visual Basic 6.0. Then it opens in to a new screen as shown in figure 1 below, with the interface elements Such as MenuBar, ToolBar, The New Project dialog box. These elements permit the user to buid different types of Visual Basic applications.

The Integrated Development Environment

One of the most significant changes in Visual Basic 6.0 is the Integrated Development Environment (IDE). IDE is a term commonly used in the programming world to describe the interface and environment that we use to create our applications. It is called integrated because we can access virtually all of the development tools that we need from one screen called an interface. The IDE is also commonly referred to as the design environment, or the program.

Tha Visual Basic IDE is made up of a number of components

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.

Figure 1 The Visual Basic startup dialog box

Page 2: vb6

Menu Bar

This Menu Bar displays the commands that are required to build an application. The main menu items have sub menu items that can be chosen when needed. The toolbars in the menu bar provide quick access to the commonly used commands and a button in the toolbar is clicked once to carry out the action represented by it.

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.

Figure 2 Toolbox window with its controls available commonly.

Control Description

Pointer Provides a way to move and resize the controls form

PictureBoxDisplays icons/bitmaps and metafiles. It displays text or acts as a 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.

OptionButtonOptionButton control which is a part of an option group allows the 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 VScrollBar

These controls allow the user to select a value within the specified range of values

Page 3: vb6

Timer Executes the timer events at specified intervals of time

DriveListBox Displays the valid disk drives and allows the user to select one of them.

DirListBox Allows the user to select the directories and paths, which are 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

Image used to display images such as icons, bitmaps and metafiles. But less capability than the PictureBox

Data Enables the use to connect to an existing database and display information from it.

OLEUsed to link or embed an object, display and manipulate data from 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.

Figure 3 Project Explorer

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

Page 4: vb6

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.

Object naming conversions of controls (prefix)

Form -frmLabel-lblTextBox-txtCommandButton-cmdCheckBox -chkOptionButton -optComboBox -cboListBox-lstFrame-fmePictureBox -picImage-imgShape-shpLine -linHScrollBar -hsbVScrollBar -vsb

Visual Basic 6.0 - Properties, Methods and EventsAll the controls in the ToolBox except the Pointer are objects in Visual Basic. These objects have associated properties, methods and events.

Real world objects are loaded with properties. For example, a flower is loaded certain color, shape and fragrance. Similarly programming objects are loaded with properties. A property is a named attribute of a programming object. Properties define the characteristics of an object such as Size, Color etc. or sometimes the way in which it behaves. For example, a TextBox accepts properties such as Enabled, Font, MultiLine, Text, Visible, Width, etc.

Enables property allows the TextBox to be enabled or disabled at run time depending on the condition set to True or False. Font property sets a particular font in the TextBox.

MultiLine property allows the TextBox to accept and display multiple lines at run time.

Text property of the TextBox control sets a particular text in the control.

Visible property is used to hide the object at run time.

Width property sets the TextBox to the desired width at design time.

The properties that are discussed above are design-time properties that can be set at the design tme by selecting the Properties Window. But certain properties cannot be set at desgn time. For example, the CurrentX and CurrentY properties of a Form cannot be set at the design time.

A method is an action that can be performed on objects. For example, a cat is an object. Its properties might include long white hair, blue eyes, 3 pounds weight etc. A complete definition of cat must only

Page 5: vb6

encompass on its looks, but should also include a complete itemization of its activities. Therefore, a cat's methods might be move, jump, play, breath etc.

Siimilarly in object-orinted programming, a method is a connected or built-in procedure, a block of code that can be invoked to impart some action on a particular object. A method requires an object to provide them with a context. For example, the word Move has no meaning in Visual Basic, but the statement,

Text1.Move 700, 400

performs a very precise action. The TextBox control has other associated methods such as Refresh, SetFocus, etc.

The Refresh method enforces a complete repaint of the control or a Form. For example, Text1.Refresh refreshes the TextBox. The Setfocus method moves the focus on the control. For Example Text1.SetFocus sets the focus to TextBox control Text1.

Event Driven Programming

Visual Basic programs are built around events. Events are various things that can happen in a program. this will become clearer when studied in contrast to procedural programming. In procedural languages, an application is written is executed by checking for the program logically through the program statements, one after another. For a temporary phase, the control may be transferred to some other point in a program. While in an event driven application, the program statements are executed only when a particular event calls a specific part of the code that is assigned to the event.

Let us consider a TextBox control and a few of its associated events to understand the concept of event driven programming. The TextBox control supports various events such as Change, Click, MouseMove and many more that will be listed in the Properties dropdown list in the code window for the TextBox control. We will look into a few of them as given below.

The code entered in the Change event fires when there is a change in the contents of the TextBox The Click event fires when the TextBox control is clicked.

The MouseMove event fires when the mouse is moved over the TextBox

As explained above, several events are associated with different controls and forms, some of the events being common to most of them and few being specific to each control.

Visual Basic 6 (VB6) Data Types, Modules and Operators

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

Page 6: vb6

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:

A name must begin with a letter. May be as much as 255 characters long (but don't forget that somebody has to type the stuff!).

Must not contain a space or an embedded period or type-declaration characters used to specify a data type; these are ! # % $ & @

Must not be a reserved word (that is part of the code, like Option, for example)

The dash, although legal, should be avoided because it may be confused with the minus sign. Instead of First-name use First_name or FirstName.

Data types in Visual Basic 6

By default Visual Basic variables are of variant data types. The variant data type can store numeric, date/time or string data. When a variable is declared, a data type is supplied for it that determines the kind of data they can store. The fundamental data types in Visual Basic including variant are integer, long, single, double, string, currency, byte and boolean. Visual Basic supports a vast array of data types. Each data type has limits to the kind of information and the minimum and maximum values it can hold. In addition, some types can interchange with some other types. A list of Visual Basic's simple data types are given below.

1. Numeric

Byte Store integer values in the range of 0 - 255

Integer Store integer values in the range of (-32,768) - (+ 32,767)

Long Store integer values in the range of (- 2,147,483,468) - (+ 2,147,483,468)

Single Store floating point value in the range of (-3.4x10-38) - (+ 3.4x1038)

Double Store large floating value which exceeding the single data type value

Currencystore monetary values. It supports 4 digits to the right of decimal point and 15 digits to the left

2. String

Page 7: vb6

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.

Operators in Visual Basic

Arithmetical Operators

Operators Description ExampleResult

+ Add 5+5 10

- Substract 10-5 5

/ Divide 25/5 5

\ Integer Division 20\3 6

* Multiply 5*4 20

^ Exponent (power of) 3^3 27

Mod Remainder of division 20 Mod 6 2

& String concatenation "George"&" "&"Bush" "George Bush"

Relational Operators

Operators Description Example Result

> Greater than 10>8 True

Page 8: vb6

< Less than 10<8 False

>= Greater than or equal to 20>=10 True

<= Less than or equal to 10<=20 True

<> Not Equal to 5<>4 True

= Equal to 5=7 False

Logical Operators

Operators Description

OR Operation will be true if either of the operands is true

AND Operation will be true only if both the operands are true

Page 9: vb6

Variables in Visual Basic 6

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

Dim variable [As Type]

For example,

Dim strName As StringDim intCounter As Integer

Using Option Explicit statement

It may be convenient to declare variables implicitly, but it can lead to errors that may not be recognized at run time. Say, for example a variable by name intcount is used implicitly and is assigned to a value. In the next step, this field is incremented by 1 by the following statement

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.

Page 10: vb6

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.

Click Options item in the Tools menu Click the Editor tab in the Options dialog box

Check Require Variable Declaration option and then click the OK button

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.

Dim sum As Integer

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.

Static intPermanent As Integer

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 AccumulateAccumulate = Accumulate + num

Page 11: vb6

RunningTotal = AccumulateEnd 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.

Static Function RunningTotal ( )

Example

The following is an example of an event procedure for a CommandButton that counts and displays the number of clicks made.

Private Sub Command1_Click ( )Static Counter As IntegerCounter = Counter + 1Print CounterEnd Sub

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.

Module Levele Variables

A module level variable is available to all the procedures in the module. They are declared using the Public or the Private keyword. 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 modulePrivate LoginTime As Date ' A private module-level variableDim 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:

' In the declarative section of Form1 modulePublic CustomerName As String ' A Public property

You can access a module property as a regular variable from inside the module and as a custom property from the outside:

' From outside Form1 module...Form1.CustomerName = "John Smith"

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

Page 12: vb6

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).

Public vs Local Variables

A variable can have the same name and different scope. For example, we can have a public variable named R and within a procedure we can declare a local variable R. References to the name R within the procedure would access the local variable and references to R outside the procedure would access the public variable.

Procedures in Visual Basic 6

Visual Basic offers different types of procedures to execute small sections of coding in applications. The various procedures are elucidated in details in this section. Visual Basic programs can be broken into smaller logical components called Procedures. Procedures are useful for condensing repeated operations such as the frequently used calculations, text and control manipulation etc. The benefits of using procedures in programming are:

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.

A Procedure can be Sub, Function or Property Procedure.

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.

Page 13: vb6

Private Sub Form_Load()....statement block..End Sub

Event Procedures acquire the declarations as Private by default.

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.

In order to add General 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.

Page 14: vb6

Function Hypotenuse (A As Double, B As Double) As DoubleHypotenuse = sqr (A^2 + B^2)End Function

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 Structures in Visual Basic 6.0

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...Then selection structure

The If...Then selection structure performs an indicated action only when the condition is True; otherwise the action is skipped.

Syntax of the If...Then selection

If <condition> ThenstatementEnd If

e.g.: If average>75 ThentxtGrade.Text = "A"End If

If...Then...Else selection structure

Page 15: vb6

The If...Then...Else selection structure allows the programmer to specify that a different action is to be performed when the condition is True than when the condition is False.

Syntax of the If...Then...Else selection

If <condition > ThenstatementsElsestatementsEnd If

e.g.: If average>50 ThentxtGrade.Text = "Pass"ElsetxtGrade.Text = "Fail"End If

Nested If...Then...Else selection structure

Nested If...Then...Else selection structures test for multiple cases by placing If...Then...Else selection structures inside If...Then...Else structures.

Syntax of the Nested If...Then...Else selection structure

You can use Nested If either of the methods as shown above

Method 1

If < condition 1 > ThenstatementsElseIf < condition 2 > ThenstatementsElseIf < condition 3 > ThenstatementsElseStatementsEnd If

Method 2

If < condition 1 > ThenstatementsElseIf < condition 2 > ThenstatementsElseIf < condition 3 > ThenstatementsElseStatementsEnd IfEnd IfEndIf

e.g.: Assume you have to find the grade using nested if and display in a text box

Page 16: vb6

If average > 75 ThentxtGrade.Text = "A"ElseIf average > 65 ThentxtGrade.Text = "B"ElseIf average > 55 ThentxtGrade.text = "C"ElseIf average > 45 ThentxtGrade.Text = "S"ElsetxtGrade.Text = "F"End If

Select...Case selection structure

Select...Case structure is an alternative to If...Then...ElseIf for selectively executing a single block of statements from among multiple block of statements. Select...case is more convenient to use than the If...Else...End If. The following program block illustrate the working of Select...Case.

Syntax of the Select...Case selection structure

Select Case IndexCase 0StatementsCase 1StatementsEnd Select

e.g.: Assume you have to find the grade using select...case and display in the text box

Dim average as Integer

average = txtAverage.TextSelect Case averageCase 100 To 75txtGrade.Text ="A"Case 74 To 65 txtGrade.Text ="B"Case 64 To 55txtGrade.Text ="C"Case 54 To 45txtGrade.Text ="S"Case 44 To 0txtGrade.Text ="F"Case ElseMsgBox "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 box functions.

Loops (Repetition Structures) in Visual Basic 6

A repetition structure allows the programmer to that an action is to be repeated until given condition is true.

Page 17: vb6

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.

Dim number As Integernumber = 1Do While number <= 100number = number + 1Loop

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.

While... Wend Statement

A While...Wend statement behaves like the Do While...Loop statement. The following While...Wend counts from 1 to 100

Dim number As Integer

number = 1While number <=100number = number + 1Wend

Do...Loop While Statement

The Do...Loop While statement first executes the statements and then test the condition after each execution. The following program block illustrates the structure:

Dim number As Longnumber = 0Do number = number + 1Loop While number < 201

The programs executes the statements between Do and Loop While structure in any case. Then it determines whether the counter is less than 501. If so, the program again executes the statements between Do and Loop While else exits the Loop.

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

Dim number As Longnumber=0

Page 18: vb6

Do Until number > 1000number = number + 1Print numberLoop

Numbers between 1 to 1000 will be displayed on the form as soon as you click on the command button.

The For...Next Loop

The For...Next Loop is another way to make loops in Visual Basic. For...Next repetition structure handles all the details of counter-controlled repetition. The following loop counts the numbers from 1 to 100:

Dim x As IntegerFor x = 1 To 50Print xNext

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 2Print xNext

The following loop counts numbers as 1, 3, 5, 7..etc

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 50Print 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.

Dim number As IntegerFor number = 1 To 10If number = 4 ThenPrint "This is number 4"ElsePrint numberEnd IfNext

In the output instead of number 4 you will get the "This is number 4".

Page 19: vb6

Exit For and Exit Do Statement in Visual basic 6

A For...Next loop condition can be terminated by an Exit For statement. Consider the following statement block.

Dim x As IntegerFor x = 1 To 10Print xIf x = 5 ThenPrint "The program exited at x=5"Exit ForEnd IfNext

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 IntegerDo While x < 10Print xx = x + 1If x = 5 ThenPrint "The program is exited at x=5"Exit DoEnd IfLoop

With...End With statement

When properties are set for objects or methods are called, a lot of coding is included that acts on the same object. It is easier to read the code by implementing the With...End With statement. Multiple properties can be set and multiple methods can be called by using the With...End With statement. The code is executed more quickly and efficiently as the object is evaluated only once. The concept can be clearly understood with following example.

With Text1.Font.Size = 14.Font.Bold = True.ForeColor = vbRed.Height = 230

Page 20: vb6

.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.

VB Array - Arrays in Visual Basic 6

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".

There are two types of arrays in Visual Basic namely:

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.

Page 21: vb6

Declaring a fixed-array

Dim numbers(5) As Integer

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.

Dim numbers (1 To 6 ) As Integer

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.

The following statement declares a two-dimensional array 50 by 50 array within a procedure.

Dim AvgMarks ( 50, 50)

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.

Dim Marks ( 101 To 200, 1 To 100)

An example for three dimensional-array with defined lower limits is given below.

Dim Details( 101 To 200, 1 To 100, 1 To 100)

Static and dynamic arrays

Basically, you can create either static or dynamic arrays. Static arrays must include a fixed number of items, and this number must be known at compile time so that the compiler can set aside the necessary amount of memory. You create a static array using a Dim statement with a constant argument:

' This is a static array. Dim Names(100) As String

Visual Basic starts indexing the array with 0. Therefore, the preceding array actually holds 101 items.

Page 22: vb6

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:

' An array defined in a BAS module (with Private scope)Dim Customers() As String...Sub Main()' Here you create the array.ReDim Customer(1000) As StringEnd Sub

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:

ReDim Customers(1 To 1000) As String

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:

ReDim Preserve Customers(2000) As String

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:

ReDim Cells(1 To 100, 10) As Integer...ReDim Preserve Cells(1 To 100, 20) As Integer ' This works.ReDim Preserve Cells(1 To 200, 20) As Integer ' This doesn't.

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:

Print LBound(Cells, 1) ' Displays 1, lower index of 1st dimensionPrint LBound(Cells) ' Same as above

Page 23: vb6

Print UBound(Cells, 2) ' Displays 20, upper index of 2nd dimension' Evaluate total number of elements.NumEls = (UBound(Cells) _ LBound(Cells) + 1) * _(UBound(Cells, 2) _ LBound(Cells, 2) + 1)

Arrays within UDTs

UDT structures can include both static and dynamic arrays. Here's a sample structure that contains both types:

Type MyUDTStaticArr(100) As LongDynamicArr() As LongEnd 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."

VB6 Arrays and variants (Visual Basic 6)

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:

ReDim Names(100) As String, var As Variant' Initialize the Names array (omitted).var = Names() ' Copy the array into the Variant.Print var(1) ' Access array items through the Variant.

You can even create an array of Variant elements on the fly using the Array function and store it in a Variant variable:

' Arrays returned by the Array() function are zero-based.Factorials = Array(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800)

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:

' A polymorphic function that sums the values in any arrayFunction ArraySum(arr As Variant) As VariantDim i As Long, result As VariantFor i = LBound(arr) To UBound(arr)result = result + arr(i)NextArraySum = resultEnd Function

Page 24: vb6

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:

' This routine returns the number of dimensions of the array' passed as an argument, or 0 if it isn't an array.Function NumberOfDims(arr As Variant) As IntegerDim dummy as LongOn Error Resume NextDodummy = UBound(arr, NumberOfDims + 1)If Err Then Exit DoNumberOfDims = NumberOfDims + 1LoopEnd Function

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:

Function ArraySum2(arr As Variant) As VariantDim i As Long, j As Long, result As Variant' First check whether we can really work with this array.Select Case NumberOfDims(arr)Case 1 ' One-dimensional arrayFor i = LBound(arr) To UBound(arr)result = result + arr(i)NextCase 2 ' Two-dimensional arrayFor i = LBound(arr) To UBound(arr)For j = LBound(arr, 2) To UBound(arr, 2)result = result + arr(i, j)NextNextCase Else ' Not an array, or too many dimensionsErr.Raise 1001, , "Not an array or more than two dimensions"End SelectArraySum2 = resultEnd Function

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:

If VarType(arr) = (vbArray + vbInteger) Then ' Array of integersElseIf VarType(arr) = (vbArray + vbLong) Then' Array of Longs

Page 25: vb6

ElseIf VarType(arr) And vbArray Then' An array of another type (just tests a bit)End If

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:

Print TypeName(arr) ' Displays "Integer()"

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

Assigning and returning arrays in Visual Basic 6

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.)

ReDim a(10, 10) As IntegerDim b() As Integer' Fill the a array with data (omitted).b() = a() ' This works!

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:

Dim v As Variant, s(100) As String, t() As String' Fill the s() array (omitted).

Page 26: vb6

v = s() ' Assign to a Variant.t() = v ' Assign from a Variant to a dynamic string array.

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:

Function InitArray(first As Long, Last As Long) As Long()ReDim result(first To Last) As LongDim i As LongFor i = first To Lastresult(i) = iNextInitArray = resultEnd Function

The new capability of returning arrays lets you write highly versatile array routines. Visual Basic 6 itself includes a few new string functions—namely Join, Split, and Filter—that rely on it. (You'll find more about these new string functions in Chapter 5). Here are two examples of what you can do with this intriguing feature:

' Returns a portion of a Long array' Note: fails if FIRST or LAST are not validFunction SubArray(arr() As Long, first As Long, last As Long, _newFirstIndex As Long) As Long()Dim i As LongReDim result(newFirstIndex To last _ first + newFirstIndex) As LongFor i = first To last result(newFirstIndex + i - first) = arr(i)NextSubArray = resultEnd Function

' Returns an array with all the selected items in a ListBoxFunction SelectedListItems(lst As ListBox) As String()Dim i As Long, j As LongReDim result(0 To lst.SelCount) As StringFor i = 0 To lst.ListCount - 1If lst.Selected(i) Thenj = j + 1result(j) = lst.List(i)End IfNextSelectedListItems = resultEnd Function

Page 27: vb6

Byte Arrays in VB6 (Visual Basic 6)

Byte 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:

Dim b() As Byte, Text As StringText = "123"b() = Text ' Now b() contains six items: 49 0 50 0 51 0

It's also possible to perform the opposite operation:

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 LongDim b() As Byte, i As Longb() = TextFor 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 + 1NextEnd 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.

Page 28: vb6

Inserting and deleting items using Arrays- Visual Basic 6

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):

Sub InsertArrayItem(arr As Variant, index As Long, newValue As Variant)Dim i As LongFor i = UBound(arr) - 1 To index Step -1arr(i + 1) = arr(i)Nextarr(index) = newValueEnd Sub

Sub DeleteArrayItem(arr As Variant, index As Long)Dim i As LongFor i = index To UBound(arr) - 1arr(i) = arr(i + 1)Next' VB will convert this to 0 or to an empty string.arr(UBound(arr)) = EmptyEnd Sub

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:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _(dest As Any, source As Any, ByVal numBytes As Long)

Sub InsertArrayItemLong(arr() As Long, index As Long, newValue As Long)' We let VB evaluate the size of each item using LenB().If index < UBound(arr) ThenCopyMemory arr(index + 1), arr(index), _(UBound(arr) _ index) * LenB(arr(index))End If

Page 29: vb6

arr(index) = newValueEnd Sub

Sub DeleteArrayItemLong(arr() As Long, index As Long)If index < UBound(arr) ThenCopyMemory arr(index), arr(index + 1), _(UBound(arr) _ index) * LenB(arr(index))End Ifarr(index) = EmptyEnd Sub

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):

Sub DeleteArrayItemDouble(arr() As Double, index As Long)' All the other statements here are the same as in DeleteArrayItemLong' ...End Sub

Sorting Data using Arrays - Visual Basic 6

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:

Sub ShellSortAny(arr As Variant, numEls As Long, descending As Boolean)Dim index As Long, index2 As Long, firstItem As LongDim distance As Long, value As Variant' Exit if it is not an array.If VarType(arr) < vbArray Then Exit SubfirstItem = LBound(arr)

Page 30: vb6

' Find the best value for distance.Dodistance = distance * 3 + 1Loop Until distance > numEls' Sort the array. Dodistance = distance \ 3For index = distance + firstItem To numEls + firstItem - 1value = arr(index)index2 = indexDo While (arr(index2 - distance) > value) Xor descendingarr(index2) = arr(index2 - distance)index2 = index2 - distanceIf index2 - distance < firstItem Then Exit DoLooparr(index2) = valueNextLoop Until distance = 1End Sub

Arrays of arrays in VB6 (Visual Basic 6)

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.)

Page 31: vb6

ReDim apps(1 To 366, 1 To MAX_APPOINTMENTS) As 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:

' A module-level variableDim apps(1 To 366) As Variant

' Add an appointment for a given day.Sub AddNewAppointment(day As Integer, description As String)Dim arr As VariantIf IsEmpty(apps(day)) Then' This is the first appointment for this day.apps(day) = Array(description)Else' Add the appointment to those already scheduled.arr = apps(day)ReDim Preserve arr(0 To UBound(arr) + 1) As Variantarr(UBound(arr)) = descriptionapps(day) = arrEnd IfEnd Sub

' Extract all the appointments for a given day.Sub ListAppointments(day As Integer, lst As ListBox)Dim i As LongFor i = 0 To UBound(apps(1))lst.AddItem apps(1)(i)NextEnd Sub

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:

' Change the description for the Nth appointment.apps(day)(n) = newDescription

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.

' Move the January 1st appointments to January 2nd. apps(2) = apps(1)apps(1) = Empty

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.)

' Extend the appointment book for another nonleap year.ReDim Preserve apps(1 to UBound(apps) + 365) As Variant

Page 32: vb6

User-Defined Data Types in Visual Basic 6Variables 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.

Private Type ProductDetailsProdID as StringProdName as StringPrice as CurrencyEnd Type

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.

Dim ElectronicGoods as ProductDetails ' One RecordDim ElectronicGoods(10) as ProductDetails ' An array of 11 records

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

If the same is implemented as an array, then the statement becomes

Text1.Text = ElectronicGoods(i).ProdName

User-defined data types can also be passed to procedures to allow many related items as one argument.

Sub ProdData( ElectronicGoods as ProductDetails)Text1.Text = ElectronicGoods.ProdNameText1.Text = ElectronicGoods.PriceEnd Sub

Constants, Data Type Conversion, Visual Basic Built-in Functions

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.

Page 33: vb6

Public Const gravityconstant As Single = 9.81

Predefined Visual Basic Constants

The predefined constants can be used anywhere in the code in place of the actual numeric values. This makes the code easier to read and write.

For example consider a statement that will set the window state of a form to be maximized.

Form1.Windowstate = 2

The same task can be performed using a Visual Basic constant

Form1.WindowState = vbMaximized

Data Type Conversion

Visual Basic functions either to convert a string into an integer or vice versa and many more conversion functions. A complete listing of all the conversion functions offered by Visual Basic is elucidated below.

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.

Page 34: vb6

Visual Basic Built-in Functions

Many built-in functions are offered by Visual Basic fall under various categories. These functions are procedures that return a value. The functions fall into the following basic categories that will be discussed in the follwing sections at length.

Date and Time Functions Format Function

String Functions

Page 35: vb6

Date and Time Functions in Visual Basic 6

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.

Function Extracted Portion

Year ( ) Year (Now)

Month ( ) Month (Now)

Day ( ) Day (Now)

WeekDay ( ) WeekDay (Now)

Hour ( ) Hour (Now)

Minute ( ) Minute (Now)

Page 36: vb6

Second ( ) Second (Now)

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.

DateDiff (interval, date1, date2[, firstdayofweek[, firstweekofyear]])

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.

Format (expression[, format[, firstdayofweek[, firstweekofyear]]])

The Format function syntax has these parts:

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

Page 37: vb6

Working with controls in Visual Basic 6

This lesson concentrates on Visual Basic controls and the ways of creating and implementing the. It also helps us to understand the concept of Control Arrays. Controls are used to recieve user input and display output and has its own set of properties, methods and events. Let us discuss few of these controls in this lesson.

Creating and Using Controls

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

Page 38: vb6

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

Here are some important points about setting up the 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

TabIndex property of Controls

Visual Basic uses the TabIndex property to determine the control that would receive the focus next when a tab key is pressed. Every time a tab key is pressed, Visual Basic looks at the value of the TabIndex for the control that has focus and then it scans through the controls searching for the next highest TabIndex number. When there are no more controls with higher TabIndex value, Visual Basic starts all over again with 0 and looks for the first control with TabIndex of 0 or higher that can accept keyboard input.

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.

You are here: Visual Basic > VB6 (Beginners Tutorial)

Previous Page | Table of Contents | Next Page

Using TextBox Control In Visual Basic 6

Page 39: vb6

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.

Setting properties to a TextBox

Text can be entered into the text box by assigning the necessary string to the text property of the control If the user needs to display multiple lines of text in a TextBox, set the MultiLine property to True

To customize the scroll bar combination on a TextBox, set the ScrollBars property.

Scroll bars will always appear on the TextBox when it's MultiLine property is set to True and its ScrollBars property is set to anything except None(0)

If you set the MultilIne property to True, you can set the alignment using the Alignment property. The test is left-justified by default. If the MultiLine property is et to False, then setting the Alignment property has no effect.

Run-Time Properties of a TextBox control

The Text property is the one you'll reference most often in code, and conveniently it's the default property for the TextBox control. Three other frequently used properties are these:

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:

Page 40: vb6

Private Sub Text1_GotFocus()Text1.SelStart = 0' A very high value always does the trick.Text1.SelLength = 9999End Sub

Always set the SelStart property first and then the SelLength or SelText properties. When you assign a new value to the SelStart property, the other two are automatically reset to 0 and an empty string respectively, thus overriding your previous settings.

The selected text can be copied to the Clipboard by using SelText:

Clipboard.SelText text, [format]

In the above syntax, text is the text that has to be placed into the Clipboard, and format has three possible values.

1. VbCFLink - conversation information2. VbCFRTF - Rich Text Format3. VbCFText - Text

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.

Property/ Method Description

 

Properties

Enabled specifies whether user can interact with this control or not

Index Specifies the control array index

LockedIf this control is set to True user can use it else if this control is set to false the control cannot be used

MaxLengthSpecifies the maximum number of characters to be input. Default value is set to 0 that means user can input any number of characters

MousePointerUsing this we can set the shape of the mouse pointer when over a TextBox

MultilineBy setting this property to True user can have more than one line in the 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

Page 41: vb6

 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

VisibleBy setting this user can make the Textbox control visible or invisible at 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

More on VB6 TextBox Controls

Trapping Keyboard Activity Validation Routines for Numbers

The CausesValidation Property and the Validate Event

Auto-Tabbing Fields and Formatting Text

Multiline TextBox Controls

See Also

TextBox Control in Visual Basic 6 CommandButton and OptionButton Controls in Visual Basic 6

CheckBox control in Visual Basic 6

Label and Frame Controls in Visual Basic 6

PictureBox and Image Controls in Visual Basic 6

Page 42: vb6

The Timer, Line, Shape and OLE Controls in Visual Basic 6

Working with Menus in Visual Basic 6

ScrollBar Control in Visual Basic 6

DriveListBox, DirListBox, and FileListBox Controls in Visual Basic 6

Trapping Keyboard Activity - Visual Basic 6 TextBox Control

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:

Private Sub Text1_KeyPress(KeyAscii As Integer)Select Case KeyAsciiCase Is < 32 ' Control keys are OK.Case 48 To 57 ' This is a digit.Case Else ' Reject any other key.KeyAscii = 0End SelectEnd Sub

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:

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)Select Case KeyCodeCase vbKeyUp

Page 43: vb6

Text1.Text = CDbl(Text1.Text) + 1Case vbKeyDownText1.Text = CDbl(Text1.Text) -1End SelectEnd Sub

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

Validation Routines for Numbers - Visual Basic 6 TextBox Control

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:

' Form-level variablesDim saveText As StringDim saveSelStart As Long

Private Sub Text1_GotFocus()' Save values when the control gets the focus.saveText = Text1.TextsaveSelStart = Text1.SelStartEnd Sub

Private Sub Text1_Change()' Avoid nested calls.Static nestedCall As BooleanIf nestedCall Then Exit Sub

' Test the control's value here.If IsNumeric(Text1.Text) Then' If value is OK, save values.saveText = Text1.TextsaveSelStart = Text1.SelStartElse' Prepare to handle a nested call. nestedCall = TrueText1.Text = saveTextnestedCall = FalseText1.SelStart = saveSelStartEnd If

Page 44: vb6

End Sub

Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)saveSelStart = Text1.SelStartEnd SubPrivate Sub Text1_MouseDown(Button As Integer, _Shift As Integer, X As Single, Y As Single)saveSelStart = Text1.SelStartEnd SubPrivate Sub Text1_MouseMove(Button As Integer, _Shift As Integer, X As Single, Y As Single)saveSelStart = Text1.SelStartEnd Sub

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,,,123345-$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:

Function CheckNumeric(text As String, DecValue As Boolean) As BooleanDim i As IntegerFor i = 1 To Len(text)Select Case Mid$(text, i, 1)Case "0" To "9"Case "-", "+"' Minus/plus signs are only allowed as leading chars.If i > 1 Then Exit FunctionCase "."' Exit if decimal values not allowed.If Not DecValue Then Exit Function' Only one decimal separator is allowed.If InStr(text, ".") < i Then Exit FunctionCase Else' Reject all other characters.Exit FunctionEnd SelectNextCheckNumeric = TrueEnd Function

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

Page 45: vb6

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

The CausesValidation Property and the Validate Event - Visual Basic 6 TextBox Control

Visual 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:

Private Sub txtRequired_Validate(Cancel As Boolean)' Check that field is not empty.If txtRequired.Text = "" ThenMsgBox "Please enter something here", vbExclamationCancel = True

Page 46: vb6

End IfEnd Sub

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

Private Sub txtNumeric_Validate(Cancel As Boolean)If Not IsNumeric(txtNumeric.Text) ThenCancel = TrueElseIf CDbl(txtNumeric.Text) < 1 Or CDbl(txtNumeric.Text) > 1000 ThenCancel = TrueEnd IfIf Cancel ThenMsgBox "Please enter a number in range [1-1000]", vbExclamationEnd IfEnd Sub

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:

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)' You can't close this form without validating the current field.If UnloadMode = vbFormControlMenu ThenOn Error Resume NextValidateControlsIf Err = 380 Then' The current field failed validation.Cancel = TrueEnd IfEnd IfEnd Sub

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

Page 47: vb6

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:

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)' You can't close this form without validating all the fields on it.If UnloadMode = vbFormControlMenu ThenOn Error Resume NextDim ctrl As Control' Give the focus to each control on the form, and then' validate it.For Each ctrl In ControlsErr.Clearctrl.SetFocusIf Err = 0 Then' Don't validate controls that can't receive input focus.ValidateControlsIf Err = 380 Then' Validation failed, refuse to close.Cancel = True: Exit SubEnd IfEnd IfNextEnd IfEnd Sub

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:

If "AX123" Like "[A-Z][A-Z]###" Then Print "OK"

Page 48: vb6

Auto-Tabbing Fields and Formatting Text - Visual Basic 6 TextBox Control

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:

Private Sub Text1_Change()If Len(Text1.Text) = Text1.MaxLength Then SendKeys "{Tab}"End Sub

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:

Private Sub txtNumber_LostFocus()On Error Resume NexttxtNumber.Text = Format(CDbl(txtNumber.Text), _

Page 49: vb6

"#,###,###,##0.######")End Sub

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:

Private Sub txtNumber_GotFocus()' On Error is necessary to account for empty fields.On Error Resume NexttxtNumber.Text = CDbl(txtNumber.Text)End Sub

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.

The FilterString routine filters out all unwanted characters in a string:

Function FilterString(Text As String, validChars As String) As StringDim i As Long, result As StringFor i = 1 To Len(Text)If InStr(validChars, Mid$(Text, i, 1)) Thenresult = result & Mid$(Text, i, 1)End IfNextFilterString = resultEnd Function

FilterNumber builds on FilterString to strip down all formatting characters in a number and can also trim trailing decimal zeros:

Function FilterNumber(Text As String, TrimZeros As Boolean) As StringDim decSep As String, i As Long, result As String' Retrieve the decimal separator symbol.decSep = Format$(0.1, ".")' Use FilterString for most of the work.result = FilterString(Text, decSep & "-0123456789")' Do the following only if there is a decimal part and the' user requested that nonsignificant digits be trimmed.If TrimZeros And InStr(Text, decSep) > 0 ThenFor i = Len(result) To 1 Step -1Select Case Mid$(result, i, 1)Case decSepresult = Left$(result, i - 1)Exit ForCase "0"result = Left$(result, i - 1)Case ElseExit ForEnd SelectNextEnd IfFilterNumber = resultEnd Function

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

Page 50: vb6

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.

The Format function lets you retrieve many locale-dependent characters and separators. Format$(0.1, ".") ' Decimal separatorFormat$(1, ",") ' Thousand separatorMid$(Format(#1/1/99#, "short date"), 2, 1) ' Date separator

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:

If Left$(Format$("12/31/1999", "short date"), 2) = 12 Then' mm/dd/yy format

Else' dd/mm/yyyy format

End If

There's no direct way to determine the currency symbol, but you can derive it by analyzing the result of this function:

Format$(0, "currency") ' Returns "$0.00" in US

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

Page 51: vb6

Private Sub txtNumber_GotFocus()' Filter out nondigit chars and trailing zeros.On Error Resume NexttxtNumber.Text = FilterNumber(txtNumber.Text, True)End SubPrivate Sub txtNumber_LostFocus()' Format as a number, grouping thousand digits.On Error Resume NexttxtNumber.Text = Format(CDbl(txtNumber.Text), _"#,###,###,##0.######")End Sub

Private Sub txtCurrency_GotFocus()' Filter out nondigit chars and trailing zeros.' Restore standard text color.On Error Resume NexttxtCurrency.Text = FilterNumber(txtCurrency.Text, True)txtCurrency.ForeColor = vbWindowTextEnd SubPrivate Sub txtCurrency_LostFocus()On Error Resume Next' Show negative values as red text.If CDbl(txtCurrency.Text) < 0 Then txtCurrency.ForeColor = vbRed' Format currency, but don't use parentheses for negative numbers.' (FormatCurrency is a new VB6 string function.)txtCurrency.Text = FormatCurrency(txtCurrency.Text, , , vbFalse)End Sub

Private Sub txtDate_GotFocus()' Prepare to edit in short-date format.On Error Resume NexttxtDate.Text = Format$(CDate(txtDate.Text), "short date")End SubPrivate Sub txtDate_LostFocus()' Convert to long-date format upon exit.On Error Resume NexttxtDate.Text = Format$(CDate(txtDate.Text), "d MMMM yyyy")End Sub

Private Sub txtPhone_GotFocus()' Trim embedded dashes.txtPhone.Text = FilterString(txtPhone.Text, "0123456789")End SubPrivate Sub txtPhone_LostFocus()' Add dashes if necessary.txtPhone.Text = FormatPhoneNumber(txtPhone.Text)End Sub

Private Sub txtCreditCard_GotFocus()' Trim embedded spaces.txtCreditCard.Text = FilterNumber(txtCreditCard.Text, True)End SubPrivate Sub txtCreditCard_LostFocus()' Add spaces if necessary.txtCreditCard.Text = FormatCreditCard(txtCreditCard.Text)End Sub

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.

Page 52: vb6

Function FormatPhoneNumber(Text As String) As StringDim tmp As StringIf Text <> "" Then' First get rid of all embedded dashes, if any.tmp = FilterString(Text, "0123456789")' Then reinsert them in the correct position.If Len(tmp) <= 7 ThenFormatPhoneNumber = Format$(tmp, "!@@@-@@@@")ElseFormatPhoneNumber = Format$(tmp, "!@@@-@@@-@@@@")End IfEnd IfEnd Function

Function FormatCreditCard(Text As String) As StringDim tmp As StringIf Text <> "" Then' First get rid of all embedded spaces, if any.tmp = FilterNumber(Text, False)' Then reinsert them in the correct position.FormatCreditCard = Format$(tmp, "!@@@@ @@@@ @@@@ @@@@")End IfEnd Function

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

Multiline TextBox Controls - Visual Basic 6 TextBox Control

You create multiline TextBox controls by setting the MultiLine property to True and the ScrollBars property to 2-Vertical or 3-Both. A vertical scroll bar causes the contents of the control to automatically wrap when a line is too long for the control's width, so this setting is most useful when you're creating memo fields or simple word processor-like programs. If you have both a vertical and a horizontal scroll bar, the TextBox control behaves more like a programmer's editor, and longer lines simply extend beyond the right border. I've never found a decent use for the other settings of the ScrollBars property (0-None and 1-Horizontal) in a multiline TextBox control. Visual Basic ignores the ScrollBars property if MultiLine is False.

Both these properties are read-only at run time, which means that you can't alternate between a regular and a multiline text box, or between a word processor-like multiline field (ScrollBars = 2-

Page 53: vb6

Vertical) and an editorlike field (ScrollBars = 3-Both). To tell the whole truth, Visual Basic's support for multiline TextBox controls leaves much to be desired. You can do very little with such controls at run time, except to retrieve and set their Text properties. When you read the contents of a multiline TextBox control, it's up to you to determine where each line of text starts and ends. You do this with a loop that searches for carriage return (CR) and line feed (LF) pairs, or even more easily using the new Split string function:

' Print the lines of text in Text1, labeling them with their line numbers.Dim lines() As String, i As Integerlines() = Split(Text1.Text, vbCrLf)For i = 0 To UBound(lines)Print (i + 1) & ": " & lines(i)Next

The support offered by Visual Basic for multiline TextBox controls ends here. The language doesn't offer any means for learning such vital information as at which point each line of text wraps, which are the first visible line and the first visible column, which line and column the caret is on, and so on. Moreover, you have no means of programmatically scrolling through a multiline text box. The solutions to these problems require Microsoft Windows API programming. In my opinion, however, Visual Basic should offer these features as built-in properties and methods.

You should account for two minor issues when including one or more multiline TextBox controls on your forms. When you enter code in a word processor or an editor, you expect that the Enter key will add a newline character (more precisely, a CR-LF character pair) and that the Tab key will insert a tab character and move the caret accordingly. Visual Basic supports these keys, but because both of them have special meaning to Windows the support is limited: The Enter key adds a CR-LF pair only if there isn't a default push button on the form, and the Tab key inserts a tab character only if there aren't other controls on the form whose TabStop property is set to True. In many circumstances, these requirements can't be met, and some of your users will find your user interface annoying. If you can't avoid this problem, at least add a reminder to your users that they can add new lines using the Ctrl+Enter key combination and insert tab characters using the Ctrl+Tab key combination. Another possible approach is to set the TabStop property to False for all the controls in the form in the multiline TextBox's GotFocus event and to restore the original values

in the LostFocus event procedure Label and Frame Controls in Visual Basic 6 (VB6)

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.

Page 54: vb6

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

Page 55: vb6

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.

VB6 CommandButton and OptionButton Controls - Visual Basic 6

Page 56: vb6

When compared to TextBox controls, these controls are really simple. Not only do they expose relatively few properties, they also support a limited number of events, and you don't usually write much code to manage them.

CommandButton Controls in VB6

Using CommandButton controls is trivial. In most cases, you just draw the control on the form's surface, set its Caption property to a suitable string (adding an & character to associate a hot key with the control if you so choose), and you're finished, at least with user-interface issues. To make the button functional, you write code in its Click event procedure, as in this fragment:

Private Sub Command1_Click()' Save data, then unload the current form.Call SaveDataToDiskUnload MeEnd Sub

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:

This fires the button's Click event.Command1.Value = True

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.

Properties of a CommandButton control

To display text on a CommandButton control, set its Caption property. An event can be activated by clicking on the CommandButton.

To set the background colour of the CommandButton, select a colour in the BackColor property.

To set the text colour set the Forecolor property.

Font for the CommandButton control can be selected using the Font property.

To enable or disable the buttons set the Enabled property to True or False

To make visible or invisible the buttons at run time, set the Visible property to True or False.

Tooltips can be added to a button by setting a text to the Tooltip property of the CommandButton.

Page 57: vb6

A button click event is handled whenever a command button is clicked. To add a click event handler, double click the button at design time, which adds a subroutine like the one given below.

Private Sub Command1_Click( )..................End Sub

OptionButton Controls in VB6

OptionButton controls are also known as radio buttons because of their shape. You always use OptionButton controls in a group of two or more because their purpose is to offer a number of mutually exclusive choices. Anytime you click on a button in the group, it switches to a selected state and all the other controls in the group become unselected.

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.

Design the Form as per the following specifications table.

Object Property Settings

Label Caption Enter a Number

Page 58: vb6

NameLabel1

TextBoxText

Name

(empty)

Text1

CommandButtonCaption

Name

&Close

Command1

OptionButtonCaption

Name

&Octal

optOct

OptionButtonCaption

Name

&Hexadecimal

optHex

OptionButtonCaption

Name

&Decimal

optDec

The application responds to the following events

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.

Private Sub Text1_Change()If optOct.Value = True Thencurrentval = Val ("&O" & LTrim (Text1.Text) & "&")Elseif optDec.value = True Thencurrentval = Val (LTrim (Text1.Text) & "&")Elsecurrentval = Val ("&H" & LTrim (Text1.Text) & "&")End ifEnd Sub

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.

Private Sub optOct_Click()Text1.Text = Oct(currentval)End Sub

Page 59: vb6

Private Sub optHex_Click()Text1.Text = Hex(currentval)End Sub

Private Sub optDec_Click()Text1.Text = Format(currentval)End Sub

The follwoing code is entered in the click event of teh Close button.

Private Sub cmdClose_Click()Unlod MeEnd Sub

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.

PictureBox and Image Controls in Visual Basic 6

Both PictureBox and Image controls let you display an image, so let's compare them and see when it makes sense to choose one or the other.

The PictureBox Control

PictureBox controls are among the most powerful and complex items in the Visual Basic Toolbox window. In a sense, these controls are more similar to forms than to other controls. For example, PictureBox controls support all the properties related to graphic output, including AutoRedraw, ClipControls, HasDC, FontTransparent, CurrentX, CurrentY, and all the Drawxxxx, Fillxxxx, and Scalexxxx properties. PictureBox controls also support all graphic methods, such as Cls, PSet, Point, Line, and Circle and conversion methods, such as ScaleX, ScaleY, TextWidth, and TextHeight. In other words, all the techniques that I described for forms can also be used for PictureBox controls (and therefore won't be covered again in this section).

Loading images

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

Page 60: vb6

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:

' These are equivalent.Picture1.Picture = LoadPicture("")Set Picture1.Picture = Nothing

The LoadPicture function has been extended in Visual Basic 6 to support icon files containing multiple icons. The new syntax is the following:

LoadPicture(filename, [size], [colordepth], [x], [y])

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

The PaintPicture method

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:

DestPictBox.PaintPicture SrcPictBox.Picture, destX, destY, [destWidth], _[destHeight], [srcX], [srcY2], [srcWidth], [srcHeight], [Opcode])

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:

Page 61: vb6

picDest.PaintPicture picSource.Picture, (picDest.ScaleWidth - 3000) / 2, _(picDest.ScaleHeight - 2000) / 2

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:

' StdPicture's Width and Height properties are expressed in' Himetric units. With Picture1width = CInt(.ScaleX(.Picture.Width, vbHimetric, vbPixels))height = CInt(.ScaleY(.Picture.Height, vbHimetric, _vbPixels))End With

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:

' Copy the upper left portion of the source image.picDest.PaintPicture picSource.Picture, 0, 0, , , , , _picSource.ScaleWidth / 2, picSource.ScaleHeight / 2

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:

' Copy the bottom-right portion of the source image' in the corresponding corner in the destination. wi = picSource.ScaleWidth / 2he = picSource.ScaleHeight / 2picDest.PaintPicture picSource.Picture, wi, he, , , wi, he, wi, he

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 = 0Do While x < picDest.ScaleWidthy = 0' For each column, start at the top and work downward.Do While y < picDest.ScaleHeightpicDest.PaintPicture picSource.Picture, x, y, , , 0, 0' Next rowy = y + picSource.ScaleHeightLoop' Next columnx = x + picSource.ScaleWidthLoop

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:

Page 62: vb6

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:

' Flip horizontally.picDest.PaintPicture picSource.Picture, _picSource.ScaleWidth, 0, -picSource.ScaleWidth' Flip vertically.picDest.PaintPicture picSource.Picture, 0, _picSource.ScaleHeight, , -picSource.ScaleHeight' Flip the image on both axes.picDest.PaintPicture picSource.Picture, picSource.ScaleWidth, _picSource.ScaleHeight, -picSource.ScaleWidth, -picSource.ScaleHeight

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.

The Image Control

Image controls are far less complex than PictureBox controls. They don't support graphical methods or the AutoRedraw and the ClipControls properties, and they can't work as containers, just to hint at their biggest limitations. Nevertheless, you should always strive to use Image controls instead of PictureBox controls because they load faster and consume less memory and system resources. Remember that Image controls are windowless objects that are actually managed by Visual Basic without creating a Windows object. Image controls can load bitmaps and JPEG and GIF images.

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:

' Load a bitmap.Image1.Stretch = FalseImage1.Picture = LoadPicture("c:\windows\setup.bmp")' Reduce it by a factor of two.Image1.Stretch = TrueImage1.Move 0, 0, Image1.Width / 2, Image1.Width / 2

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.

Page 63: vb6

The Timer, Line, Shape and OLE Controls in Visual Basic 6 (VB6)

The Timer Control

A Timer control is invisible at run time, and its purpose is to send a periodic pulse to the current application. You can trap this pulse by writing code in the Timer's Timer event procedure and take advantage of it to execute a task in the background or to monitor a user's actions. This control exposes only two meaningful properties: Interval and Enabled. Interval stands for the number of milliseconds between subsequent pulses (Timer events), while Enabled lets you activate or deactivate events. When you place the Timer control on a form, its Interval is 0, which means no events. Therefore, remember to set this property to a suitable value in the Properties window or in the Form_Load event procedure:

Private Sub Form_Load()Timer1.Interval = 500 ' Fire two Timer events per second.End Sub

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:

Private Sub Timer1_Timer()Dim strTime As StringstrTime = Time$If Mid$(lblClock.Caption, 3, 1) = ":" ThenMid$(strTime, 3, 1)= " "Mid$(strTime, 6, 1) = " "End IflblClock.Caption = strTimeEnd Sub

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

Page 64: vb6

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:

Private Sub Timer1_Timer()On Error Resume NextlblStatusBar.Caption = ActiveControl.TagEnd Sub

The Line Control

The Line control is a decorative control whose only purpose is let you draw one or more straight lines at design time, instead of displaying them using a Line graphical method at run time. This control exposes a few properties whose meaning should sound familiar to you by now: BorderColor (the color of the line), BorderStyle (the same as a form's DrawStyle property), BorderWidth (the same as a form's DrawWidth property), and DrawMode. While the Line control is handy, remember that using a Line method at run time is usually better in terms of performance.

The Shape Control

In a sense, the Shape control is an extension of the Line control. It can display six basic shapes: Rectangle, Square, Oval, Circle, Rounded Rectangle, and Rounded Square. It supports all the Line control's properties and a few more: BorderStyle (0-Transparent, 1-Solid), FillColor, and FillStyle (the same as a form's properties with the same names). The same performance considerations I pointed out for the Line control apply to the Shape control.

The OLE Control

When OLE first made its appearance, the concept of Object Linking and Embedding seemed to most developers nothing short of magic. The ability to embed a Microsoft Word Document or a Microsoft Excel worksheet within another Windows application seemed an exciting one, and Microsoft promptly released the OLE control—then called the OLE Container control—to help Visual Basic support this capability.

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.

Page 65: vb6

Using ListBox and ComboBox Controls In Visual Basic 6

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

EnabledBy setting this property to True or False user can decide whether user can interact with this control or not

Index Specifies the Control array index

ListString array. Contains the strings displayed in the drop-down list. Starting array index is 0.

ListCount Integer. Contains the number of drop-down list items

ListIndexInteger. Contains the index of the selected ComboBox item. If an item is not selected, ListIndex is -1

Locked Boolean. Specifies whether user can type or not in the ComboBox

MousePointerInteger. Specifies the shape of the mouse pointer when over the area of the ComboBox

NewIndexInteger. Index of the last item added to the ComboBox. If the ComboBox does not contain any items , NewIndex is -1

Sorted Boolean. Specifies whether the ComboBox's items are sorted or not.

Style Integer. Specifies the style of the ComboBox's appearance

Page 66: vb6

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

Adding items to a List

It is possible to populate the list at design time or run time

Design Time : To add items to a list at design time, click on List property in the property box and then add the items. Press CTRL+ENTER after adding each item as shown below.

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

Page 67: vb6

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

Private Sub Form_Load()

Combo1.AddItem 1Combo1.AddItem 2Combo1.AddItem 3Combo1.AddItem 4Combo1.AddItem 5Combo1.AddItem 6

End Sub

Removing Items from a List

The RemoveItem method is used to remove an item from a list. The syntax for this is given below.

Object.RemoveItem index

The following code verifies that an item is selected in the list and then removes the selected item from the list.

Private Sub cmdRemove_Click()If List1.ListIndex > -1 ThenList1.RemoveItem List1. ListIndexEnd IfEnd Sub

Sorting the List

The Sorted property is set to True to enable a list to appear in alphanumeric order and False to display the list items in the order which they are added to the list.

Using the ComboBox

A ComboBox combines the features of a TextBox and a ListBox. This enables the user to select either by typing text into the ComboBox or by selecting an item from the list. There are three types of ComboBox styles that are represented as shown below.

Dropdown combo

 

Simple comboDropdown list

Dropdown Combo (style 0) Simple Combo (style 1)

Page 68: vb6

Dropdown List (style 2)

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.

Object Property Settings

FormCaption

Name

ListBox

frmListBox

TextBox Text

Name

(empty)

txtName

LabelCaption

Name

Enter a name

lblName

ListBox Name lstName

LabelCaption

Name

Amount Entered

lblAmount

Label

Caption

Name

Border Style

(empty)

lblDisplay

1 Fixed Single

CommandButtonCaption

Name

Add

cmdAdd

CommandButtonCaption

Name

Remove

cmdRemove

CommandButton Caption Clear

Page 69: vb6

NamecmdClear

CommandButtonCaption

Name

Exit

cmdExit

The following event procedures are entered for the TextBox and CommandButton controls.

Private Sub txtName_Change()If (Len(txtName.Text) > 0) Then 'Enabling the Add button'if atleast one character'is enteredcmdAdd.Enabled = TrueEnd IfEnd Sub

Private Sub cmdAdd_Click()lstName.AddItem txtName.Text 'Add the entered the characters to the list box

txtName.Text = "" 'Clearing the text box

txtName.SetFocus 'Get the focus back to the'text box

lblDisplay.Caption = lstName.ListCount 'Display the number of items in the list box

cmdAdd.Enabled = False ' Disabling the Add button

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.

Private Sub cmdClear_Click()lstName.ClearlblDisplay.Caption = lstName.ListCountEnd Sub

Page 70: vb6

Private Sub cmdExit_Click()Unload MeEnd Sub

Private Sub cmdRemove_Click()Dim remove As Integer

remove = lstName.ListIndex 'Getting the index

If remove >= 0 Then 'make sure an item is selected'in the list box

lstName.RemoveItem remove 'Remove item from the list box

lblDisplay.Caption = lstName.ListCount 'Display the number of items'in 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

VB ScrollBar - Using ScrollBar Control In Visual Basic 6 (VB6)

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

Page 71: vb6

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:

' Show the current scroll bar's value. Private VScroll1_Change()Label1.Caption = VScroll1.ValueEnd SubPrivate VScroll1_Scroll()Label1.Caption = VScroll1.ValueEnd Sub

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.

Page 72: vb6

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:

Private Sub Text1_GotFocus()' Pass the focus to the scroll bar.VScroll1.SetFocusEnd SubPrivate Sub VScroll1_Change()' Scroll bar controls the text box value.Text1.Text = VScroll1.ValueEnd Sub

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.ValueEnd 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:

' size of scrollbars in twipsConst SB_WIDTH = 300 ' width of vertical scrollbarsConst SB_HEIGHT = 300 ' height of horizontal scrollbars

Page 73: vb6

Private Sub Form_Resize()' Resize the scroll bars along the form.HScroll1.Move 0, ScaleHeight - SB_HEIGHT, ScaleWidth - SB_WIDTHVScroll1.Move ScaleWidth - SB_WIDTH, 0, SB_WIDTH, _ScaleHeight - SB_HEIGHTcmdFiller.Move ScaleWidth - SB_WIDTH, ScaleHeight - SB_HEIGHT, _SB_WIDTH, SB_HEIGHT

' Put these controls on top.HScroll1.ZOrder VScroll1.ZOrdercmdFiller.ZOrderpicCanvas.BorderStyle = 0

' A click on the arrow moves one pixel.HScroll1.SmallChange = ScaleX(1, vbPixels, vbTwips)VScroll1.SmallChange = ScaleY(1, vbPixels, vbTwips)' A click on the scroll bar moves 16 pixels.HScroll1.LargeChange = HScroll1.SmallChange * 16VScroll1.LargeChange = VScroll1.SmallChange * 16

' If the form is larger than the picCanvas picture box,' we don't need to show the corresponding scroll bar.If ScaleWidth < picCanvas.Width + SB_WIDTH ThenHScroll1.Visible = TrueHScroll1.Max = picCanvas.Width + SB_WIDTH - ScaleWidthElseHScroll1.Value = 0HScroll1.Visible = FalseEnd IfIf ScaleHeight < picCanvas.Height + SB_HEIGHT ThenVScroll1.Visible = TrueVScroll1.Max = picCanvas.Height + SB_HEIGHT - ScaleHeightElseVScroll1.Value = 0VScroll1.Visible = FalseEnd If' Make the filler control visible only if necessary.cmdFiller.Visible = (HScroll1.Visible Or VScroll1.Visible)MoveCanvasEnd Sub

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.

Page 74: vb6

Control Arrays in Visual Basic 6

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

Page 75: vb6

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 = ""

Sharing Event Procedures

Event procedures related to items in a control array are easily recognizable because they have an extra Index parameter, which precedes all other parameters. This extra parameter receives the index of the element that's raising the event, as you can see in this example:

Private Sub Text1_KeyPress(Index As Integer, KeyAscii As Integer)MsgBox "A key has been pressed on Text1(" & Index & ") control"End Sub

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:

Private Sub Text1_GotFocus(Index As Integer)Text1(Index).BackColor = vbYellowEnd SubPrivate Sub Text1_LostFocus(Index As Integer)Text1(Index).BackColor = vbWhiteEnd Sub

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:

' A module-level variableDim optFrequencyIndex As Integer

Private Sub optFrequency_Click(Index As Integer)' Remember the last button selected.optFrequencyIndex = IndexEnd Sub

Creating Controls at Run Time

Control arrays can be created at run time using the statements

Load object (Index %)

Unload object (Index %)

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.

Page 76: vb6

* Design the form as shown below.

Object Propert

ySetting

FormCaption

Name

Calculator

frmCalculator

CommandButton

Caption

Name

Index

1

cmd

0

CommandButton

Caption

Name

Index

2

cmd

1

CommandButton

Caption

Name

Index

3

cmd

2

CommandButton

Caption

Name

Index

4

cmd

3

CommandButton

Caption

Name

Index

5

cmd

4

CommandButton

Caption

Name

Index

6

cmd

5

CommandButton

Caption

Name

Index

7

cmd

6

CommandButton

Caption

Name

Index

8

cmd

7

CommandButton

Caption 9

Page 77: vb6

Name

Index

cmd

8

CommandButton

Caption

Name

Index

0

cmd

10

CommandButton

Caption

Name

Index

.

cmd

11

CommandButton

Caption

Name

AC

cmdAC

CommandButton

Caption

Name

+

cmdPlus

CommandButton

Caption

Name

-

cmdMinus

CommandButton

Caption

Name

*

cmdMultiply

CommandButton

Caption

Name

/

cmdDivide

CommandButton

Caption

Name

+/-

cmdNeg

TextBoxName

Text

txtDisplay

( empty )

CommandButton

Caption

Name

=

cmdEqual

Page 78: vb6

The following variables are declared inside the general declaration

Dim Current As DoubleDim Previous As DoubleDim Choice As StringDim Result As Double

The following code is entered in the cmd_Click( ) (Control Array) event procedure

Private Sub cmd_Click(Index As Integer)txtDisplay.Text = txtDisplay.Text & cmd(Index).Caption'&is the concatenation operatorCurrent = Val(txtDisplay.Text)End Sub

The following code is entered in the cmdAC_Click ( ) event procedure

Private Sub cmdAC_Click()Current = Previous = 0txtDisplay.Text = ""End Sub

The below code is entered in the cmdNeg_Click( ) procedure

Private Sub cmdNeg_Click()Current = -CurrenttxtDisplay.Text = CurrentEnd Sub

The following code is entered in the click events of the cmdPlus, cmdMinus, cmdMultiply, cmdDevide controls respectively.

Private Sub cmdDevide_Click()txtDisplay.Text = ""Previous = CurrentCurrent = 0Choice = "/"End Sub

Private Sub cmdMinus_Click()txtDisplay.Text = ""Previous = CurrentCurrent = 0Choice = "-"End Sub

Private Sub cmdMultiply_Click()txtDisplay.Text = ""Previous = CurrentCurrent = 0Choice = "*"End Sub

Private Sub cmdPlus_Click()txtDisplay.Text = ""Previous = CurrentCurrent = 0

Page 79: vb6

Choice = "+"End Sub

To print the result on the text box, the following code is entered in the cmdEqual_Click ( ) event procedure.

Private Sub cmdEqual_Click()

Select Case Choice

Case "+"Result = Previous + CurrenttxtDisplay.Text = ResultCase "-"Result = Previous - CurrenttxtDisplay.Text = ResultCase "*"Result = Previous * CurrenttxtDisplay.Text = ResultCase "/"Result = Previous / CurrenttxtDisplay.Text = ResultEnd Select

Current = Result

End Sub

Save and run the project. On clicking digits of user's choice and an operator button, the output appears.

Iterating on the Items of a Control Array

Control arrays often let you save many lines of code because you can execute the same statement, or group of statements, for every control in the array without having to duplicate the code for each distinct control. For example, you can clear the contents of all the items in an array of TextBox controls as follows:

For i = txtFields.LBound To txtFields.UBoundtxtFields(i).Text = ""Next

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:

Dim txt As TextBoxFor Each txt In txtFieldstxt.Text = ""Next

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):

Page 80: vb6

' 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 > 1Unload txtFields(txtFields.UBound)Loop

Arrays of Menu Items

Control arrays are especially useful with menus because arrays offer a solution to the proliferation of menu Click events and, above all, permit you to create new menus at run time. An array of menu controls is conceptually similar to a regular control array, only you set the Index property to a numeric (non-negative) value in the Menu Editor instead of in the Properties window.

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

DriveListBox, DirListBox, and FileListBox Controls in Visual Basic 6

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:

Page 81: vb6

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:

Private Sub Drive1_Change()' The Drive property also returns the volume label, so trim it.Dir1.Path = Left$(Drive1.Drive, 1) & ":\"End Sub

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:

Private Sub Dir1_Change()File1.Path = Dir1.PathEnd Sub

Page 82: vb6

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.

Using a CheckBox control in Visual Basic 6

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):

Page 83: vb6

Private Sub Check1_Click()Frame1.Enabled = (Check1.Value = vbChecked)End Sub

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.

The following example illustrates the use of CheckBox control

* Open a new Project and save the Form as CheckBox.frm and save the Project as CheckBox.vbp

* Design the Form as shown below

Object Property Setting

FormCaption

Name

CheckBox

frmCheckBox

CheckBoxCaption

Name

Bold

chkBold

CheckBoxCaption

Name

Italic

chkItalic

CheckBoxCaption

Name

Underline

chkUnderline

OptionButton Caption

Name

Red

optRed

OptionButtonCaption

Name

Blue

optBlue

OptionButtonCaption

Name

Green

optGreen

TextBoxName

Text

txtDisplay

(empty)

CommandButtonCaption

Name

Exit

cmdExit

Page 84: vb6

Following code is typed in the Click() events of the CheckBoxes

Private Sub chkBold_Click()If chkBold.Value = 1 Then  txtDisplay.FontBold = TrueElse  txtDisplay.FontBold = FalseEnd IfEnd Sub

Private Sub chkItalic_Click()If chkItalic.Value = 1 Then  txtDisplay.FontItalic = TrueElse  txtDisplay.FontItalic = FalseEnd IfEnd Sub

Private Sub chkUnderline_Click()If chkUnderline.Value = 1 Then  txtDisplay.FontUnderline = TrueElse  txtDisplay.FontUnderline = FalseEnd IfEnd Sub

Following code is typed in the Click() events of the OptionButtons

Private Sub optBlue_Click()  txtDisplay.ForeColor = vbBlueEnd Sub

Private Sub optRed_Click()  txtDisplay.ForeColor = vbRedEnd Sub

Private Sub optGreen_Click()  txtDisplay.ForeColor = vbGreenEnd Sub

To terminate the program following code is typed in the Click() event of the Exit button

Page 85: vb6

Private Sub cmdExit_Click()  EndEnd Sub

Run the program by pressing F5. Check the program by clicking on OptionButtons and CheckBoxes

Working with Forms in Visual Basic 6

The Appearance of Forms

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.

The following figure illustrates the appearance of a Form

The control menu contains the following commands :

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

Page 86: vb6

Size : Lets the user resizes the control with the mouse

Minimize: Minimizes the Form

Maximize : Maximizes the Form

Close : Closes the Form

Setting the Start-Up Form

A typical application has more than a single Form. When an application runs the main Form is loaded. By setting the Project properties you can control which Form is to be displayed in the Start-Up of the application. Following figure illustrates the Project property window.

By default, Visual Basic suggests the name of the first Form created when the project started.

Loading and Unloading Forms

In order to load and unload the forms, Load and Unload statements are used. The Load statement has the following syntax :

Load FormName

And the Unload statement has the following syntax :

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.

Showing and Hiding Forms

Show method is used to Show a Form. If the Form is loaded but invisible, the Show method is used to bring the Form on Top every other window. If the Form is not loaded, the Show method loads it and then displays it.

Syntax of the Show method of the Form

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 :

Page 87: vb6

* 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

* Open a new Project and save the Project

Design the application as shown below

Object Property Setting

FormCaption

Name

Form1

frm1

FormCaption

Name

Form2

frm2

FormCaption

Name

Form3

frm3

LabelCaption

Name

Click on a button to display a Form

Label1

Page 88: vb6

The following code is typed in the Click event of the command buttons

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)

Finding out the difference between Unload and Hide method

To know what the difference is between Unload and Hide methods we will do an example. Open a new project and save the project. Draw two buttons on the form and name those as shown above.

In the click event of the Hide button Following code is entered.

Me.Hide

In the click event of the Unload button following code is entered.

Unload Me

Page 89: vb6

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.

Working with Menus in Visual Basic 6 (VB6)

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.

An expanded Menu Editor window.

Page 90: vb6

An expanded menu

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.

Page 91: vb6

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

Page 92: vb6

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. (Download the source code)

More in Menus in Visual Basic 6

Accessing Menus at Run Time Pop-Up Menus

Page 93: vb6

Accessing Menus at Run Time in Visual Basic 6

Menu controls expose only one event, Click. As you expect, this event fires when the user clicks on the menu:

Private Sub mnuFileExit_Click()Unload MeEnd Sub

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:

Private Sub mnuViewStatus_Click()' First, add or remove the check sign.mnuViewStatus.Checked = Not mnuViewStatus.Checked' Then make the status bar visible or not.staStatusBar.Visible = mnuViewStatus.CheckedEnd Sub

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.

Private Sub LoadDataFile(filename As String)' Load the file in the program.' ... (code omitted)...' Enable or disable the menu enabled state according to the file's' read-only attribute (no need for an If...Else block).mnuFileSave.Enabled = (GetAttr(filename) And vbReadOnly)End Sub

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

Page 94: vb6

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:

Private Sub mnuEdit_Click()' The user has clicked on the Edit menu,' but the menu hasn't dropped down yet.On Error Resume Next' Error handling is necessary because we don't know if ' the Active control actually supports these properties.mnuEditCopy.Enabled = (ActiveControl.SelText <> "")mnuEditCut.Enabled = (ActiveControl.SelText <> "")mnuEditClear.Enabled = (ActiveControl.SelText <> "")End Sub

Creating Pop-up Menus in Visual Basic 6

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:

Private Sub List1_MouseDown(Button As Integer, Shift As Integer, _X As Single, Y As Single)If Button And vbRightButton Then' User right-clicked the list box.PopupMenu mnuListPopupEnd IfEnd Sub

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:

PopupMenu Menu, [Flags], [X], [Y], [DefaultMenu]

Page 95: vb6

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:

PopupMenu mnuListPopup, vbPopupMenuRightButton

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:

Private Sub List1_KeyDown(KeyCode As Integer, Shift As Integer)If KeyCode = 93 Then' The system pop-up menu key has been pressed.' Show a pop-up menu near the list box's center.PopupMenu mnuListPopup, , List1.Left + _List1.Width / 2, List1.Top + List1.Height / 2End IfEnd Sub

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.

Private Sub Text1_MouseDown(Button As Integer, _Shift As Integer, X As Single, Y As Single)If Button And vbRightButton ThenText1.Enabled = FalsePopupMenu mnuMyPopupText1.Enabled = TrueEnd IfEnd Sub

Page 96: vb6

The Multiple Document Interface (MDI) in Visual Basic 6

The Multiple Document Interface (MDI) was designed to simplify the exchange of information among documents, all under the same roof. With the main application, you can maintain multiple open windows, but not multiple copies of the application. Data exchange is easier when you can view and compare many documents simultaneously.

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.

To create an MDI application, follow these steps:

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.

Page 97: vb6

Parent and Child Menus

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

* Design a menu that has the following structure.

<> MDIMenu Menu caption

MDIOpen opens a new child Form MDIExit terminates the application

* Then design the following menu for the child Form

<> ChildMenu Menu caption

Child Open opens a new child Form Child Save saves the document in the active child Form

Child Close Closes the active child Form

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

Page 98: vb6

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.

( Download the source code )

InputBox Function in Visual Basic 6 (VB6)

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.

Following is an expanded InputBox

Syntax :

memory_variable = InputBox (prompt[,title][,default])

Page 99: vb6

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.

Following example demonstrates the use of InputBox function

* Open a new project and save the Form as InputBox.frm and save the Project as InputBox.vbp

* Design the application as shown below.

Object Property Setting

Form

 

Caption

Name

InputBox test

frmInputBox

Label

 

Caption

Name

You entered

lbl1

Label

 

Caption

Name

BorderStyle

( empty)

lbl2

1-Fixed Single

CommandButton

 

Caption

Name

OK

cmdOK

Following code is entered in cmdOK_Click ( ) event

Page 100: vb6

Private Sub cmdok_Click()Dim ans As Stringans = InputBox("Enter something to be displayed in the label", "Testing", 0)If ans = "" Thenlbl2.Caption = "No message"Elselbl2.Caption = ansEnd IfEnd Sub

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

( Download the source code

Page 101: vb6

MessageBox Function in Visual Basic 6 (VB6)

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.

Following is an expanded MessageBox

Syntax :

MsgBox ( Prompt [,icons+buttons ] [,title ] )

memory_variable = MsgBox ( prompt [, icons+ buttons] [,title] )

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

Constant Value Description

vbCritical 16 Display Critical message icon

vbQuestion 32 Display Warning Query icon

Page 102: vb6

vbExclamation 48 Display Warning message icon

vbInformation 64 Display information icon

Buttons

Constant Value Description

vbOkOnly 0 Display OK button only

vbOkCancel 1 Display OK and Cancel buttons

vbAbortRetryIgnore 2Display Abort, Retry and Ignore buttons

vbYesNoCancel 3Display Yes, No and Cancel buttons

vbYesNo 4 Display Yes and No buttons

vbRetryCancel 5 Display Retry and Cancel buttons

Return Values

Constant Value Description

vbOk 1 Ok Button

vbCancel 2 Cancel Button

vbAbort 3 Abort Button

vbRetry 4 Retry Button

vbIgnore 5 Ignore Button

vbYes 6 Yes Button

vbNo 7 No Button

Following is an example illustrates the use of message boxes

* Open a new Project and save the Form as messageboxdemo.frm and save the Project as messageboxdemo.vbp

* Design the application as shown below.

Page 103: vb6

Object Property Setting

Form

 

Caption

Name

MessageBoxDemo

frmMessageBoxDemo

Label

 

Caption

Name

lblName

Name

TextBox

 

Name

Text

txtName

( empty )

ListBox Name lstName

CommandButton

 

Caption

Name

Add

cmdAdd

CommandButton

 

Caption

Name

Delete

cmdDelete

CommandButton

 

Caption

Name

Exit

cmdExit

Following code is entered in the txtName_Change ( ) event

Private Sub txtName_Change()If Len(txtName.Text) > 0 ThencmdAdd.Enabled = TrueEnd IfEnd Sub

Following code has to be entered in the cmdAdd_Click ( ) event

Private Sub cmdAdd_Click()answer = MsgBox("Do you want to add this name to the list box?", vbExclamation + vbYesNo,"Add Confirm")If answer = vbYes ThenlstName.AddItem txtName.TexttxtName.Text = ""txtName.SetFocus

Page 104: vb6

cmdAdd.Enabled = FalseEnd IfEnd Sub

Following code is entered in the cmdDelete_Click ( ) event

Private Sub cmdDelete_Click()Dim remove As Integerremove = lstName.ListIndexIf remove < 0 ThenMsgBox "No names is selected", vbInformation, "Error"Elseanswer = MsgBox("Are you sure you want to delete " & vbCrLf & "the selected name?",_vbCritical + vbYesNo, "Warning")If answer = vbYes ThenIf remove >= 0 ThenlstName.RemoveItem removetxtName.SetFocusMsgBox "Selected name was deleted", vbInformation, "Delete Confirm"

End IfEnd IfEnd IfEnd Sub

Following code is entered in the cmdExit_Click ( ) event

Private Sub cmdExit_Click()answer = MsgBox("Do you want to quit?", vbExclamation + vbYesNo, "Confirm")If answer = vbYes ThenEndElseMsgBox "Action canceled", vbInformation, "Confirm"End IfEnd Sub

Save and run the application. You can notice the different type of message box types are used to perform an action

( Download the source code

Page 105: vb6

Mouse Events In Visual Basic 6

Visual Basic responds to various mouse events, which are recognized by most of the controls. The main events are MouseDown, 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 the Form_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.

Object Property Setting

Form

 

Caption

Name

MouseDown

frmMouseDown

OptionButton

 

Caption

Name

Credit card is selected

optCredit

Page 106: vb6

  Value True

OptionButton

 

Caption

Name

Cash is selected

optCash

Image

 

Name

Picture

imgCredit

c:/credit.jpg

Image

 

Name

Picture

imgCash

c:/cash.jpg

The follwoing code is entered in the general declarations section of the Form.

Option Explicit

The following code is entered in the Form_MouseDown( ) event

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)If optCredit = True Then     imgCredit.Move X, Y  Else     imgCash.Move X, YEnd IfEnd Sub

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.

( Download the source code )

Page 107: vb6

Graphical Mouse Application In Visual Basic 6

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

Enter the following code in the Form_MouseDown ( ) procedure, Form_MouseMove ( ) procedure and cmdClear_Click ( ) procedures respectively.

Private Sub cmdClear_Click()frmDraw.ClsEnd Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)frmDraw.CurrentX = XfrmDraw.CurrentY = YEnd Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)If Button = 1 ThenLine (frmDraw.CurrentX, frmDraw.CurrentY)-(X, Y)End IfEnd Sub

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.

Page 108: vb6

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

Line (2500, 2000) - (5000, 5500)

The CurrentX and CurrentY properties are not visible in the properties window of the Form because it cannot be set at the design time. After using the Line method to draw a line in a Form, Visual Basic automatically assigns the coordinate of the line's end point to the CurrentX and CurrentY properties of the Form on which the line is drawn.

( Download the source code )

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 following code is entered in the cmdClear_Click ( ) and Form_MouseMove ( ) events respectively.

Private Sub cmdClear_Click()frmMouseMove.ClsEnd Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)Circle (X, Y), 70End Sub

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 the Form_MouseMove ( ) procedure was executed.

Page 109: vb6

( Download the source co

Visual Basic 6 -Error handling and Debugging and File Input/Output 

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.

When Error Handling should be used

Error handling should be used to process only exceptional situations, despite the fact that there is nothing to prevent that programmer from using errors as an alternate form of program control.

Page 110: vb6

This lesson explains about error handling and debugging in easy steps with quick examples. For more in-depth lessons in Error Handling click here

Contents

Error Types

Run-Time Error Trapping and Handling

General Error Handling Procedure

             Example - Simple Error Trapping

Debugging Visual Basic Programs

             Example - Debugging Example

Using the Debugging Tools

Debugging Strategies

Sequential Files

Sequential File Output (Variables)

             Quick Example: Writing Variables to Sequential Files

Sequential File Input (Variables)

             Quick Example: Reading Variables from Sequential Files

Writing and Reading Text Using Sequential Files

Random Access Files

User-Defined Variables

Writing and Reading Random Access Files

Using the Open and Save Common Dialog Boxes

             Example - Note Editor - Reading and Saving Text Files

Exercise - Information Tracking

Exercise - ‘Recent Files’ Menu Optio

Page 111: vb6

Error-Handling, Debugging - Error Types in Visual Basic 6

• No matter how hard we try, errors do creep into our programs. These errors can be grouped into three categories:

1. Syntax errors2. 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.

• Some ways to minimize 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

Error-Handling, Debugging - Run-Time Error Trapping and Handling• 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.

Page 112: vb6

• Error trapping is enabled with the On Error statement:

On Error GoTo errlabel

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()

[Declare variables, ...]

On Error GoTo HandleErrors

[Procedure code]

Exit SubHandleErrors:

Error handling code]

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.

Page 113: vb6

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

Error-Handling, Debugging - Example - Simple Error Trapping

1. Start a new project. Add a text box and a command button.

2. Set the properties of the form and each control:

Form1:BorderStyle - 1-Fixed SingleCaption - Error GeneratorName frmError

Command1:Caption - Generate ErrorDefault - TrueName - cmdGenError

Text1:Name - txtErrorText - [Blank]

The form should look something like this:

Page 114: vb6

3. Attach this code to the cmdGenError_Click event.

Private Sub cmdGenError_Click()On Error GoTo HandleErrorsErr.Raise Val(txtError.Text)Err.ClearExit Sub

HandleErrors:Select Case MsgBox(Error(Err.Number), vbCritical + vbAbortRetryIgnore, "Error Number" + Str(Err.Number))

Case vbAbort  Resume ExitLineCase vbRetry  ResumeCase vbIgnore  Resume NextEnd Select

ExitLine:

Exit SubEnd 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.

Error Number    Error Description

6                       Overflow9                       Subscript out of range11                     Division by zero13                     Type mismatch16                     Expression too complex20                     Resume without error52                     Bad file name or number53                     File not found55                     File already open61                     Disk full

Page 115: vb6

70                     Permission denied92                     For loop not initialized

Error-Handling, Debugging - Debugging Visual Basic Programs

• 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:

1. Determine values of variables2. Set breakpoints

Page 116: vb6

3. Set watch variables and expressions

4. Manually control the application

5. Determine which procedures have been called

6. Change the values of variables and properties

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.

Private Sub Command1_Click()Dim X As Integer, Y As IntegerX = 0DoY = Fcn(X)X = X + 1Loop While X <= 20End Sub

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:

Function Fcn(X As Integer) As IntegerFcn = CInt(0.1 * X ^ 2)End Function

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.

Page 117: vb6

Using the Debugging Tools

• 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.

• Printing 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.

To print to the immediate window, use the Print method:

Debug.Print [List of variables separated by commas or semi-colons]

• 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

and run the application.2. Examine the immediate window. Note how, at each iteration of the loop, the program prints the value of X and Y. You could use this information to make sure X is incrementing correctly and that Y values look acceptable.

3. Remove the Debug.Print statement.

• Breakpoints:

Page 118: vb6

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.

• Viewing Variables in the Locals Window:

The locals window shows the value of any variables within the scope of the current procedure. As execution switches from procedure to procedure, the contents of this window changes to reflect only the variables applicable to the current procedure. Repeat the above example and notice the values of X and Y also appear in the locals window.

• 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.

Page 119: vb6

Watch expressions can be edited using the Edit Watch option on the Debug menu.

• Watch Expression Example:

1. Set a breakpoint at the X = X + 1 line in the example.2. Set a watch expression for the variable X. Run the application. Notice X appears in the watch window. Every time you re-start the application, the value of X changes.

3. At some point in the debug procedure, add a quick watch on Y. Notice it is now in the watch window.

4. Clear the breakpoint. Add a watch on the expression: X = Y. Set Watch Type to ‘Break When Value Is True.’ Run the application. Notice it goes into break mode and displays the watch window whenever X = Y. Delete this last watch expression.

• 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.

• Call Stack Example:

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.

• Single Stepping (Step Into):

While at a breakpoint, you may execute your program one line at a time by pressing <F8>, choosing the Step Into option in the Debug menu, or by clicking the Step Into button on the toolbar.

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.

• Step Into Example:

1. Set a breakpoint on the Do line in the example. Run the application.2. When the program breaks, use the Step Into button to single step through the program.

3. At some point, put the cursor on the Loop While line. Try the Run To Cursor option (press Ctrl+<F8>).

Page 120: vb6

•Procedure Stepping (Step Over):

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.

• Step Over Example:

1. Run the previous example. Single step through it a couple of times.2. One time through, when you are at the line calling the Fcn function, press the Step Over button. Notice how the program did not single step through the function as it did previously.

• Function Exit (Step Out):

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.

Debugging Strategies

• We’ve looked at each debugging tool briefly. Be aware this is a cursory introduction. Use the on-line help to delve into the details of each tool described. Only through lots of use and practice can you become a proficient debugger. There are some guidelines to doing a good job, though.

• My first suggestion is: keep it simple. Many times, you only have one or two bad lines of code. And you, knowing your code best, can usually quickly narrow down the areas with bad lines. Don’t set up

Page 121: vb6

some elaborate debugging procedure if you haven’t tried a simple approach to find your error(s) first. Many times, just a few intelligently-placed Debug.Print statements or a few examinations of the immediate and locals windows can solve your problem.

• A tried and true approach to debugging can be called Divide and Conquer. If you’re not sure where your error is, guess somewhere in the middle of your application code. Set a breakpoint there. If the error hasn’t shown up by then, you know it’s in the second half of your code. If it has shown up, it’s in the first half. Repeat this division process until you’ve narrowed your search.

• And, of course, the best debugging strategy is to be careful when you first design and write your application to minimize searching for errors later

Sequential Files

• In many applications, it is helpful to have the capability to read and write information to a disk file. This information could be some computed data or perhaps information loaded into a Visual Basic object.

• Visual Basic supports two primary file formats: sequential and random access. We first look at sequential files.

• A sequential file is a line-by-line list of data. You can view a sequential file with any text editor. When using sequential files, you must know the order in which information was written to the file to allow proper reading of the file.

• Sequential files can handle both text data and variable values. Sequential access is best when dealing with files that have lines with mixed information of different lengths. I use them to transfer data between applications

Sequential File Output (Variables)• We first look at writing values of variables to sequential files. The first step is to Open a file to write information to. The syntax for opening a sequential file for output is:

Open SeqFileName For Output As #N

where SeqFileName is the name of the file to open and N is an integer file number. The filename must be a complete path to the file.

• When done writing to the file, Close it using:

Close N

Once a file is closed, it is saved on the disk under the path and filename used to open the file.

• Information is written to a sequential file one line at a time. Each line of output requires a separate Basic statement.

• There are two ways to write variables to a sequential file. The first uses the Write statement:

Write #N, [variable list]

where the variable list has variable names delimited by commas. (If the variable list is omitted, a blank line is printed to the file.) This statement will write one line of information to the file, that line containing

Page 122: vb6

the variables specified in the variable list. The variables will be delimited by commas and any string variables will be enclosed in quotes. This is a good format for exporting files to other applications like Excel.

Example

Dim A As Integer, B As String, C As Single, D As Integer..Open TestOut For Output As #1Write #1, A, B, CWrite #1, DClose 1

After this code runs, the file TestOut will have two lines. The first will have the variables A, B, and C, delimited by commas, with B (a string variable) in quotes. The second line will simply have the value of the variable D.

• The second way to write variables to a sequential file is with the Print statement:

Print #N, [variable list]

This statement will write one line of information to the file, that line containing the variables specified in the variable list. (If the variable list is omitted, a blank line will be printed.) If the variables in the list are separated with semicolons (;), they are printed with a single space between them in the file. If separated by commas (,), they are spaced in wide columns. Be careful using the Print statement with string variables. The Print statement does not enclose string variables in quotes, hence, when you read such a variable back in, Visual Basic may have trouble knowing where a string ends and begins. It’s good practice to ‘tack on’ quotes to string variables when using Print.

Example

Dim A As Integer, B As String, C As Single, D As Integer..Open TestOut For Output As #1Print #1, A; Chr(34) + B + Chr(34), CPrint #1, DClose 1

After this code runs, the file TestOut will have two lines. The first will have the variables A, B, and C, delimited by spaces. B will be enclosed by quotes [Chr(34)]. The second line will simply have the value of the variable D.

Quick Example: Writing Variables to Sequential Files

1. Start a new project.2. Attach the following code to the Form_Load procedure. This code simply writes a few variables to sequential files.

Private Sub Form_Load()Dim A As Integer, B As String, C As Single, D As IntegerA = 5B = "Visual Basic"C = 2.15D = -20Open "Test1.Txt" For Output As #1Open "Test2.Txt" For Output As #2

Page 123: vb6

Write #1, A, B, CWrite #1, DPrint #2, A, B, CPrint #2, DClose 1Close 2End Sub

3. Run the program. Use a text editor (try the Windows 95 Notepad) to examine the contents of the two files, Test1.Txt and Test2.Txt. They are probably in the Visual Basic main directory. Note the difference in the two files, especially how the variables are delimited and the fact that the string variable is not enclosed in quotes in Test2.Txt. Save the application, if you want to.

Sequential File Input (Variables)

• To read variables from a sequential file, we essentially reverse the write procedure. First, open the file using:

Open SeqFileName For Input As #N

where N is an integer file number and SeqFileName is a complete file path. The file is closed using:

Close N

• The Input statement is used to read in variables from a sequential file. The format is:

Input #N, [variable list]

The variable names in the list are separated by commas. If no variables are listed, the current line in the file N is skipped.

• Note variables must be read in exactly the same manner as they were written. So, using our previous example with the variables A, B, C, and D, the appropriate statements are:

Page 124: vb6

Input #1, A, B, CInput #1, D

These two lines read the variables A, B, and C from the first line in the file and D from the second line. It doesn’t matter whether the data was originally written to the file using Write or Print (i.e. commas are ignored).

Quick Example: Reading Variables from Sequential Files

1. Start a new project or simply modify the previous quick example.2. Attach the following code to the Form_Load procedure. This code reads in files created in the last quick example.

Private Sub Form_Load()Dim A As Integer, B As String, C As Single, D As IntegerOpen "Test1.Txt" For Input As #1Input #1, A, B, CDebug.Print "A="; ADebug.Print "B="; BDebug.Print "C="; CInput #1, DDebug.Print "D="; DClose 1End Sub

Note the Debug.Print statements and how you can add some identifiers (in quotes) for printed information.

3. Run the program. Look in the debug window and note the variable values. Save the application, if you want to.

4. Rerun the program using Test2.Txt as in the input file. What differences do you see? Do you see the problem with using Print and string variables? Because of this problem, I almost always use Write (instead of Print) for saving variable information to files. Edit the Test2.Txt file (in Notepad), putting quotes around the words Visual Basic. Rerun the program using this file as input - it should work fine now.

Writing and Reading Text Using Sequential Files

Page 125: vb6

• In many applications, we would like to be able to save text information and retrieve it for later reference. This information could be a text file created by an application or the contents of a Visual Basic text box.

• Writing Text Files:

To write a sequential text file, we follow the simple procedure: open the file, write the file, close the file. If the file is a line-by-line text file, each line of the file is written to disk using a single Print statement:

Print #N, Line

where Line is the current line (a text string). This statement should be in a loop that encompasses all lines of the file. You must know the number of lines in your file, beforehand.

If we want to write the contents of the Text property of a text box named txtExample to a file, we use:

Print #N, txtExample.Text

Example

We have a text box named txtExample. We want to save the contents of the Text property of that box in a file named MyText.ned on the c: drive in the \MyFiles directory. The code to do this is:

Open “c:\MyFiles\MyText.ned” For Output As #1Print #1, txtExample.TextClose 1

The text is now saved in the file for later retrieval.

• Reading Text Files:

To read the contents of a previously-saved text file, we follow similar steps to the writing process: open the file, read the file, close the file. If the file is a text file, we read each individual line with the Line Input command:

Line Input #1, Line

This line is usually placed in a Do/Loop structure that is repeated untill all lines of the file are read in. The EOF() function can be used to detect an end-of-file condition, if you don’t know, a prioiri, how many lines are in the file.

To place the contents of a file opened with number N into the Text property of a text box named txtExample we use the Input function:

txtExample.Text = Input(LOF(N), N)

This Input function has two arguments: LOF(N), the length of the file opened as N and N, the file number.

Example

We have a file named MyText.ned stored on the c: drive in the \MyFiles directory. We want to read that text file into the text property of a text box named txtExample. The code to do this is:

Page 126: vb6

Open “c:\MyFiles\MyText.ned” For Input As #1txtExample.Text = Input(LOF(1), 1)Close 1

The text in the file will now be displayed in the text box.

Random Access Files

• Note that to access a particular data item in a sequential file, you need to read in all items in the file prior to the item of interest. This works acceptably well for small data files of unstructured data, but for large, structured files, this process is time-consuming and wasteful. Sometimes, we need to access data in nonsequential ways. Files which allow nonsequential access are random access files.

• To allow nonsequential access to information, a random access file has a very definite structure. A random access file is made up of a number of records, each record having the same length (measured in bytes). Hence, by knowing the length of each record, we can easily determine (or the computer can) where each record begins. The first record in a random access file is Record 1, not 0 as used in Visual Basic arrays. Each record is usually a set of variables, of different types, describing some item. The structure of a random access file is:

• A good analogy to illustrate the differences between sequential files and random access files are cassette music tapes and compact discs. To hear a song on a tape (a sequential device), you must go past all songs prior to your selection. To hear a song on a CD (a random access device), you simply go directly to the desired selection. One difference here though is we require all of our random access records to be the same length - not a good choice on CD’s!

Page 127: vb6

• To write and read random access files, we must know the record length in bytes. Some variable types and their length in bytes are:

Type          Length (Bytes)

Integer       2Long          4Single        4Double      8String         1 byte per character

So, for every variable that is in a file’s record, we need to add up the individual variable length’s to obtain the total record length. To ease this task, we introduce the idea of user-defined variables.

User-Defined Variables

• Data used with random access files is most often stored in user-defined variables. These data types group variables of different types into one assembly with a single, user-defined type associated with the group. Such types significantly simplify the use of random access files.

• The Visual Basic keyword Type signals the beginning of a user-defined type declaration and the words End Type signal the end. An example best illustrates establishing a user-defined variable. Say we want to use a variable that describes people by their name, their city, their height, and their weight. We would define a variable of Type Person as follows:

Type PersonName As StringCity As StringHeight As IntegerWeight As IntegerEnd Type

These variable declarations go in the same code areas as normal variable declarations, depending on desired scope. At this point, we have not reserved any storage for the data. We have simply described to Visual Basic the layout of the data.

• To create variables with this newly defined type, we employ the usual Dim statement. For our Person example, we would use:

Page 128: vb6

Dim Lou As PersonDim John As PersonDim Mary As Person

And now, we have three variables, each containing all the components of the variable type Person. To refer to a single component within a user-defined type, we use the dot-notation:

VarName.Component

As an example, to obtain Lou’s Age, we use:

Dim AgeValue as Integer..AgeValue = Lou.Age

Note the similarity to dot-notation we’ve been using to set properties of various Visual Basic tools.

Writing and Reading Random Access Files

• We look at writing and reading random access files using a user-defined variable. For other variable types, refer to Visual Basic on-line help. To open a random access file named RanFileName, use:

Open RanFileName For Random As #N Len = RecordLength

where N is an available file number and RecordLength is the length of each record. Note you don’t have to specify an input or output mode. With random access files, as long as they’re open, you can write or read to them.

• To close a random access file, use:

Close N

• As mentioned previously, the record length is the sum of the lengths of all variables that make up a record. A problem arises with String type variables. You don’t know their lengths ahead of time. To solve this problem, Visual Basic lets you declare fixed lengths for strings. This allows you to determine record length. If we have a string variable named StrExample we want to limit to 14 characters, we use the declaration:

Page 129: vb6

Dim StrExample As String * 14

Recall each character in a string uses 1 byte, so the length of such a variable is 14 bytes.

• Recall our example user-defined variable type, Person. Let’s revisit it, now with restricted string lengths:

Type PersonName As String * 40City As String * 35Height As IntegerWeight As IntegerEnd Type

The record length for this variable type is 79 bytes (40 + 35 +2 + 2). To open a file named PersonData as File #1, with such records, we would use the statement:

Open PersonData For Random As #1 Len = 79

• The Get and Put statements are used to read from and write to random access files, respectively. These statements read or write one record at a time. The syntax for these statements is simple:

Get #N, [RecordNumber], variable

Put #N, [RecordNumber], variable

The Get statement reads from the file and stores data in the variable, whereas the Put statement writes the contents of the specified variable to the file. In each case, you can optionally specifiy the record number. If you do not specify a record number, the next sequential position is used.

• The variable argument in the Get and Put statements is usually a single user-defined variable. Once read in, you obtain the component parts of this variable using dot-notation. Prior to writing a user-defined variable to a random access file, you ‘load’ the component parts using the same dot-notation.

• There’s a lot more to using random access files; we’ve only looked at the basics. Refer to your Visual Basic documentation and on-line help for further information. In particular, you need to do a little cute programming when deleting records from a random access file or when ‘resorting’ records

Using the Open and Save Common Dialog Boxes

Page 130: vb6

• Note to both write and read sequential and random access files, we need a file name for the Open statement. To ensure accuracy and completeness, it is suggested that common dialog boxes be used to get this file name information from the user. I’ll provide you with a couple of code segments that do just that. Both segments assume you have a common dialog box on your form named cdlFiles, with the CancelError property set equal to True. With this property True, an error is generated by

Visual Basic when the user presses the Cancel button in the dialog box. By trapping this error, it allows an elegant exit from the dialog box when canceling the operation is desired.

•The code segment to obtain a file name (MyFileName with default extension Ext) for opening a file to read is:

Dim MyFileName As String, Ext As String..cdlFiles.Filter = "Files (*." + Ext + ")|*." + ExtcdlFiles.DefaultExt = ExtcdlFiles.DialogTitle = "Open File"cdlFiles.Flags = cdlOFNFileMustExist + cdlOFNPathMustExistOn Error GoTo No_OpencdlFiles.ShowOpenMyFileName = cdlFiles.filename..Exit SubNo_Open:Resume ExitLIneExitLine:Exit SubEnd Sub

A few words on what’s going on here. First, some properties are set such that only files with Ext (a three letter string variable) extensions are displayed (Filter property), the default extension is Ext (DefaultExt property), the title bar is set (DialogTitle property), and some Flags are set to insure the file and path exist (see Appendix II for more common dialog flags).

Error trapping is enabled to trap the Cancel button. Finally, the common dialog box is displayed and the filename property returns with the desired name. That name is put in the string variable MyFileName. What you do after obtaining the file name depends on what type of file you are dealing with. For sequential files, you would open the file, read in the information, and close the file. For random access files, we just open the file here. Reading and writing to/from the file would be handled elsewhere in your coding.

•The code segment to retrieve a file name (MyFileName) for writing a file is:

Dim MyFileName As String, Ext As String..cdlFiles.Filter = "Files (*." + Ext + ")|*." + ExtcdlFiles.DefaultExt = ExtcdlFiles.DialogTitle = "Save File"cdlFiles.Flags = cdlOFNOverwritePrompt + cdlOFNPathMustExistOn Error GoTo No_SavecdlFiles.ShowSaveMyFileName = cdlFiles.filename..Exit SubNo_Save:

Page 131: vb6

Resume ExitLineExitLine:Exit SubEnd Sub

Note this code is essentially the same used for an Open file name. The Flags property differs slightly. The user is prompted if a previously saved file is selected for overwrite. After obtaining a valid file name for a sequential file, we would open the file for output, write the file, and close it. For a random access file, things are trickier.

If we want to save the file with the same name we opened it with, we simply close the file. If the name is different, we must open a file (using a different number) with the new name, write the complete random access file, then close it. Like I said, it’s trickier.

•We use both of these code segments in the final example where we write and read sequential files

Example - Note Editor - Reading and Saving Text Files

1. We now add the capability to read in and save the contents of the text box in the Note Editor application from last class. Load that application. Add a common dialog box to your form. Name it cdlFiles and set the CancelError property to True.2. Modify the File menu (use the Menu Editor and the Insert button) in your application, such that Open and Save options are included. The File menu should now read:

File    New    Open    Save

    Exit

Properties for these new menu items should be:

Caption      Name                 Shortcut

&Open        mnuFileOpen        [None]&Save        mnuFileSave         [None]

3. The two new menu options need code. Attach this code to the mnuFileOpen_Click event. This uses a modified version of the code segment seen previously. We assign the extension ned to our note editor files.

Page 132: vb6

Private Sub mnuFileOpen_Click()cdlFiles.Filter = "Files (*.ned)|*.ned"cdlFiles.DefaultExt = "ned"cdlFiles.DialogTitle = "Open File"cdlFiles.Flags = cdlOFNFileMustExist + cdlOFNPathMustExistOn Error GoTo No_OpencdlFiles.ShowOpenOpen cdlFiles.filename For Input As #1txtEdit.Text = Input(LOF(1), 1)Close 1Exit SubNo_Open:Resume ExitLineExitLine:Exit SubEnd Sub

And for the mnuFileSave_Click procedure, use this code. Much of this can be copied from the previous procedure.

Private Sub mnuFileSave_Click()cdlFiles.Filter = "Files (*.ned)|*.ned"cdlFiles.DefaultExt = "ned"cdlFiles.DialogTitle = "Save File"cdlFiles.Flags = cdlOFNOverwritePrompt + cdlOFNPathMustExistOn Error GoTo No_SavecdlFiles.ShowSaveOpen cdlFiles.filename For Output As #1Print #1, txtEdit.TextClose 1Exit SubNo_Save:Resume ExitLineExitLine:Exit SubEnd Sub

Each of these procedures is similar. The dialog box is opened and, if a filename is returned, the file is read/written. If Cancel is pressed, no action is taken. These routines can be used as templates for file operations in other applications.

4. Save your application. Run it and test the Open and Save functions. Note you have to save a file before you can open one. Check for proper operation of the Cancel button in the common dialog box.

5. If you have the time, there is one major improvement that should be made to this application. Notice that, as written, only the text information is saved, not the formatting (bold, italic, underline, size). Whenever a file is opened, the text is displayed based on current settings. It would be nice to save formatting information along with the text. This can be done, but it involves a fair amount of reprogramming. Suggested steps:

A. Add lines to the mnuFileSave_Click routine that write the text box properties FontBold, FontItalic, FontUnderline, and FontSize to a separate sequential file. If your text file is named TxtFile.ned, I would suggest naming the formatting file TxtFile.fmt. Use string functions to put this name together. That is, chop the ned extension off the text file name and tack on the fmt extension. You’ll need the Len() and Left() functions.

B. Add lines to the mnuFileOpen_Click routine that read the text box properties FontBold, FontItalic, FontUnderline, and FontSize from your format sequential file. You’ll need to define

Page 133: vb6

some intermediate variables here because Visual Basic won’t allow you to read properties directly from a file. You’ll also need logic to set/reset any check marks in the menu structure to correspond to these input properties.

C. Add lines to the mnuFileNew_Click procedure that, when the user wants a new file, reset the text box properties FontBold, FontItalic, FontUnderline, and FontSize to their default values and set/reset the corresponding menu check marks.

D. Try out the modified application. Make sure every new option works as it should.

Actually, there are ‘custom’ tools (we’ll look at custom tools in Class 10) that do what we are trying to do with this modification, that is save text box contents with formatting information. Such files are called ‘rich text files’ or rtf files. You may have seen these before when transferring files from one word processor to another.

6. Another thing you could try: Modify the message box that appears when you try to Exit. Make it ask if you wish to save your file before exiting - provide Yes, No, Cancel buttons. Program the code corresponding to each possible response. Use calls to existing procedures, if possible.

Exercise - Information Tracking

Design and develop an application that allows the user to enter (on a daily basis) some piece of information that is to be saved for future review and reference. Examples could be stock price, weight, or high temperature for the day. The input screen should display the current date and an input box for the desired information. all values should be saved on disk for future retrieval and update. A scroll bar should be available for reviewing all previously-stored values.

My Solution:

Form:

Page 134: vb6

Properties:

Form frmWeight:BorderStyle = 1 - Fixed SingleCaption = Weight Program

VScrollBar vsbControl:Min = 1Value = 1

TextBox txtWeight:Alignment = 2 - CenterFontName = MS Sans SerifFontSize = 13.5

Label lblFile:BackColor = &H0000FFFF& (White)BorderStyle = 1 - Fixed SingleCaption = New FileFontName = MS Sans SerifFontBold = TrueFontItalic = TrueFontSize = 8.25

Label lblDate:Alignment = 2 - CenterBackColor = &H00FFFFFF& (White)BorderStyle = 1 - Fixed SingleFontName = MS Sans SerifFontSize = 13.5

Label Label2:Alignment = 2 - CenterCaption = WeightFontName = MS Sans SerifFontSize = 13.5FontBold = True

Label Label1:Alignment = 2 - CenterCaption = DateFontName = MS Sans SerifFontSize = 13.5FontBold = True

Page 135: vb6

CommonDialog cdlFiles:CancelError = True

Menu mnuFile: Caption = &File

Menu mnuFileNew:Caption = &New

Menu mnuFileOpen: Caption = &Open

Menu mnuFileSave: Caption = &Save

Menu mnuLine: Caption = -

Menu mnuFileExit: Caption = E&xit

Code:

General Declarations:

Option ExplicitDim Dates(1000) As DateDim Weights(1000) As StringDim NumWts As Integer

Init General Procedure:

Sub Init()NumWts = 1: vsbControl.Value = 1: vsbControl.Max = 1Dates(1) = Format(Now, "mm/dd/yy")Weights(1) = ""lblDate.Caption = Dates(1)txtWeight.Text = Weights(1)lblFile.Caption = "New File"End Sub

Form Load Event:

Private Sub Form_Load()frmWeight.ShowCall InitEnd Sub

mnufileExit Click Event:

Private Sub mnuFileExit_Click()'Make sure user really wants to exitDim Response As IntegerResponse = MsgBox("Are you sure you want to exit the weight program?", vbYesNo + vbCritical + vbDefaultButton2, "Exit Editor")If Response = vbNo Then

Page 136: vb6

Exit SubElseEndEnd IfEnd Sub

mnuFileNew Click Event:

Private Sub mnuFileNew_Click()'User wants new fileDim Response As IntegerResponse = MsgBox("Are you sure you want to start a new file?", vbYesNo + vbQuestion, "New File")If Response = vbNo ThenExit SubElseCall InitEnd IfEnd Sub

mnuFileOpen Click Event:

Private Sub mnuFileOpen_Click()Dim I As IntegerDim Today As DateDim Response As IntegerResponse = MsgBox("Are you sure you want to open a new file?", vbYesNo + vbQuestion, "New File")If Response = vbNo Then Exit SubcdlFiles.Filter = "Files (*.wgt)|*.wgt"cdlFiles.DefaultExt = "wgt"cdlFiles.DialogTitle = "Open File"cdlFiles.Flags = cdlOFNFileMustExist + cdlOFNPathMustExistOn Error GoTo No_OpencdlFiles.ShowOpenOpen cdlFiles.filename For Input As #1lblFile.Caption = cdlFiles.filenameInput #1, NumWtsFor I = 1 To NumWtsInput #1, Dates(I), Weights(I)Next IClose 1Today = Format(Now, "mm/dd/yy")If Today <> Dates(NumWts) ThenNumWts = NumWts + 1Dates(NumWts) = TodayWeights(NumWts) = ""End IfvsbControl.Max = NumWtsvsbControl.Value = NumWtslblDate.Caption = Dates(NumWts)txtWeight.Text = Weights(NumWts)Exit SubNo_Open:Resume ExitLineExitLine:Exit SubEnd Sub

mnuFileSave Click Event:

Page 137: vb6

Private Sub mnuFileSave_Click()Dim I As IntegercdlFiles.Filter = "Files (*.wgt)|*.wgt"cdlFiles.DefaultExt = "wgt"cdlFiles.DialogTitle = "Save File"cdlFiles.Flags = cdlOFNOverwritePrompt + cdlOFNPathMustExistOn Error GoTo No_SavecdlFiles.ShowSaveOpen cdlFiles.filename For Output As #1lblFile.Caption = cdlFiles.filenameWrite #1, NumWtsFor I = 1 To NumWtsWrite #1, Dates(I), Weights(I)Next IClose 1Exit SubNo_Save:Resume ExitLineExitLine:Exit SubEnd Sub

txtWeight Change Event:

Private Sub txtWeight_Change()Weights(vsbControl.Value) = txtWeight.TextEnd Sub

txtWeight KeyPress Event:

Private Sub txtWeight_KeyPress(KeyAscii As Integer)If KeyAscii >= vbKey0 And KeyAscii <= vbKey9 ThenExit SubElseKeyAscii = 0End IfEnd Sub

vsbControl Change Event:

Private Sub vsbControl_Change()lblDate.Caption = Dates(vsbControl.Value)txtWeight.Text = Weights(vsbControl.Value)txtWeight.SetFocusEnd Sub

Page 138: vb6

Exercise - Recent Files’ Menu Option

Under the File menu on nearly every application (that opens files) is a list of the four most recently-used files (usually right above the Exit option). Modify your information tracker to implement such a feature. This is not trivial -- there are lots of things to consider.

For example, you’ll need a file to store the last four file names. You need to open that file and initialize the corresponding menu entries when you run the application -- you need to rewrite that file when you exit the application. You need logic to re-order file names when a new file is opened or saved. You need logic to establish new menu items as new files are used. You’ll need additional error-trapping in the open procedure, in case a file selected from the menu no longer exists. Like I said, a lot to consider here.

My Solution:

These new menu items immediately precede the existing Exit menu item:

Menu mnuFileRecent:Caption = [Blank]Index = 0, 1, 2, 3 (a control array)Visible = False

Menu mnuFileBar:Caption = -Visible = False

Code Modifications (new code is bold and italicized):

General Declarations:

Option ExplicitDim Dates(1000) As DateDim Weights(1000) As StringDim NumWts As IntegerDim NFiles As Integer, RFile(3) As String, MenuOpen As Integer, FNmenu As String

Rfile Update General Procedure:

Sub RFile_Update(NewFile As String)‘Routine to place newest file name in proper order

Page 139: vb6

‘in menu structureDim I As Integer, J As Integer, InList As Integer'Convert name to all upper case lettersNewFile = UCase(NewFile)'See if file is already in listInList = 0For I = 0 To NFiles - 1If RFile(I) = NewFile Then InList = 1: Exit ForNext I'If file not in list, increment number of items with'a maximum of 4. Then, move others down, then place'new name at top of listIf InList = 0 ThenNFiles = NFiles + 1If NFiles > 4 ThenNFiles = 4ElseIf NFiles = 1 Then mnuFileBar.Visible = TruemnuFileRecent(NFiles - 1).Visible = TrueEnd IfIf NFiles <> 1 ThenFor I = NFiles - 1 To 1 Step -1RFile(I) = RFile(I - 1)Next IEnd IfRFile(0) = NewFileElse'If file already in list, put name at top and shift'others accordinglyIf I <> 0 ThenFor J = I - 1 To 0 Step -1RFile(J + 1) = RFile(J)Next JRFile(0) = NewFileEnd IfEnd If'Set menu captions according to new listFor I = 0 To NFiles - 1mnuFileRecent(I).Caption = "&" + Format(I + 1, "# ") + RFile(I)Next IEnd Sub

Form Load Event:

Private Sub Form_Load()Dim I As Integer'Open .ini file and load in recent file namesOpen "weight.ini" For Input As #1NFiles = 0: MenuOpen = 0For I = 0 To 3Input #1, RFile(I)If RFile(I) <> "" ThenNFiles = NFiles + 1mnuFileBar.Visible = TruemnuFileRecent(I).Caption = "&" + Format(I + 1, "# ") + RFile(I)mnuFileRecent(I).Visible = TrueEnd IfNext IClose 1frmWeight.Show

Page 140: vb6

Call InitEnd Sub

mnuFileExit Click Event:

Private Sub mnuFileExit_Click()'Make sure user really wants to exitDim Response As Integer, I As IntegerResponse = MsgBox("Are you sure you want to exit the weight program?", vbYesNo + vbCritical + vbDefaultButton2, "Exit Editor")If Response = vbNo ThenExit SubElse'Write out .ini file when doneOpen "weight.ini" For Output As #1For I = 0 To 3Write #1, RFile(I)Next IClose 1EndEnd IfEnd Sub

mnuFileOpen Click Event:

Private Sub mnuFileOpen_Click()Dim I As IntegerDim Today As DateDim Response As IntegerDim File_To_Open As StringResponse = MsgBox("Are you sure you want to open a new file?", vbYesNo + vbQuestion, "New File")If Response = vbNo Then Exit SubIf MenuOpen = 0 ThencdlFiles.Filter = "Files (*.wgt)|*.wgt"cdlFiles.DefaultExt = "wgt"cdlFiles.DialogTitle = "Open File"cdlFiles.Flags = cdlOFNFileMustExist + cdlOFNPathMustExistOn Error GoTo No_OpencdlFiles.ShowOpenFile_To_Open = cdlFiles.filenameElseFile_To_Open = FNmenuEnd IfMenuOpen = 0On Error GoTo BadOpenOpen File_To_Open For Input As #1lblFile.Caption = File_To_OpenInput #1, NumWtsFor I = 1 To NumWtsInput #1, Dates(I), Weights(I)Next IClose 1Call RFile_Update(File_To_Open)Today = Format(Now, "mm/dd/yy")If Today <> Dates(NumWts) ThenNumWts = NumWts + 1Dates(NumWts) = TodayWeights(NumWts) = ""End If

Page 141: vb6

vsbControl.Max = NumWtsvsbControl.Value = NumWtslblDate.Caption = Dates(NumWts)txtWeight.Text = Weights(NumWts)Exit SubNo_Open:Resume ExitLineExitLine:Exit Sub

BadOpen:Select Case MsgBox(Error(Err.Number), vbCritical + vbRetryCancel, "File Open Error")Case vbRetryResumeCase vbCancelResume No_OpenEnd SelectEnd Sub

mnuFileRecent Click Event:

Private Sub mnuFileRecent_Click(Index As Integer)FNmenu = RFile(Index): MenuOpen = 1Call mnuFileOpen_ClickEnd Sub

mnuFileSave Click Event:

Private Sub mnuFileSave_Click()Dim I As IntegercdlFiles.Filter = "Files (*.wgt)|*.wgt"cdlFiles.DefaultExt = "wgt"cdlFiles.DialogTitle = "Save File"cdlFiles.Flags = cdlOFNOverwritePrompt + cdlOFNPathMustExistOn Error GoTo No_SavecdlFiles.ShowSaveOpen cdlFiles.filename For Output As #1lblFile.Caption = cdlFiles.filenameWrite #1, NumWtsFor I = 1 To NumWtsWrite #1, Dates(I), Weights(I)Next IClose 1Call RFile_Update(cdlFiles.filename)Exit SubNo_Save:Resume ExitLineExitLine:Exit SubEnd Sub

Page 142: vb6

Visual Basic 6 (VB6) - Database Access Management

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.

database accessing methods are as follows;

1. Jet Engine - Accessing Microsoft Access and Visual Basic databases.2. ODBC (Open Database Connectivity) - Allow access to the client server databases on a network.

3. ISAM (Index Sequential Access Method) - Used to access flat databases such as dBase, FoxPro, ParaDox.

Click here for more in-depth lessons on ADO and OLEDB

Contents

Database Structure and Terminology

ADO Data Control (ADODC)

Data Links

Assigning Tables

Bound Data ToolsExample - Accessing the Books Database

Creating a Virtual Table

Page 143: vb6

Finding Specific RecordsExample - Rolodex’ Searching of the Books Database

Data ManagerExample - Phone Directory - Creating the Database

Database ManagementExample - Phone Directory - Managing the Database

Custom Data Aware Controls

Creating a Data ReportExercise - Home Inventory Database

Database Structure and Terminology 

• In simplest terms, a database is a collection of information. This collection is stored in well-defined tables, or matrices.

• 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.

• Here is a simple database example:

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:

Page 144: vb6

Authors Table (6246 Records, 3 Fields)

The Authors table consists of author identification numbers, the author’s name, and the year born. The Publishers table has information regarding book publishers. Some of the fields include an identification number, the publisher name, and pertinent phone numbers. The Title Author table correlates a book’s ISBN (a universal number assigned to books) with an author’s identification number. And, the Titles table has several fields describing each individual book, including title, ISBN, and publisher identification

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:

Page 145: vb6

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.

• Keeping track of all the information in a database is handled by a database management system (DBMS). They are used to create and maintain databases. Examples of commercial DBMS programs are Microsoft Access, Microsoft FoxPro, Borland Paradox, Borland dBase, and Claris FileMaker. We can also use Visual Basic to develop a DBMS. Visual Basic shares the same ‘engine’ used by Microsoft Access, known as the Jet engine. In this class, we will see how to use Visual Basic to access data, display data, and perform some elementary management operations.

ADO (ActiveX Data Object) data control 

• 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.

Page 146: vb6

• The data control can be used to perform the following tasks:

1. Connect to a database.

2. Open a specified database table.

3. Create a virtual table based on a database query.

4. Pass database fields to other Visual Basic tools, for display or editing. Such tools are bound tools (controls), or data aware.

5. Add new records or update a database.

6. Trap any errors that may occur while accessing data.

7. Close the database.

• Data Control Properties:

Align                                  Determines where data control is displayed.

Caption                              Phrase displayed on the data control.

ConnectionString           Contains the information used to establish a connection to a database.

LockType                        Indicates the type of locks placed on records during editing (default setting makes databases read-only).

Recordset                       A set of records defined by a data control’s ConnectionString and RecordSource properties. Run-time 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.

Page 147: vb6

Data Links

 

• After placing a data control on a form, you set the ConnectionString 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:

1. Open Windows Explorer.2. Open the folder where you will store your data link file.

3. Right-click the right side of Explorer and choose New. From the list of files, select Microsoft Data Link.

4. Rename the newly created file BIBLIO.UDL

5. Right-click this new UDL file and click Properties.

6. Choose the Provider tab and select Microsoft Jet 3.51 OLE DB Provider (an Access database).

7. Click the Next button to go to the Connection tab.

8. Click the ellipsis and use the Select Access Database dialog box to choose the BIBLIO.MDB file which is in the Visual Basic main folder. Click Open.

9. Click Test Connection. Then, click OK (assuming it passed). The UDL file is now created and can be assigned to ConnectionString, using the steps below.

• If a data link has been created and exists for your database, click the ellipsis that appears next to the ConnectionString 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.

Page 148: vb6

Assigning Tables

• 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.

• A table is assigned by placing a valid SQL statement in the RecordSource property of a data control. We won’t be learning any SQL here. There are many texts on the subject - in fact, many of them are in the BIBLIO.MDB database we’ve been using. Here we simply show you how to use SQL to have the data control ‘point’ to an inherent database table.

• 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:

SELECT * FROM TableName

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 and RecordSource) is:

Bound Data Tools• 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.

• Some bound data tools are:

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.

Check Box - Used to provide read/write access to a Boolean field.

Page 149: vb6

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.

• Bound Tool Properties:

DataChanged - Indicates whether a value displayed in a bound control has changed.

DataField - Specifies the name of a field in the table pointed to by the respective data control.

DataSource - Specifies which data control the control is bound to.

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.

By following these steps in order, we avoid potential data access errors.

• The relationships between the bound data control and the data control are:

Example - Accessing the Books Database

Page 150: vb6

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 SingleCaption - Books DatabaseName - frmBooks

Adodc1:Caption - Book TitlesConnectionString - BIBLIO.UDL (in whatever folder you saved it in - select, don’t type) RecordSource - SELECT * FROM TitlesName - dtaTitles

Label1:Caption - Title

Label2:Caption - ISBN

Text1:DataSource - dtaTitles (select, don’t type)DataField - Title (select, don’t type)Locked - TrueMultiLine - TrueName - txtTitleText - [Blank]

Text2:DataSource - dtaTitles (select, don’t type)DataField - ISBN (select, don’t type)Locked - TrueName - txtISBN

Page 151: vb6

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.

Creating a Virtual Table• 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.

Quick Example: Forming a Virtual Table

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:

SELECT Author,Titles.ISBN,Title FROM Authors,[Title Author],Titles WHERE Authors.Au_ID=[Title Author].Au_ID AND Titles.ISBN=[Title Author].ISBN ORDER BY Author

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

Page 152: vb6

Text1:DataSource - dtaTitles (select, don’t type)DataField - Author (select, don’t type)Locked - TrueName - txtAuthorText - [Blank]

When done, the form should resemble this:

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

Finding Specific Records

• 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 False and 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:

Page 153: vb6

MoveFirst - Move to the first record in the table.MoveLast - Move to the last record in the table.MoveNext - Move to the next record (with respect to the current record) in the table.MovePrevious - Move to the previous record (with respect to the current record) in the table.

• 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

• There is a method used for searching a database:

Find - Find a record that meets the specified search criteria.

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:

Criteria = “Title >= ‘S’”

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.

• The SearchDirection argument has two possible values: adSearchForward or adSearchBackward. Note, in conjunction with the four Move methods, the SearchDirection argument can be used to provide a variety of search types (search from the top, search from the bottom, etc.)

• 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 return to that position later. The example illustrates its use.

Example - Rolodex’ Searching of the Books Database

Page 154: vb6

1. 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!)

Private Sub Form_Load()Dim I As Integer‘Size buttonscmdLetter(0).Width = (frmBooks.ScaleWidth - 2* cmdLetter(0).Left) / 26For I = 1 To 25Load cmdLetter(I) ' Create new control array element'Position new letter next to previous onecmdLetter(I).Left = cmdLetter(I - 1).Left + cmdLetter(0).Width'Set caption and make visiblecmdLetter(I).Caption = Chr(vbKeyA + I)cmdLetter(I).Visible = TrueNext IEnd Sub

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:

Page 155: vb6

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).

Private Sub cmdLetter_Click(Index As Integer)

Dim BookMark1 As Variant 'Mark your place in case no match is foundBookMark1 = dtaTitles.Recordset.Bookmark 'Move to top of table to start search

dtaTitles.Recordset.MoveFirstdtaTitles.Recordset.Find "Author >= '" + cmdLetter(Index).Caption + "'", 0, adSearchForwardIf dtaTitles.Recordset.EOF = True Then   dtaTitles.Recordset.Bookmark = BookMark1End IftxtAuthor.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.

Data Manager in Visual Basic 6 (VB6)

Page 156: vb6

• 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.

• To create a new database, 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 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.

Example - Phone Directory - Creating the Database

Page 157: vb6

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:

Page 158: vb6

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.

Database Management in Visual Basic 6

• The Data Manager is a versatile utility for creating and viewing databases. However, its interface is not that pretty and its

Page 159: vb6

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.

Update - Saves the current contents of all bound tools.

• 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

VB6 Database Example - Phone Directory - Managing the Database

Page 160: vb6

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.

*frmBooks (this is the old name):Caption - Phone ListName - frmPhone

*dtaTitles (this is the old name):Caption - Phone NumbersConnectionString - [your phone database data link] (select, don’t type)RecordSource - SELECT * FROM PhoneList ORDER BY Name (the ORDER keyword sorts the database by the given field)Name - dtaPhoneLockType - adLockOptimistic

*Label1:Caption - Description

*Label2:Caption - Phone

*Label3:Caption - Name

*txtAuthor (this is the old name):DataSource - dtaPhone (select, don’t type)DataField - Name (select, don’t type)Locked - FalseName - txtNameMaxLength - 40TabIndex - 1

Page 161: vb6

*txtISBN (this is the old name):DataSource - dtaPhone (select, don’t type)DataField - Phone (select, don’t type)Locked - False Name - txtPhoneMaxLength - 15TabIndex - 3

*txtTitle (this is the old name):DataSource - dtaPhone (select, don’t type)DataField - Description (select, don’t type)Locked - False Name - txtDescMaxLength - 40TabIndex - 2

*Command1:Caption - &AddName - cmdAdd

*Command2:Caption - &SaveEnabled - FalseName - cmdSave

*Command3:Caption - &DeleteName - cmdDelete

When done, my form looked like this:

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.

4. In the cmdLetter_Click procedure, replace all occurrences of the word dtaTitles with dtaPhone. Replace all occurrences of Author with Name. The modified code will be:

Private Sub cmdLetter_Click(Index As Integer)Dim BookMark1 As Variant'Mark your place in case no match is foundBookMark1 = dtaPhone.Recordset.BookmarkdtaPhone.Recordset.MoveFirstdtaPhone.Recordset.Find "Name >= '" + cmdLetter(Index).Caption + "'"If dtaPhone.Recordset.EOF = True ThendtaPhone.Recordset.Bookmark = BookMark1End If

Page 162: vb6

txtName.SetFocusEnd Sub

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.

Private Sub cmdAdd_Click()cmdAdd.Enabled = FalsecmdSave.Enabled = TruecmdDelete.Enabled = FalsedtaPhone.Recordset.AddNewtxtName.SetFocusEnd Sub

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.

Private Sub cmdSave_Click()dtaPhone.Recordset.UpdatedtaPhone.RefreshcmdAdd.Enabled = TruecmdSave.Enabled = FalsecmdDelete.Enabled = TruetxtName.SetFocusEnd Sub

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.

Private Sub cmdDelete_Click()dtaPhone.Recordset.DeletedtaPhone.Recordset.MoveNextIf dtaPhone.Recordset.EOF = True ThendtaPhone.RefreshIf dtaPhone.Recordset.BOF = True ThenMsgBox "You must add a record.", vbOKOnly + vbInformation, "Empty file"Call cmdAdd_ClickElsedtaPhone.Recordset.MoveFirstEnd IfEnd IftxtName.SetFocusEnd Sub

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.

Custom Data Aware Controls - VB6 Database Tools

Page 163: vb6

• 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.

Some properties of the DataList box are:

DataSource - Name of data control that is updated by the selection.

DataField - Name of field updated in Recordset specified by DataSource.

RowSource - Name of data control used as source of items in list box.

ListField - Name of field in Recordset specified by RowSource used to fill list box.

BoundColumn - Name of field in Recordset specified by RowSource to be passed to DataField, once selection is made. This is usually the same as ListField.

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

Page 164: vb6

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:

Page 165: vb6

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.

Creating a Data Report in Visual Basic 6 (VB6)

• 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.

Example - Phone Directory - Building a Data Report

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.

Creating a Data Environment

1. Start a new Standard EXE project.

2. On the Project menu, click Add Data Environment. If this item is not on the menu, click Components. Click the Designers tab, and choose Data Environment and click OK to add the designer to your menu.

3. We need to point to our database. In the Data Environment window, right-click the Connection1 tab and select Properties. In the Data Link Properties dialog box, choose Microsoft Jet 3.51 OLE DB Provider. Click Next to get to the Connection tab. Click the ellipsis button. Find your phone database (mdb) file. Click OK to close the dialog box.

4. We now tell the Data Environment what is in our database. Right-click the Connection1 tab and click Rename. Change the name of the tab to Phone. Right-click this newly named tab and click Add Command to create a Command1

Page 166: vb6

tab. Right-click this tab and choose Properties. Assign the following properties:

Command Name - PhoneListConnection - PhoneDataBase Object - TableObjectName - PhoneList

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 Save denPhone 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):

Creating a Data Report

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.

2. Set the following properties for the report:

Name - rptPhoneCaption - Phone DirectoryDataSource - 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

Page 167: vb6

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.

Accessing the Data 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.

3. Use this code in cmdReport_Click:

Private Sub cmdReport_Click()rptPhone.ShowEnd Sub

4. This uses the Show method to display the data report.

5. Save the application and run it. Click the Show Report button and this should appear:

Page 168: vb6

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.

Exercise - Home Inventory DatabaseDesign 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:

Page 169: vb6

Project Design:

Form:

Properties:

Form frmHome:BorderStyle = 1 - Fixed SingleCaption = Home Inventory

CommandButton cmdExit: Caption = E&xit

ADO Data Control dtaHome: Caption = Book TitlesConnectionString = HomeInv.udl (in whatever folder you saved it in - select, don’t type) RecordSource = SELECT * FROM MyStuffVisible = False

CommandButton cmdShow:

Page 170: vb6

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 = LocationDataSource = dtaHomeFontName = MS Sans SerifFontSize = 9.75MaxLength = 40

TextBox txtValue:DataField = New ValueDataSource = dtaHomeFontName = MS Sans SerifFontSize = 9.75

TextBox txtDate:DataField = Date PurchasedDataSource = dtaHomeFontName = MS Sans SerifFontSize = 9.75MaxLength = 20

TextBox txtSerial:DataField = Serial NumberDataSource = dtaHomeFontName = MS Sans SerifFontSize = 9.75MaxLength = 20

TextBox txtItem:DataField = ItemDataSource = dtaHomeFontName = MS Sans SerifFontSize = 9.75MaxLength = 40

Label Label5:Caption = LocationFontName = Times New Roman FontSize = 12

Label Label4:Caption = New ValueFontName = Times New Roman

Page 171: vb6

FontSize = 12

Label Label3:Caption = Purchase DateFontName = Times New Roman FontSize = 12

Label Label2:Caption = Serial NumberFontName = Times New Roman FontSize = 12

Label Label1:Caption = ItemFontName = Times New Roman FontSize = 12

Code:

General Declarations:

Option Explicit

cmdAdd Click Event:Private Sub cmdAdd_Click()'Add new item to databasedtaHome.Recordset.AddNewtxtItem.SetFocusEnd Sub

cmdDelete Click Event:Private Sub cmdDelete_Click()'Delete item from databaseDim Rvalue As IntegerRvalue = MsgBox("Are you sure you want to delete this item?", vbQuestion + vbYesNo, "Delete Item")If Rvalue = vbNo Then Exit SubdtaHome.Recordset.DeletedtaHome.Recordset.MoveNextIf dtaHome.Recordset.EOF ThenIf dtaHome.Recordset.BOF ThenMsgBox "You must add an item.", vbOKOnly + vbInformation, "Empty Database"Call cmdAdd_ClickElsedtaHome.Recordset.MoveFirstEnd IfEnd IftxtItem.SetFocusEnd Sub

cmdExit Click Event:Private Sub cmdExit_Click()EndEnd Sub

cmdNext Click Event:

Page 172: vb6

Private Sub cmdNext_Click()'Move to next item - if at end-of-file, backup one itemdtaHome.Recordset.MoveNextIf dtaHome.Recordset.EOF Then dtaHome.Recordset.MovePrevioustxtItem.SetFocusEnd Sub

cmdPrevious Click Event:Private Sub cmdPrevious_Click()'Move to previous item - if at beginning-of-file, go down one itemdtaHome.Recordset.MovePreviousIf dtaHome.Recordset.BOF Then dtaHome.Recordset.MoveNexttxtItem.SetFocusEnd Sub

cmdShow Click Event:Private Sub cmdShow_Click()rptHomeInv.ShowEnd Sub

 

Page 173: vb6

.