C#接收键盘钩子回调在不同的线程中

时间:2011-08-29 07:18:46

标签: c# multithreading keyboard hook

我写了一些程序。它通过SetWindowsHookEx挂钩用户输入。而且效果很好。

然后我想知道如何在不同的线程中实现WindowsHook,以便学习C#。

但我刚接触C#,所以我找不到答案。

帮帮我。

感谢。

修改

这是我的InputHook类。有些代码是缩写的。

public class InputHooker
{

    public delegate IntPtr inputHookedDelegate(int nCode, IntPtr wParam, IntPtr lParam);
    public inputHookedDelegate keyHookHandler;


    public InputHooker()
    {
        keyHookHandler = onKeyHooked;
    }

    public void StartInputHook()
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            curKeyHookID = SetWindowsHookEx(WH_KEYBOARD_LL, keyHookHandler, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private IntPtr onKeyHooked(int nCode, IntPtr wParam, IntPtr lParam)
    {
        return CallNextHookEx(curKeyHookID, nCode, wParam, lParam);
    }

}

我试着跟随代码;

        MyInputHooker = new InputHooker();
        Thread myInputHookThread = new Thread(new ThreadStart(MyInputHooker.StartInputHook));
        myInputHookThread.Name = "UOCInputHookThread";
        myInputHookThread.Priority = ThreadPriority.Normal;
        myInputHookThread.Start();

但它不起作用。 (SetWindowsHookEx是成功的,但onKeyHooked在键盘按下时没有被调用。)相反,后续代码运行良好。

        MyInputHooker = new InputHooker();
        MyInputHooker.StartInputHook();

1 个答案:

答案 0 :(得分:3)

失败的原因可以在WinAPI文档中找到:

http://msdn.microsoft.com/en-us/library/ms644985(v=vs.85).aspx

  

在安装它的线程的上下文中调用此钩子。   通过向安装了该安装的线程发送消息来进行调用   钩。因此,安装钩子的线程必须有一个   消息循环。

正在发生的事情是你新创建的线程正在设置钩子并立即退出,所以当Windows想要通过向线程发送消息来调用你的钩子程序时,它找不到它,因为它已经退出。 / p>

如果这只是为了学习目的,您可以通过在Application.Run方法结束时调用StartInputHook在帖子中添加消息泵。 (至少我认为这样可行 - 没有亲自尝试过。)对于真正的代码,最好的办法是在主应用程序线程中调用SetWindowsHookEx。我假设你已经在它工作的情况下这样做了,应用程序的消息泵正在为你处理这个问题。

老实说,如果这只是为了学习C#,SetWindowsHookEx可能有点过于先进。使用它需要了解许多事情如何在幕后工作。