我会努力更好地解释我的意思,我也会努力让这个问题不受语言的影响,尽管如果有一种方法可以在C#中做我想做的事情,而不必引用任何东西,那就太好了。无论如何
我正在处理键盘输入,并将其转换为字符串。一切都好。我得到了Shift键和CapsLock键的状态,并对其进行EXOR运算,这样我就可以计算出结果字符串的大小写。
bool shift = KeyDown(SHIFT_KEY)
bool capslock = KeyToggled(CAPSLOCK)
bool stringCasing = shift ^ capslock //if both are true/false, the string will be lowercase. Otherwise uppercase.
foreach Key k in [list of keys passed as parameter]
char c = (char)k
if stringCasing
c = Char.ToUpper(c)
else
c = Char.ToLower(c)
end foreach
现在没有问题。如果用户在按住shift或切换capslock时键入"a",它将变为"a"。
但是,如果用户决定键入"!",即"1"加上shift,我只得到一个1,因为大写的"1"仍然是"1"。
在问这个问题之前,我在网上看了一下,但我得到的只是"自己绘制钥匙图"。这真的是唯一的答案吗?此外,如果我映射了键,然后一个具有不同键盘布局的用户尝试使用我的应用程序,会发生什么?提前谢谢。
这可以通过Win32 ToAscii
函数(MSDN参考)来实现。我不知道有任何.NET框架方法包装这些函数,所以可能有必要使用P/Invoke。
与ToAscii
一起,您可能需要对VkKeyScan
的引用来将密钥转换为虚拟密钥代码。此密钥代码用作ToAscii
的参数。这些方法的简单P/Invoke声明如下:
[DllImport("user32.dll")]
static extern short VkKeyScan(char c);
[DllImport("user32.dll", SetLastError=true)]
static extern int ToAscii(
uint uVirtKey,
uint uScanCode,
byte[] lpKeyState,
out uint lpChar,
uint flags
);
注意,ToAscii
的第三个参数是引用每个键的状态的256元素数组;值0x80(高位设置)表示密钥被设置。设置元素0x10(Shift的虚拟键代码)模拟按下Shift。
然后,我们可以定义一个助手方法,该方法将表示键的字符作为参数,并在按下Shift时输出该键:
public static char GetModifiedKey(char c)
{
short vkKeyScanResult = VkKeyScan(c);
// a result of -1 indicates no key translates to input character
if (vkKeyScanResult == -1)
throw new ArgumentException("No key mapping for " + c);
// vkKeyScanResult & 0xff is the base key, without any modifiers
uint code = (uint)vkKeyScanResult & 0xff;
// set shift key pressed
byte[] b = new byte[256];
b[0x10] = 0x80;
uint r;
// return value of 1 expected (1 character copied to r)
if (1 != ToAscii(code, code, b, out r, 0))
throw new ApplicationException("Could not translate modified state");
return (char)r;
}
调用此方法将返回与Shift相关联的字符+输入字符的基本键(其中基本键是为输入字符而按下的物理键,例如<1>是!
的基本键)。例如,对于US键盘,GetModifiedKey('7')
和GetModifiedKey('&')
都将返回"&"。返回值将使用加载的键盘布局;例如,在德语键盘上(其中Shift+7为/
),该方法将返回/
。