1. 程式人生 > >C#監測全域性鍵盤與滑鼠事件

C#監測全域性鍵盤與滑鼠事件

         在C#中一般不能用SetWindowHookEx監視全域性鍵盤與滑鼠事件,微軟給出的解釋是託管程式不能與非託管共享連結庫互動,在網上找了老半天才發現了這個解決方案,拿出來與大家分享一下,希望可以節約對這方面又需求和希望學習的朋友們的時間.

         WH_KEYBOARD_LLWH_MOUSE_LL是個例外,可以做到對全域性滑鼠與鍵盤事件監控.具體示例程式碼如下:

using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using System.ComponentModel;

namespace ScreenCapyure2
{
      public class UserActivityHook
      {
          #region Windows structure definitions

          [StructLayout(LayoutKind.Sequential)]
          private class POINT
          {
              public int x;
              public int y;
          }

          [StructLayout(LayoutKind.Sequential)]
          private

class MouseHookStruct
          {
              public POINT pt;
              public int hwnd;
              public int wHitTestCode;
              public int dwExtraInfo;
          }

          [StructLayout(LayoutKind.Sequential)]
          private class MouseLLHookStruct
          {
              public POINT pt;
              public int

mouseData;
              public int flags;
              public int time;
              public int dwExtraInfo;
          }

          [StructLayout(LayoutKind.Sequential)]
          private class KeyboardHookStruct
          {
              public int vkCode;
              public int scanCode;
              public int flags;
              public int time;
              public int dwExtraInfo;
          }
          #endregion

          #region Windows function imports

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

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

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

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

          [DllImport("user32")]
          private static extern int ToAscii(
              int uVirtKey,
              int uScanCode,
              byte[] lpbKeyState,
              byte[] lpwTransKey,
              int fuState);

          [DllImport("user32")]
          private static extern int GetKeyboardState(byte[] pbKeyState);

          [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
          private static extern short GetKeyState(int vKey);

          #endregion

          #region Windows constants

          private const int WH_MOUSE_LL = 14;
          private const int WH_KEYBOARD_LL = 13;
          private const int WH_MOUSE = 7;
          private const int WH_KEYBOARD = 2;
          private const int WM_MOUSEMOVE = 0x200;
          private const int WM_LBUTTONDOWN = 0x201;
          private const int WM_RBUTTONDOWN = 0x204;
          private const int WM_MBUTTONDOWN = 0x207;
          private const int WM_LBUTTONUP = 0x202;
          private const int WM_RBUTTONUP = 0x205;
          private const int WM_MBUTTONUP = 0x208;
          private const int WM_LBUTTONDBLCLK = 0x203;
          private const int WM_RBUTTONDBLCLK = 0x206;
          private const int WM_MBUTTONDBLCLK = 0x209;
          private const int WM_MOUSEWHEEL = 0x020A;
          private const int WM_KEYDOWN = 0x100;
          private const int WM_KEYUP = 0x101;
          private const int WM_SYSKEYDOWN = 0x104;
          private const int WM_SYSKEYUP = 0x105;

          private const byte VK_SHIFT = 0x10;
          private const byte VK_CAPITAL = 0x14;
          private const byte VK_NUMLOCK = 0x90;

          #endregion

          public UserActivityHook()
          {
              Start();
          }

          public UserActivityHook(bool InstallMouseHook, bool InstallKeyboardHook)
          {
              Start(InstallMouseHook, InstallKeyboardHook);
          }

          ~UserActivityHook()
          {
              Stop(true, true, false);
          }

          public event MouseEventHandler OnMouseActivity;
          public event KeyEventHandler KeyDown;
          public event KeyPressEventHandler KeyPress;
          public event KeyEventHandler KeyUp;

          private int hMouseHook = 0;
          private int hKeyboardHook = 0;

          private static HookProc MouseHookProcedure;
          private static HookProc KeyboardHookProcedure;
          public void Start()
          {
              this.Start(true, true);
          }
          public void Start(bool InstallMouseHook, bool InstallKeyboardHook)
          {
              if (hMouseHook == 0 && InstallMouseHook)
              {
                  MouseHookProcedure = new HookProc(MouseHookProc);
                  hMouseHook = SetWindowsHookEx(
                      WH_MOUSE_LL,
                      MouseHookProcedure,
                      Marshal.GetHINSTANCE(
                          Assembly.GetExecutingAssembly().GetModules()[0]),
                      0);
                  if (hMouseHook == 0)
                  {
                      int errorCode = Marshal.GetLastWin32Error();
                      Stop(true, false, false);
                      throw new Win32Exception(errorCode);
                  }
              }
              if (hKeyboardHook == 0 && InstallKeyboardHook)
              {
                  KeyboardHookProcedure = new HookProc(KeyboardHookProc);
                  hKeyboardHook = SetWindowsHookEx(
                      WH_KEYBOARD_LL,
                      KeyboardHookProcedure,
                      Marshal.GetHINSTANCE(
                      Assembly.GetExecutingAssembly().GetModules()[0]),
                      0);
                  if (hKeyboardHook == 0)
                  {
                      int errorCode = Marshal.GetLastWin32Error();
                      Stop(false, true, false);
                      throw new Win32Exception(errorCode);
                  }
              }
          }

          public void Stop()
          {
              this.Stop(true, true, true);
          }

          public void Stop(bool UninstallMouseHook, bool UninstallKeyboardHook, bool ThrowExceptions)
          {
              if (hMouseHook != 0 && UninstallMouseHook)
              {
                  int retMouse = UnhookWindowsHookEx(hMouseHook);
                  hMouseHook = 0;
                  if (retMouse == 0 && ThrowExceptions)
                  {
                      int errorCode = Marshal.GetLastWin32Error();
                      throw new Win32Exception(errorCode);
                  }
              }
              if (hKeyboardHook != 0 && UninstallKeyboardHook)
              {
                  int retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
                  hKeyboardHook = 0;
                  if (retKeyboard == 0 && ThrowExceptions)
                  {
                      int errorCode = Marshal.GetLastWin32Error();
                      throw new Win32Exception(errorCode);
                  }
              }
          }

          private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
          {
              if ((nCode >= 0) && (OnMouseActivity != null))
              {
                  MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
                  MouseButtons button = MouseButtons.None;
                  short mouseDelta = 0;
                  switch (wParam)
                  {
                      case WM_LBUTTONDOWN:
                          button = MouseButtons.Left;
                          break;
                      case WM_LBUTTONUP:
                          button = MouseButtons.Right;
                          break;
                      case WM_MOUSEWHEEL:
                          mouseDelta = (short)((mouseHookStruct.mouseData >> 16) & 0xffff);
                          break;
                  }
                  int clickCount = 0;
                  if (button != MouseButtons.None)
                      if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2;
                      else clickCount = 1;
                  MouseEventArgs e = new MouseEventArgs(
                                                     button,
                                                     clickCount,
                                                     mouseHookStruct.pt.x,
                                                     mouseHookStruct.pt.y,
                                                     mouseDelta);
                  OnMouseActivity(this, e);
              }
              return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
          }
          private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
          {
              bool handled = false;
              if ((nCode >= 0) && (KeyDown != null || KeyUp != null || KeyPress != null))
              {
                  KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                  if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
                  {
                      Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                      KeyEventArgs e = new KeyEventArgs(keyData);
                      KeyDown(this, e);
                      handled = handled || e.Handled;
                  }
                  if (KeyPress != null && wParam == WM_KEYDOWN)
                  {
                      bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
                      bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

                      byte[] keyState = new byte[256];
                      GetKeyboardState(keyState);
                      byte[] inBuffer = new byte[2];
                      if (ToAscii(MyKeyboardHookStruct.vkCode,
                                MyKeyboardHookStruct.scanCode,
                                keyState,
                                inBuffer,
                                MyKeyboardHookStruct.flags) == 1)
                      {
                          char key = (char)inBuffer[0];
                          if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
                          KeyPressEventArgs e = new KeyPressEventArgs(key);
                          KeyPress(this, e);
                          handled = handled || e.Handled;
                      }
                  }
                  if (KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
                  {
                      Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                      KeyEventArgs e = new KeyEventArgs(keyData);
                      KeyUp(this, e);
                      handled = handled || e.Handled;
                  }

              }
              if (handled)
                  return 1;
              else
                  return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
          }
      }
}

以下為在窗體中監視事件

UserActivityHook choosesc;


choosesc = new UserActivityHook();
             choosesc.OnMouseActivity += new MouseEventHandler(choose_OnMouseActivity);
             choosesc.KeyDown += new KeyEventHandler(MyKeyDown);
             choosesc.KeyPress += new KeyPressEventHandler(MyKeyPress);
             choosesc.KeyUp += new KeyEventHandler(MyKeyUp);

public void MyKeyDown(object sender, KeyEventArgs e)
         {
         }

         public void MyKeyPress(object sender, KeyPressEventArgs e)
         {
         }

         public void MyKeyUp(object sender, KeyEventArgs e)
         {
         }

void choose_OnMouseActivity(object sender, MouseEventArgs e)
          {
              if (e.Clicks > 0)
              {
                  if ((MouseButtons)(e.Button) == MouseButtons.Left)
                  {
                      point[0] = e.Location;
                  }
                  if ((MouseButtons)(e.Button) == MouseButtons.Right)
                  {
                      point[1] = e.Location;
                  }
              }
              //throw new Exception("The method or operation is not implemented.");
          }