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 

版權聲明:本文為博主原創文章,未經博主同意不得轉載。












免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM