将 Shift+1 转换为 ! C# 中的符号
Convert Shift+1 to ! Symbol in C#
我正在做的项目需要记录键盘上的全局击键,具有不同的组合键和按下哪个控制键(左或右)。似乎唯一可能的方法是使用 KeyDown
和 KeyUp
事件而不是 KeyPress
。但是,我还需要记录输入的是哪个字符。
我知道如果我使用 KeyPress
事件,我总是会得到正确的字符,但是对于 KeyDown
和 KeyUp
事件,它只会给出 KeyCode 而不管组合键。解决方案之一是使用 Dictionary
映射 Shift 键,但它对国际环境不友好,因为不同的本地化键盘具有不同的符号。例如,Shift-2
在美国键盘上给出 @
符号,但在英国键盘上给出 "
符号。
请问有没有什么方法可以不用手动映射所有键盘布局,自动转换组合?
一个稍微复杂但离题的问题是,如果用户使用一些软件键映射程序给键不同的输出怎么样?例如,交换 a
和 s
键的定义,当键入 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());
}
}
}
对于德文键盘布局,这产生了 " 而对于美式键盘布局,我得到了 @ 。
我猜你需要的差不多了。
我无法使用第三方键映射器对此进行测试,因此您只需尝试一下即可。
我正在做的项目需要记录键盘上的全局击键,具有不同的组合键和按下哪个控制键(左或右)。似乎唯一可能的方法是使用 KeyDown
和 KeyUp
事件而不是 KeyPress
。但是,我还需要记录输入的是哪个字符。
我知道如果我使用 KeyPress
事件,我总是会得到正确的字符,但是对于 KeyDown
和 KeyUp
事件,它只会给出 KeyCode 而不管组合键。解决方案之一是使用 Dictionary
映射 Shift 键,但它对国际环境不友好,因为不同的本地化键盘具有不同的符号。例如,Shift-2
在美国键盘上给出 @
符号,但在英国键盘上给出 "
符号。
请问有没有什么方法可以不用手动映射所有键盘布局,自动转换组合?
一个稍微复杂但离题的问题是,如果用户使用一些软件键映射程序给键不同的输出怎么样?例如,交换 a
和 s
键的定义,当键入 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());
}
}
}
对于德文键盘布局,这产生了 " 而对于美式键盘布局,我得到了 @ 。 我猜你需要的差不多了。
我无法使用第三方键映射器对此进行测试,因此您只需尝试一下即可。