我可以更改用户的键盘输入吗?

时间:2010-01-14 20:39:33

标签: c# low-level keyboard-layout keyboard-hook

我找到了这个键盘钩子代码,我试图为我的目的略微修改: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这样的应用程序会输入一个输入键,检查它并返回一个不同的字符。我如何在这做同样的事情?

谢谢!

2 个答案:

答案 0 :(得分:5)

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

然后我用SendInput发送了我想要'注入'的新密钥。

所以基本上它的工作原理如下:

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

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

答案 1 :(得分:0)

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

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

但: 1.安装系统范围的挂钩会严重搞砸你的系统(确保你转发你不翻译的钥匙)。 2.请...不要创建另一个键盘记录器