将 Shift+1 转换为 ! C# 中的符号

Convert Shift+1 to ! Symbol in C#

我正在做的项目需要记录键盘上的全局击键,具有不同的组合键和按下哪个控制键(左或右)。似乎唯一可能的方法是使用 KeyDownKeyUp 事件而不是 KeyPress。但是,我还需要记录输入的是哪个字符。

我知道如果我使用 KeyPress 事件,我总是会得到正确的字符,但是对于 KeyDownKeyUp 事件,它只会给出 KeyCode 而不管组合键。解决方案之一是使用 Dictionary 映射 Shift 键,但它对国际环境不友好,因为不同的本地化键盘具有不同的符号。例如,Shift-2 在美国键盘上给出 @ 符号,但在英国键盘上给出 " 符号。

请问有没有什么方法可以不用手动映射所有键盘布局,自动转换组合?

一个稍微复杂但离题的问题是,如果用户使用一些软件键映射程序给键不同的输出怎么样?例如,交换 as 键的定义,当键入 a 时它输出 s,反之亦然。全局钩子会发生什么?我没有装过这种软件所以没法测试,有没有人有操作经验?

有趣的问题。我设法使用此处的答案获得了正确的偏移值: Keyboard Mapping in .NET

using System.Runtime.InteropServices;
public static class User32Interop
{
    public static char ToAscii(Keys key, Keys modifiers)
    {
        var outputBuilder = new StringBuilder(2);
        int result = ToAscii((uint)key, 0, GetKeyState(modifiers),
            outputBuilder, 0);
        if (result == 1)
            return outputBuilder[0];
        else
            throw new Exception("Invalid key");
    }

    private const byte HighBit = 0x80;
    private static byte[] GetKeyState(Keys modifiers)
    {
        var keyState = new byte[256];
        foreach (Keys key in Enum.GetValues(typeof(Keys)))
        {
            if ((modifiers & key) == key)
            {
                try
                {
                    keyState[(int) key] = HighBit;
                }
                catch { }
            }
        }
        return keyState;
    }

    [DllImport("user32.dll")]
    private static extern int ToAscii(uint uVirtKey, uint uScanCode,
        byte[] lpKeyState,
        [Out] StringBuilder lpChar,
        uint uFlags);
}

然后在 KeyDown 事件中像这样使用它:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode != Keys.ShiftKey)
    {
        if (e.Modifiers.ToString() == "Shift")
        {
            var c = User32Interop.ToAscii(e.KeyCode, Keys.ShiftKey);
            MessageBox.Show(c.ToString());
        }
    }
}

对于德文键盘布局,这产生了 " 而对于美式键盘布局,我得到了 @ 。 我猜你需要的差不多了。

我无法使用第三方键映射器对此进行测试,因此您只需尝试一下即可。