使用低级键盘钩子更改键盘字符

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 的文档 - 它说:您不能将此重载方法与值类型一起使用。

以上是关于使用低级键盘钩子更改键盘字符的主要内容,如果未能解决你的问题,请参考以下文章

用于 C# 和 WPF 的高级全局键盘钩子,用于读取键盘楔形卡扫描仪

键盘钩子怎么 使用

c++实现键盘记录仪(键盘钩子)

delphi键盘钩子没效果

C# WinForm键盘钩子

键盘钩子失灵