键盘监控的实现Ⅰ——Keyboard Hook API函数

简介:

在实际应用中,键盘监控是一种很常见的技术,它包括按键的记录、按键的过滤、按键的修改(映射)等。比方说,我们想统计用户的击键情况,这个就是按键的记录;我们想屏蔽某些系统键(例如Alt键、Win键),这个是按键的过滤;我们想改变按键的值,例如按下A,出来的是Z,在例如按下A,出来按键的组合SDFG等(貌似这个在游戏中比较多,有些游戏的大绝招都比较难按,用这个一劳永逸),这个是按键的修改。

  键盘监控的具体实现,用的是微软的Keyboard Hook API函数。

  首先解释下,什么是Hook函数。

  WINDOW的消息处理机制为了能在应用程序中监控系统的各种事件消息,提供了挂接各种反调函数(HOOK)的功能。这种挂钩函数(HOOK)类似扩充中断驱动程序,挂钩上可以挂接多个反调函数构成一个挂接函数链。系统产生的各种消息首先被送到各种挂接函数,挂接函数根据各自的功能对消息进行监视、修改和控制等,然后交还控制权或将消息传递给下一个挂接函数以致最终达到窗口函数。WINDOW系统的这种反调函数挂接方法虽然会略加影响到系统的运行效率,但在很多场合下是非常有用的,通过合理有效地利用键盘事件的挂钩函数监控机制可以达到预想不到的良好效果。

  简单的说,就是在消息到达Window之前,系统允许你安装Hook函数来拦截消息,并对消息进行处理。Hook函数也是有类别的,不同的函数实现不同的功能。

  先看下函数的申明:

  Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" ( _

    ByVal idHook As Integer,  _       '安装的钩子的类型

    ByVal lpfn As HookProc,  _       '消息的处理函数

    ByVal hMod As IntPtr, _        '应用程序事例句柄

    ByVal dwThreadId As Integer _     '线程ID

    ) As Integer

  钩子卸载函数

  Private Declare Function UnhookWindowsHookEx Lib "user32" ( _

    ByVal idHook As Integer _      '要卸载的HOOK函数的句柄

    ) As Integer

  调用下一个HOOK函数

  Private Declare Function CallNextHookEx Lib "user32" ( _

    ByVal idHook As Integer,  _      '本HOOK函数的句柄

    ByVal nCode As Integer,  _      '消息的类型

    ByVal wParam As Integer,  _      '消息的参数

    ByVal lParam As IntPtr _        '消息的参数

    ) As Integer

  

  消息函数的委托

  Private Delegate Function HookProc( _

    ByVal nCode As Integer,  _      '消息的类型

    ByVal wParam As Integer, _      '消息的参数

    ByVal lParam As IntPtr _        '消息的参数

    ) As Integer

  钩子类型的常数

  Private Const  WH_KEYBOARD_LL  As  Integer= 13    '全局键盘钩子(又称为底层)
Private Const  WH_KEYBOARD As  Integer = 2      '普通键盘钩子

 

  按键信息结构

  Public Structure KeyboardHookStruct
Dim vkCode As Integer
Dim ScanCode As Integer
Dim Flags As Integer
Dim Time As Integer
Dim DwExtraInfo As Integer
End Structure

 

  我们用一个类来实现键盘的监控。

  首先定义两个变量

  Private hKeyboardHook As Integer
Private KeyboardHookProcedure As HookProc

  

  装载钩子的函数

  Public Sub Hook()
If hKeyboardHook = 0 Then
KeyboardHookProcedure = New HookProc(AddressOf KeyboardHookProc)
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.GetModules()(0)), 0)

      If hKeyboardHook = 0 Then
UnHook()
Throw New Win32Exception(Marshal.GetLastWin32Error)
End If
         End If
End Sub

  注:函数执行后,会安装Hook,所有的按键消息在到达window前都会被函数KeyboardHookProc拦截到。我们在后面的KeyboardHookProc函数中处理拦截的消息。

 

  卸载钩子的函数

  Public Sub UnHook()
If hKeyboardHook <> 0 Then
Dim retKeyboard As Integer = UnhookWindowsHookEx(hKeyboardHook)
hKeyboardHook = 0
If retKeyboard = 0 Then Throw New Win32Exception(Marshal.GetLastWin32Error)
End If
End Sub

 

  按键消息的处理函数

  Private Function KeyboardHookProc(ByVal nCode As IntegerByVal wParam As IntegerByVal lParam As IntPtr) As Integer
      Dim MyKeyboardHookStruct As KeyboardHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(KeyboardHookStruct)), KeyboardHookStruct)

  

  自己处理的一些代码,例如:记录、屏蔽、映射等

 

  Return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)
End Function

 

  以上就是基本的按键监控类的代码。不过要注意以下几点:

  1、Keyboard的HOOK函数分为两种,WH_KEYBOARD_LL和WH_KEYBOARD。我们一般用第一种,全局的键盘钩子,能拦截所有的键盘按键的消息。

  2、网上有人说,全局的钩子要放在单独的DLL中才能使用。我试了一下,不放在单独的DLL中,在XP+VS2005下,调试和运行都没有问题;在XP+VS2008下,调试会出错,不过编译后能运行;在WIN7+VS2010下,调试会出错,编译后能运行。这方面有研究的网友,望不吝赐教。

  3、WH_KEYBOARD_LL和WH_KEYBOARD,这是两种不同的钩子,虽然最后都是KeyboardHookProc函数处理拦截的消息,但是具体的每个参数的意义却完全不一样。

    WH_KEYBOARD钩子。KeyboardHookProc函数的各个参数意义如下:

    nCode    消息的类型,分HC_ACTION和HC_NOREMOVE

    wParam    按键的虚拟键码 

    lParam    按键的相关参数信息,包括重复时间、按键的状态(按下或弹起)等

 

    WH_KEYBOARD_LL钩子。KeyboardHookProc函数的各个参数意义如下:

     nCode    消息的类型,有HC_ACTION

    wParam    按键的状态(按下或弹起)WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、WM_SYSKEYUP

    lParam    指向KeyboardHookStruct结构的指针,该结构包含了按键的详细信息。     

    可以看出,这两种钩子的参数的定义是完全不一样的。而在之前的代码中:Dim MyKeyboardHookStruct As KeyboardHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(KeyboardHookStruct)), KeyboardHookStruct)就是将该指针指向的内容复制到指定的结构中。

 

  本文介绍了全局键盘钩子的实现中的一些基本的HOOK API函数的介绍。具体的实现留待后文详解。


    本文转自万仓一黍博客园博客,原文链接:http://www.cnblogs.com/grenet/archive/2010/12/07/1898840.html,如需转载请自行联系原作者

相关文章
|
1月前
|
缓存 JavaScript 算法
活用 Composition API 核心函数,打造卓越应用(下)
活用 Composition API 核心函数,打造卓越应用(下)
|
1月前
|
存储 JavaScript API
活用 Composition API 核心函数,打造卓越应用(上)
活用 Composition API 核心函数,打造卓越应用(上)
|
25天前
|
人工智能 关系型数据库 Serverless
Serverless 应用引擎常见问题之API生成的函数镜像改为自定义的镜像如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
37 3
|
24天前
|
Java 数据库连接 API
Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API
Java 是一种广泛使用的、面向对象的编程语言,始于1995年,以其跨平台性、安全性和可靠性著称,应用于从移动设备到数据中心的各种场景。基础概念包括变量(如局部、实例和静态变量)、数据类型(原始和非原始)、条件语句(if、else、switch等)、函数、循环、异常处理、数据结构(如数组、链表)和面向对象编程(类、接口、继承等)。深入学习还包括包、内存管理、集合框架、序列化、网络套接字、泛型、流、JVM、垃圾回收和线程。构建工具如Gradle、Maven和Ant简化了开发流程,Web框架如Spring和Spring Boot支持Web应用开发。ORM工具如JPA、Hibernate处理对象与数
88 3
|
1月前
|
数据采集 存储 监控
利用API接口进行竞品价格监控
在电子商务和零售行业,了解竞争对手的定价策略对于保持市场竞争力至关重要。随着技术的发展,通过编程接口(API)获取商品详情成为企业监控竞品价格的有效手段。本文将详细介绍如何利用API接口实现竞品价格监控的流程和策略。
|
1月前
|
存储 数据采集 监控
利用API接口进行竞品价格监控的综合指南
在竞争日益激烈的市场中,实时监控竞争对手的价格对于保持竞争优势至关重要。通过API接口自动化收集和分析竞品价格信息,企业可以迅速做出反应,调整自身的定价策略。以下是如何利用API接口进行有效的竞品价格监控的详细步骤:
|
3月前
|
运维 监控 API
监控API的指标
监控API的指标
|
3月前
|
监控 JavaScript 前端开发
这个 hook api,是 useState 的双生兄弟
这个 hook api,是 useState 的双生兄弟
|
4月前
|
存储 API 数据安全/隐私保护
FreeRTOS入门教程(信号量的概念及API函数使用)
FreeRTOS入门教程(信号量的概念及API函数使用)
92 0
|
5月前
|
监控 网络协议 API
开发常用的 3种 API 监控报告
API 监控报告是一种监测 API 异常的工具。在 API 管理中,查看 API 异常监控的监控报告,是 Eolink Apikit 常用的功能。Eolink Apikit 的监控报告有 3种:单接口监控报告、流程监控报告、项目监控报告
39 0