Hour 9

Combining Code and Controls

This hour's lesson takes a short break from the theory you've seen for the past few lessons. In this lesson you will put some of the code you've seen into a fairly large application and run the application to work with the results. You've already learned a lot about Visual Basic. Nevertheless, as this lesson illustrates, you've got a lot of exciting things yet to learn over the next few lessons.

This lesson's primary goal is to refresh your Visual Basic knowledge once again by putting together the big picture. In this lesson you'll build a simple but complete application just to get practice working with both code and the controls you've learned so far. Once you refresh your application-building skills in this lesson, the next lesson teaches more controls from the toolbox. The more controls you learn to use, the more powerful your applications become.

The highlights of this hour include

The Interest Calculation Application

The previous lesson describes how to compute compound interest using a For loop. You studied the code in the previous lesson, and this lesson will build a simple application around that interest calculation.


NOTE: In creating an application from scratch, this hour lets you review the application, controls, form, and standard modules. Therefore, when the next lesson begins to teach some more advanced controls, you'll be better prepared for them.

Figure 9.1 shows the running application that you'll create here.

Figure 9.1. The interest calculating application's window.

Perform these steps to create the interest calculating application:

1. Start a new project (select File|New Project). Double-click the Standard EXE icon (the icon you'll most often choose for regular applications).

2.
Change the form's Name property to frmInterest. Change the Caption property to Interest Calculation.

3.
Change the form's StartUpPosition property to 2-CenterScreen. You've not seen the StartUpPosition property yet. The StartUpPosition property determines the location of the Form window when the user runs the program. Let Visual Basic center the form on your user's screen because you don't know the exact measurements of the screen that your users will use. If you set StartUpPosition to 2-CenterScreen, Visual Basic always places the form in the middle of the screen no matter what the user's screen size and resolution are. (Use the WindowState property to open the Form window in its maximized state if you want a full-screen Form window when the application starts.)


NOTE: The StartUpPosition property makes the Form Layout window unnecessary in most cases. StartUpPosition gives you much more accurate placement of the form than the Form Layout window.
4. You've now got to add the labels and text boxes. The form's title label is simple to generate. Place a label on the form and set the following properties: Name: lblTitle, Alignment: 2-Center, BorderStyle: 1-Fixed Single, Caption: Interest Calculator, Font: Bold 18, Height: 495, Left: 2090, Top: 240, and Width: 3855.

5.
You now must set up a series of three label/text box pairs. Notice that Figure 9.1's labels all have hotkeys. Although a label cannot accept the focus, pressing Alt+hotkey sends the focus to the control next in line, which will be the text box next to the label (assuming that you place the text box right after you place the corresponding label).

Set the interest rate label as follows: Name: lblRate, Alignment: 1-RightJustify, Caption: &Interest rate (8 for 8%):, Font: Regular 14, Height: 375, Left: 2040, Top: 1080, and Width: 2895. Set the interest rate text box as follows: Name: txtRate, Alignment: 0-LeftJustify, Font: 10, Height: 375, Left: 5160, ToolTipText: Annual rate investment grows, Top: 1080, and Width: 615. Blank out the Text property so nothing appears in the text box at startup. Notice that you are adding ToolTipText at the same time you add the control that the user interacts with. Design time is the best time to add ToolTipText because the control's meaning is clearest in your mind then.

Using Control Arrays

This is a great time to introduce a new concept called control arrays. A control array is a group of more than one control of the same control type. You will better understand control arrays after you learn about data arrays in Hour 10, "List Boxes and Data Lists," but the interest rate application makes this a great project to introduce them.

Notice that the interest calculator's Term and Investment Amount labels and text boxes all look similar to the Interest rate label and text box you just placed on the form. All the font information and Height properties are the same. Therefore, while you could enter the remaining labels and text boxes, you can utilize the Windows Clipboard to make the job go faster.

Highlight both the existing Interest rate label and text box. You can select multiple controls by pressing the Ctrl key while you click on each control, or you can lasso the controls by dragging a rectangle around the two controls. When you select both controls, sizing handles appear around them, as shown in Figure 9.2.

Figure 9.2. The sizing handles show that two controls are selected.

Select Edit|Copy to copy the selected controls to the Windows Clipboard. Now select Edit|Paste, and Visual Basic pops up a warning dialog box that reads You already have a control named `txtRate'. Do you want to create a control array?

A control array is a set of multiple controls that have the same name. You distinguish between the controls inside the array with an index value. For this particular example, you should not create a control array (you will create one in the next lesson). Therefore, answer No to the dialog box and again answer No when Visual Basic asks you about creating a control array for the text box.


NOTE: Visual Basic saw that you wanted to paste two controls on the form that already had controls with those same names. Visual Basic cannot replace existing controls when you paste new ones with the same name, so Visual Basic guessed (in this case incorrectly) that you wanted to add a control array named txtRate. When you refused the control array, Visual Basic made up its own name for the new label (Label1) and the new text box (Text1).

Move the pasted label and text box to their correct positions under the first pair and set these properties for the label: Name: lblTerm, Caption: &Term (annual periods):, Left: 2040, Top: 1800, and Width: 2895. The Height and Font properties are already correct because you borrowed these properties from the control you originally copied from. Set these properties for the text box: Name: txtTerm, Left: 5160, ToolTipText: Number of periods, Top: 1800, and Width: 615. As you can see, you don't have to set as many properties when you paste from an existing similar control.

New Term: Default properties are the properties Visual Basic assumes if you omit the properties from a control inside the Code window.

Click the form and select Edit|Paste once more (the Clipboard still holds those first two controls you sent there), refuse the control array, and set the following properties for the new label: Name: lblInvest, Caption: I&nvestment Amount:, Left: 1920, Top: 2520, and Width: 2895. Set the text box's properties to Name: txtInvest, Left: 5040, ToolTipText: Money you invested, Top: 2520, and Width: 1215.

Your screen should look something like Figure 9.3.

Figure 9.3. Proper form design takes a while.

Finishing the Form

You can quickly finish the form now. While the label and text box still reside on the Windows Clipboard, this would be a good time to add the Ending Investment label and text box. Select Edit | Paste once again and set the pasted label's properties as follows: Name: lblEnding, Caption: Ending Investment:, Left: 1800, Top: 4560, and Width: 2895. Set the text box's properties as follows: Name: txtEnding, Left: 4920, Locked: True, TabStop: False (so the user cannot send the focus to this text box), Top: 4560, ToolTipText: Compounded Investment, and Width: 1455.

The new property you set just now is the Locked property. When you lock a control, Visual Basic allows no user editing of the control. Therefore, the code beneath the form can modify the text box's Text property but the user cannot. The final text box will be a holding place for the calculated compound investment amount, so the user should not be allowed to edit the control even though it's a Text Box control.


NOTE: You might wonder why the application uses a text box and not a read-only control such as a label. The Label control would work just as well and would not require a Locked property setting because labels can never be changed by the user. Nevertheless, the text box keeps a uniform appearance throughout the form, so we're using a text box here.

Add a command button named cmdCompute, add the caption &Compute Interest, and add a ToolTipText value of Click to compute final investment. Place and size the command button as follows: Height: 495, Left: 2640, Top: 3360, and Width: 2535. Add a final command button named cmdExit to the lower-right corner with the E&xit Caption property.


NOTE: See, building an application can be tedious, but your productivity is greater with Visual Basic than with virtually every other application development system available. Although you've seen most of this lesson's concepts before, this is the first lesson that truly ties things together by walking you through the entire application-creation process.

Adding Code

Often, programmers run their applications as they build them despite the fact that no code exists yet to make the application do real work. You should be able to run your application now to make sure that the labels and text boxes all look correct. Check out the tooltip text to make sure you've entered the text properly. Click the toolbar's End button to stop the program so that you can add the final code.

The code is going to borrow a bit from the interest calculation routine you learned about in Hour 8, "Visual Basic Looping." You'll have to modify the routine somewhat so the data comes from the Text Box controls you've set up. You want the calculation to take place when the user clicks the center command button, so add the following code to the command button's Click() event procedure. Double-click the Form window's Compute Interest command button to open the cmdCompute_Click () event procedure to complete the code that follows:

Private Sub cmdCompute_Click()
` Use a For loop to calculate a final total
` investment using compound interest.
`
` intNum is a loop control variable
` sngIRate is the annual interest rate
` intTerm is the number of years in the investment
` curInitInv is the investor's initial investment
` sngInterest is the total interest paid
   Dim sngIRate As Single, sngInterest As Single
   Dim intTerm As Integer, intNum As Integer
   Dim curInitInv As Currency

   sngIRate = txtRate.Text / 100#
   intTerm = txtTerm.Text
   
   curInitInv = txtInvest.Text
   sngInterest = 1#   ` Begin at one for first compound

   ` Use loop to calculate total compound amount
   For intNum = 1 To intTerm
      sngInterest = sngInterest * (1 + sngIRate)
   Next intNum

   ` Now we have total interest,
   ` calculate the total investment
   ` at the end of N years
   txtEnding.Text = curInitInv * sngInterest
End Sub


NOTE: This is basically the same code that you saw in the previous lesson when studying For loops. This code does include a few minor differences so that the application's control names properly initialize and receive values.


TIP: Visual Basic supports default properties for most controls. The default property is the property Visual Basic uses if you don't explicitly specify a property. For example, if you use a Text Box control in code and don't type the Text property, Visual Basic assumes you mean Text (as long as you don't specify a different property). Therefore, the first assignment in the application is now sngIRate = txtRate.Text / 100#, but the following statement is identical in every respect because Visual Basic assumes that you are using the text box's Text property: sngIRate = txtRate / 100#.

You must also add the terminating code for the Exit command button. Here's a simple way the Code window lets you add new procedures:

1. Click the drop-down object list box (the left list box, directly beneath the toolbar) and select cmdExit.

2.
Select the event for which you want to add code in the right drop-down list box whose tooltip reads Object. (The default procedure listed for command buttons is Click, so in this case you don't need to select a different procedure.)

Add the following code for the command button's event procedure:

Private Sub cmdExit_Click()
   ` Unload the form and terminate application
   Unload frmInterest
   End
End Sub

The Unload Statement

The Exit command button's Click event procedure contains a statement you've not seen until now. The Unload statement unloads a form from memory. If the form to unload is currently displayed, Visual Basic removes the form and returns all of the form's control values back to their design-time state.

In most cases the Unload statement is unnecessary, especially when your application contains only a single form. If you add multiple forms to the application, however, the user could have closed one of the Form windows (by clicking the form's window close buttons), and the End statement could fail to release that form's resources properly.

The Unload statement lets you use a shortcut that looks like this:

Unload Me

Me is a special object that refers to the currently active form. Use Unload Me when the application contains only a single form if you don't want to type the full form name. For a multiple-form application, however, be sure to unload all the forms before terminating the program.

Finishing Touches

Run your application and enter some sample values. Figure 9.4 shows the application with some sample data entered for a five-year investment. As shown in Figure 9.4, if you invested $1,000 today at 11% interest, in five years you will have approximately $1,685.

Figure 9.4. The running application computes the final investment amount.

The application is not really complete and ready for distribution. Although you've mastered the mechanics of this simple application, more is needed to make the application professional. Obviously, the ending investment's decimal place precision is far too high.

You need to format the value shown in the Ending Investment text box. When you format a value, you don't change the value, but you change the value's look. Visual Basic includes a built-in function called Format() that formats numeric and string values so you can display such values as dollars and cents, area code formats, or whatever formats you want to use. Although Hour 14, "Built-in Functions Save Time," explains Format() in detail, you can use the Format() function now to spruce up your application.

New Term: To format is to change the way a value appears to the user.

At the end of the cmdCompute_Click() event procedure, change the ending investment's assignment to this:

txtEnding.Text = Format(curInitInv * sngInterest, "$###,##0.00")


TIP: Some formats get lengthy, so programmers often declare a string variable and assign the format to the variable. They then use the variable inside the Format() function instead of using the string literal for the format. If you use the same format in several locations within the code, the variable means less typing on your part, and if you ever change the format, you only have to change the format in one place.

The Format() function's basic format is this:

Format(expression, strFormat)

Visual Basic changes the look of expression to match that of the format string you supply. Therefore, the format string "$###,##0.00" instructs Visual Basic to display the value with a dollar sign, floating numbers with the # (if the number is less than $100,000.00 the numbers will move left to touch the dollar sign instead of leaving a gap for the missing digits), commas in the amount if the amount is over $1,000, and a decimal point with two decimal places showing. If the value happens to be $0.00, the zeros ensure that the value prints, whereas if you used a # in place of each 0, the # would show nothing if the result were zero.

Once you format the value and rerun the application with the numbers used earlier, you'll see a result that looks better, as Figure 9.5 shows.

Figure 9.5. The Format() function improved the output.

Error Checking

A big problem still exists with the application if you plan to distribute it to others. The problem is not in the logic or in the calculation or in the form. The problem is the application's lack of error checking. If the user does not enter a value in one or more of the text boxes, the calculation will not work properly. Even worse, an error such as a divide by zero error could occur and stop the running program. Mathematically, one cannot divide by zero, and Visual Basic stops the program and issues a runtime error message if a divide by zero occurs. Any time you write an application that performs division, you should check to make sure that you never divide by zero.

Therefore, you'll need to add error checking to the application to make sure the user enters positive values greater than 0 in each of the text boxes before clicking the computational command button.

The error checking can be fairly simple. Convert the text box values to numbers, and if any text box contains zero or less, perform the following:

1. Tell the user about the problem with a message box.

2. When the user closes the message box, set the focus on the control with the bad value so the user can more easily enter a corrected value.

3. Test the controls again before any calculation is performed to ensure that the problem is fixed.

Several approaches exist for handling this error. The approach this lesson uses is slightly advanced, but it gives you a chance to see an external standard module added to an application (an external code module that is different from the form module), and you'll get a glimpse of the function-writing instruction you'll learn in Hour 13, "Modular Programming." You will actually create your own function instead of using one of the built-in functions supplied with Visual Basic.

First, assign the hook to the other function in your cmdCompute_Click() event procedure like this:

Private Sub cmdCompute_Click()
` Use a For loop to calculate a final total
` investment using compound interest.
`
` intNum is a loop control variable
` sngIRate is the annual interest rate
` intTerm is the number of years in the investment
` curInitInv is the investor's initial investment
` sngInterest is the total interest paid
   Dim sngIRate As Single, sngInterest As Single
   Dim intTerm As Integer, intNum As Integer
   Dim curInitInv As Currency
   
   ` Error-checking
   If ErrorCheck() = 1 Then
     Exit Sub
   End If
   
   sngIRate = txtRate.Text / 100#
  intTerm = txtTerm.Text


NOTE: The rest of the procedure is identical to the earlier listing. You only need to add the four lines that follow the variable declarations.

The ErrorCheck() is a procedure you'll add that checks the form for bad values. You will add this procedure in a separate module, not at the bottom of the form module. Notice that you use the ErrorCheck() procedure just as you use built-in functions: You call the function with an empty argument list (no arguments are necessary), and the function returns a value. If that value is 1, the form contains an error, so you use the Exit Sub statement to terminate the event procedure and return the user to the form. (The previous lesson described other forms of the Exit statement such as Exit For.) If no error exists, the ErrorCheck() procedure will not return a 1, and the processing continues as normal.

New Term: A function procedure is a procedure that you write that accepts zero or more arguments and returns a single value.

New Term: A subroutine procedure is a procedure that you write that accepts zero or more arguments but does not return a value.

You must now add the ErrorCheck() procedure. Unlike the event procedures you've been writing until now, the ErrorCheck() procedure is a function procedure and not a subroutine procedure. A function procedure always returns a value, whereas a subroutine procedure never returns a value. (Again, you'll learn more about function and subroutine procedures in Hour 13.)

To add an extra module to your project, perform these steps:

1. Select Project | Add Module to add a new module (that you can view in a Code window) to the project. You could also right-click over your Project window and add the module from the pop-up menu.

2. Click the Module icon that appears in the Add Module dialog box. Visual Basic adds a new module with the default name Module1 (and the filename Module1.BAS). Figure 9.6's Project window shows the new module in your project. Your Code window will now display a blank module where you can type the module's code.

Figure 9.6. You've now added another code module to the project.

3. Maneuver between modules and the form by double-clicking the Project window object you want to work with. For now, however, stay inside the new module.

Type the following function procedure inside the new module's Code window:

Public Function ErrorCheck() As Integer
   ` Error-checking for the form
   If Val(frmInterest.txtRate.Text) <= 0 Then
      intPress = MsgBox("Enter a value for the rate", vbCritical)
      frmInterest.txtRate.SetFocus
      ErrorCheck = 1
      Exit Function
   End If
   If Val(frmInterest.txtTerm.Text) <= 0 Then
      intPress = MsgBox("Enter a value for the term", vbCritical)
      frmInterest.txtTerm.SetFocus
      ErrorCheck = 1
      Exit Function
   End If
   If Val(frmInterest.txtInvest.Text) <= 0 Then
      intPress = MsgBox("Enter a value for the investment", vbCritical)
      frmInterest.txtInvest.SetFocus
      ErrorCheck = 1
      Exit Function
   End If
   ` No error occurred if execution gets here
   ErrorCheck = 0
End Function

The first difference you'll notice between the function procedure and the event subroutine procedures you've seen so far is the difference between the opening and closing statements. The keyword Function distinguishes the function procedure from a subroutine procedure. The procedures you've seen until now were subroutine procedures that used the Sub keyword to define them. In addition, the function procedure's opening line ends with As Integer. This qualifier tells Visual Basic that the function procedure will return an integer value. Functions can return any data type as long as you define the function to return the proper data type with the As keyword.

The function then checks each text box on the form. All form references include the form name! Therefore, instead of referring to the interest rate text box as txtRate, the code qualifies the text box with a form name as follows: frmInterest.txtRate. You've got to remember that an external standard module, such as this one, is not part of a form's code found in the form module. A standard module might need access to several forms in the same project, so the standard module needs the qualifying form name before each control name.

Once a text box is found to hold a bad value, a message box describes the problem. The module then sets the focus to that control. Therefore, the focus goes straight to the problem so the user can edit the control without having to find it first once the error message box goes away.


WARNING: SetFocus is not a property or an event. SetFocus is known as a method. Controls usually support all three: properties, events, and methods. A method is a built-in routine attached directly to a control. In a way, the control executes its own method. You'll append method names to the end of a control as done here. Read the methods from right to left to understand them fully. For example, frmInterest.txtTerm.SetFocus tells Visual Basic to set the focus on the control named txtTerm located on the frmInterest form.

Finally, the code sets the function's return value to 1 if an error occurs and exits the function (and therefore the module) and returns the return value to the calling code, which is the form module. To return a value from a function procedure, you simply assign the value that you want to return to the function name.

Figure 9.7 shows the message box that appears if the user enters a term value that's zero or less.

Figure 9.7. The user must enter better data.

Save your project (Lesson 9 Int Proj would be a good name). When you save the project, Visual Basic asks for a form name and a module name as well (use Lesson 9 Int Form and Lesson 9 Int Mod to follow the naming convention that this 24-hour tutorial uses).

Summary

This hour develops a complete application. Through the development process, you saw how even a simple project can require detailed components such as error checking and proper form management. Too many books rush to the theory without hands-on work or rush to the hands-on without explaining the process. This lesson gives your 24-hour tutorial a needed boost with both hands-on development that strengthens what you already knew and some new topics to consider such as function procedures and form placement.

The next hour describes important list-based controls. You'll learn how to produce drop-down list boxes and how to initialize and work with such lists.

Q&A

Q Why does End not terminate an application properly? End seems to work fine without the extra Unload statement.

A
End does work fine for single-form applications. Problems can arise, however, if you create applications with multiple forms. In certain cases, the End statement may fail to release every form's resources. In today's multitasking, multiuser networked world, you need to release resources as soon as you can so that other processes have access to those resources (such as memory and CPU time). The Unload statement takes care of closing forms properly.

Q How can I find the default properties for all controls?

A
Surprisingly, Visual Basic's online help does not list the default properties. The default properties are the most common properties referenced for a control. Therefore, the default property for a text box is the Text property, and the default property for a label is the Caption control. Generally, using a control's default property makes for less typing, but default properties can add confusion later when you try to figure out the code and change it. Therefore, if you use default properties, use them only for the label and text box, but specify all other controls' default properties explicitly so that your code is as clear as possible.

Workshop

The quiz questions and exercises are provided for your further understanding. See Appendix C, "Answers," for answers.

Quiz

1. What does the form's StartUpPosition value do?

2.
Why do label captions often show hotkey letter combinations?

3.
When is the best time to enter ToolTipText properties and why?

4.
What is a control array?

5.
Why does Visual Basic like to offer a control array when you paste a control on a form that has the source of the paste already on the form?

6.
Why might you want to lock a Text Box control?

7.
What is the proper way to terminate an application?

8.
What happens when you attempt to divide by zero?

9.
True or false: The following two statements are identical:
lblTitle = "The Sound of Multimedia"

lblTitle.Caption = "The Sound of Multimedia"
10. What is the difference between a function procedure and a subroutine procedure?

Exercises

1. Change this lesson's application's form properties so the user cannot resize the form. Search through the form properties until you find the property that will do this.

2.
Add input box routines to the application so that the user sees the error message in the input box and can enter the replacement values in the input box. The code then places the input box's value into the form. Once the form gets a replacement value, be sure to check the controls again to make sure that the replacement value is correct. You might want to add a Do-While loop around the input box routines so that the user keeps seeing the input box warnings until the user enters a value greater than zero.