Title | Make a numeric field |
Keywords | numeric field, KeyPress |
Categories | Controls |
|
|
By Jim Maloy.
Something I've run into repeatedly is requiring an integer-only user input,
where the range of values is just too big to use a dropdown or scrollbar.
The only practical means is a text box, but then you get into the mess of
writing custom validation code. A simple IsNumeric() doesn't work, because
that will allow floating-point, scientific notation, etc.
There's an easier and more direct way to deal with it, by making use of the
text box's KeyPress event. The event passes in (by reference) the ASCII
value of the key that was pressed. If you set the input parameter to zero,
then VB will discard the key press. This lets you make it impossible for
the user to enter anything other than digits in the text field.
|
|
Private Sub Text1_KeyPress(KeyAscii As Integer)
'If a backspace (ASCII-8) or a tab (ASCII-9) was
' entered, allow it unconditionally.
If (KeyAscii = 8) Or (KeyAscii = 9) Then Exit Sub
'Block the keypress if it is not a digit (ASCII-48
' through 57).
If (KeyAscii < 48) Or (KeyAscii > 57) Then KeyAscii = 0
End Sub
|
|
The first line is to ensure that the user can still use the backspace (to
delete or correct the contents) and the tab (to exit the text box).
Technically the tab would work anyway, because the KeyPress event won't fire
if the user tabs out of the text box -- the text box loses the focus before
the KeyPress event can happen. But I put the tab check in there anyway just
to be sure.
This code can be expanded in various ways. For instance, you can limit the
input to a certain number of digits (say, five) by incorporating a check on
the length of the Text1.Text. Note that this check needs to account for the
.SelLength, because the user may highlight the entire current entry and then
type in a new value to replace it.
|
|
Private Sub Text1_KeyPress(KeyAscii As Integer)
Dim nLengthAfterEntry As Integer
'If a backspace (ASCII-8) or a tab (ASCII-9) was
' entered, allow it unconditionally.
If (KeyAscii = 8) Or (KeyAscii = 9) Then Exit Sub
'Determine what the text length will be after the entry
nLengthAfterEntry = Len(Text1.Text) - Text1.SelLength + _
1
'Block the keypress if it is not a digit (ASCII-48
' through 57), or if it will yield a length of over
' five characters.
If (KeyAscii < 48) Or (KeyAscii > 57) Or _
(nLengthAfterEntry > 5) Then _
KeyAscii = 0
End Sub
|
|
Another variation is to enforce an upper range limit, by converting the text
to a numeric variable and then comparing it to the maximum value. This
example enforces an upper limit of 65,535.
|
|
Private Sub Text1_KeyPress(KeyAscii As Integer)
Dim nNewValue as Long
'If a backspace (ASCII-8) or a tab (ASCII-9) was
' entered, allow it unconditionally.
If (KeyAscii = 8) Or (KeyAscii = 9) Then Exit Sub
'Confirm that this is a digit before doing the
' conversion and range check. Block the keypress
' outright if it isn't a digit.
If (KeyAscii >= 48) And (KeyAscii <= 57) Then
nNewValue = CLng(Text1.Text & Chr(KeyAscii))
If (nNewValue > 65535) Then KeyAscii = 0
Else
KeyAscii = 0
End If
End Sub
|
|
The basic technique can be adapted to restrict the user input to valid
hexadecimal values, or specific letters, or whatever other restrictions your
application requires.
[Note that setting the ES_NUMBER extended window style on the TextBox will make it accept only digits, though
that doesn't help with ranges and other formats.
Note also the method described here also doesn't catch the right-click context menu which allows the user to paste
any text into the TextBox. See this example for more information.
Finally note that my book Custom Controls Library shows how to make field controls that do this sort of thing.]
|
|
-->