You are here:
Visual
Basic > VB6
(Beginners Tutorial)
Previous Page
| Table of Contents | Next
Page
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 variables
Dim saveText As String
Dim saveSelStart As Long
Private Sub Text1_GotFocus()
' Save values when the control gets the focus.
saveText = Text1.Text
saveSelStart = Text1.SelStart
End Sub
Private Sub Text1_Change()
' Avoid nested calls.
Static nestedCall As Boolean
If nestedCall Then Exit Sub
' Test the control's value here.
If IsNumeric(Text1.Text) Then
' If value is OK, save values.
saveText = Text1.Text
saveSelStart = Text1.SelStart
Else
' Prepare to handle a nested call.
nestedCall = True
Text1.Text = saveText
nestedCall = False
Text1.SelStart = saveSelStart
End If
End Sub
Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
saveSelStart = Text1.SelStart
End Sub
Private Sub Text1_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
saveSelStart = Text1.SelStart
End Sub
Private Sub Text1_MouseMove(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
saveSelStart = Text1.SelStart
End 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,,,123
345-
$1234 ' What if it isn't a currency field?
2.4E10 ' What if I don't want to support scientific notation?
To cope with this issue, I have prepared an alternative function, which you
can modify for your particular purposes. (For instance, you can add support for
a currency symbol or the comma as the decimal separator.) Note that this function
always returns True when it's passed a null string, so you might need to perform
additional tests if the user isn't allowed to leave the field blank:
Function CheckNumeric(text As String, DecValue As Boolean) As Boolean
Dim i As Integer
For 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 Function
Case "."
' Exit if decimal values not allowed.
If Not DecValue Then Exit Function
' Only one decimal separator is allowed.
If InStr(text, ".") < i Then Exit Function
Case Else
' Reject all other characters.
Exit Function
End Select
Next
CheckNumeric = True
End 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 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.
More on VB6 TextBox Controls
See Also
Previous Page | Table
of Contents | Next Page
|