8

我找到了这个键盘钩子代码,我试图为我的目的稍微修改:http: //blogs.msdn.com/toub/archive/2006/05/03/589423.aspx

作为一个概述,我想让用户按下一个键,比如“E”,并让键盘返回一个不同的字符“Z”,以显示任何应用程序的焦点。

我现在更改的相关方法如下所示:

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            //The truely typed character:
            int vkCode = Marshal.ReadInt32(lParam);
            Console.WriteLine((Keys)vkCode);

            KBDLLHOOKSTRUCT replacementKey = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
            replacementKey.vkCode = 90; // char 'Z'
            Marshal.StructureToPtr(replacementKey, lParam, false);

            //Now changed to my set character
            vkCode = Marshal.ReadInt32(lParam);
            Console.WriteLine((Keys)vkCode);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

控制台正确地将其输出为:

E
Z
T
Z
G
Z
etc.

但是,焦点应用程序仍然键入“E”而不是“Z”。为什么?我将挂钩的键盘输入更改为包含“Z”而不是“E”,并且控制台行显示它已正确更改!

据我了解,调用return CallNextHookEx(_hookID, nCode, wParam, lParam);是将“立即打印”命令发送到打开的应用程序的原因。这不是它的工作原理吗?有什么东西阻止我输入我想要的字符吗?我知道像 AutoHotkey 这样的应用程序需要一个输入键,检查它,然后返回一个不同的字符。我如何在这里做同样的事情?

谢谢!

4

2 回答 2

5

我以前做过,但有点不同。
我没有尝试更改发送到的参数CallNextHookEx,而是“吞下”了按键(您可以通过从钩子过程返回一个非零值来做到这一点,以防止调用后续过程)。

然后我使用SendInput发送我想“注入”的新密钥。

所以基本上它是这样工作的:

  • 钩子程序识别目标键被按下
  • 使用新键调用 SendInput
  • 从钩子过程中返回 1 以忽略原始密钥

小心循环重定向,即“a”重定向到“b”重定向到“a”,它很容易爆炸;)

于 2010-01-14T21:06:00.030 回答
0

您很可能安装了“线程范围”而不是“系统范围”的挂钩,这意味着密钥转换只会发生在安装挂钩的线程上。

为了在“系统范围内”安装它,您将需要两部分:一个具有“挂钩提供程序”的 dll 和一个管理它的 exe。这是一个很好的教程 http://www.codeproject.com/KB/system/hooksys.aspx 这里是一个例子: http: //www.codeguru.com/cpp/com-tech/shell/article.php/c4509 /

但是: 1. 安装系统范围的钩子可能会严重破坏您的系统(确保转发您不翻译的密钥)。2. 请...不要创建另一个键盘记录器

于 2010-01-14T21:05:07.920 回答