从使用Raw Input API检索的按键集合中获取字符串

我正在使用Raw Input API从键盘(实际上是模拟键盘的磁条卡读卡器)获取按键的集合。 这里有几个代码摘录,所以你可以知道我是如何获得密钥的。

[StructLayout(LayoutKind.Sequential)] internal struct RAWKEYBOARD { [MarshalAs(UnmanagedType.U2)] public ushort MakeCode; [MarshalAs(UnmanagedType.U2)] public ushort Flags; [MarshalAs(UnmanagedType.U2)] public ushort Reserved; [MarshalAs(UnmanagedType.U2)] public ushort VKey; [MarshalAs(UnmanagedType.U4)] public uint Message; [MarshalAs(UnmanagedType.U4)] public uint ExtraInformation; } [StructLayout(LayoutKind.Explicit)] internal struct RAWINPUT { [FieldOffset(0)] public RAWINPUTHEADER header; [FieldOffset(16)] public RAWMOUSE mouse; [FieldOffset(16)] public RAWKEYBOARD keyboard; [FieldOffset(16)] public RAWHID hid; } Queue MyKeys = new Queue(); // buffer has the result of a GetRawInputData() call RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT)); MyKeys.Enqueue((char)raw.keyboard.VKey); 

运行代码时,读卡器输出字符串%B40^TEST ,但在MyKeys集合中,我有以下值:

 { 16 '', 53 '5', 16 '', 66 'B', 52 '4', 48 '0', 16 '', 54 '6', 16 '', 84 'T', 16 '', 69 'E', 16 '', 83 'S', 16 '', 84 'T' } 

这些似乎是实际按键( duh! )的集合,而不是它们代表的字符串。 键码16似乎是Shift ,因此在读卡器当前配置的键盘映射中,使用Shift + 5生成%字符,由{16,53}表示。 以下字符,大写B ,是Shift + B或{16,66}。 所以它适用于其他角色。

显然,简单地将这些转换为char (就像我现在正在做的那样)并不是要走的路。 所以,我的问题是:如何将这个按键数组转换为它们代表的String?

做了一些额外的研究之后,我自己找到了答案。 我正在为其他读这篇文章发帖。 以下是一个小型测试应用程序,演示如何将虚拟键集合( ushort键代码)转换为其字符串表示forms。 我正在使用问题中描述的集合作为输入。

 class Program { [DllImport("user32.dll")] static extern int MapVirtualKey(uint uCode, uint uMapType); [DllImport("user32.dll")] private static extern int ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, [Out] StringBuilder lpChar, uint uFlags); static void Main(string[] args) { byte[] keyState = new byte[256]; ushort[] input = { 16, 53, 16, 66, 52, 48, 16, 54, 16, 84, 16, 69, 16, 83, 16, 84 }; StringBuilder output = new StringBuilder(); foreach (ushort vk in input) AppendChar(output, vk, ref keyState); Console.WriteLine(output); Console.ReadKey(true); } private static void AppendChar(StringBuilder output, ushort vKey, ref byte[] keyState) { if (MapVirtualKey(vKey, 2) == 0) { keyState[vKey] = 0x80; } else { StringBuilder chr = new StringBuilder(2); int n = ToAscii(vKey, 0, keyState, chr, 0); if (n > 0) output.Append(chr.ToString(0, n)); keyState = new byte[256]; } } }