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