- 浏览: 117592 次
- 性别:
- 来自: 南宁
文章分类
最新评论
今天,有个同事问我,怎样在C#中使用全局钩子?以前写的全局钩子都是用unmanaged C或C++写个DLL来实现,可大家都知道,C#是基于.Net Framework的,是managed,怎么实现全局钩子呢?于是开始到网上搜索,好不容易找到一篇,318804 - HOW TO: Set a Windows Hook in Visual C# .NET,里面详细的说明了如何使用鼠标钩子捕获鼠标的移动等,可是,它只能在Application里起作用,出了Application就没用了,就是说它还是没有实现全局钩子,而且文章结尾处说:“Global Hooks are not supported in the .NET Framework...”,这可怎么办呢?
别担心,办法总是有的,经过一番摸索以后,发现WH_KEYBORAD_LL和WH_MOUSE_LL这两个low-level的hook可以被安装成全局的,这就好办了,我们不妨用这两个low-level的hook替换掉WH_KEYBORAD和WH_MOUSE,于是开始测试。结果成功了,在C#里实现了全局钩子。
我们来看一下主要代码段。
首先倒入所需要的windows函数,主要有三个,SetWindowsHookEX用来安装钩子,UnhookWindowsHookEX用来卸载钩子以及CallNextHookEX用来将hook信息传递到链表中下一个hook处理过程。
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(
int idHook,
int nCode,
int wParam,
IntPtr lParam);
下面是有关这两个low-level hook在Winuser.h中的定义:
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level mouse input events.
/// </summary>
private const int WH_MOUSE_LL = 14;
/// <summary>
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard input events.
/// </summary>
private const int WH_KEYBOARD_LL = 13;
在安装全局钩子的时候,我们就要做替换了,将WH_MOUSE和WH_KEYBORAD分别换成WH_MOUSE_LL和WH_KEYBORAD_LL:
hMouseHook = SetWindowsHookEx(
WH_MOUSE_LL, //原来是WH_MOUSE
MouseHookProcedure,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
//install hook
hKeyboardHook = SetWindowsHookEx(
WH_KEYBOARD_LL, //原来是WH_KEYBORAD
KeyboardHookProcedure,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
下面是关于鼠标和键盘的两个Callback函数:
private int MouseHookProc(int nCode, int wParam, IntPtr lParam) { // if ok and someone listens to our events if ((nCode >= 0) && (OnMouseActivity != null)) { //Marshall the data from callback. MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
//detect button clicked MouseButtons button = MouseButtons.None; short mouseDelta = 0; switch (wParam) { case WM_LBUTTONDOWN: //case WM_LBUTTONUP: //case WM_LBUTTONDBLCLK: button = MouseButtons.Left; break; case WM_RBUTTONDOWN: //case WM_RBUTTONUP: //case WM_RBUTTONDBLCLK: button = MouseButtons.Right; break; case WM_MOUSEWHEEL: //If the message is WM_MOUSEWHEEL, the high-order word of mouseData member is the wheel delta. //One wheel click is defined as WHEEL_DELTA, which is 120. //(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value mouseDelta = (short)((mouseHookStruct.mouseData >> 16) & 0xffff); //TODO: X BUTTONS (I havent them so was unable to test) //If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, //or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released, //and the low-order word is reserved. This value can be one or more of the following values. //Otherwise, mouseData is not used. break; }
//double clicks int clickCount = 0; if (button != MouseButtons.None) if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2; else clickCount = 1;
//generate event MouseEventArgs e = new MouseEventArgs( button, clickCount, mouseHookStruct.pt.x, mouseHookStruct.pt.y, mouseDelta); //raise it OnMouseActivity(this, e); } //call next hook return CallNextHookEx(hMouseHook, nCode, wParam, lParam); } |
{
//indicates if any of underlaing events set e.Handled flag
bool handled = false;
//it was ok and someone listens to events
if ((nCode >= 0) && (KeyDown != null || KeyUp != null || KeyPress != null))
{
//read structure KeyboardHookStruct at lParam
KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
//raise KeyDown
if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyDown(this, e);
handled = handled || e.Handled;
}
// raise KeyPress
if (KeyPress != null && wParam == WM_KEYDOWN)
{
bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);
byte[] keyState = new byte[256];
GetKeyboardState(keyState);
byte[] inBuffer = new byte[2];
if (ToAscii(MyKeyboardHookStruct.vkCode,
MyKeyboardHookStruct.scanCode,
keyState,
inBuffer,
MyKeyboardHookStruct.flags) == 1)
{
char key = (char)inBuffer[0];
if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
KeyPressEventArgs e = new KeyPressEventArgs(key);
KeyPress(this, e);
handled = handled || e.Handled;
}
}
// raise KeyUp
if (KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
{
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
KeyEventArgs e = new KeyEventArgs(keyData);
KeyUp(this, e);
handled = handled || e.Handled;
}
}
//if event handled in application do not handoff to other listeners
if (handled)
return 1;
else
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
发表评论
-
v6 常用数据操做 VB数据库记录集查询四种方法
2012-02-26 15:09 1091在VB中进行数据库记录的查询操作,必需根据打开数据库的 ... -
.net级联删除自联表树结构
2011-07-21 21:35 1008今天同事问我说如何删除树结构的自联表,要求是子树是无限的未知的 ... -
request 操作大全
2011-06-14 11:09 879using System; using System.Web; ... -
。net操作各类时间段获取当前月的1号和月尾
2011-06-09 16:58 1796DateTime dt = DateTime.Now; // ... -
c#连接各类数据库大全
2011-06-01 17:10 1020C#连接SQL数据库 中国 ... -
。net 绑定日期格式化处理
2011-05-09 12:08 814日期和时间的格式化处 ... -
超级简洁的.net防止重复提交数据的处理方法仅仅1行代码
2011-05-09 11:47 676Response.Redirect(Request.Raw ... -
gridview自定义分页样式
2011-01-13 17:13 1234gridview自定义分页样式 2009年12月12日 星期 ... -
GridView分页模版
2011-01-13 17:12 898<PagerTemplate> ... -
.net DateTable的用法
2011-01-13 14:22 814SqlConnection con = new SqlCo ... -
cs vb 链接webconfig的 链接字符串
2011-01-12 22:39 8181.如果这个<add....... />在< ... -
vb.net 生成静态页面列表分页
2010-12-20 15:03 1000Sub test() Dim t As li ... -
.net上传图片生成缩略图,加文字水印和图片水印
2010-12-09 20:53 1537引用页的代码: Imports dll图片水印缩略图 ... -
Directory 常用的成员和方法
2010-12-08 11:06 678GetLogicalDrives 检索此计算机上格式为“&l ...
相关推荐
比如,目前市场上很多界面库在绘制窗口标题栏的时候,去掉了窗口的WS_CAPTION属性, 导致GetClientRect、GetWindowRect方法失效,从而加大了界面开发和设计的难度,当然也导致不能完美支持SDI/MDI等界面框架。...
关于钩子(hook)编程的源码,方方面面都有介绍,各种钩子,全局钩子,鼠标钩子等等 关于钩子的原理,在本人博客有详细介绍: http://blog.cdsn.net/mingojiang
Hook(钩子)并不是一项很难的技术,但对于初学者来说还是一个不小的门槛。为此,我将键盘Hook做成了...2.你可以参考我的控件设计模式来设计自己的Hook控件,如键盘Hook。 黄晓斌 hxb_leiyuan2000@163.net QQ:478522325
2.你可以参考我的控件设计模式来设计自己的Hook控件,如键盘Hook。3.本来想写一个组件包的,其中包括各种Hook控件,以及读写端口的控件,以方便初学者的使用,可是要些论文,以后再说吧。 黄晓斌 hxb_leiyuan2000@...
ActiveX Designer ActiveX 设计器 ActiveX Document Migration Wizard ActiveX 文档移植向导 ActiveX-enabled 支持 ActiveX 的 Add key/ Multiply key/ Substract key/ Devide key 加号键/ 乘号键/ 减号键/ 除号键 ...
· SpyWorks hook控件和子类控件(subclassing)的更新版本,支持Visual Studio .NET的最终版,包含相关的.NET Primary InterOp程序集。 · 支持从Visual Studio .NET程序集导出函数。 · 该更新版包含大量的样例 ...
资源包含文件:设计报告word+源码 部分网站的 url 构成中含有加密参数,这些参数的加密方法写在了 JavaScript 中,而 js 通常经过了压缩,混淆和加密;本项目通过 AJAX 断点,hook 方法先寻找到加密入口,其次通过 ...
皮肤控件研究文档,破解后的库文件,皮肤设计工具使用教程 皮肤控件 skin++ skincrafter SkinFeature IrisSkin 我共享的都是本人实际验证过的精品,有文档,破解后的库文件,皮肤设计工具使用教程, 1 软件界面 每...
至于这样设计软件做什么用的,我就不说了,请自行领会。不过大飞飞基于学习目的开发,希望大家不要用做不正当用途,感谢!有啥问题可以与我联系:hedda # Plusii.com 这里提供的是RAR制作的安装包, 也可以直接改为...
比如,目前市场上很多界面库在绘制窗口标题栏的时候,去掉了窗口的WS_CAPTION属性, 导致GetClientRect、GetWindowRect方法失效,从而加大了界面开发和设计的难度,当然也导致不能完美支持SDI/MDI等界面框架。...
该 XPMenu.ocx 也是网上来的,很流行的HookMenu,但居然不支持MDI窗体(无法显示图标),实在令人失望。 这个代码完整的实现了 Office XP 风格界面,虽然许多地方都是模拟的,但往往最简单的方法就是最好的,反正...
基于Cesium+VUE模拟实现火箭发射全过程效果组件...文章描述:https://blog.csdn.net/qq_34205305/article/details/125582004 代码不易,略收小费,使用过程中如果有任何问题欢迎在文章下进行评论或者私信,百分百回复哦
设计类: AutoCAD 2004 、圆方BtoCAD、等 <br> 4. ................... <br> <br>SEFS--透明加密内核 ============================================= 商业授权:sales@sefs.net Bug 报告:bug@...
hook api 、 com 接口和 delphi 对象方法 属性表控件 32 位位图 数据结构和事件系统 点九图 用于生成不同 delphi 版本的组件包 使用 THttpClient 的简单自动更新程序 一个 pascal 代码实现的类似 html5 ...
4.1.3 设计对话框 150 4.2 创建与销毁对话框 153 4.2.1 模态对话框 153 4.2.2 非模式对话框 159 4.2.3 属性页对话框 163 4.3 消息对话框 173 4.4 通用对话框 175 4.4.1 文件打开对话框 176 4.4.2 文件保存对话框 178...
##设计模式 ##HTTPS ##JS全栈 ##Underscore.js ##文件上传 ##SWFUpload ##柯里化 ##jqGrid ##localStorage/sessionStorage ##Cookie ##onunload/onbeforeunload ##模板引擎 ##达夫设备 ##Promise ##Hook ##函数式...
12.2.2 .NET程序设计语言 428 12.2.3 通用类型系统 428 12.3 中间语言 429 12.3.1 求值堆栈 430 12.3.2 活动记录 430 12.3.3 IL指令 430 12.3.4 代码实例 433 12.4 反编译器 443 12.5 混淆器 444 12.5.1 重命名符号 ...