|[ Team LiB ]|
Recipe 11.3 Classify Keypresses in a Language-Independent Manner
You need to be able to classify a keypress as a character, a digit, or neither. You also need to know if a character is uppercase or lowercase. You know you can write code to handle this, but if you do that, you're limiting yourself to a single national language, since languages classify their characters differently. Since Windows knows about various character sets, is there some way you can use Windows to do this work for you?
You could write VBA code to classify characters, but it wouldn't be language-independent. For example, the ANSI character 65 is an uppercase character in the standard multinational character set, but it may be different in another character set. If you want your applications to work in various languages, you must not assume specific character ranges. The Windows API includes a number of functions you can call to categorize characters based on their ANSI values. The isCharAlpha and isCharAlphaNumeric functions both are faster than the built-in VBA functions and are able to deal with international issues. Luckily, an ANSI value is exactly what the KeyPress event procedure in Access sends you, so you can use these functions from within KeyPress event procedures that you write.
In addition to the necessary function declarations, the sample database 11-03.MDB includes a demonstration form showing all the ANSI characters and their classifications. Load and run frmCharClasses from 11-03.MDB, and you'll see a display like that in Figure 11-3. By scrolling through the form, you'll be able to see all 255 ANSI characters and their classifications.
To use this functionality in your own applications, follow these steps:
For example, imagine that you need to limit the number of characters typed into a text box, and the number of allowable characters isn't known until runtime. In addition, you want to allow only alphabetic or numeric values, but that isn't known until runtime either. Although you could programmatically control the input masks, creating a new one each time conditions change, it is simpler to handle this problem using the KeyPress event and some code that checks the state of the current keypress. The sample form, frmInputTest (Figure 11-4), shows a simple test form. The text box labeled "Enter some characters" allows you to enter up to as many characters as shown in the "Maximum number of characters" text box, and you can enter only characters whose type you've chosen in the character type option group.
The code attached to txtCharTest's KeyPress event looks like this:
Sub txtCharTest_KeyPress (KeyAscii As Integer) ' Always allow a backspace. If KeyAscii = vbKeyBack Then Exit Sub ' If txtChars is non-null and greater than 0, and txtCharTest ' is non-null and has too many characters, set KeyAscii to 0. If Not IsNull(Me.txtChars) Then If Me.txtChars > 0 Then If Not IsNull(Me.txtCharTest.Text) Then If Len(Me.txtCharTest.Text) >= Me.txtChars Then KeyAscii = 0 End If End If End If End If ' In any case, if the keypress isn't the correct type, ' set KeyAscii to 0. If Me.grpCharType = 1 Then If (acb_apiIsCharAlpha(KeyAscii) = 0) Then KeyAscii = 0 Else If (acbIsCharNumeric(KeyAscii) = 0) Then KeyAscii = 0 End If End Sub
In the KeyPress event, Access sends you the parameter KeyAscii, which contains the ANSI value of the key that was just pressed. To tell Access to disregard this key, modify its value to 0 during the event procedure. In this case, if there's no room left in the field (based on the number in Me.txtChars) or if the character is not the right type (based on calls to acb_apiIsCharAlpha and acbIsCharNumeric), the code sets the value of KeyAscii to 0, causing Access to disregard the keypress. Play with the sample form, changing the values, to see how the code works.
Windows internally maintains information about the currently selected language and character set. For each language, certain characters are treated as uppercase and others aren't. Some characters in the character set represent alphabetic characters and others don't. It would be impractical to maintain this information for each language your application might use. Luckily, you don't have to manage this. The Access UCase and LCase functions handle case conversions for you, but Access doesn't include case-testing functions. That's the role of the functions introduced in this solution: they allow you to test the classification of characters, no matter what the language. Attempting to perform this task in VBA will cause you trouble if you plan on working internationally.
You may not need these routines often, but when you do, the API versions are both faster and more reliable than handwritten code would be. Don't count on specific ANSI values to be certain characters, uppercase or lowercase, because these values change from version to version of internationalized Windows.
|[ Team LiB ]|