关于用HOOK拦截键盘的一些问题
先看回调函数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”(http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/aboutkeyboardinput.asp)。这个参数由以下一个或多个值组成:
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.
扫描码
扫描码的值是当用户按下键时由键盘硬件生成的。这个值是与硬件设备相关的,标志着键按下、抬起时所表示的键对应的字符。应用程序通常忽略扫描码,而使用与硬件设备无关的虚拟键盘码代替,虚拟键盘码用来表示击键消息。
关于用HOOK拦截键盘的一些问题的更多相关文章
- 简单全局HOOK拦截大部分键盘消息
前言:学习HOOK中,万一老师讲解HOOK入门教程:http://www.cnblogs.com/del/category/124150.html http://www.cnblogs.com/del ...
- 初探hook的键盘获取
初探hook的键盘获取 import pyHook import pythoncom class e(): keyIsPressed = False #键盘是否按下 按住.. def onKeyDow ...
- hook 鼠标键盘消息实例分析
1.木马控制及通信方法包含:双管道,port重用.反弹技术.Hook技术,今天重点引用介绍一下hook的使用方法,hook信息后能够将结果发送到hacker邮箱等.实现攻击的目的. 转自:http:/ ...
- windows hook + pyhook3 + python win32api hook + C 键盘hook
安装pyhook3见:https://www.cnblogs.com/lqerio/p/12096710.html 使用见:https://www.cnblogs.com/lqerio/p/12106 ...
- [Windows Hook] 屏蔽键盘按键
//该例程为在系统级屏蔽一些系统键.如WIN.TAB.CAP.POWER.SLEEP.HOME等! //屏蔽组合键下面例程不适用!(比如CTRL+ESC需要在钩子函数中用(p.vkCode = VK_ ...
- HOOK 底层键盘消息---WH_KEYBOARD_LL
代码:屏蔽三个全局快捷键 代码的作用是屏蔽掉凝视中的三个快捷键. LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LP ...
- hook鼠标键盘记录和回放
unit Unit1; // download by http://www.codefans.net interface uses Windows, Messages, SysUtils, Class ...
- hook键盘驱动中的分发函数实现键盘输入数据的拦截
我自己在看<寒江独钓>这本书的时候,书中除了给出了利用过滤的方式来拦截键盘数据之外,也提到了另外一种方法,就是hook键盘分发函数,将它替换成我们自己的,然后再自己的分发函数中获取这个数据 ...
- Java语言的Hook实现
引言:最近在玩完美时空的诛仙Online(不知道这里有没人有共同爱好的),这个游戏每晚七点会出现一个任务"新科试炼".这个任务简单地说就是做选择题,范围小到柴米油盐,大到世界大千, ...
随机推荐
- PHP优化之批量操作MySQL
设计一个数据表如下: create table optimization( id INT NOT NULL AUTO_INCREMENT, value VARCHAR(10) NOT NULL, PR ...
- python3--命名空间字典
命名空间字典 我们学到了模块的命名空间实际上是以字典的形式实现的,并且可以由内置属性__dict__显示这一点.类和实例对象也是如此:属性点号运算其实内部就是字典的索引运算,而属性继承其实就是搜索连结 ...
- TOJ 4701 求阴影部分面积
4701: 求阴影部分面积 本文版权归BobHuang和博客园共有,不得转载.如想转载,请联系作者,并注明出处. Time Limit(Common/Java):1000MS/3000MS ...
- 机器学习实战之kNN算法
机器学习实战这本书是基于python的,如果我们想要完成python开发,那么python的开发环境必不可少: (1)python3.52,64位,这是我用的python版本 (2)numpy 1.1 ...
- shell的while循环
while循环用于不断执行一系列命令,也用于从输入文件中读取数据:命令通常为测试条件.其格式为: while command do Statement(s) to be executed if ...
- jquery滚动条插件slimScroll
参数 width: 'auto', //可滚动区域宽度 height: '100%', //可滚动区域高度 size: '10px', //组件宽度 c ...
- USACO 2.1 The Castle
题目大意:给你一个城堡让你求有多少房间,最大房间有多大,敲掉一堵墙后最大的房间有多大,敲掉那座墙 思路:比较恶心的bfs题,反正就是bfs使劲敲 /*{ ID:a4298442 PROB:castle ...
- tarkjan求无向图割点模板
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n,m; ; ; struct node { ...
- AXMLPrinter2.jar反编译xml文件
apk里的AndroidManifest.xml 为二进制文件,可通过AXMLPrinter2.jar包反编译出来 cmd命令行运行一下命令: java -jar AXMLPrinter2.jar A ...
- poj 2987 Firing
Firing Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 10696 Accepted: 3226 Descript ...