ToDo_0914

  博客园 :: :: 博问 :: 闪存 :: :: :: :: 管理 ::

Qt win32 全局鼠标键盘钩子 的实现

win32 中 实现全局钩子,需要用到  SetWindowsHookEx 和 UnhookWindowsHookEx 两个API 并且必须在 动态链接库(DLL)中实现对消息的截获。

在这里我们用到了 qt 信号槽 方便的通知机制,在DLL中导出了 可以对全局鼠标键盘消息进行截获 并用发射信号的方式通知给代码用户。

api 说明

SetWindowsHookEx API

原型 

1 HHOOK SetWindowsHookEx(
2   int idHook,        // hook type
3   HOOKPROC lpfn,     // hook procedure
4   HINSTANCE hMod,    // handle to application instance
5   DWORD dwThreadId   // thread identifier
6 );

目的:安装 指定类型的消息钩子,指定其消息处理函数,并返回 钩子的句柄。

参数:

   int idHook:in,指定钩子的类型,可取的值有 WH_MOUSE_LL(底层鼠标钩子)、WH_KEYBOARD_LL(底层键盘钩子)等等,我们用到的就是这两种钩子。

   HOOKPROC lpfn:in,指定消息处理函数的地址,不同的钩子参数的意义不同,键盘钩子处理函数原型如下:

LRESULT CALLBACK hookProc(
  int code,       // 钩子类型标志
  WPARAM wParam,  // 按键按下与抬起标志,可取值 有 WM_KEYUP 和 WM_KEYDOWN。
  LPARAM lParam   // 指向 按键钩子信息结构体 KBDLLHOOKSTRUCT 的指针,该结构体含有按键消息的各种属性。
);

返回值:钩子句柄。

UnhookWindowsHookEx API

原型

BOOL UnhookWindowsHookEx(  HHOOK hhk   // handle to hook procedure
);

 

 

目的:卸载 指定的消息钩子。

参数: 

        HHOOK hhk;要卸载的钩子句柄。

返回值:卸载成功返回true否则返回false。

DLL 实现

文件列表:

  • GlobalHook.pro        // 省略,项目向导中选择 C++ Library 模板即可。
  • XGlobalHook.h
  • XGlobalHook.cpp
 1 #ifndef XGLOBALHOOK_H
 2 #define XGLOBALHOOK_H
 3 
 4 #include <QObject>
 5 #include <QtGlobal>
 6 #include <QMutex>
 7 #include <QSharedPointer>
 8 #include "windows.h"
 9 
10 #if defined(GLOBALHOOK_LIBRARY)
11 #  define GLOBALHOOKSHARED_EXPORT Q_DECL_EXPORT
12 #else
13 #  define GLOBALHOOKSHARED_EXPORT Q_DECL_IMPORT
14 #endif
15 
16 #define xHook XGlobalHook::instance().data()
17 
18 class GLOBALHOOKSHARED_EXPORT XGlobalHook : public QObject
19 {
20   Q_OBJECT
21 
22   /// 单例
23 private:
24   XGlobalHook(QObject* parent = 0) : QObject(parent) {}
25   XGlobalHook(const XGlobalHook& hook) = delete;
26   XGlobalHook& operator==(const XGlobalHook&) = delete;
27 
28 public:
29   virtual ~XGlobalHook() final;
30   static QSharedPointer<XGlobalHook>& instance();
31 
32 private:
33   static QMutex mutex;
34   static QSharedPointer<XGlobalHook> hook_instance;
35 
36   /// 用户接口
37 public:
38   // 鼠标钩子
39   bool installMouseHook();          // 安装钩子
40   bool uninstallMouseHook();        // 卸载钩子
41   bool isMouseHookRunning() const;  // 运行状态
42   // 键盘钩子
43   bool installKeyHook();            // 安装钩子
44   bool uninstallKeyHook();          // 卸载钩子
45   bool isKeyHookRunning() const;    // 运行状态
46 
47 signals:
48   void mouseEvent(PMOUSEHOOKSTRUCT pMouseHookStruct);
49   void keyEvent(PKBDLLHOOKSTRUCT pKeyHookStruct);
50 
51   /// DLL 钩子接口
52 #if defined GLOBALHOOK_LIBRARY
53 public:
54   void onMouseEvent(PMOUSEHOOKSTRUCT pMouseHookStruct);
55   void onKeyEvent(PKBDLLHOOKSTRUCT pKeyHookStruct);
56 #endif
57 };
58 
59 #endif // XGLOBALHOOK_H
XGlobalHook.h

 

  1 #include "XGlobalHook.h"
  2 
  3 /// 静态变量定义
  4 QMutex XGlobalHook::mutex;
  5 QSharedPointer<XGlobalHook> XGlobalHook::hook_instance;
  6 
  7 /// 全局变量定义
  8 HINSTANCE g_hInstance = Q_NULLPTR;
  9 HHOOK g_hMouseHook = Q_NULLPTR;  //鼠标钩子 句柄
 10 HHOOK g_hKeyHook = Q_NULLPTR;    //键盘钩子 句柄
 11 
 12 /// 全局函数定义
 13 // DllMain
 14 BOOL WINAPI DllMain(
 15     HINSTANCE hinstDLL,  // DLL模块的句柄
 16     DWORD fdwReason,     // 调用的情况
 17     LPVOID lpReserved    // reserved
 18     );
 19 
 20 // 鼠标钩子处理函数
 21 LRESULT CALLBACK MouseProc(int nCode,       // 钩子码
 22                            WPARAM wParam,   // 消息ID
 23                            LPARAM lParam    // 鼠标坐标
 24                            );
 25 
 26 // 键盘钩子处理函数
 27 LRESULT CALLBACK KeyboardProc(int nCode,            // 钩子码
 28                               WPARAM wParam,        // 虚拟键码
 29                               LPARAM lParam         // 键击信息
 30                               );
 31 
 32 
 33 XGlobalHook::~XGlobalHook()
 34 {
 35   uninstallMouseHook();
 36   uninstallKeyHook();
 37 }
 38 
 39 QSharedPointer<XGlobalHook>&XGlobalHook::instance()
 40 {
 41   if (hook_instance.isNull())
 42   {
 43     QMutexLocker mutexLocker(&mutex);
 44     if (hook_instance.isNull())
 45       hook_instance = QSharedPointer<XGlobalHook>(new XGlobalHook());
 46   }
 47   return hook_instance;
 48 }
 49 
 50 bool XGlobalHook::installMouseHook()
 51 {
 52   g_hMouseHook =SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)MouseProc, g_hInstance, 0);
 53   return Q_LIKELY(g_hMouseHook);
 54 }
 55 
 56 bool XGlobalHook::uninstallMouseHook()
 57 {
 58   if (Q_UNLIKELY(!g_hMouseHook)) {
 59     return true;
 60   }
 61 
 62   bool success = false;
 63   success = UnhookWindowsHookEx(g_hMouseHook);
 64   if (success) {
 65     g_hMouseHook = Q_NULLPTR;
 66   }
 67   return success;
 68 }
 69 
 70 bool XGlobalHook::isMouseHookRunning() const
 71 {
 72   return Q_LIKELY(g_hMouseHook);
 73 }
 74 
 75 bool XGlobalHook::installKeyHook()
 76 {
 77   g_hKeyHook =SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, g_hInstance, 0);
 78   return Q_LIKELY(g_hKeyHook);
 79 }
 80 
 81 bool XGlobalHook::uninstallKeyHook()
 82 {
 83   if (Q_UNLIKELY(!g_hKeyHook)) {
 84     return true;
 85   }
 86 
 87   bool success = false;
 88   success = UnhookWindowsHookEx(g_hKeyHook);
 89   if (success) {
 90     g_hKeyHook = Q_NULLPTR;
 91   }
 92   return success;
 93 }
 94 
 95 bool XGlobalHook::isKeyHookRunning() const
 96 {
 97   return Q_LIKELY(g_hKeyHook);
 98 }
 99 
100 /// DLL 钩子接口
101 #if defined GLOBALHOOK_LIBRARY
102 
103 void XGlobalHook::onMouseEvent(PMOUSEHOOKSTRUCT pMouseHookStruct)
104 {
105   emit mouseEvent(pMouseHookStruct);
106 }
107 
108 void XGlobalHook::onKeyEvent(PKBDLLHOOKSTRUCT pKeyHookStruct)
109 {
110   emit keyEvent(pKeyHookStruct);
111 }
112 
113 #endif
114 
115 LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
116 {
117 
118   PMOUSEHOOKSTRUCT pmshs = reinterpret_cast<PMOUSEHOOKSTRUCT>(lParam);
119   xHook->onMouseEvent(pmshs);
120   return CallNextHookEx(g_hMouseHook,nCode,wParam,lParam);
121 }
122 
123 LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
124 {
125   PKBDLLHOOKSTRUCT pkbhs = reinterpret_cast<PKBDLLHOOKSTRUCT>(lParam);
126   xHook->onKeyEvent(pkbhs);
127   return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);
128 }
129 
130 BOOL WINAPI DllMain(
131     HINSTANCE hinstDLL,  // DLL模块的句柄
132     DWORD fdwReason,     // 调用的情况
133     LPVOID lpReserved )  // reserved
134 {
135   Q_UNUSED(lpReserved);
136   // 在不同的情况下都会调用DllMain函数,分别处理
137   switch( fdwReason )
138   {
139     // 加载Dll
140     case DLL_PROCESS_ATTACH:
141     {
142       g_hInstance = hinstDLL;
143       break;
144     }
145       // 新建线程
146     case DLL_THREAD_ATTACH:
147     break;
148       // 线程退出
149     case DLL_THREAD_DETACH:
150     break;
151       // 释放Dll
152     case DLL_PROCESS_DETACH:
153       g_hInstance = Q_NULLPTR;
154     break;
155   }
156   return TRUE;
157 }
XGlobalHook.cpp

类库使用:

  • 包含 XGlobalHook.h 文件
  • 指定 Lib 文件
  • 将 DLL 放到可执行文件
  • xHook 为 XGlobalHook 单例类的对象指针 ,操作同 qApp

 

posted on 2018-11-29 05:31  ToDo_0914  阅读(3436)  评论(1编辑  收藏  举报