纯C#钩子实现及应用
要实现系统钩子其实很简单,调用三个Win32的API即可。5 W5 Y' x" Y0 j& }# l
SetWindowsHookEx 用于设置钩子。(设立一道卡子,盘查需要的信息)
4 d0 M( l# e9 t) Q" f# L打造最好的电脑自学交流论坛
1 R) n( ^+ P$ ]8 R! V电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站 [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]我爱电脑技术社区--打造最好的电脑技术自学交流平台, t3 n& d7 t9 ~7 j" i3 l+ _3 E
public static extern IntPtr SetWindowsHookEx ( WH_Codes idHook, HookProc lpfn,
0 q( A2 a, ^8 v, ?7 i打造最好的电脑自学交流论坛 IntPtr pInstance, int threadId );我爱电脑技术社区--打造最好的电脑技术自学交流平台( H& o$ m) T7 l' ]/ ?5 J
我爱电脑技术论坛$ z2 M4 }, X# {% m
CallNextHookEx 用于传递钩子(消息是重要的,所以从哪里来,就应该回到哪里去,除非你决定要封锁消息)打造最好的电脑自学交流论坛# w8 W5 w% y$ `; ^2 J n& g) p, M
, w, x5 P+ a4 a" k s1 V# Q电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站 [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站" L( b& @$ Y1 n. M
public static extern int CallNextHookEx ( IntPtr pHookHandle, int nCode,我爱电脑技术论坛, a, ~# v# V8 v* p2 x
Int32 wParam, IntPtr lParam );我爱电脑技术社区--打造最好的电脑技术自学交流平台+ r6 S, V" \* L8 f1 q. U) j7 W
4 G+ a0 f) r9 o% m3 D2 [: `6 r \电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站 UnhookWindowsHookEx 卸载钩子(卸载很重要,卡子设多了会造成拥堵)www.520diannao.com/ z, A- d) s( D8 i2 {
[DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]我爱电脑技术论坛0 }7 a% b& ~( z N1 f7 b
public static extern bool UnhookWindowsHookEx ( IntPtr pHookHandle );打造最好的电脑自学交流论坛& l9 j1 i" W% ^. L- o+ e
打造最好的电脑自学交流论坛) L+ C: I; l* b
在《HOW TO:在 Visual C# .NET 中设置窗口挂钩》一文中有如下描述: 在 .NET 框架中不支持全局挂钩www.520diannao.com# M, ?# e3 j _/ p' F4 j
您无法在 Microsoft .NET 框架中实现全局挂钩。若要安装全局挂钩,挂钩必须有一个本机动态链接库 (DLL) 导出以便将其本身插入到另一个需要调入一个有效而且一致的函数的进程中。这需要一个 DLL 导出,而 .NET 框架不支持这一点。托管代码没有让函数指针具有统一的值这一概念,因为这些函数是动态构建的代理。网上查找了很多代码,大都另外包含了一个C++的DLL,用于标识包含lpfn所指的子程的DLL,似乎也验证了这一说法。
9 R1 j" @" `$ t6 O: swww.520diannao.com电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站' y5 O3 A3 p5 m2 o }
但实际上并非如此,使用如下代码即可实现全局钩子:
. M; L0 O! p& `6 \4 q$ G IntPtr pInstance = Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().ManifestModule );
% z9 ]4 ^4 R/ `& S7 Z电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站 Win32API.SetWindowsHookEx( WH_MOUSE_LL,m_MouseHookProcedure, pInstance, 0 );注:ManifestModule属性是.Net Framework 2.0中新增加的,所以当你依然使用.Net Framework 1.x的时候,可以使用GetModules方法获取当前程序集的所有模块,然后用其中的一个作为GetHINSTAN方法的参数,来获得合适的句柄指针。
9 V* b- m7 c" u4 c- l) q$ i9 |# G我爱电脑技术论坛打造最好的电脑自学交流论坛& L6 Q$ z) d* i
钩子应用DEMO-屏幕放大器
- P& j& \$ h. o7 i) R2 r& z! b# ]! q* \) J5 X& U1 w" Z
点击下载可执行文件(Shift + Esc 退出程序)
# v4 Q& X$ X3 R我爱电脑技术论坛 点击下载源文件
% c7 |6 H( O# F& I我爱电脑技术论坛% R. [1 G# E, ^2 ~
所谓屏幕放大器,类似与WINDOWS系统中的辅助工具中的放大镜。
$ Z) Q. q* K# i" [我爱电脑技术社区--打造最好的电脑技术自学交流平台 前两天在找资料的时候突然发现在2.0中,Graphics类多了一个CopyFromScreen方法,可以直接实现屏幕抓取,于是有了做屏幕放大器的想法。
; g4 [7 \7 I, \3 r4 s电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站9 S" k; c+ M9 r4 u# L" q
首先我定义了是SKHOOK类,来截取键盘及鼠标。
- L! j% d. V) ?& F" s: u) r* P电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站 由于需要获得全局的鼠标消息来确定截屏位置,同时要建立一个全局的快捷键来退出程序,所以只能用上面说的钩子来实现。
2 @. a( G) c, X我爱电脑技术社区--打造最好的电脑技术自学交流平台打造最好的电脑自学交流论坛! h3 p' K# q' B* a- k
然后我通过鼠标点来设置采样区域,以及窗体的位置。5 k7 L; |$ v! w: r
采样区域为鼠标点为中心的50*50的矩形区域。窗体位置只实现了简单的鼠标跟随,同时保证了和采样区域不重叠。电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站# G5 E& U0 ~/ {. N$ P
电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站& j, U! M0 A* a& S
另外我使用了一个BackgroundWorker来定时刷新更新窗体。主要是为了实现动画内容(GIF、Flash等)的显示。我爱电脑技术论坛! }2 @3 c1 g3 I7 R6 u3 Z7 o6 Y% K
8 l0 c% { f5 v* m/ l2 M 至于移动的时候使用SetWindowPos,主要是为了保证窗体一直位于顶层,否则的话一些置顶的窗口(如QQ)等将覆盖当前窗口。
9 | h B) l Q/ `( F, s" Z打造最好的电脑自学交流论坛我爱电脑技术论坛2 M6 @4 d: K( a* i' y6 ?
已知问题:打造最好的电脑自学交流论坛5 D7 s0 w7 @* O0 {
1。不支持视频截取电脑,技术,IT,学习,交流,网络安全,QQ,硬件,软件,编程,教程,建站& L3 B y+ o, _# g
2。部分ToolTip提示无法显示
P, V- o0 [7 w! W$ ^: q5 G我爱电脑技术社区--打造最好的电脑技术自学交流平台 3。可能会造成背景窗口部分显示失效。打造最好的电脑自学交流论坛- h, G# [" K: B5 S9 q
4。SKHook类中,对于键盘事件处理,存在不足。# C. f6 G* y$ F6 q& u
. y* ^# e) B6 U0 l6 U$ jwww.520diannao.com 还有一个问题,就是当鼠标移动比较快的时候,窗口边框会有残影,不知道是什么原因。这个问题在以往的Fram窗体中一直是困扰我的问题,至今没有找到解决的办法。