C#局部鼠标钩子实现

很早之前搜集的一个局部鼠标钩子的使用方法,这两天又用到了。winform实现一些特效还是太费劲。幸好还可以用win api。以下是局部鼠标钩子的创建、安装、使用以及卸载的方法。

public class MouseHookHelper
{
   //安装钩子
   [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
   public static extern IntPtr SetWindowsHookEx(WH_Codes idHook, HookProc lpfn, IntPtr pInstance, int threadId);

   //卸载钩子
   [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
   public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

   //传递钩子
   [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
   public static extern int CallNextHookEx(IntPtr pHookHandle, int nCode, Int32 wParam, IntPtr lParam);

   //获取当前鼠标位置
   [DllImport("user32.dll")]
   public extern static int GetCursorPos(ref POINT lpPoint);

   [StructLayout(LayoutKind.Sequential)]
   public struct POINT
   {
       public int X;
       public int Y;

   }
   /// 钩子委托声明
   public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

   /// 无返回委托声明
   public delegate void VoidCallback();

   public enum WH_Codes : int
   {
       /// <summary>
       /// 底层鼠标钩子
       /// </summary>
       WH_MOUSE_LL = 7
   }

   // 添加
   public event MouseEventHandler OnMouseActivity;
   public enum WM_MOUSE : int
   {
       /// <summary>
       /// 鼠标开始
       /// </summary>
       WM_MOUSEFIRST = 0x200,

       /// <summary>
       /// 鼠标移动
       /// </summary>
       WM_MOUSEMOVE = 0x200,

       /// <summary>
       /// 左键按下
       /// </summary>
       WM_LBUTTONDOWN = 0x201,

       /// <summary>
       /// 左键释放
       /// </summary>
       WM_LBUTTONUP = 0x202,

       /// <summary>
       /// 左键双击
       /// </summary>
       WM_LBUTTONDBLCLK = 0x203,

       /// <summary>
       /// 右键按下
       /// </summary>
       WM_RBUTTONDOWN = 0x204,

       /// <summary>
       /// 右键释放
       /// </summary>
       WM_RBUTTONUP = 0x205,

       /// <summary>
       /// 右键双击
       /// </summary>
       WM_RBUTTONDBLCLK = 0x206,

       /// <summary>
       /// 中键按下
       /// </summary>
       WM_MBUTTONDOWN = 0x207,

       /// <summary>
       /// 中键释放
       /// </summary>
       WM_MBUTTONUP = 0x208,

       /// <summary>
       /// 中键双击
       /// </summary>
       WM_MBUTTONDBLCLK = 0x209,

       /// <summary>
       /// 滚轮滚动
       /// </summary>
       /// <remarks>WINNT4.0以上才支持此消息</remarks>
       WM_MOUSEWHEEL = 0x020A
   }

   /// 鼠标钩子句柄
   private IntPtr m_pMouseHook = IntPtr.Zero;

   /// 鼠标钩子委托实例
   private HookProc m_MouseHookProcedure;

   [DllImport("kernel32.dll")]
   public static extern int GetCurrentThreadId();

   #region 鼠标钩子事件结构定义
   [StructLayout(LayoutKind.Sequential)]
   public struct MouseHookStruct
   {
       public POINT Point;
       public UInt32 MouseData;
       public UInt32 Flags;
       public UInt32 Time;
       public UInt32 ExtraInfo;
   }
   #endregion

   #region 钩子处理函数
   private int MouseHookProc(int nCode, Int32 wParam, IntPtr lParam)
   {
       if ((nCode >= 0) && (OnMouseActivity != null))
       {
           MouseHookStruct mouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
           MouseButtons button = MouseButtons.None;
           short mouseDelta = 0;
           switch (wParam)
           {
               case (int)WM_MOUSE.WM_LBUTTONDOWN:
                   button = MouseButtons.Left;
                   break;
               case (int)WM_MOUSE.WM_RBUTTONDOWN:
                   button = MouseButtons.Right;
                   break;
               case (int)WM_MOUSE.WM_MOUSEWHEEL:

                   mouseDelta = (short)((mouseHookStruct.MouseData >> 16) & 0xffff);

                   break;
           }

           //double clicks
           int clickCount = 0;
           if (button != MouseButtons.None)
               if (wParam == (int)WM_MOUSE.WM_LBUTTONDBLCLK || wParam == (int)WM_MOUSE.WM_RBUTTONDBLCLK) clickCount = 2;
               else clickCount = 1;

           //generate event
           MouseEventArgs e = new MouseEventArgs(button, clickCount, mouseHookStruct.Point.X, mouseHookStruct.Point.Y, mouseDelta);
           //raise it
           OnMouseActivity(this, e);
       }
       return CallNextHookEx(this.m_pMouseHook, nCode, wParam, lParam);
   }
   #endregion

   #region 安装钩子
   public bool InstallHook()
   {
       IntPtr pInstance = Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule);
       if (this.m_pMouseHook == IntPtr.Zero)
       {
           m_MouseHookProcedure = new HookProc(this.MouseHookProc);
           this.m_pMouseHook = SetWindowsHookEx(WH_Codes.WH_MOUSE_LL, m_MouseHookProcedure, (IntPtr)0, GetCurrentThreadId());
           if (this.m_pMouseHook == IntPtr.Zero)
           {
               this.UnInstallHook();
               return false;
           }
       }
       return true;
   }
   #endregion

   #region 卸载钩子
   public bool UnInstallHook()
   {
       bool result = true;
       if (this.m_pMouseHook != IntPtr.Zero)
       {
           result = (UnhookWindowsHookEx(this.m_pMouseHook) && result);
           this.m_pMouseHook = IntPtr.Zero;
       }

       return result;
   }
   #endregion
}

//以下是钩子使用方法
MouseHookHelper mouseHookHelper = new MouseHookHelper();
//安装钩子
mouseHookHelper.InstallHook();
//绑定鼠标事件
mouseHookHelper.OnMouseActivity += new MouseEventHandler(mouseHookHelper_OnMouseActivity);

void mouseHookHelper_OnMouseActivity(object sender, MouseEventArgs e)
{
   //处理鼠标事件业务逻辑
}

//卸载钩子
mouseHookHelper.UnInstallHook();