GetKeyState、GetAsyncKeyState、GetKeyboardState函數的區別:

    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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章