Globalhook



  • Guten Tag,

    ich arbeite mit WPF und bräuchte einen Globalhook, der auch in einem Spiel Tasten abfängt, bzw. mitbekommt, welche Taste gedrückt wurde. Das Programm muss also nicht im Fokus sein, damit es weiß, welche Taste gedrückt wurde. Ich habe mich auch schon erkundigt und das gefunden:
    http://www.codeproject.com/KB/cs/globalhook.aspx
    Jedoch ist es für WinForms und wenn ich versuche es in WPF zu kompilieren, werden mir bei Keys, KeyPressEventHandler und KeyEventArgs Fehler ausgespuckt, da diese ja eig. im Namespace Forms enthalten sind. An der einen oder anderen Stelle krieg ich auch nochn Fehler, die aber wohl durch die 3 oben genannten kommen.
    Meine Frage also, hätte jemand einen Globalhook für WPF oder kann man den Code noch umändern, dass er für WPF läuft?

    Mit freundlichen Grüßen, Freaky



  • Normalerweise ist es ja nicht meine Art fertigen Code zu posten, aber ich will ja mal nicht so sein 😛
    Ich will auch gar nicht behaupten, das der Code nur von mir ist. Ich hatte irgendeine Vorlage dafür, würde mich also nicht wundern, wenn man ihn ähnlich irgendwo bei google findet.

    [assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
    namespace NorthWeave
    {
      public class GlobalKeyboardHook
      {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;
        private static NativeMethods.LowLevelKeyboardProc _proc;
        private static IntPtr _hookId = IntPtr.Zero;
    
        private static GlobalKeyboardHook _instance = null;
        private static object _lockHelper = new object();
    
        public event EventHandler<KeyboardHookEventArgs> KeyDown;
        public event EventHandler<KeyboardHookEventArgs> KeyUp;
    
        private GlobalKeyboardHook()
        {
          _proc = HookCallback;
          _hookId = SetHook(_proc);
        }
    
        ~GlobalKeyboardHook()
        {
            NativeMethods.UnhookWindowsHookEx(_hookId);
            _hookId = IntPtr.Zero;
            _proc = null;
    
            lock(_lockHelper)
              _instance = null;
        }
    
        public static GlobalKeyboardHook GetHook()
        {
          if(_instance == null)
            lock(_lockHelper)
              if(_instance == null)
              {
                _instance = new GlobalKeyboardHook();
                return _instance;
              }
    
          return _instance;
        }
    
        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
          if(nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            RaiseKeyDown(Marshal.ReadInt32(lParam));
          else
            RaiseKeyUp(Marshal.ReadInt32(lParam));
    
          return NativeMethods.CallNextHookEx(_hookId, nCode, wParam, lParam);
        }
    
        private void RaiseKeyDown(int keyCode)
        {
          if(KeyDown != null)
            KeyDown(this, new KeyboardHookEventArgs(keyCode));
        }
    
        private void RaiseKeyUp(int keyCode)
        {
          if(KeyUp != null)
            KeyUp(this, new KeyboardHookEventArgs(keyCode));
        }
    
        private static IntPtr SetHook(NativeMethods.LowLevelKeyboardProc proc)
        {
          using(Process currentProcess = Process.GetCurrentProcess())
          using(ProcessModule currentModule = currentProcess.MainModule)
          {
            return NativeMethods.SetWindowsHookEx(WH_KEYBOARD_LL, proc,
              NativeMethods.GetModuleHandle(currentModule.ModuleName), 0);
          }
        }
    
        private static class NativeMethods
        {
          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          internal static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
    
          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          [return: MarshalAs(UnmanagedType.Bool)]
          internal static extern bool UnhookWindowsHookEx(IntPtr hhk);
    
          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          internal static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    
          [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          internal static extern IntPtr GetModuleHandle(string lpModuleName);
    
          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
          internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
          internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        }
      }
    
      public class KeyboardHookEventArgs : EventArgs
      {
        public int KeyCode { get; private set; }
    
        public KeyboardHookEventArgs(int keyCode)
          : base()
        {
          KeyCode = keyCode;
        }
      }
    


  • Ich habe den Code jetzt nicht getestet, aber es sieht recht ordentlich aus. Könntest du vllt. noch kurz erklären, wie man damit umgehen muss?
    Vielen dank schonmal.



  • Okay, habe es hinbekommen

    GlobalKeyboardHook gk = GlobalKeyboardHook.GetHook();
    gk.KeyDown += new EventHandler<KeyboardHookEventArgs>(MyKeyDown);
    

    und das Ding läuft.
    Vielen Dank nochmal.

    Mit freundlichen Grüßen, Freaky



  • hast du sonst versucht die entsprehenden Assemblies (System.Windows.Forms) als verweis ins Projekt einzubinden?


Anmelden zum Antworten