如何在C#中使用全局鼠标、键盘Hook

摘要:
今天,一位同事问我如何在C#中使用全局钩子?以前,全局钩子是通过使用非托管C或C++编写DLL来实现的,但众所周知,C#是基于NetFramework的。如何实现全局钩子?于是我开始在互联网上搜索,最后找到了一篇文章,318804-HOWTO:SetaWindowsHook in Visual C#NET,它详细解释了如何使用鼠标钩子捕捉鼠标移动,但它只能用于

  今天,有个同事问我,怎样在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#里实现了全局钩子。

  我们来看一下主要代码段。示例源码下载地址请访问我的网站:http://www.vczx.com/article/show.php?id=1672

  首先倒入所需要的windows函数,主要有三个,SetWindowsHookEX用来安装钩子,UnhookWindowsHookEX用来卸载钩子以及CallNextHookEX用来将hook信息传递到链表中下一个hook处理过程。

如何在C#中使用全局鼠标、键盘Hook第1张[DllImport("user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook第1张           CallingConvention 
= CallingConvention.StdCall, SetLastError = true)]
如何在C#中使用全局鼠标、键盘Hook第1张        
private static extern int SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook第1张            
int idHook,
如何在C#中使用全局鼠标、键盘Hook第1张            HookProc lpfn,
如何在C#中使用全局鼠标、键盘Hook第1张            IntPtr hMod,
如何在C#中使用全局鼠标、键盘Hook第1张            
int dwThreadId);
如何在C#中使用全局鼠标、键盘Hook第1张
如何在C#中使用全局鼠标、键盘Hook第1张[DllImport(
"user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook第1张            CallingConvention 
= CallingConvention.StdCall, SetLastError = true)]
如何在C#中使用全局鼠标、键盘Hook第1张        
private static extern int UnhookWindowsHookEx(int idHook);
如何在C#中使用全局鼠标、键盘Hook第1张
如何在C#中使用全局鼠标、键盘Hook第1张[DllImport(
"user32.dll", CharSet = CharSet.Auto,
如何在C#中使用全局鼠标、键盘Hook第1张             CallingConvention 
= CallingConvention.StdCall)]
如何在C#中使用全局鼠标、键盘Hook第1张        
private static extern int CallNextHookEx(
如何在C#中使用全局鼠标、键盘Hook第1张            
int idHook,
如何在C#中使用全局鼠标、键盘Hook第1张            
int nCode,
如何在C#中使用全局鼠标、键盘Hook第1张            
int wParam,
如何在C#中使用全局鼠标、键盘Hook第1张            IntPtr lParam);

  下面是有关这两个low-level hook在Winuser.h中的定义:

如何在C#中使用全局鼠标、键盘Hook第20张如何在C#中使用全局鼠标、键盘Hook第21张/**//// <summary>
如何在C#中使用全局鼠标、键盘Hook第22张        
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level mouse input events.
如何在C#中使用全局鼠标、键盘Hook第23张        
/// </summary> 

如何在C#中使用全局鼠标、键盘Hook第1张        private const int WH_MOUSE_LL       = 14;
如何在C#中使用全局鼠标、键盘Hook第20张如何在C#中使用全局鼠标、键盘Hook第21张        
/**//// <summary>
如何在C#中使用全局鼠标、键盘Hook第22张        
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard  input events.
如何在C#中使用全局鼠标、键盘Hook第23张        
/// </summary> 

如何在C#中使用全局鼠标、键盘Hook第1张        private const int WH_KEYBOARD_LL    = 13;

  在安装全局钩子的时候,我们就要做替换了,将WH_MOUSE和WH_KEYBORAD分别换成WH_MOUSE_LL和WH_KEYBORAD_LL:

如何在C#中使用全局鼠标、键盘Hook第1张//install hook
如何在C#中使用全局鼠标、键盘Hook第1张
                hMouseHook = SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook第1张                    WH_MOUSE_LL, 
//原来是WH_MOUSE
如何在C#中使用全局鼠标、键盘Hook第1张
                    MouseHookProcedure,
如何在C#中使用全局鼠标、键盘Hook第1张                    Marshal.GetHINSTANCE(
如何在C#中使用全局鼠标、键盘Hook第1张                        Assembly.GetExecutingAssembly().GetModules()[
0]),
如何在C#中使用全局鼠标、键盘Hook第1张                    
0);
如何在C#中使用全局鼠标、键盘Hook第1张
如何在C#中使用全局鼠标、键盘Hook第1张
//install hook
如何在C#中使用全局鼠标、键盘Hook第1张
                hKeyboardHook = SetWindowsHookEx(
如何在C#中使用全局鼠标、键盘Hook第1张                    WH_KEYBOARD_LL, 
//原来是WH_KEYBORAD
如何在C#中使用全局鼠标、键盘Hook第1张
                    KeyboardHookProcedure,
如何在C#中使用全局鼠标、键盘Hook第1张                    Marshal.GetHINSTANCE(
如何在C#中使用全局鼠标、键盘Hook第1张                    Assembly.GetExecutingAssembly().GetModules()[
0]),
如何在C#中使用全局鼠标、键盘Hook第1张                    
0);
 
  这样替换了之后,我们就可以实现全局钩子了,而且,不需要写DLL。看一下程序运行情况:

如何在C#中使用全局鼠标、键盘Hook第45张

  下面是关于鼠标和键盘的两个Callback函数:

如何在C#中使用全局鼠标、键盘Hook第1张private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
如何在C#中使用全局鼠标、键盘Hook第20张如何在C#中使用全局鼠标、键盘Hook第21张        
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张            
// if ok and someone listens to our events
如何在C#中使用全局鼠标、键盘Hook第22张
            if ((nCode >= 0&& (OnMouseActivity != null))
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张            
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                
//Marshall the data from callback.
如何在C#中使用全局鼠标、键盘Hook第22张
                MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                
//detect button clicked
如何在C#中使用全局鼠标、键盘Hook第22张
                MouseButtons button = MouseButtons.None;
如何在C#中使用全局鼠标、键盘Hook第22张                
short mouseDelta = 0;
如何在C#中使用全局鼠标、键盘Hook第22张                
switch (wParam)
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张                
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                    
case WM_LBUTTONDOWN:
如何在C#中使用全局鼠标、键盘Hook第22张                        
//case WM_LBUTTONUP: 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//case WM_LBUTTONDBLCLK: 
如何在C#中使用全局鼠标、键盘Hook第22张
                        button = MouseButtons.Left;
如何在C#中使用全局鼠标、键盘Hook第22张                        
break;
如何在C#中使用全局鼠标、键盘Hook第22张                    
case WM_RBUTTONDOWN:
如何在C#中使用全局鼠标、键盘Hook第22张                        
//case WM_RBUTTONUP: 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//case WM_RBUTTONDBLCLK: 
如何在C#中使用全局鼠标、键盘Hook第22张
                        button = MouseButtons.Right;
如何在C#中使用全局鼠标、键盘Hook第22张                        
break;
如何在C#中使用全局鼠标、键盘Hook第22张                    
case WM_MOUSEWHEEL:
如何在C#中使用全局鼠标、键盘Hook第22张                        
//If the message is WM_MOUSEWHEEL, the high-order word of mouseData member is the wheel delta. 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//One wheel click is defined as WHEEL_DELTA, which is 120. 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
如何在C#中使用全局鼠标、键盘Hook第22张
                        mouseDelta = (short)((mouseHookStruct.mouseData >> 16& 0xffff);
如何在C#中使用全局鼠标、键盘Hook第22张                        
//TODO: X BUTTONS (I havent them so was unable to test)
如何在C#中使用全局鼠标、键盘Hook第22张                        
//If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released, 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//and the low-order word is reserved. This value can be one or more of the following values. 
如何在C#中使用全局鼠标、键盘Hook第22张                        
//Otherwise, mouseData is not used. 
如何在C#中使用全局鼠标、键盘Hook第22张
                        break;
如何在C#中使用全局鼠标、键盘Hook第86张                }

如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                
//double clicks
如何在C#中使用全局鼠标、键盘Hook第22张
                int clickCount = 0;
如何在C#中使用全局鼠标、键盘Hook第22张                
if (button != MouseButtons.None)
如何在C#中使用全局鼠标、键盘Hook第22张                    
if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2;
如何在C#中使用全局鼠标、键盘Hook第22张                    
else clickCount = 1;
如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                
//generate event 
如何在C#中使用全局鼠标、键盘Hook第22张
                 MouseEventArgs e = new MouseEventArgs(
如何在C#中使用全局鼠标、键盘Hook第22张                                                    button,
如何在C#中使用全局鼠标、键盘Hook第22张                                                    clickCount,
如何在C#中使用全局鼠标、键盘Hook第22张                                                    mouseHookStruct.pt.x,
如何在C#中使用全局鼠标、键盘Hook第22张                                                    mouseHookStruct.pt.y,
如何在C#中使用全局鼠标、键盘Hook第22张                                                    mouseDelta);
如何在C#中使用全局鼠标、键盘Hook第22张                
//raise it
如何在C#中使用全局鼠标、键盘Hook第22张
                OnMouseActivity(this, e);
如何在C#中使用全局鼠标、键盘Hook第86张            }

如何在C#中使用全局鼠标、键盘Hook第22张            
//call next hook
如何在C#中使用全局鼠标、键盘Hook第22张
            return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
如何在C#中使用全局鼠标、键盘Hook第23张        }

如何在C#中使用全局鼠标、键盘Hook第1张
如何在C#中使用全局鼠标、键盘Hook第1张private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
如何在C#中使用全局鼠标、键盘Hook第20张如何在C#中使用全局鼠标、键盘Hook第21张        
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张            
//indicates if any of underlaing events set e.Handled flag
如何在C#中使用全局鼠标、键盘Hook第22张
            bool handled = false;
如何在C#中使用全局鼠标、键盘Hook第22张            
//it was ok and someone listens to events
如何在C#中使用全局鼠标、键盘Hook第22张
            if ((nCode >= 0&& (KeyDown != null || KeyUp != null || KeyPress != null))
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张            
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                
//read structure KeyboardHookStruct at lParam
如何在C#中使用全局鼠标、键盘Hook第22张
                KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
如何在C#中使用全局鼠标、键盘Hook第22张                
//raise KeyDown
如何在C#中使用全局鼠标、键盘Hook第22张
                if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张                
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                    Keys keyData 
= (Keys)MyKeyboardHookStruct.vkCode;
如何在C#中使用全局鼠标、键盘Hook第22张                    KeyEventArgs e 
= new KeyEventArgs(keyData);
如何在C#中使用全局鼠标、键盘Hook第22张                    KeyDown(
this, e);
如何在C#中使用全局鼠标、键盘Hook第22张                    handled 
= handled || e.Handled;
如何在C#中使用全局鼠标、键盘Hook第86张                }

如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                
// raise KeyPress
如何在C#中使用全局鼠标、键盘Hook第22张
                if (KeyPress != null && wParam == WM_KEYDOWN)
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张                
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                    
bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80== 0x80 ? true : false);
如何在C#中使用全局鼠标、键盘Hook第22张                    
bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);
如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                    
byte[] keyState = new byte[256];
如何在C#中使用全局鼠标、键盘Hook第22张                    GetKeyboardState(keyState);
如何在C#中使用全局鼠标、键盘Hook第22张                    
byte[] inBuffer = new byte[2];
如何在C#中使用全局鼠标、键盘Hook第22张                    
if (ToAscii(MyKeyboardHookStruct.vkCode,
如何在C#中使用全局鼠标、键盘Hook第22张                              MyKeyboardHookStruct.scanCode,
如何在C#中使用全局鼠标、键盘Hook第22张                              keyState,
如何在C#中使用全局鼠标、键盘Hook第22张                              inBuffer,
如何在C#中使用全局鼠标、键盘Hook第22张                              MyKeyboardHookStruct.flags) 
== 1)
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张                    
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                        
char key = (char)inBuffer[0];
如何在C#中使用全局鼠标、键盘Hook第22张                        
if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
如何在C#中使用全局鼠标、键盘Hook第22张                        KeyPressEventArgs e 
= new KeyPressEventArgs(key);
如何在C#中使用全局鼠标、键盘Hook第22张                        KeyPress(
this, e);
如何在C#中使用全局鼠标、键盘Hook第22张                        handled 
= handled || e.Handled;
如何在C#中使用全局鼠标、键盘Hook第86张                    }

如何在C#中使用全局鼠标、键盘Hook第86张                }

如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张                
// raise KeyUp
如何在C#中使用全局鼠标、键盘Hook第22张
                if (KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
如何在C#中使用全局鼠标、键盘Hook第52张如何在C#中使用全局鼠标、键盘Hook第53张                
如何在C#中使用全局鼠标、键盘Hook第49张{
如何在C#中使用全局鼠标、键盘Hook第22张                    Keys keyData 
= (Keys)MyKeyboardHookStruct.vkCode;
如何在C#中使用全局鼠标、键盘Hook第22张                    KeyEventArgs e 
= new KeyEventArgs(keyData);
如何在C#中使用全局鼠标、键盘Hook第22张                    KeyUp(
this, e);
如何在C#中使用全局鼠标、键盘Hook第22张                    handled 
= handled || e.Handled;
如何在C#中使用全局鼠标、键盘Hook第86张                }

如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第86张            }

如何在C#中使用全局鼠标、键盘Hook第22张
如何在C#中使用全局鼠标、键盘Hook第22张            
//if event handled in application do not handoff to other listeners
如何在C#中使用全局鼠标、键盘Hook第22张
            if (handled)
如何在C#中使用全局鼠标、键盘Hook第22张                
return 1;
如何在C#中使用全局鼠标、键盘Hook第22张            
else
如何在C#中使用全局鼠标、键盘Hook第22张                
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
如何在C#中使用全局鼠标、键盘Hook第23张        }

参考资料:MSDN

免责声明:文章转载自《如何在C#中使用全局鼠标、键盘Hook》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C++ 宏和模板简介foreign key constraint fails错误的原因下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

从word中复制内容包含图片到fckeditor编辑器中

如何做到 ueditor批量上传word图片? 1、前端引用代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="ht...

java执行linux shell命令,并拿到返回值

1 packagecom.pasier.xxx.util; 2 3 importjava.io.IOException; 4 importjava.io.InputStream; 5 importjava.nio.charset.Charset; 6 7 importorg.slf4j.Logger; 8 importorg.slf4j.LoggerF...

JAVA之编码----&amp;gt;CSV在文本下是正常的,用EXCEL打开是乱码的问题

JAVA之编码---->CSV在文本下是正常的,用EXCEL打开是乱码的问题 在JAVA下输出文件流,保存成CSV(用UTF-8)文件,怎么处理用EXCEL下是乱码,但是在记事本等其他软件都是正常的,同时显示也是UTF-8的编码,经过测试发现如下结果: 1、EXCEL只能打开ANSI的编码,而ANSI需要当前操作系统是什么编码,就用什么编码。如中文...

git hook相关内容

一、Git钩子 Git 能在特定的重要动作发生时触发自定义脚本,它能完成下列一些很常用的场景: 1.多人开发代码语法、规范强制统一2.commit message 格式化、是否符合某种规范3.如果有需要,测试用例的检测4.服务器代码有新的更新的时候通知所有开发成员5.代码提交后的项目自动打包(git receive之后) 等等... 每一个使用了 git...

c# 定时关闭 MessageBox 或弹出的模态窗口

我们都知道,MessageBox弹出的窗口是模式窗口,模式窗口会自动阻塞父线程的。所以如果有以下代码: MessageBox.Show("内容',"标题"); 则只有关闭了MessageBox的窗口后才会运行下面的代码。而在某些场合下,我们又需要在一定时间内如果在用户还没有关闭窗口时能自动关闭掉窗口而避免程序一直停留不前。这样的话我们怎么做呢?上面也说...

MySQL varchar 最大长度,text 类型占用空间剖析

MySQL 表中行的最大大小为 65,534(实际行存储从第二个字节开始)字节。每个 BLOB 和 TEXT 列只占其中的 5 至 9 个字节。 那么来验证下 varchar 类型的实际最大长度:测试环境:MySQL版本 5.7.19 //首先要设置下 mysql 为严格执行模式,不然 varchar 超出最大长度为自动转为 text 类型 set sql...