代表当前文化中的一个特殊键盘键

本文关键字:一个 键盘 文化中 | 更新日期: 2023-09-27 18:00:39

场景

我使用现代RawInput技术编写了一个简单的键盘记录程序,注册所需的设备进行事件/数据拦截。

  • 关于原始输入

然后,我基本上使用所有这些Windows API成员定义:

  • 原始输入函数
  • 原始输入结构

问题/问题

我用的是一个非英语键盘和一个非英文的O。S,那么,当我试图解析这个键盘的一个特殊键时,我的问题就开始了,比如被识别为System.Windows.Forms.Keys.OemTilde键的ñ/nie字符,或被识别为System.Windows.Forms.Keys.OemQuestion密钥的ç/Ç字符。

我想让我的键盘记录程序的语言特定(或者至少,对我当前的文化有适当的字符识别,es es),但我被卡住了,因为我缺乏开始正确检索这些字符的知识。

请注意,我的意图是学习如何像O那样以高效/自动化的方式完成这项工作。当我按下ñ字符时,S会对我的键盘进行操作,它会键入ã

Select Case MyKey
    Case Keys.OemTilde
        char = "ñ"c
End Select

这不是我想要的行为,但我可以理解,也许我需要额外的"东西"来为每种keayborad复制这些字符的良好识别/翻译,但我需要什么"东西"?。


研究

我不知道如何继续,因为正如我所说,我不知道这个问题的答案(这就是我问的原因),但我想会涉及到当前键盘布局的知识,然后,我知道我可以用CultureInfo.CurrentCulture.KeyboardLayoutId属性检索当前键盘布局。

我知道文化en-US的键盘布局是1033,而文化es es3082

另外,请注意RAWKEYBOARD结构的MakeCode成员的文档,也许这似乎是我假装做什么的提示,我不知道:

MakeCode

型号:USHORT

按下按键后的扫描代码。键盘超限的扫描代码为keyboard_overrun_MAKE_code。

代表当前文化中的一个特殊键盘键

但实际上这是一项猜测工作这是我找到的代码。

正确的解决方案是ToUnicode WinAPI函数:

[DllImport("user32.dll")]
public static extern int ToUnicode(uint virtualKeyCode, uint scanCode,
    byte[] keyboardState,
    [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
    StringBuilder receivingBuffer,
    int bufferSize, uint flags);

static string GetCharsFromKeys(Keys keys, bool shift, bool altGr)
{
    var buf = new StringBuilder(256);
    var keyboardState = new byte[256];
    if (shift)
        keyboardState[(int) Keys.ShiftKey] = 0xff;
    if (altGr)
    {
        keyboardState[(int) Keys.ControlKey] = 0xff;
        keyboardState[(int) Keys.Menu] = 0xff;
    }
    WinAPI.ToUnicode((uint) keys, 0, keyboardState, buf, 256, 0);
    return buf.ToString();
}

Console.WriteLine(GetCharsFromKeys(Keys.E, false, false));    // prints e
Console.WriteLine(GetCharsFromKeys(Keys.E, true, false));     // prints E
// Assuming British keyboard layout:
Console.WriteLine(GetCharsFromKeys(Keys.E, false, true));     // prints é
Console.WriteLine(GetCharsFromKeys(Keys.E, true, true));      // prints É