2017-07-08 50 views
0

我想要捕獲按鍵(例如,ctrl + WinKey或只有逗號)。我在C#中使用WH_KEYBOARD_LL鉤子和GetAsyncKeyState。如果我在調試器下運行它(即沒有設置斷點的調試器),它就可以正常工作。但是,如果我運行它沒有調試器,它很少工作。不調用熱鍵代碼 - 與在調試器下工作的代碼非常相似。GetAsyncKeyState隨機在發佈版本中工作

我注意到,如果我添加日誌記錄代碼,那麼它的工作原理也沒有調試器。 它通常也適用於較慢的PC。

我該如何解決問題?

以下是從鉤處理器

private bool HotKeyHandler(WPARAM wParam, LPARAM lParam, WH_KEYBOARD_LL.KBDLLHOOKSTRUCT KeyInfo) { 

if ((WH_KEYBOARD_LL.GetAsyncKeyState(Keys.LWin) < 0 || WH_KEYBOARD_LL.GetAsyncKeyState(Keys.RWin) < 0)) { 
    if ((int)wParam == WH_KEYBOARD_LL.WM_KEYDOWN) { 
      if (WH_KEYBOARD_LL.GetAsyncKeyState(Keys.ControlKey) < 0) { 
       switch (KeyInfo.VkCode) { 
        case WH_KEYBOARD_LL.VK_OEM_COMMA: 
         // Some action - this doesn't work randomly ... 
        return true; 
... 
       } 
      } 

     } 
    } 
return false; 
} 


WH_KEYBOARD_LL.Initialize(HotKeyHandler); 

     public static void Initialize(Func<WPARAM, LPARAM, KBDLLHOOKSTRUCT, bool> Handler) { 
      HandlerI = Handler; 
      KeyboardHookProcedureHandle = NativeCalls.Hooks.SetWindowsHookEx(NativeCalls.Hooks.HookType.WH_KEYBOARD_LL, KeyboardLLHandler, IntPtr.Zero, 0); 
     } 

     private static NativeCalls.Hooks.Procedure KeyboardLLHandler = KeyboardProcedure; 

     private static LRESULT KeyboardProcedure(int MustProcessMessage, WPARAM wParam, LPARAM lParam) { 
      if (MustProcessMessage != HC_ACTION) { return NativeCalls.Hooks.CallNextHookEx(KeyboardHookProcedureHandle, MustProcessMessage, wParam, lParam); } 

      var KeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); 
      return HandlerI(wParam, lParam, KeyInfo) ? (IntPtr)1 : NativeCalls.Hooks.CallNextHookEx(KeyboardHookProcedureHandle, MustProcessMessage, wParam, lParam); 
     } 

     [DllImport("user32.dll")] 
     public static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey); 

     [StructLayout(LayoutKind.Sequential)] 
     public struct KBDLLHOOKSTRUCT { 
      public DWORD VkCode; 
      public DWORD ScanCode; 
      public DWORD Flags; 
      public DWORD Time; 
      public ULONG_PTR DwExtraInfo; 
     } 

     public const int HC_ACTION = 0; 
     public const int WM_KEYDOWN = 0x0100; 
     public const int WM_KEYUP = 0x0101; 
     public const int WM_SYSKEYUP = 0x0105; 
     public const int VK_OEM_COMMA = 0xBC; 
     public const int VK_OEM_PERIOD = 0xBE; 
     public const int VK_TAB = 0x09; 
     public const int VK_ESCAPE = 0x18; 

     public const int VK_1 = 0x31; 
     public const int VK_2 = 0x32; 
     public const int VK_3 = 0x33; 
     public const int VK_4 = 0x34; 
     public const int VK_5 = 0x35; 
     public const int VK_6 = 0x36; 
     public const int VK_7 = 0x37; 
     public const int VK_8 = 0x38; 
     public const int VK_9 = 0x39; 

     public const int VK_N = 0x4E; 
     public const int VK_W = 0x57; // Virtual-Key Codes - https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx 
     public const int VK_Z = 0x5A; 

/* 
using DWORD = System.UInt32; 
using HHOOK = System.IntPtr; 
using LPARAM = System.IntPtr; 
using LRESULT = System.IntPtr; 
using ULONG_PTR = System.UIntPtr; 
using WPARAM = System.UIntPtr; 
*/ 

回答

1

GetAsyncKeyState就在你打電話的那一刻,不跟你計較其他鍵同步的狀態檢索狀態代碼摘錄。你已經有了一個鉤子,你可以在鉤子中跟蹤自己的Win鍵狀態。

相關問題