GetAsyncKeyState
首先介紹一下幾個概念:
按位與運算符"&":是雙目運算符,其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為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
?
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhangkala/archive/2010/09/07/5868067.aspx
總結
以上是生活随笔為你收集整理的GetAsyncKeyState的全部內容,希望文章能夠幫你解決所遇到的問題。