电竞比分网-中国电竞赛事及体育赛事平台

分享

GetAsyncKeyState()& 0x8000f

 昵稱(chēng)16975664 2014-04-24

GetAsyncKeyState()& 0x8000f

(2012-04-01 08:14:56)
標(biāo)簽:

it

分類(lèi): code

首先說(shuō)明,有好多程序或書(shū)上是0x8000f,這個(gè)f不是十六進(jìn)制的f而是代表浮點(diǎn)數(shù)。其實(shí)& 8000才是本質(zhì)。小魚(yú)我整理后自己寫(xiě)了點(diǎn)東西,總結(jié)一下


首先介紹一下幾個(gè)概念:
按位與運(yùn)算符"&":是雙目運(yùn)算符,其功能是參與運(yùn)算的兩數(shù)各對(duì)應(yīng)的二進(jìn)位相與。只有對(duì)應(yīng)的兩個(gè)二進(jìn)位均為1時(shí),結(jié)果位才為1 ,否則為0。參與運(yùn)算的數(shù)以補(bǔ)碼方式出現(xiàn)。例如:0x11 & 0x12(即0001 0001 & 0001 0010)的結(jié)果是0x10(0001 0000);(關(guān)于vs取反參考附)
虛鍵:指的是非字母可以明確表示的鍵.(例如ESC BS TAB NumLock 等,虛鍵列表見(jiàn)附);
物理鍵狀態(tài):在操作系統(tǒng)的控制面板中設(shè)置鼠標(biāo)左右鍵的映射(實(shí)際的鼠標(biāo)左鍵可以映射成右鍵點(diǎn)擊事件),或者通過(guò)程序也可以這樣設(shè)置,這樣就產(chǎn)生了(實(shí)際的)物理鍵狀態(tài);
邏輯鍵狀態(tài):使用 GetKeyState,GetKeyboardState,等函數(shù)得到的邏輯鍵狀態(tài),模擬按下按鍵;
GetAsyncKeyState函數(shù)功能:讀取的是物理鍵狀態(tài),也是就是不管你怎么鼠標(biāo)鍵盤(pán)映射,它只讀取實(shí)際的按鍵狀態(tài)。MSDN上給出了例子很恰當(dāng)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.也就是說(shuō)如果你重新設(shè)置了映射,GetAsyncKeyState還是只讀取物理狀態(tài);
GetAsyncKeyState的返回值:表示兩個(gè)內(nèi)容,一個(gè)是最高位bit的值,代表這個(gè)鍵是否被按下,按下為1,抬起為0;一個(gè)是最低位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:英文意思是異步的

實(shí)際當(dāng)中GetAsyncKeyState的返回值是什么呢?小魚(yú)我寫(xiě)了個(gè)程序來(lái)獲取返回值:
#include <Windows.h>
#include <stdio.h>

void main()
{
while(1)
{
short a = ::GetAsyncKeyState(VK_LSHIFT)
printf( "0x%x",a);
sleep(10);
}
}
當(dāng)然,用MessageBox可以這樣寫(xiě):
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字節(jié),而是%x打印出32位,前十六位補(bǔ)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這個(gè)常數(shù)呢?
答案是:獲取按鍵狀態(tài),屏蔽掉其他的可能狀態(tài),按照MSDN上說(shuō)低位should ignore。
網(wǎng)上有人這樣寫(xiě),意思很明確:
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

程序應(yīng)該是:
if(GetAsyncKeyState(VK_LSHIFT)&&0x8000)
對(duì)于虛鍵而言下面這樣寫(xiě)邏輯是不對(duì)的,雖然結(jié)果一樣:
if(GetAsyncKeyState(VK_LSHIFT))

所以讓鍵盤(pán)的"上下左右"出發(fā)事件可以這樣寫(xiě):
if( ::GetAsyncKeyState(VK_LEFT) & 0x8000 )
code...
if( ::GetAsyncKeyState(VK_RIGHT)& 0x8000 )
code...
if( ::GetAsyncKeyState(VK_UP) & 0x8000 )
code...
if( ::GetAsyncKeyState(VK_DOWN) & 0x8000 )
code...

關(guān)于GetAsyncKeyState與GetKeyState區(qū)別:
GetAsyncKeyState上面已經(jīng)講差不多了,關(guān)于GetAsyncKeyState與GetKeyState二者最大區(qū)別:GetAsyncKeyState在按鍵不按的情況下為0,而GetKeyState在按鍵不按的情況下開(kāi)始為0,當(dāng)一次‘按下抬起’后變?yōu)?,依次循環(huán)。

SHORT GetKeyState(int nVirtKey // virtual-key code);
作用:返回鍵的狀態(tài),按下、釋放或鎖定(down、up or toggled)
參數(shù):虛擬鍵代碼(VK_)。如果是字母a-z、A-Z 或數(shù)字0-9, 則為其對(duì)應(yīng)的ASCII碼(比如字母O的ASCII碼為十六進(jìn)制的0x4F)
返回值:返回碼的高位顯示當(dāng)前是否有鍵被按下,低位(0位)則顯示NumLock、CapsLock、ScrollLock的狀態(tài)(ON或OFF,為ON時(shí)鍵盤(pán)指示燈亮)。即高位為1,返回值小于0,說(shuō)明有鍵按下;最低位為1表示處于鎖定(ON)狀態(tài)(參考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. )
注:此函數(shù)不應(yīng)該在鍵盤(pán)消息處理程序以外使用,因?yàn)樗祷氐男畔⒅挥性阪I盤(pán)消息從消息隊(duì)列中被檢索到之后才有效。若確實(shí)需要,請(qǐng)使用GetAsyncKeyState

----------------------------------------
網(wǎng)上還找到了一些資料:

關(guān)于和其他的幾個(gè)函數(shù)的區(qū)別:
SHORT GetKeyState(int nVirtKey);
SHORT GetAsyncKeyState(int vKey);
BOOL GetKeyboardState(PBYTE lpKeyState);

三個(gè)取key status的函數(shù)的最大區(qū)別是:
第一個(gè):是從windows消息隊(duì)列中取得鍵盤(pán)消息,返回key status.
第二個(gè):是直接偵測(cè)鍵盤(pán)的硬件中斷,返回key status.
第三個(gè):是當(dāng)從windows消息隊(duì)列中移除鍵盤(pán)消息時(shí),才返回key status.

keybd_event函數(shù),是模擬鍵盤(pán)擊鍵,一次完整的擊鍵模擬事件,是"按下"和"彈起"兩個(gè)消息,所以 keybd_event(VK_F12,0,0,0);keybd_event(VK_F12,0,KEYEVENTF_KEYUP,0); 完成了一次完整的點(diǎn)擊 F12 的事件。

GetAsyncKeyState()函數(shù),是直接偵測(cè)鍵盤(pán)的硬件中斷。(有些人說(shuō),是一種“實(shí)時(shí)性”的偵測(cè),這種說(shuō)法,感覺(jué)不對(duì),比如你調(diào)用 Sleep(),就算是中斷一年的時(shí)間,只要在這期間程序還在運(yùn)行,它都可以把那個(gè)鍵的狀態(tài)偵測(cè)出來(lái))。自上一次調(diào)用GetAsyncKeyState()函數(shù)以來(lái)(在某些循環(huán)中,N次調(diào)用GetAsyncKeyState(),它每次檢查的,都是自上次調(diào)用之后,鍵的狀態(tài)),若鍵已被按過(guò),則返回1,否則,返回0;有些資料顯示:倘若輸入焦點(diǎn)從屬于與調(diào)用函數(shù)的輸入線(xiàn)程不同的另一個(gè)線(xiàn)程,則返回零(例如,在另一個(gè)程序擁有輸入焦點(diǎn)時(shí),應(yīng)該返回零)。實(shí)驗(yàn)證明,這種說(shuō)法并不完全,函數(shù)實(shí)際是在大部份范圍內(nèi)工作的,只有少數(shù)是另外)。


---------------
附:
VC++編譯器,計(jì)算~10,得出的結(jié)果是-11。為什么不是5呢

10的二進(jìn)制表示為1010,按位取反應(yīng)該為0101,也就是十進(jìn)制的5,為什么會(huì)得出-11?


VC是32位編譯器,所以

10 = 00000000 00000000 00000000 00001010

~10 = 11111111 11111111 11111111 11110101 = -11

可以通過(guò)掩碼(位與) 與15位與

15 = 00000000 00000000 00000000 00001111

~10 = 00000000 00000000 00000000 00000101 = -11
附:
VK_LBUTTON 鼠標(biāo)左鍵 0x01
VK_RBUTTON 鼠標(biāo)右鍵 0x02
VK_CANCEL Ctrl + Break 0x03
VK_MBUTTON 鼠標(biāo)中鍵 0x04

VK_BACK Backspace 鍵 0x08
VK_TAB Tab 鍵 0x09

VK_RETURN 回車(chē)鍵 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' 數(shù)字 0 - 9 0x30 - 0x39
'A' – 'Z' 字母 A - Z 0x41 - 0x5A

VK_LWIN 左WinKey(104鍵盤(pán)才有) 0x5B
VK_RWIN 右WinKey(104鍵盤(pán)才有) 0x5C
VK_APPS AppsKey(104鍵盤(pán)才有) 0x5D

VK_NUMPAD0 小鍵盤(pán) 0 鍵 0x60
VK_NUMPAD1 小鍵盤(pán) 1 鍵 0x61
VK_NUMPAD2 小鍵盤(pán) 2 鍵 0x62
VK_NUMPAD3 小鍵盤(pán) 3 鍵 0x63
VK_NUMPAD4 小鍵盤(pán) 4 鍵 0x64
VK_NUMPAD5 小鍵盤(pán) 5 鍵 0x65
VK_NUMPAD6 小鍵盤(pán) 6 鍵 0x66
VK_NUMPAD7 小鍵盤(pán) 7 鍵 0x67
VK_NUMPAD8 小鍵盤(pán) 8 鍵 0x68
VK_NUMPAD9 小鍵盤(pán) 9 鍵 0x69

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

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

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多