阅读本文章前应具有一定编程基础和 Window API 相关知识
第一步,先封装HookBase抽象类,因所有Hook的都具有注册、卸载逻辑,且注册、卸载大同小易。如下:
public abstract class HookBase : IHook
{
private static Dictionary<int, IHook> m_Hooks;
private IntPtr m_ProcessId;
private int m_ThreadId;
private HookType m_HookType;
private HookProc m_HookProc;
protected internal int m_HookId;
static HookBase()
{
m_Hooks = new Dictionary<int, IHook>();
}
private HookBase(HookType hookType)
{
m_HookType = hookType;
m_HookProc = HookProc;
}
protected HookBase(IntPtr processId, HookType hookType)
: this(hookType)
{
m_ProcessId = processId;
if (m_ProcessId == IntPtr.Zero)
{
m_ProcessId = HookHelper.GetCurrentProcessId();
}
}
protected HookBase(int threadId, HookType hookType)
: this(hookType)
{
m_ThreadId = threadId;
if (m_ThreadId == 0)
{
m_ThreadId = HookHelper.GetCurrentThreadId();
}
}
public void Install()
{
if (m_ThreadId != 0)
{
m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, IntPtr.Zero, m_ThreadId);
}
else
{
if (m_ProcessId == IntPtr.Zero)
{
return;
}
m_HookId = HookHelper.SetWindowsHookEx(m_HookType, m_HookProc, m_ProcessId, 0);
}
if (m_HookId == 0)
{
return;
}
if (!m_Hooks.ContainsKey(m_HookId))
{
m_Hooks.Add(m_HookId, this);
}
}
public void Uninstall()
{
if (m_HookId == 0)
{
return;
}
var flag = HookHelper.UnhookWindowsHookEx(m_HookId);
if (flag)
{
if (m_Hooks.Remove(m_HookId))
{
m_HookId = 0;
}
}
}
protected abstract int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
第二步 ,因鼠标Hook分为线程鼠标Hook以及全局鼠标Hook两种,仅注册方式有点区别。为使用方便,将其封装为事件注册方式。如下
public abstract class MouseHookBase : HookBase
{
protected MouseHookBase(IntPtr processId)
: base(processId, HookType.WH_MOUSE_LL)
{
}
protected MouseHookBase(int threadId)
: base(threadId, HookType.WH_MOUSE)
{
}