因为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”(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拦截键盘的一些问题的更多相关文章

  1. 简单全局HOOK拦截大部分键盘消息

    前言:学习HOOK中,万一老师讲解HOOK入门教程:http://www.cnblogs.com/del/category/124150.html http://www.cnblogs.com/del ...

  2. 初探hook的键盘获取

    初探hook的键盘获取 import pyHook import pythoncom class e(): keyIsPressed = False #键盘是否按下 按住.. def onKeyDow ...

  3. hook 鼠标键盘消息实例分析

    1.木马控制及通信方法包含:双管道,port重用.反弹技术.Hook技术,今天重点引用介绍一下hook的使用方法,hook信息后能够将结果发送到hacker邮箱等.实现攻击的目的. 转自:http:/ ...

  4. windows hook + pyhook3 + python win32api hook + C 键盘hook

    安装pyhook3见:https://www.cnblogs.com/lqerio/p/12096710.html 使用见:https://www.cnblogs.com/lqerio/p/12106 ...

  5. [Windows Hook] 屏蔽键盘按键

    //该例程为在系统级屏蔽一些系统键.如WIN.TAB.CAP.POWER.SLEEP.HOME等! //屏蔽组合键下面例程不适用!(比如CTRL+ESC需要在钩子函数中用(p.vkCode = VK_ ...

  6. HOOK 底层键盘消息---WH_KEYBOARD_LL

    代码:屏蔽三个全局快捷键 代码的作用是屏蔽掉凝视中的三个快捷键. LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LP ...

  7. hook鼠标键盘记录和回放

    unit Unit1; // download by http://www.codefans.net interface uses Windows, Messages, SysUtils, Class ...

  8. hook键盘驱动中的分发函数实现键盘输入数据的拦截

    我自己在看<寒江独钓>这本书的时候,书中除了给出了利用过滤的方式来拦截键盘数据之外,也提到了另外一种方法,就是hook键盘分发函数,将它替换成我们自己的,然后再自己的分发函数中获取这个数据 ...

  9. Java语言的Hook实现

    引言:最近在玩完美时空的诛仙Online(不知道这里有没人有共同爱好的),这个游戏每晚七点会出现一个任务"新科试炼".这个任务简单地说就是做选择题,范围小到柴米油盐,大到世界大千, ...

随机推荐

  1. php 注册与登录

    <body background="timg.jpg"><div class="dak"> <div class="zu ...

  2. 九度oj 题目1099:后缀子串排序

    题目描述: 对于一个字符串,将其后缀子串进行排序,例如grain其子串有:grain rain ain in n 然后对各子串按字典顺序排序,即: ain,grain,in,n,rain 输入: 每个 ...

  3. HDU——4549M斐波那契数列(矩阵快速幂+快速幂+费马小定理)

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Su ...

  4. 洛谷P3758 - [TJOI2017]可乐

    Portal Description 给出一张\(n(n\leq30)\)个点\(m(m\leq100)\)条边的无向图.初始时有一个可乐机器人在点\(1\),这个机器人每秒会做出以下三种行为之一:原 ...

  5. 在VMWare下为CentOS设置静态IP通过NAT访问外网

    一.背景 安装好的CentOS系统默认是通过DHCP自动分配地址来共享主机的IP以达到访问外网的目的,但是因为莫名的原因无法访问外网.只好改为通过静态IP的方式访问外网. 二.操作步骤 2.1 确认开 ...

  6. 转 C++STL之string

    http://www.cnblogs.com/wangkangluo1/archive/2011/07/22/2114118.html string类的构造函数: string(const char ...

  7. Xcode打包应用为ipa

    Xcode教程 Xcode4发布测试 打包Archive操作是本文要介绍的内容,发布测试的最后一步打包(Archive),Xcode4帮助文档有比较详细介绍,但是居然是错的,这里说明一下. 1.设置& ...

  8. Day 10 Linux nfs && crond(摘)

    (摘) 介绍: NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系 ...

  9. poj1149最大流经典构图神题

    题意:n个顾客依次来买猪,有n个猪房,每个顾客每次可以开若干个房子,买完时,店主可以调整这位顾客 开的猪房里的猪,共m个猪房,每个猪房有若干猪,求最多能卖多少猪. 构图思想:顾客有先后,每个人想要的猪 ...

  10. python实现显示安装进度条

    一直很好奇那种安装进度条,或者启动程序时候显示的进度条是怎么实现的,学习了python之后,sys模块中有个方法可以实现,代码如下:   1 2 3 4 5 6     import sys,time ...