When you get a WM_CHAR message, keep in mind that wParam may legitimately have values above 128. Don't assume that anything above 127 is an invalid character.
You may want to convert a character to uppercase. Don't use your own algorithm:
if (ch >= 'a' && ch <= 'z')
ch -= 32 ; // WRONG !!!
That's a poor practice even when writing non-Windows C. But don't use the standard C function either:
ch = toupper (ch) ; // WRONG !!!
Both these functions work only for the lower half of the ANSI character set. They will not convert a C0H to an E0H.
Instead, you should use the Windows functions AnsiUpper and AnsiLower. If str is a zero-terminated character string, you can convert it to uppercase using AnsiUpper:
AnsiUpper (pString) ;
or using the AnsiUpperBuff function for character strings that are not zero-terminated:
AnsiUpperBuff (pString, nLength) ;
You can also use AnsiUpper to convert a single character, but some casting is required because the high-order word of the parameter must be zero:
ch = AnsiUpper ((LPSTR) (LONG) (BYTE) ch) ;
If ch is defined as an unsigned character, the initial BYTE cast is not required. Windows also includes AnsiLower and AnsiLowerBuff functions for converting to lowercase.
If you are really serious about writing Windows programs that can be easily converted to foreign languages, you should also investigate the AnsiNext and AnsiPrev functions. These functions facilitate handling of multibyte character sets. The Japanese character set requires more than 256 characters, some of which use 2 bytes. If you use normal C pointer arithmetic to scan a string (perhaps searching for a backslash character in a directory path string), you may think you've found the character when you've really found the second byte of a 2-byte character code. AnsiNext and AnsiPrev take a far pointer to a character string and return a far pointer that has been correctly incremented or decremented past 2-byte character codes.