Our next application is more advanced, but not as advanced as it looks. It’s a math calculator with a typical visual interface that demonstrates how Visual Basic can simplify programming. If you haven’t tried it.you may think that writing an application such as this one is way too complicated, but it isn’t. The Math application is shown. and you’ll find it in this chapter’s folder on the CD. The Math application emulates the operation of a hand-held calculator and implements the basic arithmetic operations. It has the structure of a working math calculator, and . you can easily expand it by adding more features. Adding features like cosines and logarithms is actually simpler than performing the basic arithmetic operations.
The application’s interface is straight forward, but it takes quite a bit of effort. You must align a number of buttons on the Form and make the calculator look like a hand-held calculator as much as possible. You don’t have to redesign the interface or.the operation of a calculator, so you can start building the application’s Form. Start a new project, name its main Form MathCalc, and save the project as Math in a new folder (the project is stored in the Math folder on the CD). Now, follow these steps:
1. Select a font that you like for the Form. All the Command buttons you’ll place on the Form will inherit this font. The MathCalc application on the CD uses la-point Verdana font.
2. Add the Label control, which will become the calculator’s display. Set its BorderStyle property to I-Fixed Single so that it will have a 3-D look, as shown.
3. Draw a Command button on the Form, change its caption to “0”, name it Digits, and set its Index to O.We’ll create an array of buttons .
Place the button ill its final position on the Form
Creating an array of controls Inny sound strange, but here’s why you do it. We could create 11buttons and give them different names, for example, DigitI, Digit2, and so on. But then we would have to provide a separate subroutine for their Click event, in other words, one subroutine per Command button. By creating an array of Command buttons, we can provide a single subroutine for the Click event of all buttons. You’ll see later how this naming scheme simplifies our code.
5. Right-click the button and select Copy from the shortcut menu. The Command button is copied to the Clipboard, and now you can paste it on the Form (which is much faster than designing an identical button).
6. Right-click somewhere on the Form and from the shortcut menu select Paste to create a copy of the button you copied earlier. Visual Basic displays a dialog box with the following message:
You already have a control named ‘Digits’. Do you want to create a control array?
You want to create an array of Command buttons, so click on Yes.
7. Repeat steps 5 and 6 eight more times, once for each numeric digit. Each time a new Command button is pasted on the Form, visual Basic gives it the name Digits and sets its Index property to a value that’s larger than the previous one by 1. Each button’s Index property will be the same as its caption, as long as you set the captions sequentially, If you place the Command buttons for the digits in any other order, the application won’t work. As you have guessed, we’ll be using the Index property to handle the buttons from within our code, and it’s crucial that their captions are the same as their indices.
8. When the buttons of the numeric digits are all on the Form, place two more buttons, one for the C (Clear) operation and one fat the Period button. Name them ClearBttn and DotBttn, and set their captions accordingly. Use a larger font size for the Period button to make its caption easier to read.
9. When all the Digit buttons of the first group are on the Form and in their approximate positions, align them with the commands on ‘the Format menu.
a. .First, align the buttons in a row and make their horizontal spacing equal. Then do the same with the buttons in a column; and this time, make sure their vertical distances are equal.
b. Now-you can align the buttons in each row and each column separately. Use one of the buttons you aligned in the last step as the guide for the rest of them. The buttons can be aligned in many ways, so don’t worry if somewhere in the process you ruin the alignment. You can always use the Undo command in the Edit menu.
10.. Now, place the Command buttons for the operations. Table 2.1 lists their .” captions and names.
11. Use the commands on the Format menu to align these buttons as shown. The control with the blue handles can be used as a reference for aligning the other controls into rows and columns.
Programming the Math Application
Now you’re ready to add some code to the application. Double-dick one of the Digit buttons on the Form, and you’ll see the following in the Code window:
Private Sub Digits_Click(Index As Integer)
This, is the Click event’s handler for all Command buttons that represent digits. All buttons have the same name, and they are differentiated by their index. When the user clicks one of them, Visual Basic generates the Digits_Click event and uses the Index argument to report the index of the button that was clicked.
What happens on a hand-held calculator when you press a numeric button? The corresponding digit.is appended to the display. To emulate this behavior, insert the following line in the Click event handler:
Display.Caption = Display.Caption + Digits(Index).Caption
This line appends the digit clicked to the calculator’s display. The Caption property of the control that was clicked is the digit of the button. For example, if you – have already entered the value 345, clicking the digit 0 displays the value 3450 -on the Label control that acts as the calculator’s display.
‘The code, behind the Digit buttons’ needs a few more lines. If you run the application now, you’ll see what happens after an operation is performed and the result is displayed. If you click another digit, it’s appended to the existing number. But this isn’t the way a hand-held calculator works. The first time a Digit button is pressed after a result is displayed, the display must clear and then print the new digit. Revise the Digits_Click event handler as follows.
What if the user makes a mistake and wants to undo an entry? The typical hand held calculator has no backspace key. The Clear key erases the current number on the display. Let’s implement this feature. Double-click the C button and enter the following code in its Click event:
Display.Caption – ” “
And now we can look at the Period button. A calculator, no matter how sample, should be able to handle fractional numbers. The Period button works just like the Digit buttons, with one exception. A digit can appear any number of times in a numeric value, but the period can appear only once. A number like 99,991 is valid, but you must make sure that the user can’t enter numbers such as 23.456.55. Once a period is entered, this button mustn’t insert another one. The following code accounts for this.
The InStr (Display. Caption, ‘.’) function returns the location of the first, instance of the period in the caption of the Label control. If this number is positive, the number entered contains a period already, and another can’t be entered. In this case, the program exits the subroutine. If the InStr() function returns 0, the period is appended to the number entered so far, as is a regular digit.
The InStr(Display. Caption, ‘.’) function returns the location of the first, instance of the period in the caption of the Label control. If this number is positive, the number entered contains a period already, and another can’t be entered. In this case, the program exits the subroutine. If the InStr() function returns 0, the period is appended to the number entered so far, as is a regular digit.
InStr(“Welcome to Visual Basic’, ‘Visual’).
However, the following function returns 9 because the string “Java” doesn’t appear anywhere in the first string.
InStr(‘Welcome to Visual Basic’, ‘Java’)
The following expression returns a positive number if the value already on the display contains a period:
If that’s the case, the program exits the subroutine without taking any action. If the value returned by the InStr() function is.a positive number, the value entered is an Integer, and the period is displayed.
Check out the operation of the application. We have already created a function user interface that emulates a hand-held calculator with data entry capabilities. It .doesn’t perform any operations yet, but we have already created a functional use, , interface with only a small number of statements.
Now we can move to the interesting part of the application: considering how a calculator works, Let’s start by defining three variables:
• Operand1 The first number in the operation
• Operator The desired operation .
• Operand2 The second number in the operation
When the user clicks a number, or Operand1, the value on the display is stored in a variable. If the user then clicks the Plus button, or Operator, the program must make a note to itself that the current operation is an addition, and then clear the display so that the user can enter another value. ‘The user enters another value, at Operand2, and then clicks the Equals button to see the result. At this point, our program must do the following:
1. Read the Operand2 value on the display.
2. Add that value to Operand1.
3. Display the result .
The Equals button must perform the following operation:
Operand1 Operator Operand2
Suppose the number on the display when the user clicks the Plus button is 3,342. The user then enters the value 23 and clicks the Equals button. The program must carry out the addition:
3342 + 23
If the user clicks the Division button, the operation is:
3342 / 23
In both cases, the result is displayed (and it may become the first operand for the next operation).
The variables in the previous examples are local in the subroutines where they are declared. Other subroutines have no access to them and can’t read or set their values. Sometimes, however variables must be accessed from many places in a program. If the Operand1, Operand2, and Operator variables in this application must be accessed from within more than one subroutine, they must be declared outside any subroutine. The same is true for the ClearDisplay variable. Their declarations therefore, must appear outside any procedure, and they usually appear at the beginning of the code Module (the first lines in the Code window are usually declarations of variables that must be accessed from within any subroutine).
within the other Formats). In other words, any subroutine on a Form on which the variables are declared can read or set the values of the variables, but no subroutine outside that Form can do so,
With the variable declarations out of the way, we can now implement the Operator buttons, Double-click the Plus button and in the Click event’s handler, enter the following lines:
The variable Operandl Is assigned the value currently on the display. The Val() function returns the numeric value of its argument, As you may recall, a Label’s Caption property is a string. For example, you can assign the value “My Label” to a Label’s Caption property. The actual value stored in the Caption property is not a number. It’s a String such as “428”, which is different from the numeric value 428. That’s why we use the ValO function to convert the value of the Label’s caption to a numeric value.
So far, we have implemented the following functionality in our application: When an Operator button is clicked, the program stores the value on the display in the Operandl variable and the operator in the Operator variable. It then clears the display SO that the user can enter the second operand. After the second operand is entered, the user can click the Equals button to calculate the result. When this happens, the following code is executed.
The result variable is declared as Double so that the result of the operation will be stored with maximum pieclsion. The code extracts the value displayed in the· Label control and stores it in the variable Operand2. It then F?.-fo..ms the operation with a string of If statements:
.• If the operator is “+”, the result is the sum of the two operands .
• If the Operator is “r”, the result is the difference of tite first perand DunUS’ the second. ..
• If the Operator is II.”, the result is the product of the two operands . If the Operator is ” /”, the result is the quotient of the first operand divided by the second operand, provided that the divisor is not zero.
Now run the application and check i~out It works just like a hand-held calculator, and you can’t crash it by specifying invalid data. We didn’t have to use any data validation code in thiS example because the user doesn’t get a chance to type invalid data. The data entry mechanism is foolproof. The user can enter only numeric values because there are only numeric digits on the calculator. The only possible error is to divide by Zero, and that’s handled in the Equals button.
Adding More Features
Now that we have implemented the basic functionality of a hand-held calculator, we can add more features to our application. Let’s add two more useful buttons:
• The +/ – button, which inverts the sign of the number on the display
• The l/x button, which inverts the number on the display,
Open the Code window for each of the Command buttons and enter the following code in the corresponding Click event handlers. For the +/ – button, enter:
As with the Division button, we don’t attempt to invert a zero value. The operation 1/0 is undefined and causes a runtime error. Notice also that I use the value displayed on the Label control directly in the code. It could have stored the Display .Caption value to a variable and used the variable instead:
This is also better coding, but in short code segments, we all tend to minimize the number of statements.
You can easily expand the Math application by adding Function buttons to it. For example, you can add buttons to calculate common functions, such as Cos, Sin, and Log. The Cos button calculates the cosine of the number on the display. The code behind this button’s Click event is a one-liner:
Display.Caption = Cos(Val(Display.Caption))
It doesn’t require a second operand and it doesn’t keep track of the operation. You can implement all math functions with a single line of code. Of course, you should add some error trapping, and in some cases, you can use data-validation techniques. For example, the SqrO function, which calculates the square root of a number, expects a positive argument. If the number on the display is negative, you can issue a warning:
The LogO function can calculate the logarithms of positive numbers only. Other functions, however, can easily cause overflows. For example, the ExpO function can easily produce very large numbers.
One more feature you could add to the calculator is a limit to ‘the number of ,4 digits on the display. Most calculators can display a limited number of digits. To add this feature to the Math application (if you consider this a ~feature”), use the Len() function to find out the number of digits on the display and ignore any digits entered after the number has reached the maximum number of allowed digits. But don’t do anything about it yet. Let’s see if we can crash this application.
Crashing this application won’t be as easy as crashing the Loan application, but it’s not impossible either. Start multiplying very large numbers (start again with the national debt), and continue multiplying with large numbers. The result will eventually become larger than the largest number Visual Basic can represent and it will bring the program to a halt with an overflow error message.
The error’s number is 6, and its description is “Overflow” (one of the worst, because it can’t be remedied easily). Many errors are caused by conditions that can be remedied from within your code. If a file wasn’t found, for instance, you can prompt the user for another file name. If a field’s value is empty, you can ask the user to enter a different value or use a generic value. But the overflow is always the result of a series of math operations you can’t undo.
How do you prevent this? Data validation isn’t going to help. You just can’t predict the result of an operation without actually performing the operation. And if the operation causes an overflow, you can’t prevent it.
The solution is to trap the error. The overflow will occur no matter what, but you . can trap it, and instead of letting the error message show up and embarrass you, you can handle it from within your code. To handle errors from within your code, you insert a so-called error trap, with the following statement:
On Error Goto ErrorLabel
The ErrorLabel entry is a label in your code. This statement asks Visual Basic to jump to the statement following the label ErrorLabel. (This has nothing to do . with the Label control; it’s a mark in the code that identifies a specific line and it can be any string.)
The structure of a subroutine with an error trap is as follows:
The first statement isn’t executable. It doesn’t cause any action to be taken. It simply tells Visual Basic that if an error occurs, it must execute the lines following the label ErrorHandler. ErrorHandler is not a statement or keyword. It’s a string that identifies the beginning of the error-handling code. Notice the colon at the end of the label. This is how Visual Basic knows that ErrorHandler is a label and not a procedure name.
If no error occurs during execution, the subroutine’s statements are executed as if ‘the error-trapping statements aren’t there. After the subroutine’s statements are executed and the Exit Sub statement is reached, the subroutine exits as usual. If an error occurs during the execution of the statements, however, the program jumps to the statement following the ErrorHandler label. The lines following the ErrorHandler label form an error handler, a subroutine that handles the error. The error handler shown in the example is generic; it displays a message and exits the subroutine.
Writing a Simple Error-Handler
The error handler for the Math application must tell the user what kind of error occurred and then stop the operation. Let’s examine its implementation. The ” overflow error will occur only when the Equals button is pressed, so this is the subroutine you must modify. Open the Code window, and in the button’s Click event, add the underlined statements.
Most of the time, the error handler remains inactive and doesn’t interfere with the operation of the program, If an error occurs, which most likely will be an overflow error, the Presrant’s control is. transferred to he error handler. It doesn’t make any difference with line in the code produces the error-all errors activate the .’ same error handler. Of course, each procedure must have its own er.ror handler.
The error handler displays a message box with the description of the error, prints the stri’l8 “ERROR” on the calculator’s display and sets the ClearDisplay variable to True so that when another Digit button is clicked, a new number will appear on the display. The vbCrU constant inserts a line break between the literal . string and the error’s description.