2013-03-21 3 views
0

WH_KEYBOARD_LL과 함께 SetWindowsHookEx()를 사용하기 때문에 글로벌 키보드 메시지를 캡처해야합니다. 그러나 응용 프로그램이 포커스가 있고 콜백을 전역 적으로 트리거하지 않을 때만 작동합니다. 거의 동일한 코드가 mouse_LL과 잘 작동합니다 (다른 구조 & 등). 도와주세요!글로벌 키보드 후크

public const int WH_KEYBOARD_LL = 13; 
public const int VK_INSERT = 0x2D; 
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); 
HookProc KeyboardHookProcedure; 

[DllImport("user32.dll", CharSet = CharSet.Auto, 
    CallingConvention = CallingConvention.StdCall)] 
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, 
    IntPtr hInstance, int threadId); 

[DllImport("user32.dll", CharSet = CharSet.Auto, 
    CallingConvention = CallingConvention.StdCall)] 
    public static extern bool UnhookWindowsHookEx(int idHook); 

[DllImport("user32.dll", CharSet = CharSet.Auto, 
    CallingConvention = CallingConvention.StdCall)] 
    public static extern int CallNextHookEx(int idHook, int nCode, 
    IntPtr wParam, IntPtr lParam); 

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr GetModuleHandle(string lpModuleName); 

[StructLayout(LayoutKind.Sequential)] 
    private struct KBDLLHOOKSTRUCT 
    { 
    public uint vkCode; 
    public uint scanCode; 
    public uint flags; 
    public uint time; 
    public IntPtr dxExtraInfo; 
    } 

private void SetHookKeyboard() 
    { 
    if (kHook == 0) 
    { 
     KeyboardHookLL(); 

     //If the SetWindowsHookEx function fails. 
     if (kHook == 0) 
     { 
      MessageBox.Show("SetWindowsHookEx Failed"); 
      return; 
     } 
     button1.Text = "UnHook Windows Hook"; 
    } 
    else 
    { 
     bool ret = UnhookWindowsHookEx(kHook); 
     //If the UnhookWindowsHookEx function fails. 
     if (ret == false) 
     { 
      MessageBox.Show("UnhookWindowsHookEx Failed"); 
      return; 
     } 
     kHook = 0; 
     this.Text = "Keyboard Hook"; 
    } 
    } 

private void KeyboardHookLL() 
    { 
    KeyboardHookProcedure = new HookProc(MainForm.KeyboardHookProc); 
    kHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle("user32"), 0); 
    } 

public static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
    KBDLLHOOKSTRUCT MyKeyboardHookStruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); 
    if (nCode < 0) 
    { 
     return CallNextHookEx(hHook, nCode, wParam, lParam); 
    } 
    else 
    { 
     Form tempForm = Form.ActiveForm; 
     tempForm.Text = MyKeyboardHookStruct.vkCode.ToString(); 
     if (MyKeyboardHookStruct.vkCode == VK_INSERT) 
     { 
      MainForm.botAlive = false; 
      MessageBox.Show(MainForm.botAlive.ToString()); 
     } 
     return CallNextHookEx(hHook, nCode, wParam, lParam); 
    } 
    } 
+0

일반적으로 후크 대신 단축기를 사용하는 것이 더 안전합니다. 바로 가기 키 대신 후크가 필요한 특별한 이유가 있습니까? – Guido

+0

Yeap, "레코더"가 될 것이므로 모든 입력을 캡처해야합니다. – UnknitSplash

+0

이것이 메인 폼의 코드라면, 이벤트 핸들러를 어딘가에 등록해서는 안됩니까? – Guido

답변

0

"디버그"기능에 문제가 있습니다. 폼 tempForm = Form.ActiveForm;

1

신용 여기에 존 간다 :

int vs IntPtr when you have a handle?

나는 이것이 이전 게시물 알고 내가 조금 빗나가 다,하지만 난 돌아 서서 당신을 물지 수있는 원래의 코드에 좀 불길한 단점을 발견 때가 아주 아주 나쁜 (나는 내 ​​경우에 한 알) :

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); 

더 바람직하게해야합니다

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
    static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId); 

다른 시그니처에도 비슷한 변경 사항을 적용해야합니다. microsoft 자체에 반환 형식 (https://support.microsoft.com/en-us/kb/318804)으로 int를 사용하여 SetwindowsHookEx를 표시하는 리소스가 있더라도 'IntPtr'대신 다른 유형 인을 천천히 사용해야합니다. 이 경우 'int'는 32 비트 OS에서만 'IntPtr'과 동일합니다. 64 비트 플랫폼에서 'IntPtr'은 64 비트이고 'int'는 웜의 전체를 열 수있는 32 비트 만 유지합니다. 'int'를 사용하는 최악의 경우 중 하나는 SetWindowsHookEx의 반환 값이 그 안에 들어 맞지 않으면 엉켜 붙은 int-handle (희귀하지만 생각할 수없는)으로 끝날 것입니다.

응용 프로그램의 수명이 후크를 푸시/처분하는 시점을 지나면 (즉, 언 후크 호출이 시작될 수있는 것이 아니라 ...) 그러면 마우스가 정지 될 수 있습니다 키보드를 호스트 프로세스가 종료 될 때까지 완전히 종료하십시오. 대부분의 사람들은 그 시점에서 컴퓨터를 재부팅하고 앱을 모두 처분 할 것입니다. 이 "키보드/마우스 고정"문제는 호스트 응용 프로그램의 메시지 펌프에 도달해야하기 때문에 발생합니다. 호스트 응용 프로그램의 메시지 펌프에 도달해야하기 때문에 분명히 처리 할 수 ​​없습니다.

TL : DR : 사용중인 p/invoke 메소드의 서명과 특히 IntPtrs에주의하십시오.