我正在创建一个程序,它安装一个键盘钩子来捕获所有键并显示一些与它们相关的文本。
但是,我遇到了一个障碍,那就是安装钩子时一些键会改变行为。
我会看到发布一个小而完整的测试程序,但现在我只描述这个问题。
该问题出现在 .NET 4.0 中的 Windows 7 64 位 C# 程序中。我认为这些都不重要。
我的钩子通过安装自己SetWindowsHookEx
,然后处理系统中处理的所有密钥。
如果钩子方法只是简单地返回,或者对键进行最少的处理(我将在一秒钟内发布改变行为的内容),那么键盘将按程序中的预期运行。
但是,如果我ToAscii
从 User32.dll 调用此函数来确定我的键盘 OemTilde 或类似键上的哪个键,那么任何“覆盖下一个键”的键都会停止运行。我不知道这些键的正确名称,但是两种撇号类型,`` 和 ´ , as well as
~ and
¨`,停止工作。
例如,如果我点击~
then N
,它会显示如下:
- 未安装键盘挂钩:ñ
- 安装了键盘挂钩:n(注意没有〜上面)
有谁知道为什么会发生这种情况以及我该如何解决这个问题?
现在我将满足于在其他程序中正确处理键,即使这意味着我将无法在我自己的程序中正确检测到正确的键序列。
更多信息:
如果我将该ToAscii
函数作为钩子方法的一部分调用,则会出现不同的问题。像这样的键¨
被处理两次,即。如果我点击¨
一次,记事本会收到两个¨¨
字符,N
现在点击只会添加N
.
但是,如果我BeginInvoke
在单独的线程上处理按键,在从键盘钩子方法返回后,就会出现第一个问题。
我的程序可能有点特别:
- 我不使用键盘状态(即我传递的“键状态”256 字节数组只是充满了 0)
- 我不关心死键(从某种意义上说,我的程序不会处理它们,我只关心它们,我不希望我的程序使它们对系统的其余部分无用)
因此,我的代码最终看起来如下:
private bool IsDeadKey(uint key)
{
return ((Hook.Interop.MapVirtualKey(key, 2) & 2147483648) == 2147483648);
}
void _Hook_KeyDown_Async(KeyDownEventArgs e)
{
var inBuffer = new byte[2];
char key = '\0';
if (!IsDeadKey((uint)e.KeyCode))
{
int ascii = Hook.Interop.ToAscii((int) e.KeyCode,
e.ScanCode,
_KeyState,
inBuffer,
e.Flags);
if (ascii == 1)
{
key = Char.ToUpper((char) inBuffer[0]);
}
}
BeginInvoke(
new Action<Keys, Boolean, Boolean, Boolean, Char>(ProcessKeyboardEvent),
e.KeyCode, e.Control, e.Shift, e.Alt, key);
}