C # получает перехват вызова клавиатуры в другом потоке - PullRequest
1 голос
/ 29 августа 2011

Я написал какую-то программу. Он перехватывает пользовательский ввод через SetWindowsHookEx. и это работает очень хорошо.

и тогда я хочу узнать, как реализовать WindowsHook в другом потоке, для изучения C #.

но я недавно на C #, поэтому не могу найти ответ.

помоги мне.

спасибо.

1012 * редактировать *

вот мой класс 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 Ответ

3 голосов
/ 29 августа 2011

Причину этого можно найти в документации WinAPI здесь:

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

Этот хук вызывается в контексте потока, который его установил. Вызов осуществляется путем отправки сообщения в поток, который установил крюк. Поэтому нить, на которой установлен крюк, должна иметь Цикл сообщений.

То, что происходит, - то, что ваш недавно созданный поток устанавливает ловушку и немедленно завершает работу, поэтому, когда Windows хочет вызвать вашу процедуру ловушки, отправив сообщение потоку, она не может найти его, потому что она уже вышла.

Если это только для целей обучения, вы можете поместить насос сообщений в ветку, вызвав Application.Run в конце вашего StartInputHook метода. (По крайней мере, я думаю, что это сработает - не пробовал сам.) Для реального кода лучше всего сделать вызов SetWindowsHookEx в основном потоке приложения. Я предполагаю, что вы делаете это уже в том случае, если это работает, и насос сообщений приложения позаботится об этом за вас.

Честно говоря, если это только для изучения C #, SetWindowsHookEx может быть слишком продвинутым. Для его использования необходимо знать, как много вещей работает под одеялом.

...