Qt-Qt使用鍵盘钩子Hook(支持判断按下、弹起、自动)


相关资料:

https://www.cnblogs.com/chyshx/p/12614148.html      钩子的使用

http://www.bubuko.com/infodetail-3073312.html      虚拟键码表(供函数GetAsyncKeyState()使用)

https://blog.csdn.net/joyopirate/article/details/109077913       Qt利用钩子函数实现键盘监听

https://download.csdn.net/download/zhujianqiangqq/71923476         csdn代码包下载

实例代码:

.pro

 1 QT       += core gui
 2 
 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 4 
 5 CONFIG += c++11
 6 
 7 # The following define makes your compiler emit warnings if you use
 8 # any Qt feature that has been marked deprecated (the exact warnings
 9 # depend on your compiler). Please consult the documentation of the
10 # deprecated API in order to know how to port your code away from it.
11 DEFINES += QT_DEPRECATED_WARNINGS
12 
13 # You can also make your code fail to compile if it uses deprecated APIs.
14 # In order to do so, uncomment the following line.
15 # You can also select to disable deprecated APIs only up to a certain version of Qt.
16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
17 
18 SOURCES += \
19     Hook.cpp \
20     main.cpp \
21     mainwindow.cpp
22 
23 HEADERS += \
24     Hook.h \
25     mainwindow.h
26 
27 FORMS += \
28     mainwindow.ui
29 
30 LIBS += -luser32
31 
32 # Default rules for deployment.
33 qnx: target.path = /tmp/$${TARGET}/bin
34 else: unix:!android: target.path = /opt/$${TARGET}/bin
35 !isEmpty(target.path): INSTALLS += target

main.cpp

 1 #include "mainwindow.h"
 2 
 3 #include 
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     QApplication a(argc, argv);
 8     MainWindow w;
 9     w.show();
10     return a.exec();
11 }

manwindow.h

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include 
 5 #include 
 6 
 7 
 8 #include 
 9 #include 
10 #include 
11 #include 
12 #include "Hook.h"
13 
14 QT_BEGIN_NAMESPACE
15 namespace Ui { class MainWindow; }
16 QT_END_NAMESPACE
17 
18 class MainWindow : public QMainWindow
19 {
20     Q_OBJECT
21 
22 public:
23     MainWindow(QWidget *parent = nullptr);
24     ~MainWindow();
25 private slots:
26     void on_pushButton_clicked();
27     void UpdateCapslockTip(int keyCode, bool downOrUp, bool aotu);
28 private:
29     Ui::MainWindow *ui;
30     Hook *m_pHook;
31 };
32 #endif // MAINWINDOW_H

mainwindow.cpp

 1 #include "mainwindow.h"
 2 #include "ui_mainwindow.h"
 3 
 4 MainWindow::MainWindow(QWidget *parent)
 5     : QMainWindow(parent)
 6     , ui(new Ui::MainWindow)
 7 {
 8     ui->setupUi(this);
 9     setWindowTitle(QStringLiteral("Qt使用鍵盘钩子Hook(支持判断按下、弹起、自动)"));
10 
11     #ifdef Q_OS_WIN
12     m_pHook = new Hook();
13     m_pHook->installHook();
14     m_pHook->SetKeyboardCall(std::bind(&MainWindow::UpdateCapslockTip, this, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
15     #endif
16 }
17 
18 MainWindow::~MainWindow()
19 {
20     m_pHook->unInstallHook();
21     delete ui;
22 }
23 
24 void MainWindow::on_pushButton_clicked()
25 {
26     ui->textEdit->clear();
27 }
28 
29 void MainWindow::UpdateCapslockTip(int keyCode, bool downOrUp, bool aotu)
30 {
31     QString s = "key pressed:--------:%1  downOrUp:%2  aotu:%3";
32     s = s.arg(keyCode).arg(downOrUp).arg(aotu);
33     ui->textEdit->append(s);
34     qDebug() << "key pressed:--------:" << keyCode
35              << "downOrUp:" << downOrUp
36              << "aotu:" << aotu;
37 }

hook.h

 1 #ifndef HOOK_H
 2 #define HOOK_H
 3 
 4 #include
 5 #include
 6 #ifdef Q_OS_WIN  // 代表只有WIN系统才会启用
 7 #include"Windows.h"
 8 #include // 回调函数引入
 9 #include // 时间函数引入
10 
11 class Hook
12 {
13 public:
14     Hook();
15     void installHook();
16     void unInstallHook();
17     static LRESULT CALLBACK keyProc(int nCode,WPARAM wParam,LPARAM lParam);
18     void SetKeyboardCall(const std::function<void (int,bool,bool)> & func){ m_func = func; }
19 private:
20     static std::function<void(int,bool,bool)> m_func;
21 };
22 #endif
23 
24 #endif // HOOK_H

hook.cpp

  1 #include "Hook.h"
  2 
  3 #ifdef Q_OS_WIN
  4 Hook::Hook()
  5 {
  6 
  7 }
  8 
  9 static HHOOK keyHook = nullptr;
 10 std::function<void(int,bool,bool)> Hook::m_func = nullptr;
 11 bool m_bAuto = false;// 是否为自动按键,false代表是手动按下,true代表是自动按下。
 12 int m_nKey = 0;// 上次的按键值
 13 bool m_bDownOrUp = false;// 是否按下,false弹起,true按下。
 14 
 15 LRESULT CALLBACK Hook::keyProc(int nCode,WPARAM wParam,LPARAM lParam)
 16 {
 17     // GetAsyncKeyState 判断正在按下某键 取异步键状态 物理键状态(实际的)
 18     // GetKeyState GetKeyboardState 判断刚按过了某键 逻辑键状态(虚拟的)
 19 //    KBDLLHOOKSTRUCT *pkbhs=(KBDLLHOOKSTRUCT*)lParam;
 20 //    if(nCode == HC_ACTION){
 21 //            if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL)& 0x8000 && GetAsyncKeyState(VK_SHIFT)&0x8000){
 22 //                        qDebug() << "Ctrl+Shift+Esc";
 23 //            }else if(pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL) & 0x8000){
 24 //                qDebug() << "Ctrl+Esc";
 25 //            }else if(pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN){
 26 //                qDebug() << "Alt+Tab";
 27 //            }else if(pkbhs->vkCode == VK_ESCAPE && pkbhs->flags &LLKHF_ALTDOWN){
 28 //                qDebug() << "Alt+Esc";
 29 //            }else if(pkbhs->vkCode == VK_LWIN || pkbhs->vkCode == VK_RWIN){
 30 //                qDebug() << "LWIN/RWIN";
 31 //            }else if(pkbhs->vkCode == VK_F4 && pkbhs->flags & LLKHF_ALTDOWN){
 32 //                qDebug() << "Alt+F4";
 33 //            }
 34 //            return CallNextHookEx(keyHook, nCode, wParam, lParam);//返回1表示截取消息不再传递,返回0表示不作处理,消息继续传递
 35 //        }
 36 
 37     // 当前进程
 38     HWND hwnd = GetForegroundWindow();
 39     DWORD Fid = GetWindowThreadProcessId(hwnd, NULL);
 40     DWORD Cid = GetCurrentThreadId();
 41     if (Fid != Cid)
 42     {
 43         return CallNextHookEx(keyHook, nCode, wParam, lParam);
 44     }
 45 
 46      KBDLLHOOKSTRUCT *pKBDLLHook= (KBDLLHOOKSTRUCT*)lParam;
 47 
 48      if(nCode == HC_ACTION){
 49          // 处理自动按下
 50          if (m_nKey == (int)pKBDLLHook->vkCode)
 51          {
 52              m_bAuto = true;
 53          }else
 54          {
 55              m_bAuto = false;
 56              m_nKey = pKBDLLHook->vkCode;
 57          }
 58 
 59          if (wParam== WM_KEYDOWN)
 60          {
 61              m_bDownOrUp = true;
 62          }
 63          if (wParam== WM_KEYUP)
 64          {
 65              m_bDownOrUp = false;
 66              m_bAuto = false;
 67              m_nKey = 0;
 68          }
 69      }
 70 
 71      if (m_func)
 72      {
 73          m_func(pKBDLLHook->vkCode, m_bDownOrUp, m_bAuto);
 74      }
 75 
 76 //     if (GetAsyncKeyState(VK_LSHIFT)&0x8000)
 77 //     {
 78 //         QDateTime dateTime;
 79 //         QString s;
 80 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_LSHIFT";
 81 //         qDebug() << s;
 82 //     }
 83 //     if (GetAsyncKeyState(VK_RSHIFT)&0x8000)
 84 //     {
 85 //         QDateTime dateTime;
 86 //         QString s;
 87 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_RSHIFT";
 88 //         qDebug() << s;
 89 //     }
 90 //     if (GetAsyncKeyState(VK_UP)&0x8000)
 91 //     {
 92 //         QDateTime dateTime;
 93 //         QString s;
 94 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_UP";
 95 //         qDebug() << s;
 96 //     }
 97 //     if (GetAsyncKeyState(VK_DOWN)&0x8000)
 98 //     {
 99 //         QDateTime dateTime;
100 //         QString s;
101 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_DOWN";
102 //         qDebug() << s;
103 //     }
104 //     if (GetAsyncKeyState(VK_LEFT)&0x8000)
105 //     {
106 //         QDateTime dateTime;
107 //         QString s;
108 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_LEFT";
109 //         qDebug() << s;
110 //     }
111 //     if (GetAsyncKeyState(VK_RIGHT)&0x8000)
112 //     {
113 //         QDateTime dateTime;
114 //         QString s;
115 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_RIGHT";
116 //         qDebug() << s;
117 //     }
118 //     if (GetAsyncKeyState(VK_RETURN)&0x8000)
119 //     {
120 //         QDateTime dateTime;
121 //         QString s;
122 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_RETURN";
123 //         qDebug() << s;
124 //     }
125 //     if (GetAsyncKeyState(VK_ESCAPE )&0x8000)
126 //     {
127 //         QDateTime dateTime;
128 //         QString s;
129 //         s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_ESCAPE ";
130 //         qDebug() << s;
131 //     }
132 
133 //    if (wParam== WM_KEYUP && pKBDLLHook->vkCode== VK_F10)
134 //    {
135 //        QDateTime dateTime;
136 //        QString s;
137 //        s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_F10";
138 //        qDebug() << s;
139 //    }
140 //    if (wParam== WM_KEYDOWN  && pKBDLLHook->vkCode== VK_F10)
141 //    {
142 //        QDateTime dateTime;
143 //        QString s;
144 //        s = "WM_KEYDOWN:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_F10";
145 //        qDebug() << s;
146 //    }
147 //    if (wParam== WM_KEYUP && pKBDLLHook->vkCode== VK_TAB)
148 //    {
149 //        QDateTime dateTime;
150 //        QString s;
151 //        s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_TAB";
152 //        qDebug() << s;
153 //    }
154 //    if (wParam== WM_KEYDOWN  && pKBDLLHook->vkCode== VK_TAB)
155 //    {
156 //        QDateTime dateTime;
157 //        QString s;
158 //        s = "WM_KEYDOWN:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_TAB";
159 //        qDebug() << s;
160 //    }
161 //    if (wParam== WM_KEYUP && pKBDLLHook->vkCode== 'A')
162 //    {
163 //        QDateTime dateTime;
164 //        QString s;
165 //        s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - A";
166 //        qDebug() << s;
167 //    }
168 //    if (wParam== WM_KEYDOWN  && pKBDLLHook->vkCode== 'A')
169 //    {
170 //        QDateTime dateTime;
171 //        QString s;
172 //        s = "WM_KEYDOWN:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - A";
173 //        qDebug() << s;
174 //    }
175 //    if (pKBDLLHook->flags & LLKHF_ALTDOWN)
176 //    {
177 //        QDateTime dateTime;
178 //        QString s;
179 //        s = ":" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - LLKHF_ALTDOWN";
180 //        qDebug() << s;
181 //    }
182 //    if (GetAsyncKeyState(VK_CONTROL)& 0x8000)
183 //    {
184 //        QDateTime dateTime;
185 //        QString s;
186 //        s = ":" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_CONTROL";
187 //        qDebug() << s;
188 //    }
189 //    if (GetAsyncKeyState(VK_SHIFT)&0x8000)
190 //    {
191 //        QDateTime dateTime;
192 //        QString s;
193 //        s = ":" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - VK_SHIFT";
194 //        qDebug() << s;
195 //    }
196 //    if (GetKeyState(VK_CONTROL)&0x8000)
197 //    {
198 //        QDateTime dateTime;
199 //        QString s;
200 //        s = ":" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - GetKeyState VK_CONTROL";
201 //        qDebug() << s;
202 //    }
203 //    if (GetKeyState(VK_SHIFT)&0x8000)
204 //    {
205 //        QDateTime dateTime;
206 //        QString s;
207 //        s = ":" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - GetKeyState VK_SHIFT";
208 //        qDebug() << s;
209 //    }
210 //    if (wParam== WM_KEYUP && (pKBDLLHook->vkCode == VK_LWIN || pKBDLLHook->vkCode == VK_RWIN))
211 //    {
212 //        QDateTime dateTime;
213 //        QString s;
214 //        s = "WM_KEYUP:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - WM_KEYUP WIN";
215 //        qDebug() << s;
216 //    }
217 //    if (wParam== WM_KEYDOWN  && (pKBDLLHook->vkCode == VK_LWIN || pKBDLLHook->vkCode == VK_RWIN))
218 //    {
219 //        QDateTime dateTime;
220 //        QString s;
221 //        s = "WM_KEYDOWN:" + dateTime.currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz") + " - WM_KEYDOWN WIN";
222 //        qDebug() << s;
223 //    }
224     return CallNextHookEx(keyHook, nCode, wParam, lParam);
225 }
226 
227 void Hook::unInstallHook()
228 {
229     if(keyHook != nullptr)// 原作者说是担心一次释放不稳定,才释放二次的。
230     {
231         UnhookWindowsHookEx(keyHook);//键盘钩子句不为空时销毁掉
232         keyHook = nullptr;
233     }
234    if(keyHook != nullptr)
235     {
236         UnhookWindowsHookEx(keyHook);//键盘钩子句不为空时销毁掉
237         keyHook = nullptr;
238     }
239 }
240 
241 void Hook::installHook()
242 {
243     keyHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyProc, nullptr, 0);
244 }
245 
246 #endif

 

相关