VSTO Office二次开发键盘鼠标钩子使用整理
可能通过程序控制键盘的操作和控制鼠标的一些操作,网上提供比较多的也是比较好的就是通过钩子(Hook)的方式实现。
简单整理了一下,没有找到很好的程序示例,做了个简单的Hook测试。(对于Hook的原理和调用细则,这里不涉及了,只是简单的Hook小测试,感兴趣的查一下吧)
1.Win32API函数:(简单封装对于API函数的调用)
View Code
2.HookHelper.cs:(对于一些标识的定义,特别注意鼠标和键盘的标识参数)
View Code
3.Hook.cs:(简单对于键盘、鼠标的操作进行监控)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace TestHook.MyHook { public class Hook { #region 定义变量 //定义鼠标钩子处理函数 private Win32API.HookProc MouseHookProcedure = null; //定义键盘钩子处理函数 private Win32API.HookProc KeyboardProcDelegate = null; //定义键盘钩子句柄 private IntPtr khook; //定义鼠标钩子句柄 private IntPtr hHook = IntPtr.Zero; //定义鼠标事件 public event MouseEventHandler OnMouseActivity; #endregion /// <summary> /// 安装钩子 /// </summary> public void InstallHook(HookHelper.HookType hookType) { if (hookType == HookHelper.HookType.KeyOperation) { if (khook == IntPtr.Zero)//键盘钩子 { uint id = Win32API.GetCurrentThreadId(); this.KeyboardProcDelegate = new Win32API.HookProc(this.KeyboardProc); khook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_KEYBOARD_LL, this.KeyboardProcDelegate, IntPtr.Zero, id); } } else { if (hHook == IntPtr.Zero)//鼠标钩子 { uint id = Win32API.GetCurrentThreadId(); this.MouseHookProcedure = new Win32API.HookProc(this.MouseHookProc); //这里挂节钩子 hHook = Win32API.SetWindowsHookEx((IntPtr)HookHelper.WH_Codes.WH_MOUSE_LL, MouseHookProcedure, IntPtr.Zero, id); } } } /// <summary> /// 卸载鼠标钩子 /// </summary> public void UnInstallHook(HookHelper.HookType hookType) { bool isSuccess = false; if (hookType == HookHelper.HookType.KeyOperation)//键盘钩子 { if (khook != IntPtr.Zero) { isSuccess = Win32API.UnhookWindowsHookEx(khook); this.khook = IntPtr.Zero; } } else { if (this.hHook != IntPtr.Zero)//鼠标钩子 { isSuccess = Win32API.UnhookWindowsHookEx(hHook); this.hHook = IntPtr.Zero; } } if (isSuccess) { MessageBox.Show("卸载成功!"); } else { MessageBox.Show("卸载失败!"); } } /// <summary> /// 鼠标钩子处理函数 /// </summary> /// <param name="nCode"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < (int)HookHelper.WH_Codes.HC_ACTION) { return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam); } if (OnMouseActivity != null) { //Marshall the data from callback. HookHelper.MouseHookStruct mouseHookStruct = (HookHelper.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.MouseHookStruct)); MouseButtons button = MouseButtons.None; short mouseDelta = 0; switch ((int)wParam) { case (int)HookHelper.WM_MOUSE.WM_LBUTTONDOWN: //case WM_LBUTTONUP: //case WM_LBUTTONDBLCLK: button = MouseButtons.Left; break; case (int)HookHelper.WM_MOUSE.WM_RBUTTONDOWN: //case WM_RBUTTONUP: //case WM_RBUTTONDBLCLK: button = MouseButtons.Right; break; case (int)HookHelper.WM_MOUSE.WM_MOUSEWHEEL: //button = MouseButtons.Middle;//滚动轮 //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value mouseDelta = (short)((mouseHookStruct.MouseData >> 16) & 0xffff); break; } int clickCount = 0;//点击数 if (button != MouseButtons.None) { if ((int)wParam == (int)HookHelper.WM_MOUSE.WM_LBUTTONDBLCLK || (int)wParam == (int)HookHelper.WM_MOUSE.WM_RBUTTONDBLCLK) { clickCount = 2;//双击 } else { clickCount = 1;//单击 } } //鼠标事件传递数据 MouseEventArgs e = new MouseEventArgs(button, clickCount, mouseHookStruct.Point.X, mouseHookStruct.Point.Y, mouseDelta); //重写事件 OnMouseActivity(this, e); } return Win32API.CallNextHookEx(hHook, nCode, wParam, lParam); } /// <summary> /// 键盘钩子处理函数 /// </summary> /// <param name="code"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> private int KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam) { try { if (nCode < (int)HookHelper.WH_Codes.HC_ACTION) { return Win32API.CallNextHookEx((IntPtr)khook, nCode, wParam, lParam); } HookHelper.KeyboardHookStruct keyHookStruct = (HookHelper.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(HookHelper.KeyboardHookStruct)); #region //if ((int)wParam == (int)Keys.C && ((int)lParam & (int)Keys.ControlKey) != 0 ||//Ctrl+C // (int)wParam == (int)Keys.X && ((int)lParam & (int)Keys.ControlKey) != 0)//Ctrl+V //{ // MessageBox.Show("C||V"); //} //if (lParam.ToInt32() > 0)//捕获键盘按下 //{ // Keys keys = (Keys)wParam; // MessageBox.Show("键盘按下"); //} //if (lParam.ToInt32() < 0)//捕获键盘抬起 //{ // MessageBox.Show("键盘抬起"); //} /**************** //全局键盘钩子判断是否按下键 wParam = = 0x100 // 键盘按下 wParam = = 0x101 // 键盘抬起 ****************/ //return 0;//如果返回1,则结束消息,消息截止,不再传递。如果返回0或调用CallNextHookEx函数,消息出这个钩子继续往下传递。 #endregion } catch { } return Win32API.CallNextHookEx(khook, nCode, wParam, lParam); } } }
如果不好理解,将键盘、鼠标操作分离为两个文件分别封装:KeyHook.cs和MouseHook.cs
KeyHook.cs文件:
View Code
MouseHook.cs文件:
View Code
4.对于Hook文件的调用,使用一个WinForm窗体做的测试,鼠标监控按钮、键盘监控按钮、停止监控按钮,一个RichTextBox显示监控日志,一个Label显示鼠标坐标监控:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using TestHook.MyHook; namespace TestHook { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Hook hook = new Hook();//总钩子控制 private KeyHook keyHook = new KeyHook();//键盘钩子 private MouseHook mouseHook = new MouseHook();//鼠标钩子 private void Form1_Load(object sender, EventArgs e) { hook.OnMouseActivity += new MouseEventHandler(hook_OnMouseActivity); mouseHook.OnMouseActivity += new MouseEventHandler(mouseHook_OnMouseActivity); keyHook.OnKeyDown += new KeyEventHandler(keyHook_OnKeyDown); } void keyHook_OnKeyDown(object sender, KeyEventArgs e) { WriteLog("KeyDown - " + e.KeyData.ToString()); } void hook_OnMouseActivity(object sender, MouseEventArgs e) { this.lblMousePosition.Text = string.Format("X:{0} Y={1} Wheel={2}", e.X, e.Y, e.Delta); if (e.Clicks > 0) { WriteLog("MouseButton -" + e.Button.ToString()); } } private void btnMouseHook_Click(object sender, EventArgs e) { //mouseHook.InstallHook(); hook.InstallHook(HookHelper.HookType.MouseOperation); } private void btnKeyHook_Click(object sender, EventArgs e) { keyHook.InstallHook(); //hook.InstallHook(HookHelper.HookType.KeyOperation); } private void btnUnIntallHook_Click(object sender, EventArgs e) { //mouseHook.UnInstallHook(); //keyHook.UnInstallHook(); hook.UnInstallHook(HookHelper.HookType.KeyOperation);//卸载键盘钩子 hook.UnInstallHook(HookHelper.HookType.MouseOperation);//卸载鼠标钩子 } private void WriteLog(string message) { if (string.IsNullOrWhiteSpace(this.richMessage.Text)) { this.richMessage.Text = "监控鼠标和键盘操作记录:" + Environment.NewLine; } this.richMessage.AppendText(message + Environment.NewLine); this.richMessage.SelectionStart = this.richMessage.Text.Length; } void mouseHook_OnMouseActivity(object sender, MouseEventArgs e) { this.lblMousePosition.Text = string.Format("X:{0} Y={1} Wheel={2}",e.X,e.Y,e.Delta); if (e.Clicks > 0) { WriteLog("MouseButton -"+e.Button.ToString()); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { hook.UnInstallHook(HookHelper.HookType.KeyOperation);//卸载键盘钩子 hook.UnInstallHook(HookHelper.HookType.MouseOperation);//卸载鼠标钩子 } } }
代码整理,模拟数据:来自蓝天旭日的《C#钩子实现简单鼠标键盘的监控和屏蔽 》文章,其示例来自Germany的George Mamaladze的开源代码:
http://www.codeproject.com/KB/cs/globalhook.aspx
本文转自SanMaoSpace博客园博客,原文链接:http://www.cnblogs.com/SanMaoSpace/archive/2013/02/27/2935852.html,如需转载请自行联系原作者