使用低级键盘钩子更改键盘字符
Posted
技术标签:
【中文标题】使用低级键盘钩子更改键盘字符【英文标题】:Using a low-level keyboard hook to change keyboard characters 【发布时间】:2011-01-04 23:40:23 【问题描述】:我正在创建自定义键盘布局。作为开始步骤,我想让用户按下一个键,让我的键盘钩子拦截它,并输出我选择的不同键。
我找到了这个键盘钩子代码,我正在尝试对其进行稍微修改以用于我的目的: http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
我已经把相关方法改成这样了:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
KBDLLHOOKSTRUCT replacementKey = new KBDLLHOOKSTRUCT();
Marshal.PtrToStructure(lParam, replacementKey);
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, true);
return CallNextHookEx(_hookID, nCode, wParam, lParam);
我希望它声明一个新的 KBD 结构对象,将键盘挂钩提供的 KBD 结构复制到其中,修改我的对象的 vkCode 以使用不同的字符,然后用我修改后的版本覆盖提供的对象。这应该希望所有内容都保持不变,除了它写了一个不同的字符。
很遗憾,它不起作用。键入了原始键盘字符。 Visual Studio 输出窗格也会出现A first chance exception of type 'System.ArgumentException' occurred in MirrorBoard.exe
错误。
我可以在这里做什么来拦截键盘钩子并将其替换为我选择的字符?
谢谢!
【问题讨论】:
【参考方案1】:Marshal.PtrToStructure
的第二个参数必须是类而不是结构,KBDLLHOOKSTRUCT
可能是结构。
您应该像这样使用它:
KBDLLHOOKSTRUCT replacementKey = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, false);
【讨论】:
Visual Studio 告诉我它是Marshal.PtrToStructure(IntPtr ptr, object structure);
...这与您所说的是否相符?它不会抛出错误或任何东西,编译得很好。
它编译得很好,但在运行时会抛出一个ArgumentException
。
如果不将 Ptr 保存到结构中,为什么要称为 PtrToStructure?但是如果我确实需要更改它,我应该在这里做什么?如果我不能使用 KBD 结构来保存指向 KBD 结构的指针,我该如何修改它?
PtrToStructure
无法将 ptr 保存到结构中,因为它已装箱(即它是副本)。我在答案中添加了正确的解决方案。
您还可以查看msdn.microsoft.com/en-us/library/30ex8z62.aspx 的文档 - 它说:您不能将此重载方法与值类型一起使用。以上是关于使用低级键盘钩子更改键盘字符的主要内容,如果未能解决你的问题,请参考以下文章