winform键盘全局与线程Hook
程序员文章站
2022-05-18 14:29:45
定义数据结构 /// /// 声明键盘钩子的封送结构类型 /// [StructLayout(LayoutKind.Sequential)] public class KeyboardHookStruct { public int vkCode;//表示一个 ......
定义数据结构
声明hook相关方法
//使用windows api函数代替获取当前实例的函数,防止钩子失效 [dllimport("kernel32.dll")] public static extern intptr getmodulehandle(string lpmodulename); //安装钩子 [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 int callnexthookex(int idhook, int ncode, int32 wparam, intptr lparam); //卸载钩子 [dllimport("user32.dll", charset = charset.auto, callingconvention = callingconvention.stdcall)] public static extern bool unhookwindowshookex(int idhook); // 取得当前线程编号(线程钩子需要用到) [dllimport("kernel32.dll")] static extern int getcurrentthreadid();
hook拦截方法
全局hook
private int keyboardhookproc(int ncode, int32 wparam, intptr lparam) { if ((ncode >= 0) && (onkeydownevent != null || onkeyupevent != null || onkeypressevent != null)) { keyboardhookstruct mykbhookstruct = (keyboardhookstruct)marshal.ptrtostructure(lparam, typeof(keyboardhookstruct)); //引发onkeydownevent if (onkeydownevent != null && (wparam == wm_keydown || wparam == wm_syskeydown)) { keys keydata = (keys)mykbhookstruct.vkcode; keyeventargs e = new keyeventargs(keydata); onkeydownevent(this, e); } } return callnexthookex(hkeyboardhook, ncode, wparam, lparam); }
线程hook
private int keyboardhookproc(int ncode, int32 wparam, intptr lparam) { if ((ncode >= 0) && (onkeydownevent != null || onkeyupevent != null || onkeypressevent != null)) { //引发onkeydownevent if (onkeydownevent != null && ncode==0) { keys keydata = (keys)wparam; keyeventargs e = new keyeventargs(keydata); onkeydownevent(this, e); } } return callnexthookex(hkeyboardhook, ncode, wparam, lparam); }
全局/线程hook参数结构区别
线程hook keyboardhookproc函数的各个参数意义如下: ncode 消息的类型,分hc_action和hc_noremove wparam 按键的虚拟键码 lparam 按键的相关参数信息,包括重复时间、按键的状态(按下或弹起)等 全局hook keyboardhookproc函数的各个参数意义如下: ncode 消息的类型,有hc_action wparam 按键的状态(按下或弹起)wm_keydown、wm_keyup、wm_syskeydown、wm_syskeyup lparam 指向keyboardhookstruct结构的指针,该结构包含了按键的详细信息。
添加hook
全局hook
public void start() { if (hkeyboardhook == 0) { keyboardhookprocedure = new hookproc(keyboardhookproc); using (system.diagnostics.process curprocess = system.diagnostics.process.getcurrentprocess()) using (system.diagnostics.processmodule curmodule = curprocess.mainmodule) hkeyboardhook = setwindowshookex(13, keyboardhookprocedure, getmodulehandle(curmodule.modulename), 0); if (hkeyboardhook == 0) { stop(); throw new exception("set globalkeyboardhook failed!"); } } }
线程hook
public void start() { if (hkeyboardhook == 0) { keyboardhookprocedure = new hookproc(keyboardhookproc); hkeyboardhook = setwindowshookex(2, keyboardhookprocedure, intptr.zero, getcurrentthreadid()); if (hkeyboardhook == 0) { stop(); throw new exception("set globalkeyboardhook failed!"); } } }
注:idhook 钩子类型,即确定钩子监听何种消息
线程钩子监听键盘消息应设为2,全局钩子监听键盘消息应设为13
线程钩子监听鼠标消息应设为7,全局钩子监听鼠标消息应设为14