键盘监听

GetKeyState(), GetAsyncKeystate(), GetKeyboardSlate()
GetKeyState、GetAsyncKeyState、GetKeyboardState函数的差别:

1、BOOL GetKeyboardState( PBYTE lpKeyState );获得全部的256个键(键盘按键、鼠标按键等等)的状态,lpKeyState是指向一个256bit的数组。存放全部键的状态。

2、SHORT GetAsyncKeyState( int vKey );推断Virtual-KeyCodes为vKey的键是否down或up。用返回值的最高位表示键的状态(up或down)。用返回值的最低位表示vKey键在此函数调用之前是否被按下过。GetAsyncKeyState直接侦測键盘的硬件中断。

3、SHORT GetKeyState( int nVirtKey );用于推断nVirtKey的状态。用返回值的最高位表示。最高位为1表示当前键处于down的状态。最高位为0当前键处于up状态。

此函数从消息队列中读取消息进行处理。

以下是转载的内容:http://bingtears.iteye.com/blog/663149

0x8000 & GetKeyState(VK_SHIFT); 这句是推断是否有按下shift键

为什么GetAsyncKeyState()&

首先说明,有好多程序或书上是0x8000f,这个f不是十六进制的f而是代表浮点数。事实上& 8000才是本质。

小鱼我整理后自己写了点东西,总结一下

首先介绍一下几个概念:
按位与运算符"&":是双目运算符,其功能是參与运算的两数各相应的二进位相与。仅仅有相应的两个二进位均为1时。结果位才为1 ,否则为0。

參与运算的数以补码方式出现。比如:0x11 & 0x12(即0001 0001 & 0001 0010)的结果是0x10(0001 0000);(关于vs取反參考附)
虚键:指的是非字母能够明白表示的键.(比如ESC BS TAB NumLock 等,虚键列表见附);
物理键状态:在操作系统的控制面板中设置鼠标左右键的映射(实际的鼠标左键能够映射成右键点击事件),或者通过程序也能够这样设置,这样就产生了(实际的)物理键状态;
逻辑键状态:使用 GetKeyState,GetKeyboardState,等函数得到的逻辑键状态,模拟按下按键;
GetAsyncKeyState函数功能:读取的是物理键状态。也是就是无论你怎么鼠标键盘映射,它仅仅读取实际的按键状态。

MSDN上给出了样例非常恰当For example, the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button.也就是说假设你又一次设置了映射,GetAsyncKeyState还是仅仅读取物理状态。
GetAsyncKeyState的返回值:表示两个内容,一个是最高位bit的值,代表这个键是否被按下。按下为1,抬起为0;一个是最低位bit的值,在windowsCE下要忽略(參考自MSDNIf the most significant bit is set, the key is down. The least significant bit is not valid in Windows CE, and should be ignored.)
Asynchronous:英文意思是异步的

实际其中GetAsyncKeyState的返回值是什么呢?小鱼我写了个程序来获取返回值:
#include <Windows.h>
#include <stdio.h>

void main()
{
while(1)
{
short a = ::GetAsyncKeyState(VK_LSHIFT)
printf( “0x%x”,a);
sleep(10);
}
}
当然。用MessageBox能够这样写:
if(short a = ::GetAsyncKeyState(VK_LSHIFT))
{
char buffer[30];
sprintf(buffer, “0x%x”,a);
MessageBox(0, buffer, “a的值”, MB_OK);
}

GetAsyncKeyState按键不按或抬起后不按的返回值0x0 即0000 0000 0000 0000 0000 0000 0000 0000
GetAsyncKeyState按键被按下后的返回值 返回0xffff8001 即1111 1111 1111 1111 1000 0000 0000 0001 (这里并非返回4字节,而是%x打印出32位,前十六位补f)
0x8000 即0000 0000 0000 0000 1000 0000 0000 0000
GetAsyncKeyState(VK_LSHIFT) & 0x8000 返回0x1 即0000 0000 0000 0000 1000 0000 0000 0000

那么为什么GetAsyncKeyState要 ‘与’上 0x8000这个常数呢?
答案是:获取按键状态。屏蔽掉其它的可能状态,依照MSDN上说低位should ignore。
网上有人这样写,意思非常明白:
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ?

0 : 1)

程序应该是:
if(GetAsyncKeyState(VK_LSHIFT)&&0x8000)
对于虚键而言以下这样写逻辑是不正确的。尽管结果一样:
if(GetAsyncKeyState(VK_LSHIFT))

所以让键盘的"上下左右"出发事件能够这样写:
if( ::GetAsyncKeyState(VK_LEFT) & 0x8000 )
code…
if( ::GetAsyncKeyState(VK_RIGHT)& 0x8000 )
code…
if( ::GetAsyncKeyState(VK_UP) & 0x8000 )
code…
if( ::GetAsyncKeyState(VK_DOWN) & 0x8000 )
code…

关于GetAsyncKeyState与GetKeyState差别:
GetAsyncKeyState上面已经讲几乎相同了,关于GetAsyncKeyState与GetKeyState二者最大差别:GetAsyncKeyState在按键不按的情况下为0,而GetKeyState在按键不按的情况下開始为0。当一次‘按下抬起’后变为1,依次循环。

SHORT GetKeyState(int nVirtKey // virtual-key code);
作用:返回键的状态,按下、释放或锁定(down、up or toggled)
參数:虚拟键代码(VK_)。假设是字母a-z、A-Z 或数字0-9, 则为其相应的ASCII码(比方字母O的ASCII码为十六进制的0x4F)
返回值:返回码的高位显示当前是否有键被按下,低位(0位)则显示NumLock、CapsLock、ScrollLock的状态(ON或OFF,为ON时键盘指示灯亮)。

即高位为1,返回值小于0,说明有键按下;最低位为1表示处于锁定(ON)状态(參考MSDN:If the high-order bit is 1, the key is down; otherwise, it is up.
If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key’s indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled. )
注:此函数不应该在键盘消息处理程序以外使用。由于它返回的信息仅仅有在键盘消息从消息队列中被检索到之后才有效。

若确实须要。请使用GetAsyncKeyState


网上还找到了一些资料:

关于和其它的几个函数的差别:
SHORT GetKeyState(int nVirtKey);
SHORT GetAsyncKeyState(int vKey);
BOOL GetKeyboardState(PBYTE lpKeyState);

三个取key status的函数的最大差别是:
第一个:是从windows消息队列中取得键盘消息,返回key status.
第二个:是直接侦測键盘的硬件中断,返回key status.
第三个:是当从windows消息队列中移除键盘消息时,才返回key status.

keybd_event函数,是模拟键盘击键。一次完整的击键模拟事件,是"按下"和"弹起"两个消息,所以 keybd_event(VK_F12,0,0,0);keybd_event(VK_F12,0,KEYEVENTF_KEYUP,0); 完毕了一次完整的点击 F12 的事件。

GetAsyncKeyState()函数。是直接侦測键盘的硬件中断。(有些人说,是一种“实时性”的侦測,这样的说法,感觉不正确。比方你调用 Sleep(),就算是中断一年的时间,仅仅要在这期间程序还在执行,它都能够把那个键的状态侦測出来)。自上一次调用GetAsyncKeyState()函数以来(在某些循环中。N次调用GetAsyncKeyState(),它每次检查的,都是自上次调用之后。键的状态),若键已被按过,则返回1,否则,返回0;有些资料显示:倘若输入焦点从属于与调用函数的输入线程不同的还有一个线程,则返回零(比如,在还有一个程序拥有输入焦点时,应该返回零)。

实验证明。这样的说法并不全然,函数实际是在大部份范围内工作的,仅仅有少数是另外)。


附:
VC++编译器,计算~10,得出的结果是-11。

为什么不是5呢

10的二进制表示为1010。按位取反应该为0101。也就是十进制的5,为什么会得出-11?

VC是32位编译器,所以

10 = 00000000 00000000 00000000 00001010

~10 = 11111111 11111111 11111111 11110101 = -11

能够通过掩码(位与) 与15位与

15 = 00000000 00000000 00000000 00001111

~10 = 00000000 00000000 00000000 00000101 = -11
附:
VK_LBUTTON 鼠标左键 0x01
VK_RBUTTON 鼠标右键 0x02
VK_CANCEL Ctrl + Break 0x03
VK_MBUTTON 鼠标中键 0x04

VK_BACK Backspace 键 0x08
VK_TAB Tab 键 0x09

VK_RETURN 回车键 0x0D

VK_SHIFT Shift 键 0x10
VK_CONTROL Ctrl 键 0x11
VK_MENU Alt 键 0x12
VK_PAUSE Pause 键 0x13
VK_CAPITAL Caps Lock 键 0x14

VK_ESCAPE Esc 键 0x1B

VK_SPACE 空格键 0x20
VK_PRIOR Page Up 键 0x21
VK_NEXT Page Down 键 0x22
VK_END End 键 0x23
VK_HOME Home 键 0x24
VK_LEFT 左箭头键 0x25
VK_UP 上箭头键 0x26
VK_RIGHT 右箭头键 0x27
VK_DOWN 下箭头键 0x28
VK_SNAPSHOT Print Screen 键 0x2C
VK_Insert Insert 键 0x2D
VK_Delete Delete 键 0x2E

‘0’ – ‘9’ 数字 0 - 9 0x30 - 0x39
‘A’ – ‘Z’ 字母 A - Z 0x41 - 0x5A

VK_LWIN 左WinKey(104键盘才有) 0x5B
VK_RWIN 右WinKey(104键盘才有) 0x5C
VK_APPS AppsKey(104键盘才有) 0x5D

VK_NUMPAD0 小键盘 0 键 0x60
VK_NUMPAD1 小键盘 1 键 0x61
VK_NUMPAD2 小键盘 2 键 0x62
VK_NUMPAD3 小键盘 3 键 0x63
VK_NUMPAD4 小键盘 4 键 0x64
VK_NUMPAD5 小键盘 5 键 0x65
VK_NUMPAD6 小键盘 6 键 0x66
VK_NUMPAD7 小键盘 7 键 0x67
VK_NUMPAD8 小键盘 8 键 0x68
VK_NUMPAD9 小键盘 9 键 0x69

VK_F1 - VK_F24 功能键F1 – F24 0x70 - 0x87

VK_NUMLOCK Num Lock 键 0x90
VK_SCROLL Scroll Lock 键 0x91

版权声明:本文为博主原创文章,未经博主同意不得转载。

!!!!

(bit)(da&0x8000)什么意思 分享 举报 1个回答 #活动# 重返童年,好礼相送 tianmaxk0131
2011-06-10 这是单片机 C 语言代码2113, (bit)da&0x8000 相当于取变量 da
的从右边5261数第十个二进制位4102. 你可以参考这个贴1653子:
http://zhidao.baidu.com/question/32856445.html

GetAsyncKeyState

 

就是调用GetAsyncKeyState函数得到某个键的状态,然后判断返回值的最高位是不是1,如果是表示这个处于按下状态

1&与操作,&0x8000就是判断这个返回值的high-order bit(高位字节)
2、如果high-order bit是1,则是按下状态,否则UP状态

 

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 
意思你应该看的懂吧。 
说明一下,带的参数要是虚拟打描码! 
比如下的码是 VK_DOWN ,ESC是 VK_ESCAPE

 

GetAsyncKeyState 取异步键状态。 
比如,一般情况下,你可以在操作系统的控制面板中设置鼠标左右键的映射(实际的鼠标左键可以映射成右键点击事件),或者通过程序也可以这样设置,这样就产生了物理键状态(实际的),逻辑键状态(虚拟的,)。使用 GetKeyState,GetKeyboardState,等函数得到的就是逻辑键状态。 
而GetAsyncKeyState 读取的是物理键状态,也是就是不管你怎么鼠标键盘映射,它只读取实际的按键状态。
VC中的GetKeyState函数怎么用?需要加什么头文件?
我直接GetKeyState函数提示没有定义.不知道为什么.哪位高手指教一下.也试过::GetKeyState,还是不行.加上Winuer.h还是不行啊.提示找不到加上"Winuser.h".莫非是我的版本有问题.我用的是... 展开
 我来答 分享 举报
4个回答 #活动# 重返童年,好礼相送
 littlebeck  
推荐于2017-09-13
加上
"Winuser.h""windows.h"(
例如测试Ctrl键是5261否按下的代码如下:
if (::GetKeyState(VK_CONTROL) < 0)
{
AfxMessageBox("Ctrl 键按下了4102。1653");
}
else
{
AfxMessageBox("Ctrl 键没按下。");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值