7.8 Fill a List Box with a List of Files

11.3 Classify Keypresses in a Language-Independent Manner

11.3.1 Problem

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?

11.3.2 Solution

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.

Figure 11-3. frmCharClasses shows all the ANSI characters and their classifications

figs/acb_1103.gif

To use this functionality in your own applications, follow these steps:

  1. Import the module basClassifyChars from 11-03.MDB into your application.

  2. To classify an ANSI value, call one or more of the functions in Table 11-2. Each of these functions takes as its parameter a value between 1 and 255. Each function returns a nonzero value if the character code you passed is a member of the function's tested group, or 0 if it's not. (As you can see from Table 11-2, some of the functions come directly from the Windows API and others return values based on those functions.) These functions will return correct values no matter which language version of Windows is running.

     

    Table 11-2. The character classification functions in basClassifyChars

    Function

    API?

    Inclusion class

    acb_apiIsCharAlphaNumeric

    Yes

    Language-defined alphabetic or numeric characters

    acb_apiIsCharAlpha

    Yes

    Language-defined alphabetic characters

    acbIsCharNumeric

    No

    Alphanumeric, but not alphabetic

    acbIsSymbol

    No

    Not alphanumeric

    acb_apiIsCharUpper

    Yes

    Language-defined uppercase characters

    acb_apiIsCharLower

    Yes

    Language-defined lowercase characters

     

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.

Figure 11-4. frmInputTest uses character classifications to disallow keypresses

figs/acb_1104.gif

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 a parameter, KeyAscii, that 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.

11.3.3 Discussion

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.



Access Cookbook
Access Data Analysis Cookbook (Cookbooks)
ISBN: 0596101228
EAN: 2147483647
Year: 2005
Pages: 174

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net