最近做一个项目,需要截获特定应用程序里鼠标和键盘的消息事件。之前本人对windows底层的消息处理机制并不熟悉,通过学习知道钩子机制可以帮助我们截获处理windows消息或特定事件,现将本人所掌握的知识内容总结如下:
1.调用windows底层API,定义winAPI类
using System.Runtime.InteropServices;
public class WinApi
{
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//安装钩子
[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("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
//获得窗体名称
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText();
}
2.定义鼠标钩子和键盘钩子
public class MouseHook
{
private Point point;
private Point Point
{
get { return point; }
set
{
if (point != value)
{
point = value;
}
}
}
private int hHook;
public const int WH_MOUSE_LL = 14;
public WinApi.HookProc hProc;
public MouseHook()
{
this.Point = new Point();
}
public int SetHook()
{
hProc = new WinApi.HookProc(MouseHookProc);
hHook = WinApi.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero,0);
return hHook;
}
public void UnHook()
{
WinApi.UnhookWindowsHookEx(hHook);
}
private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
WinApi.MouseHookStruct MyMouseHookStruct = (WinApi.MouseHookStruct)Marshal.PtrToStructure
(lParam, typeof(WinApi.MouseHookStruct));
MouseButtons button = MouseButtons.None;
int clickCount = 0;
switch ((Int32)wParam)
{
case WM_LBUTTONDOWN:
button = MouseButtons.Left;
clickCount = 1;
var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
MouseClick(this, e);
break;
case WM_MOUSEMOVE:
var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
MouseMove(this, e);
break;
}
this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
//委托+事件(把钩到的消息封装为事件,由调用者处理)
public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
public event MouseMoveHandler MouseMove;
public delegate void MouseClickHandler(object sender, MouseEventArgs e);
public event MouseClickHandler MouseClick;
}
public class KeyboardHook
{
private int hHook;
public WinApi.HookProc hProc;
public int SetHook()
{
hProc = new WinApi.HookProc(KeyboardHookProc);
hHook = WinApi.SetWindowsHookEx(WH_KEYBOARD_LL, hProc, IntPtr.Zero,0);
return hHook;
}
public void UnHook()
{
WinApi.UnhookWindowsHookEx(hHook);
}
private int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
WinApi.KeyboardHookStruct kbhs= (WinApi.KeyboardHookStruct)Marshal.PtrToStructure(lParam,
typeof(WinApi.KeyboardHookStruct));
Keys key = (Keys)kbhs.vkCode;
switch ((Int32)wParam)
{
case WM_KEYDOWN:
var e = new KeyEventArgs(key);
KeyDown(this, e);
break;
case WM_KEYUP:
var e1 = new KeyEventArgs(key);
KeyUp(this, e1);
break;
}
}
return WinApi.CallNextHookEx(hHook, nCode, wParam, lParam);
}
//委托+事件(把钩到的消息封装为事件,由调用者处理)
public delegate void KeyDownEventHandler(object sender, KeyEventArgs e);
public delegate void KeyUpEventHandler(object sender, KeyEventArgs e);
public event KeyDownEventHandler KeyDown;
public event KeyUpEventHandler KeyUp;
}
3.应用程序调用
MouseHook mh;
KeyboardHook kh;
public Form1()
{
InitializeComponent();
//启动程序自动隐藏窗体
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
SetVisibleCore(false);
}
private void Form1_Load(object sender, EventArgs e)
{
mh = new MouseHook();
mh.SetHook();
mh.MouseMove += mh_MouseMove;
mh.MouseClick += mh_MouseClick;
kh = new KeyboardHook();
kh.SetHook();
kh.KeyDown += kh_KeyDown;
kh.KeyUp += kh_KeyUp;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
mh.UnHook();
kh.UnHook();
}
private void mh_MouseMove(object sender, MouseEventArgs e)
{
}
private void mh_MouseClick(object sender, MouseEventArgs e)
{
}
private void kh_KeyDown(object sender, KeyEventArgs e)
{
}
private void kh_KeyUp(object sender, KeyEventArgs e)
{
}