使用VC獲取全局鍵盤消息的話,可以使用鉤子函數。在Qt平臺上,因爲Qt是跨平臺的,鉤子函數是在windon平臺上面的,所以如果使用鉤子函數的獲取全局鍵盤消息,要使用<windows.h>頭文件和user32.lib,這也可能破壞了Qt跨平臺的優勢。
因爲某某原因,需要實現類似的功能。在界面上實現按住control鍵點擊鼠標實現多選,但是把功能簡單實現後,發現如果按住control最小化窗口,接着釋放control鍵再返回界面,這個時候界面保留了control鍵是按下的狀態,也就是說失去焦點的窗口無法檢測外部按鍵狀態。爲了修復這個bug,首先我想到的是檢測窗口是否獲取焦點,但是點擊窗口上的按鍵也會觸發窗口失去焦點事件,界面控件太多,實現不起來。然後只能想想使用Hook技術了,也就是鉤子函數。當我把鉤子掛好了之後,卻發現最小化窗口竟然會卸載鉤子???what???用的鉤子沒有使用外部dll鉤子方法,是使用在cpp裏註冊鉤子和使用回調函數的方法。想來想去,那麼有沒有可以直接檢測鍵盤按鍵狀態的函數呢?那就是使用getKeystate啦。就這樣簡單地把問題解決啦。鉤子函數回調函數:
HHOOK g_lowLevelKeyHook = NULL;
LRESULT CALLBACK keyHookEvent(int code,WPARAM wParam,LPARAM lParam){
if (nCode<0)
return CallNextHookEx(g_lowLevelKeyHook,nCode,wParam,LPARAM lParam)
if(wParam == WM_KEYUP)
{
if(((KBDLLHOOKSTRUCT*)lParam)->vkCode == 162)
{
//do something you want
return 1;
} else if(((KBDLLHOOKSTRUCT*)lParam)->vkCode == 163){
//do something you want
return 1;
}
}
return CallNextHookEx(g_lowLevelKeyHook,nCode,wParam,LPARAM lParam);
}
鉤子回調函數要是全局的哦。變量也是全局的。還有要在用到鉤子函數的時候註冊鉤子。 g_lowLevelKeyHook = SetWIndowsHookEx(WH_KEYBOARD_LL,LowLevelKeyHookEvent,GetModuleHandle(NULL),0); 鉤子可以抓取全局鍵盤消息,但是最小化卻莫名奇妙地卸載鉤子,這裏面的玄機還得好好研究一下。接下去就說一說直接檢測鍵盤按鍵狀態的方法。
GetKeyState();函數只有一個參數,即虛擬鍵碼。返回值爲SHORT類型,即短整型。GetKeyState函數是用來獲取指定的虛擬鍵碼的按鍵的狀態。得到的狀態表示按鍵是按下了還是彈起的,還是狀態切換(大小寫狀態、數字鍵盤鎖狀態)。
方法1:如果高位爲1表示按鍵按下,此時返回值爲負數(<0);如果高位爲0表示按鍵彈起,此時返回值爲正數(>0)。所以可以通過返回值與0比較進行判斷按鍵是否按下。
方法2:如果高位爲1表示按鍵按下,此時返回值爲1xxx xxxx xxxx xxxx,與0x8000(二進制 形式:1000 0000 0000 0000)進行按位與操作,結果爲1;反之,如果按鍵彈起,按位與後結果爲0。