GetKeyState、GetAsyncKeyState、GetKeyboardState函數(shù)的區(qū)別:
1、BOOL GetKeyboardState( PBYTE lpKeyState );獲得所有的256個(gè)鍵(鍵盤按鍵、鼠標(biāo)按鍵等等)的狀態(tài),lpKeyState是指向一個(gè)256bit的數(shù)組,存放所有鍵的狀態(tài)。
2、SHORT GetAsyncKeyState( int vKey );判斷Virtual-KeyCodes為vKey的鍵是否down或up。用返回值的最高位表示鍵的狀態(tài)(up或down),用返回值的最低位表示vKey鍵在此函數(shù)調(diào)用之前是否被按下過。GetAsyncKeyState直接偵測(cè)鍵盤的硬件中斷。
3、SHORT GetKeyState( int nVirtKey );用于判斷nVirtKey的狀態(tài)。用返回值的最高位表示,最高位為1表示當(dāng)前鍵處于down的狀態(tài);最高位為0當(dāng)前鍵處于up狀態(tài)。此函數(shù)從消息隊(duì)列中讀取消息進(jìn)行處理
0x8000 & GetKeyState(VK_SHIFT); 這句是判斷是否有按下shift鍵
為什么GetAsyncKeyState()&
首先說明,有好多程序或書上是0x8000f,這個(gè)f不是十六進(jìn)制的f而是代表浮點(diǎn)數(shù)。其實(shí)& 8000才是本質(zhì)。小魚我整理后自己寫了點(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 等,虛鍵列表見附); 物理鍵狀態(tài):在操作系統(tǒng)的控制面板中設(shè)置鼠標(biāo)左右鍵的映射(實(shí)際的鼠標(biāo)左鍵可以映射成右鍵點(diǎn)擊事件),或者通過程序也可以這樣設(shè)置,這樣就產(chǎn)生了(實(shí)際的)物理鍵狀態(tài); 邏輯鍵狀態(tài):使用 GetKeyState,GetKeyboardState,等函數(shù)得到的邏輯鍵狀態(tài),模擬按下按鍵; GetAsyncKeyState函數(shù)功能:讀取的是物理鍵狀態(tài),也是就是不管你怎么鼠標(biāo)鍵盤映射,它只讀取實(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.也就是說如果你重新設(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的返回值是什么呢?小魚我寫了個(gè)程序來獲取返回值: #include <Windows.h> #include <stdio.h>
void main() { while(1) { short a = ::GetAsyncKeyState(VK_LSHIFT) printf( "0x%x",a); sleep(10); } } 當(dāng)然,用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字節(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上說低位should ignore。 網(wǎng)上有人這樣寫,意思很明確: #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ì)于虛鍵而言下面這樣寫邏輯是不對(duì)的,雖然結(jié)果一樣: if(GetAsyncKeyState(VK_LSHIFT))
所以讓鍵盤的"上下左右"出發(fā)事件可以這樣寫: 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在按鍵不按的情況下開始為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í)鍵盤指示燈亮)。即高位為1,返回值小于0,說明有鍵按下;最低位為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)該在鍵盤消息處理程序以外使用,因?yàn)樗祷氐男畔⒅挥性阪I盤消息從消息隊(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ì)列中取得鍵盤消息,返回key status. 第二個(gè):是直接偵測(cè)鍵盤的硬件中斷,返回key status. 第三個(gè):是當(dāng)從windows消息隊(duì)列中移除鍵盤消息時(shí),才返回key status.
keybd_event函數(shù),是模擬鍵盤擊鍵,一次完整的擊鍵模擬事件,是"按下"和"彈起"兩個(gè)消息,所以 keybd_event(VK_F12,0,0,0);keybd_event(VK_F12,0,KEYEVENTF_KEYUP,0); 完成了一次完整的點(diǎn)擊 F12 的事件。
GetAsyncKeyState()函數(shù),是直接偵測(cè)鍵盤的硬件中斷。(有些人說,是一種“實(shí)時(shí)性”的偵測(cè),這種說法,感覺不對(duì),比如你調(diào)用 Sleep(),就算是中斷一年的時(shí)間,只要在這期間程序還在運(yùn)行,它都可以把那個(gè)鍵的狀態(tài)偵測(cè)出來)。自上一次調(diào)用GetAsyncKeyState()函數(shù)以來(在某些循環(huán)中,N次調(diào)用GetAsyncKeyState(),它每次檢查的,都是自上次調(diào)用之后,鍵的狀態(tài)),若鍵已被按過,則返回1,否則,返回0;有些資料顯示:倘若輸入焦點(diǎn)從屬于與調(diào)用函數(shù)的輸入線程不同的另一個(gè)線程,則返回零(例如,在另一個(gè)程序擁有輸入焦點(diǎn)時(shí),應(yīng)該返回零)。實(shí)驗(yàn)證明,這種說法并不完全,函數(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
可以通過掩碼(位與) 與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 回車鍵 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鍵盤才有) 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
|