简介
- include <windows.h>
- 本版本使用的LL版,提供了获取虚拟键码,鼠标坐标等方法,比较全面。
- 采用了观察者模式,将所有注册进来的函数放置到list里面,当事件触发的时候遍历和调用。
- hookhelper.h 和 hookhelper.cpp 考虑了移植性和多线程,所以写的复杂了许多,但是功能是全面的,且做成DLL也是比较方便的。
- 重要文档
源代码
hookhelper.h
#ifndef HOOKHELPER_H
#define HOOKHELPER_H
#include <iostream>
#include <Windows.h>
#include <string>
#include <list>
#include <mutex>
using namespace std;
enum class e_WParam;
typedef void (*f_keyEvent )(e_WParam wParam, LPARAM lParam);
typedef void (*f_print)(string str);
struct s_KeyCallMsg{
string name;
WPARAM listenWParam;
f_keyEvent callback;
};
struct s_MouseCallMsg{
string name;
WPARAM listenWParam;
f_keyEvent callback;
};
enum class e_HookType{
MOUSE,
KEY_BOARD
};
enum class e_WParam{
KEYDOWN=0x0100,
KEYUP=0x0101,
SYSKEYDOWN=0x0104,
SYSKEYUP=0x0105,
LBUTTONUP=0x0202,
LBUTTONDOWN=0x0201,
RBUTTONDOWN=0x0204,
RBUTTONUP=0x0205,
MOUSEHWHEEL=0x020E,
MOUSEWHEEL=0x020A,
MOUSEMOVE=0x0200
};
DWORD GetKeyCode(LPARAM lParam);
POINT GetMousePoint(LPARAM lParam);
void SetPrintFunction(f_print f);
BOOL AddKeyBoardHookCallBack(s_KeyCallMsg callMsg);
BOOL AddMouseHookCallBack(s_MouseCallMsg callMsg);
BOOL UninstallHook(string name,e_HookType type);
BOOL UninstallAllHook(e_HookType type) ;
#endif
hookhelper.cpp
#include "hookhelper.h"
HHOOK g_keyHHook;
HHOOK g_mouseHHook;
list<s_KeyCallMsg> g_keyCallMsgList;
list<s_MouseCallMsg> g_mouseCallMsgList;
BOOL g_keyIsInstall=FALSE;
BOOL g_mouseIsInstall=FALSE;
f_print g_print = NULL;
static mutex g_keyMu;
static mutex g_mouseMu;
void _PrivateLog(string str){
if(g_print==NULL){
return;
}
(*g_print)(str);
}
DWORD GetKeyCode(LPARAM lParam){
PKBDLLHOOKSTRUCT st = (PKBDLLHOOKSTRUCT)lParam;
return st->vkCode;
}
POINT GetMousePoint(LPARAM lParam){
PMSLLHOOKSTRUCT st =(PMSLLHOOKSTRUCT)lParam;
return st->pt;
}
LRESULT CALLBACK ProcForKeyBoard(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0 || code == HC_NOREMOVE) {
return CallNextHookEx(g_keyHHook, code, wParam, lParam);
}
DWORD vkCode = GetKeyCode(lParam);
for(auto it=g_keyCallMsgList.begin();it!=g_keyCallMsgList.end();it++){
s_KeyCallMsg callMsg = *it;
if(callMsg.listenWParam == 0){
callMsg.callback(e_WParam(wParam),lParam);
}else if(callMsg.listenWParam == vkCode){
callMsg.callback(e_WParam(wParam),lParam);
}
}
return CallNextHookEx( g_keyHHook, code, wParam, lParam);
}
LRESULT CALLBACK ProcForMouseBoard(int code, WPARAM wParam, LPARAM lParam) {
if (code < 0 || code == HC_NOREMOVE) {
return CallNextHookEx(g_mouseHHook, code, wParam, lParam);
}
for(auto it=g_mouseCallMsgList.begin();it!=g_mouseCallMsgList.end();it++){
s_MouseCallMsg callMsg = *it;
if(callMsg.listenWParam == 0){
callMsg.callback(e_WParam(wParam),lParam);
}else if(callMsg.listenWParam == wParam){
callMsg.callback(e_WParam(wParam),lParam);
}
}
return CallNextHookEx( g_mouseHHook, code, wParam, lParam);
}
void SetPrintFunction(f_print f){
g_print = f;
}
BOOL InstallHook(e_HookType type) {
BOOL flag = FALSE;
if(type==e_HookType::KEY_BOARD){
if(!g_keyIsInstall){
g_keyMu.lock();
if(!g_keyIsInstall){
g_keyHHook = SetWindowsHookEx(WH_KEYBOARD_LL, ProcForKeyBoard, nullptr, 0);
if ( g_keyHHook == NULL) {
_PrivateLog("全局钩子注册失败");
flag = FALSE;
g_keyIsInstall = FALSE;
}else{
flag = TRUE;
g_keyIsInstall = TRUE;
}
}
g_keyMu.unlock();
}
}else if(type == e_HookType::MOUSE){
if(!g_mouseIsInstall){
g_mouseMu.lock();
if(!g_mouseIsInstall){
g_mouseHHook = SetWindowsHookEx(WH_MOUSE_LL, ProcForMouseBoard, GetModuleHandle(NULL), 0);
if ( g_mouseHHook == NULL) {
_PrivateLog("全局钩子注册失败");
flag = FALSE;
g_mouseIsInstall = FALSE;
}else{
flag = TRUE;
g_mouseIsInstall = TRUE;
}
}
g_mouseMu.unlock();
}
}
return flag;
}
BOOL AddKeyBoardHookCallBack(s_KeyCallMsg callMsg){
BOOL flag = InstallHook(e_HookType::KEY_BOARD);
if(!flag){
return FALSE;
}
g_keyCallMsgList.push_back(callMsg);
return TRUE;
}
BOOL AddMouseHookCallBack(s_MouseCallMsg callMsg){
BOOL flag = InstallHook(e_HookType::MOUSE);
if(!flag){
return FALSE;
}
g_mouseCallMsgList.push_back(callMsg);
return TRUE;
}
BOOL UninstallHook(string name,e_HookType type) {
BOOL unFlag = FALSE;
switch(type){
case e_HookType::KEY_BOARD:
g_keyMu.lock();
if(g_keyIsInstall){
size_t size = g_keyCallMsgList.size();
if(size==1){
unFlag = UnhookWindowsHookEx( g_keyHHook);
if(unFlag){
g_keyCallMsgList.clear();
}
g_keyIsInstall = unFlag ? FALSE : TRUE;
}else if(size>1){
for(auto it=g_keyCallMsgList.begin();it!=g_keyCallMsgList.end();it++){
s_KeyCallMsg callMsg = *it;
if(callMsg.name == name){
g_keyCallMsgList.erase(it);
break;
}
}
unFlag=TRUE;
}
}else{
unFlag = TRUE;
}
g_keyMu.unlock();
return unFlag;
case e_HookType::MOUSE:
g_mouseMu.lock();
if(g_mouseIsInstall){
size_t size = g_mouseCallMsgList.size();
if(size==1){
unFlag = UnhookWindowsHookEx(g_mouseHHook);
if(unFlag){
g_mouseCallMsgList.clear();
}
g_mouseIsInstall = unFlag ? FALSE : TRUE;
}else if(size>1){
for(auto it=g_mouseCallMsgList.begin();it!=g_mouseCallMsgList.end();it++){
s_MouseCallMsg callMsg = *it;
if(callMsg.name == name){
g_mouseCallMsgList.erase(it);
break;
}
}
unFlag=TRUE;
}
}else{
unFlag = TRUE;
}
g_mouseMu.unlock();
return unFlag;
default:
return TRUE;
}
}
BOOL UninstallAllHook(e_HookType type) {
BOOL unFlag = FALSE;
switch(type){
case e_HookType::KEY_BOARD:
g_keyMu.lock();
if(g_keyIsInstall){
unFlag = UnhookWindowsHookEx( g_keyHHook);
if(unFlag){
g_keyCallMsgList.clear();
}
g_keyIsInstall = unFlag ? FALSE : TRUE;
}else{
unFlag = TRUE;
}
g_keyMu.unlock();
return unFlag;
case e_HookType::MOUSE:
g_mouseMu.lock();
if(g_mouseIsInstall){
unFlag = UnhookWindowsHookEx(g_mouseHHook);
if(unFlag){
g_mouseCallMsgList.clear();
}
g_mouseIsInstall = unFlag ? FALSE : TRUE;
}else{
unFlag = TRUE;
}
g_mouseMu.unlock();
return unFlag;
default:
return TRUE;
}
}
QT 中使用示例
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "hookhelper.h"
void keyEvent(e_WParam wParam, LPARAM lParam){
DWORD keyCode;
switch(wParam){
case e_WParam::KEYUP:
keyCode = GetKeyCode(lParam);
qDebug()<< keyCode <<",按键松开了";
break;
case e_WParam::KEYDOWN:
qDebug()<<"按键按下了";
break;
case e_WParam::SYSKEYDOWN:
qDebug()<<"系统按键按下了";
break;
case e_WParam::SYSKEYUP:
qDebug()<<"按键松开了";
break;
}
}
void mouseEvent(e_WParam wParam, LPARAM lParam){
POINT p;
switch(wParam){
case e_WParam::LBUTTONUP:
p = GetMousePoint(lParam);
qDebug()<< p.x << "," << p.y<<",鼠标左键松开了";
break;
case e_WParam::LBUTTONDOWN:
qDebug()<<"鼠标左键按下了";
break;
case e_WParam::RBUTTONDOWN:
qDebug()<<"鼠标右键按下了";
break;
case e_WParam::RBUTTONUP:
qDebug()<<"鼠标右键松开了";
break;
}
}
void _print(std::string str){
qDebug() << "输出:"<< QString::fromLocal8Bit(str.data());
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
SetPrintFunction(_print);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
s_KeyCallMsg callMsg;
callMsg.name = "keyCall";
callMsg.callback = keyEvent;
callMsg.listenWParam = 0;
BOOL flag = AddKeyBoardHookCallBack(callMsg);
qDebug() << "Hook结果" << flag;
}
void MainWindow::on_pushButton_3_clicked()
{
s_MouseCallMsg callMsg;
callMsg.name = "mouseCall";
callMsg.callback = mouseEvent;
callMsg.listenWParam = 0;
BOOL flag = AddMouseHookCallBack(callMsg);
qDebug() << "Hook结果" << flag;
}
void MainWindow::on_pushButton_2_clicked()
{
UninstallAllHook(e_HookType::KEY_BOARD);
UninstallAllHook(e_HookType::MOUSE);
}