Перехватчик нажатия клавиши С# при сворачивании

Хорошо, поэтому я пытаюсь написать программу, которая будет отслеживать нажатия клавиш во время игры, чтобы я мог позже проанализировать данные, чтобы помочь мне улучшить свою игру. Я пытался реализовать Global Hotkey Hook, используя RegisterHotKey user32.dll. но это полностью фиксирует нажатие клавиши, и игра больше не получает нажатие клавиши. Я не знаю, куда идти отсюда, и любые указатели будут высоко оценены. Вот дополнительная информация:

  • Я использую С#
  • .NET 4
  • Использование Visual Studio 2010
  • Я НЕ пытаюсь сделать что-то незаконное или против игровых TOS.

person Michael    schedule 25.04.2014    source источник
comment
Поиск C# Keyboard Hook должен найти множество примеров. Мне нравится пример Стивена Туба   -  person Damien_The_Unbeliever    schedule 25.04.2014


Ответы (1)


Это взято из блога Stephan Toubs еще в 2006 году:

http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class InterceptKeys
{
   private const int WH_KEYBOARD_LL = 13;
   private const int WM_KEYDOWN = 0x0100;
   private static LowLevelKeyboardProc _proc = HookCallback;
   private static IntPtr _hookID = IntPtr.Zero;

   public static void Main()
   {
       _hookID = SetHook(_proc);
       Application.Run();
       UnhookWindowsHookEx(_hookID);
   }

   private static IntPtr SetHook(LowLevelKeyboardProc proc)
   {
       using (Process curProcess = Process.GetCurrentProcess())
       using (ProcessModule curModule = curProcess.MainModule)
       {
        return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            GetModuleHandle(curModule.ModuleName), 0);
       }
    }

    private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
   {
       if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
       {
           int vkCode = Marshal.ReadInt32(lParam);
           Console.WriteLine((Keys)vkCode);
       }

       return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   private static extern IntPtr SetWindowsHookEx(int idHook,
   LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   [return: MarshalAs(UnmanagedType.Bool)]
   private static extern bool  UnhookWindowsHookEx(IntPtr hhk);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
    IntPtr wParam, IntPtr lParam);

   [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   private static extern IntPtr GetModuleHandle(string lpModuleName);
}
person Yuval Itzchakov    schedule 25.04.2014
comment
используя свои навыки работы с Google, я наткнулся на это сам, но никогда не думал попробовать, потому что я думал, что это больше похоже на то, что я уже пробовал, чем на то, что это на самом деле. Посмотрю и попробую! Я дам вам знать, как это происходит - person Michael; 25.04.2014
comment
Отлично работает для меня. Я также совсем недавно возился с перехватами клавиатуры по тем же причинам и получил похожий пример, в котором говорилось, что у вас должна быть форма окна, чтобы иметь возможность получать эти нажатия клавиш, но, как оказалось, этот пример демонстрирует, что вы действительно может скомпилировать это как консольное приложение, вам просто нужно добавить ссылку на System.Windows.Forms и Application.Run();, чтобы запустить цикл сообщений. Поэтому никакой явной формы не требуется. - person DrCopyPaste; 25.04.2014
comment
Хорошо, поэтому я должен с грустью признать, что, поскольку моя единственная форма обучения программированию была самоучкой, я очень мало понимаю в этом с первого взгляда .... Я перешел по ссылке и сделал, как было сказано, и у меня есть 2 проблемы. ... Если я сделаю это как консольное приложение (как написано на веб-сайте), у него будет ТОННА ошибок компиляции. Если я делаю это как WinForm, он компилируется после добавления Using System; наверх, но он ничего не делает (что, как я понимаю, вероятно, не произойдет, пока я не добавлю что-то еще. Я просто не знаю, что это еще должно быть... какие-нибудь советы? Еще раз спасибо! :) - person Michael; 25.04.2014
comment
@Michael для этих ошибок, вероятно, было бы лучше просто начать новый вопрос там, потому что я смог просто скопировать и вставить код, добавить ссылку, и это было сделано (хотя и с использованием vs 2012), но, возможно, эти ошибки достаточно тривиальны, чтобы разобраться в комментариях? Вам действительно нужно сделать его консольным приложением, добавили ли вы ссылку на System.Windows.Forms после этого (просто ссылка не делает его проектом Windows Forms)? - person DrCopyPaste; 25.04.2014
comment
Я отменяю свой предыдущий комментарий ... Я понял это ... Я просто установил его как обычный старый класс и добавил ссылку на System.Windows.Forms, как указано DrCopyPaste, теперь он работает! - person Michael; 25.04.2014
comment
@DrCopyPaste еще раз спасибо вам обоим! еще один быстрый вопрос, хотя я задам его отдельно как новый вопрос, если вы думаете, что это будет проще, но с чего мне начать, если я хочу (вместо вывода на консоль) сделать что-то еще. или, лучше сказать, как лучше всего использовать этот класс с winforms? извините, если это супернубский вопрос... - person Michael; 25.04.2014
comment
@Michael должен быть таким же простым, как switch outputtype in project's properties to Windows Application, add a form to the project, и запускать эту форму как параметр Application.Run(new YourFormName()) Или вы начинаете новый проект как приложение Windows Forms, добавляете тот же код и включаете форму в Application.Run() - person DrCopyPaste; 25.04.2014
comment
@DrCopyPaste Итак, последний вопрос ... У меня есть форма Windows для загрузки, но, как я уже сказал, я не на 100% понимаю каждую строку в примере, поэтому я не знаю, что изменить, чтобы он вернулся ко мне значение, которое я могу использовать, можете ли вы указать мне правильное направление еще раз! ;D Еще раз спасибо! - person Michael; 25.04.2014
comment
давайте продолжим это обсуждение в чате - person DrCopyPaste; 25.04.2014