Qt是一個跨平台開發的框架,可以實現一套代碼多平台編譯運行。但是有時候我們想實現的功能卻和平台深度掛鈎,比如本文想要描述的鍵盤鈎子,也就是KeyBoard Hook。在Windows平台開發時,如果我們需要監聽鍵盤的操作或者屏蔽一些鍵盤操作時,比較容易的辦法就是使用Windows 自帶的API,包含SetWindowsHookEx、CallNextHookEx、UnhookWindowsHookEx。但是Mac系統下是沒有這些API供我們使用的,那么在使用Qt進行擴平台開發時,我們該如何做呢?
可以想到的辦法就是使用條件編譯的方式,讓我們的軟件能夠在Windows平台下先支持鍵盤鈎子。那如果進行條件編譯呢,主要需要關注一下幾個地方:
1.首先需要在Qt的工程文件中,添加lib文件user32.lib,因為該lib是一個系統lib,所以我們只需要指定名稱即可,需要注意的是我們希望是只在win系統下引入庫,所以我們可以進行lib引用的限定(也可以通過在項目節點上右鍵,添加庫的方式添加,效果一樣),如下所示:
2.windows.h文件的導入,QT已經自帶一些預定義宏來標識系統類型,如Q_OS_WIN代表windows系統,Q_OS_MAC代表MAC OS,這些內容可以查看幫助文檔。此時,我們將windows.h的include操作就可以放到一個系統類型判斷條件中了,如下所示:
這樣一來,當把整個功能移植到MAC上進行編譯時,由於條件不滿足,所以也就不會引入這個windows.h文件。
3.安裝鈎子以及卸載鈎子的操作,也可以放到條件編譯中去,如圖:
這樣確保函數的定義都在Windows系統下定義和實現,在其他平台編譯時不會出錯。
4.最后一步就是調用時夜的根據不同的系統去調用,比如當前是Windows,那么我們就可以調用這些定義的API。
這些是本人在研究跨平台桌面程序開發時遇到的關於與平台掛鈎的鍵盤鈎子功能時的處理方式。
附上本人的鍵盤鈎子代碼。
Hook.h
1 #ifndef HOOK_H 2 #define HOOK_H 3 #include<QObject> 4 #ifdef Q_OS_WIN 5 #include"Windows.h" 6 7 class Hook 8 { 9 public: 10 Hook(); 11 void installHook(); 12 void unInstallHook(); 13 }; 14 15 #endif 16 #endif // HOOK_H
Hook.c
1 #include "hook.h" 2 #include<QDebug> 3 #ifdef Q_OS_WIN 4 Hook::Hook() 5 { 6 7 } 8 9 static HHOOK keyHook=nullptr; 10 LRESULT CALLBACK keyProc(int nCode,WPARAM wParam,LPARAM lParam) 11 { 12 KBDLLHOOKSTRUCT *pkbhs=(KBDLLHOOKSTRUCT*)lParam; 13 if(nCode == HC_ACTION){ 14 if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL)& 0x8000 && GetAsyncKeyState(VK_SHIFT)&0x8000){ 15 qDebug() << "Ctrl+Shift+Esc"; 16 }else if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL) & 0x8000){ 17 qDebug() << "Ctrl+Esc"; 18 }else if(pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN){ 19 qDebug() << "Alt+Tab"; 20 }else if(pkbhs->vkCode == VK_ESCAPE && pkbhs->flags &LLKHF_ALTDOWN){ 21 qDebug() << "Alt+Esc"; 22 }else if(pkbhs->vkCode == VK_LWIN || pkbhs->vkCode == VK_RWIN){ 23 qDebug() << "LWIN/RWIN"; 24 }else if(pkbhs->vkCode == VK_F4 && pkbhs->flags & LLKHF_ALTDOWN){ 25 qDebug() << "Alt+F4"; 26 } 27 return 1;//返回1表示截取消息不再傳遞,返回0表示不作處理,消息繼續傳遞 28 } 29 return CallNextHookEx(keyHook, nCode, wParam, lParam); 30 } 31 32 void Hook::unInstallHook() 33 { 34 if(keyHook!=nullptr) 35 { 36 UnhookWindowsHookEx(keyHook);//鍵盤鈎子句不為空時銷毀掉 37 keyHook=nullptr; 38 } 39 if(keyHook!=nullptr) 40 { 41 UnhookWindowsHookEx(keyHook);//鍵盤鈎子句不為空時銷毀掉 42 keyHook=nullptr; 43 } 44 } 45 46 void Hook::installHook() 47 { 48 keyHook =SetWindowsHookEx( WH_KEYBOARD_LL,keyProc,nullptr,0); 49 qDebug() << "0"; 50 } 51 #endif