博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于用HOOK拦截键盘的一些问题
阅读量:5763 次
发布时间:2019-06-18

本文共 4545 字,大约阅读时间需要 15 分钟。

因为MSDN上说要这样做,所以我就这样做的,读懂MSDN是关键,下面来仔细阅读一下MSDN,看它到底是怎样描述的。阅读的时候我先给出原文,再进行自己的一些翻译或描述。
先看回调函数KeyboardProc的参数描述:
Syntax
LRESULT CALLBACK KeyboardProc( 
 int code,
 WPARAM wParam,
 LPARAM lParam
);
Parameters
code
[in] Specifies a code the hook procedure uses to determine how to process the message. If code is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx. This parameter can be one of the following values.
HC_ACTION
The wParam and lParam parameters contain information about a keystroke message.
HC_NOREMOVE
The wParam and lParam parameters contain information about a keystroke message, and the keystroke message has not been removed from the message queue. (An application called the PeekMessage function, specifying the PM_NOREMOVE flag.)
wParam
[in] Specifies the virtual-key code of the key that generated the keystroke message.
lParam
[in] Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. For more information about the lParam parameter, see Keystroke Message Flags. This parameter can be one or more of the following values. 
0-15
Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
16-23
Specifies the scan code. The value depends on the OEM.
24
Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
25-28
Reserved.
29
Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
30
Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31
Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
第一个参数原文说了“This parameter can be one of the following values.”(这个参数可以是以下取值中的一个),总共只列出了两个值HC_ACTION和HC_NOREMOVE,所以这里我们采用了HC_ACTION值,代码写成“If code = HC_ACTION Then”,这个想必对你来说理解起来难度不大。
第二个参数原文说wParam表示的是一个“virtual-key code”,这里我们称为虚拟键盘码,virtual-key code是不区分大小写的,如果要判断输入的大小写状态,可以用API函数GetKeyState或GetAsyncKeyState,也可以用GetKeyboardState函数把256个virtual-key code状态全部扫描一遍,这些函数怎么判断这里不再阐述,查阅MSDN就能得到答案。那么键盘上“A”的virtual-key code是多少,如果你安装过VC++的话,可以在“winuser.h”中第371行看到这样定义的“VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)”(虚拟键盘码A到Z与它们的ASCII码相同)。这里我用的ASCII码采用的16进制,所以我写成“If wParam = &H41 Then”,这里写16进制还是10进制并没什么影响,如果你习惯使用10进制表示的ASCII码就用10进制表示,我之所以喜欢用16进制表示字符,是由于系统自带的“字符映射表”工具中都是用16进制表示的,通过查表后不需作进制转换直接用16进制描述字符更方便点。
第三个参数可能就是你问题最大的地方,它关系到判断按键的状态,所以我把第三个参数翻译一遍:
lParam
[输入]表示了重复次数,扫描码,扩展键标志,上下文码,按键之前的状态标志,和按键状态跃变标志,要获得更多关于lParam参数的信息,查阅“Keystroke Message Flags”( )。这个参数由以下一个或多个值组成:
0-15
表示重复次数。其值是用户保持按下键状态导致的重复击键次数。
16-23
表示扫描码。该值与OEM厂商有关。(什么是扫描码稍候可以简介一下)
24
表示键是否是一个扩展键,例如一个功能键或数字键盘区的键。如果这个键是一个扩展键,其值为1,否则值为0。
25-28
保留,未使用。
29
表示上下文码。如果ALT键是按下状态,其值为1,否则值为0。
30
表示按键之前的状态标志。如果在这个消息发送之前,键是被按下状态,其值为1;如果在这个消息发送之前,键是抬起状态,其值为0。
31
表示按键状态跃变标志。如果键跃变到按下状态,其值为0;如果键跃变到释放状态,其值为1。
这个参数描述的0-31可以用后面的图来表示其意义:

 

 

从这个参数的解释来看,要判断键是按下还是抬起状态,甚至持续按下状态,可以用30和31位来表示,因此,我们只关心30、31位的值,为了不使其他位的值干扰我们判断的结果,我们先把其他位的值都变成0。于是我们代码中写成“lParam And &HC0000000”这里&HC0000000是16进制,展开成2进制就是(1100 0000 0000 0000 0000 0000 0000 0000),意义就是通过与运算只保留30、31位的原值。与运算完成后,仅剩30、31位有意义了,这时再来判断键的状态。

如果要判断按下键,那么在按键之前键肯定是处于抬起状态的,所以30位应该是0;当键被按下后,其状态从释放状态跃变到按下状态,所以31位应该是0;剩下的0-29位也是0,所以“(lParam And &HC0000000) = &H0”就是按下键的标志。
如果要判断抬起键,那么在按键之前键肯定是处于按下状态的,所以30位应该是1;当键被按下后,其状态从按下状态跃变到释放状态,所以31位应该是1;剩下的0-29位也是0,所以“(lParam And &HC0000000) = &HC0000000”就是抬起键的标志,上面已经说了&HC0000000的2进制是(1100 0000 0000 0000 0000 0000 0000 0000)。
如果要判断持续按下键,那么在这个按键消息到达之前键肯定是处于按下状态的,所以30位应该是1;当这个按键消息到达后,其状态仍然是按下状态,没有跃变到释放状态,所以31位应该是0;剩下的0-29位也是0,所以“(lParam And &HC0000000) = &H40000000”就是持续按下键的标志,&H40000000的2进制是(0100 0000 0000 0000 0000 0000 0000 0000)。
说道这里,判断的方法你应该弄明白了吧。
前面还提到一个概念叫“scan code”,扫描码,这里可以简单介绍一下扫描码的概念,感兴趣的可以继续往下看。先看看MSDN对“scan code”的说明,然后再翻译一下大家应该就明白了,原文如下:
Scan Code
The scan code is the value that the keyboard hardware generates when the user presses a key. It is a device-dependent value that identifies the key pressed, as opposed to the character represented by the key. An application typically ignores scan codes. Instead, it uses the device-independent virtual-key codes to interpret keystroke messages.
扫描码
扫描码的值是当用户按下键时由键盘硬件生成的。这个值是与硬件设备相关的,标志着键按下、抬起时所表示的键对应的字符。应用程序通常忽略扫描码,而使用与硬件设备无关的虚拟键盘码代替,虚拟键盘码用来表示击键消息。

转载于:https://www.cnblogs.com/ct0421/p/3666018.html

你可能感兴趣的文章
SAS vs SSD对比测试MySQL tpch性能
查看>>
Spring boot 整合CXF webservice 全部被拦截的问题
查看>>
Pinpoint跨节点统计失败
查看>>
【Canal源码分析】Canal Server的启动和停止过程
查看>>
机房带宽暴涨问题分析及解决方法
查看>>
XP 安装ORACLE
查看>>
八、 vSphere 6.7 U1(八):分布式交换机配置(vMotion迁移网段)
查看>>
[转载] 中华典故故事(孙刚)——19 万岁
查看>>
Maven学习总结(十)——使用Maven编译项目gbk的不可映射问题
查看>>
php5编译安装常见错误和解决办法集锦
查看>>
Linux远程访问及控制
查看>>
MongoDB实战系列之五:mongodb的分片配置
查看>>
Unable to determine local host from URL REPOSITORY_URL=http://
查看>>
ORACLE配置,修改tnsnames.ora文件实例
查看>>
Workstation服务无法启动导致无法访问文件服务器
查看>>
ant中文教程
查看>>
Linux常用命令(一)
查看>>
【VMCloud云平台】SCAP(四)租户(一)
查看>>
基于 Android NDK 的学习之旅----- C调用Java
查看>>
Windows 10 技术预览
查看>>