我正在创建一个程序,它安装键盘挂钩来捕获所有键并显示与它们相关的一些文本。键盘挂钩改变键的行为
但是,我遇到了一个问题,那就是当安装钩子时,一些键会改变行为。
我会看到发布一个小的,但完整的测试程序,但现在我只会描述这个问题。
该问题在Windows 7 64位,.NET 4.0中是一个C#程序。我认为这些都不重要。
我的挂钩通过SetWindowsHookEx
安装,然后处理系统中处理的所有密钥。
如果钩子方法返回简单或对键进行最小限度的处理(我会发布什么会在一秒内改变行为),键盘按照程序中的预期运行。但是,如果我从User32.dll中调用此函数ToAscii
来确定我的键盘OemTilde或类似键上的哪个键,那么任何“覆盖下一个键”的键都将停止运行。我不知道这些键的正确名称,但是两个撇号类型,和', as well as
〜and
',停止运作。
例如,如果我打~
然后N
,它显示如下:
- 没有键盘钩子安装:安装ñ
- 随着键盘钩子:N(注意没有〜上文)
有谁知道为什么会发生这种情况,我该如何解决这个问题?
现在我会解决在其他程序中正确处理密钥的问题,即使这意味着我无法在自己的程序中正确检测到正确的密钥序列。
一些更多信息:
如果我所说的ToAscii
函数作为钩方法的一部分,则发生另一个问题。诸如¨
之类的键被处理两次,即,如果我点击¨
一次,记事本收到两个¨¨
字符,并且打N
现在只是增加了N
。
但是,如果我使用BeginInvoke
来处理单独的线程上的键,从键盘挂接方法返回后,会出现第一个问题。
我的程序可能是有点在那个特殊:
- 我不使用键盘的状态(即。我传过来的“Key State”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);
}
删除对'ToAscii'的调用会很好,但由于我的应用程序的全部重点是*显示*您按哪些键,并且国际键盘上的许多键返回导致不同键的虚拟键码,所以我需要*一些*获取这些密钥的方式。也许我可以缓存所有这些,尽管这可能是可能的... – 2010-08-23 15:43:32
@Lasse V. Karlsen:我没有深入研究,但也许你可以通过使用[MapVirtualKey](http:// msdn.microsoft.com/en-us/library/ms646306.aspx)函数? – 2010-08-23 15:47:37
或者你可以在*调用'ToAscii' /'ToUnicode'之前检查是否按下了死键? – 2010-08-23 15:55:56