因为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 上传文件名出现乱码

    想必很多朋友在进行utf8编码的php开发上传功能的时候,都会遇到这样的一个问题,就是上传中文文件名的文件时,文件名会变成乱码,其实我们可以用iconv函数对文件名进行重新编码就解决问题了 可能会有不 ...

  2. json的两种表示结构(对象和数组).。

    JSON有两种表示结构,对象和数组.对象结构以”{”大括号开始,以”}”大括号结束.中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如 ...

  3. 【Luogu】P2831愤怒的小鸟(手算抛物线+状压DP)

    题目链接 设f[s]表示二进制集合表示下的s集合都打掉用了多少小鸟. 预处理出lne[i][j]表示i.j确定的抛物线能打掉的小鸟集合. 于是就有f[s|lne[i][j]]=min(f[s|lne[ ...

  4. BZOJ3996 [TJOI2015]线性代数 【最小割】

    题目 给出一个NN的矩阵B和一个1N的矩阵C.求出一个1*N的01矩阵A.使得 D=(AB-C)A^T最大.其中A^T为A的转置.输出D 输入格式 第一行输入一个整数N,接下来N行输入B矩阵,第i行第 ...

  5. 【霍夫曼树】 poj 1521 Entropy

    poj.org/problem?id=1521 注意只有特殊情况:只有一种字母 #include<iostream> #include<cstdio> #include< ...

  6. LightOJ1125 Divisible Group Sums

    Divisible Group Sums Given a list of N numbers you will be allowed to choose any M of them. So you c ...

  7. 清除svn检出导致的所有文件的问号

    问题:将svn项目检出到桌面后,桌面的图标都有问号了,怎么消除这一大堆问号? 解决方案:(1)新建一个a.txt文件,把这行代码复制进去for /r . %%a in (.) do @if exist ...

  8. PAT (Advanced Level) 1088. Rational Arithmetic (20)

    简单题. 注意:读入的分数可能不是最简的.输出时也需要转换成最简. #include<cstdio> #include<cstring> #include<cmath&g ...

  9. P2136 拉近距离(spfa判负环)

    洛谷—— P2136 拉近距离 题目背景 我是源点,你是终点.我们之间有负权环. ——小明 题目描述 在小明和小红的生活中,有N个关键的节点.有M个事件,记为一个三元组(Si,Ti,Wi),表示从节点 ...

  10. java设计模式图

    一.什么是设计模式                                                                                           ...