c# - 如何根据当前键盘布局将虚拟键码转换为字符?

标签 c# winapi

我已经浏览了几个关于这个的早期问题,到目前为止我找到的最佳答案是这样的:

(char) WinAPI.MapVirtualKey((uint) Keys.A, 2)

但是,这在两种情况下不起作用:

  • 它总是返回大写字母。对于 Keys.A 我希望得到字符 a,而对于 Keys.A | Keys.ShiftKey 我希望得到 A;但是,我似乎都得到了 A

  • 它似乎没有考虑键盘布局。例如,对于 Keys.OemMinus,我似乎总是得到字符 -,即使当前键盘布局是德语,我希望此键返回 ß .

正确的解决方案是什么?

最佳答案

正确的解决方案是 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 É

也可以使用 ToUnicodeEx检索不是当前事件键盘布局的字符。签名是相同的,除了一个额外的参数,即输入语言环境 ID,可以使用 LoadKeyboardLayout 检索它。功能。

关于c# - 如何根据当前键盘布局将虚拟键码转换为字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6929275/

相关文章:

c# - 如何在SmtpClient中实现安全连接(No | SSL | STARTTLS)来发送邮件?

c# - 您也可以将 Settings.Settings 文件用于 ASP.Net 站点吗?

c# - 如何在 C# 中获取 ConcurrentDictionary 的即时快照?

C#/XAML winRT 应用导出 PDF

c++ - 从扬声器录制并通过按键结束录制过程,而不是等待指定的时间

c# - 为什么 C# 编译器不能推导出返回值的类型参数?

c# - 我可以只使用 Office Web Apps Server 吗

c++ - 从 CListCtrl 中删除图像

windows - Access Violation '0xc0000005' 的范围到底是什么?

c - 错误 C2275 : illegal use of this type as an expression