2012-09-20 46 views
0

我正在運行一個應用程序,我希望在按住鼠標左鍵的同時重複單擊左鍵單擊鼠標(因此基本上不需要繼續單擊)。我編寫了一個小型測試應用程序,它鉤住鼠標事件,並聽取lb向下/向上事件。不過,該應用程序會在桌面上的任何位置監聽鼠標點擊。有沒有辦法讓它只聽一個特定的過程?C#鼠標鉤入特定進程

下面是測試程序我使用監聽鼠標點擊:

class Program 
{ 
     private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 
     private static LowLevelMouseProc _proc = HookCallback; 
     private static IntPtr _hookID = IntPtr.Zero; 
     private static bool _leftButtonDown; 

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

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

     private static IntPtr HookCallback(
      int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && 
       MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam) 
      { 
       _leftButtonDown = false; 
       Console.WriteLine(_leftButtonDown); 
      } 

      if (nCode >= 0 && 
       MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) 
      { 
       _leftButtonDown = true; 
       Console.WriteLine(_leftButtonDown); 
       StartTest(); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 

     private static void StartTest() 
     { 
      Task.Factory.StartNew(() => 
       { 
        while (_leftButtonDown) 
        { 
         Console.WriteLine("SENDING"); 
        } 
       }); 
     } 

     private const int WH_MOUSE_LL = 14; 

     private enum MouseMessages 
     { 
      WM_LBUTTONDOWN = 0x0201, 
      WM_LBUTTONUP = 0x0202 
     } 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr SetWindowsHookEx(int idHook, 
      LowLevelMouseProc 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); 

     [DllImport("User32.dll")] 
     public static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] input, int structSize); 

     [StructLayout(LayoutKind.Sequential)] 
     public struct MOUSEINPUT 
     { 
      public int dx; 
      public int dy; 
      public uint mouseData; 
      public uint dwFlags; 
      public uint time; 
      public IntPtr dwExtraInfo; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct KEYBDINPUT 
     { 
      public ushort wVk; 
      public ushort wScan; 
      public uint dwFlags; 
      public uint time; 
      public IntPtr dwExtraInfo; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct HARDWAREINPUT 
     { 
      uint uMsg; 
      ushort wParamL; 
      ushort wParamH; 
     } 

     [StructLayout(LayoutKind.Explicit)] 
     public struct INPUT 
     { 
      [FieldOffset(0)] 
      public int type; 
      [FieldOffset(4)] //* 
      public MOUSEINPUT mi; 
      [FieldOffset(4)] //* 
      public KEYBDINPUT ki; 
      [FieldOffset(4)] //* 
      public HARDWAREINPUT hi; 
     } 
    } 
+0

改爲指定SetWindowsHookEx()的線程ID參數。 –

+0

感謝漢斯。如果您將答案添加爲回覆,我可以將您的答案標記爲已接受。 – Flack

回答

1

正如評論指出的那樣,你可以使用SetWindowsHookEx函數的)的第四個參數(中,dwThreadId說法,是有選擇性的。您需要傳遞要監視的進程的GUI線程的線程ID。如果你有一個進程擁有的窗口的句柄,用GetWindowThreadProcessId()來獲得值。如果它是你自己的進程,那麼使用GetCurrentThreadId()。如果它是Winforms應用程序,則支持IMessageFilter而不是掛鉤。