by Michael S. Kaplan, published on 2006/03/23 04:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/03/23/558674.aspx
(Be sure to grab the KeysEx enumeration from Part #1 of this series; I'll tell you where it needs to go!)
We will start in the most elemental place, with the Scan Codes.
These are the numbers that the keyboard hardware sends to the computer, the ones that are mapped to Virtual Keys, and sometimes even to characters.
We will need the following functions from the Win32 API to start off.
Basically, here is our algorithm:
Nice and simple, right? Ok, here goes:
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace KeyboardLayouts {
class Class1 {
// You'll want to insert that enumeration here!
internal const uint KLF_NOTELLSHELL = 0x00000080;
[DllImport("user32.dll", CharSet=CharSet.Unicode, EntryPoint="MapVirtualKeyExW", ExactSpelling=true)]
internal static extern uint MapVirtualKeyEx(
uint uCode,
uint uMapType,
IntPtr dwhkl);
[DllImport("user32.dll", CharSet=CharSet.Unicode, EntryPoint="LoadKeyboardLayoutW", ExactSpelling=true)]
internal static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);
[DllImport("user32.dll", ExactSpelling=true)]
internal static extern bool UnloadKeyboardLayout(IntPtr hkl);
[DllImport("user32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
internal static extern int ToUnicodeEx(
uint wVirtKey,
uint wScanCode,
KeysEx[] lpKeyState,
StringBuilder pwszBuff,
int cchBuff,
uint wFlags,
IntPtr dwhkl);
[STAThread]
static void Main(string[] args) {
IntPtr hkl = LoadKeyboardLayout(args[0], KLF_NOTELLSHELL);
if(hkl == IntPtr.Zero) {
Console.WriteLine("Sorry, that keyboard does not seem to be valid.");
}
else {
KeysEx[] lpKeyState = new KeysEx[256];
for(uint sc = 0x01; sc <= 0x7f; sc++) {
uint vk = MapVirtualKeyEx(sc, 1, hkl);
if(vk != 0) {
StringBuilder sb = new StringBuilder(10);
int rc = ToUnicodeEx(vk, sc, lpKeyState, sb, sb.Capacity, 0, hkl);
if(rc == 1) {
Console.WriteLine("{0:x2}\t{1:x4}\t{2:x2}\t{3}\t{4}",
sc, ((ushort)sb.ToString()[0]), vk, ((KeysEx)vk).ToString(), ((Keys)vk).ToString());
}
}
}
UnloadKeyboardLayout(hkl);
}
}
}
}
And here is what it printed out for me:
C:\Sample\KeyboardLayouts\bin\Debug>KeyboardLayouts.exe 0000409
01 001b 1b VK_ESCAPE Escape
02 0031 31 VK_1 D1
03 0032 32 VK_2 D2
04 0033 33 VK_3 D3
05 0034 34 VK_4 D4
06 0035 35 VK_5 D5
07 0036 36 VK_6 D6
08 0037 37 VK_7 D7
09 0038 38 VK_8 D8
0a 0039 39 VK_9 D9
0b 0030 30 VK_0 D0
0c 002d bd VK_OEM_MINUS OemMinus
0d 003d bb VK_OEM_PLUS Oemplus
0e 0008 08 VK_BACK Back
0f 0009 09 VK_TAB Tab
10 0071 51 VK_Q Q
11 0077 57 VK_W W
12 0065 45 VK_E E
13 0072 52 VK_R R
14 0074 54 VK_T T
15 0079 59 VK_Y Y
16 0075 55 VK_U U
17 0069 49 VK_I I
18 006f 4f VK_O O
19 0070 50 VK_P P
1a 005b db VK_OEM_4 OemOpenBrackets
1b 005d dd VK_OEM_6 OemCloseBrackets
1c 000d 0d VK_RETURN Enter
1e 0061 41 VK_A A
1f 0073 53 VK_S S
20 0064 44 VK_D D
21 0066 46 VK_F F
22 0067 47 VK_G G
23 0068 48 VK_H H
24 006a 4a VK_J J
25 006b 4b VK_K K
26 006c 4c VK_L L
27 003b ba VK_OEM_1 OemSemicolon
28 0027 de VK_OEM_7 OemQuotes
29 0060 c0 VK_OEM_3 Oemtilde
2b 005c dc VK_OEM_5 OemPipe
2c 007a 5a VK_Z Z
2d 0078 58 VK_X X
2e 0063 43 VK_C C
2f 0076 56 VK_V V
30 0062 42 VK_B B
31 006e 4e VK_N N
32 006d 4d VK_M M
33 002c bc VK_OEM_COMMA Oemcomma
34 002e be VK_OEM_PERIOD OemPeriod
35 002f bf VK_OEM_2 OemQuestion
37 002a 6a VK_MULTIPLY Multiply
39 0020 20 VK_SPACE Space
4a 002d 6d VK_SUBTRACT Subtract
4e 002b 6b VK_ADD Add
56 005c e2 VK_OEM_102 OemBackslash
7c 0009 09 VK_TAB Tab
Ok, there is obviously a lot missing here, for example:
But that is what future posts are for, right? :-)
Stay tuned!
This post brought to you by "1" (U+0031, DIGIT ONE)
A Unicode character that is in the very small family of those whose VK value is the same as it's code point!
# geoff.appleby on 23 Mar 2006 4:40 AM:
# Michael S. Kaplan on 23 Mar 2006 4:46 AM:
referenced by
2008/02/11 Who assigns the VK_OEM_* values in keyboards?
2006/04/22 Getting all you can out of a keyboard layout, Part #10a
2006/04/13 Getting all you can out of a keyboard layout, Part #9b
2006/04/12 Getting all you can out of a keyboard layout, Part #9a
2006/04/10 Getting all you can out of a keyboard layout, Part #8
2006/04/06 Getting all you can out of a keyboard layout, Part #7
2006/03/31 Getting all you can out of a keyboard layout, Part #6
2006/03/28 Getting all you can out of a keyboard layout, Part #5
2006/03/27 Getting all you can out of a keyboard layout, Part #4
2006/03/24 Getting all you can out of a keyboard layout, Part #3
2006/03/24 Getting all you can out of a keyboard layout, Part #2