windows api学习笔记-键盘钩子

DLL项目的头文件

#ifdef KEYHOOKLIB_EXPORT //此宏将在CPP文件中定义
#define KEYHOOKLIB_API __declspec(dllexport)
#else
#define KEYHOOKLIB_API __declspec(dllimport)
#endif
 
#define HM_KEY WM_USER+101
 
BOOL KEYHOOKLIB_API WINAPI SetKeyHook(BOOL bInstall,DWORD dwThreadId = 0,HWND hWndCaller=NULL);

DLL项目CPP文件

#include <windows.h>
#define KEYHOOKLIB_EXPORT
#include "a.h"
 
#pragma data_seg("MyShared")//用共享数据段来保存主窗口句柄和钩子句柄
HWND g_hWndCaller = NULL;
HHOOK g_hHook = NULL;
#pragma data_seg()
 
//通过内存地址取得模块句柄
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
    MEMORY_BASIC_INFORMATION mbi;//此结构请查看MSDN
    if(::VirtualQuery(pv,&mbi,sizeof(mbi)))
    {
        return (HMODULE)mbi.AllocationBase;
    }
    return NULL;
}
 
//钩子的回调函数
LRESULT CALLBACK KeyHookProc(int nCode,//HOOK代码,钩子函数使用这个参数来确定任务
                             WPARAM wParam,
                             LPARAM lParam)
{
    if(nCode<0||nCode == HC_NOREMOVE)//没用的消息
    {
        return ::CallNextHookEx(g_hHook,nCode,wParam,lParam);
    }
    if(lParam&0x40000000)//消息重复
    {
        return ::CallNextHookEx(g_hHook,nCode,wParam,lParam);
    }
    ::PostMessage(g_hWndCaller,WM_CLOSE,0,0);
    return ::CallNextHookEx(g_hHook,nCode,wParam,lParam);
}
 
//给系统注册钩子
BOOL WINAPI SetKeyHook(BOOL bInstall,DWORD dwThreadId,HWND hWndCaller)
{
    BOOL bOK;
    g_hWndCaller = hWndCaller;
    if(bInstall)
    {
        HMODULE temp = ModuleFromAddress(KeyHookProc);//钩子函数所在的DLL的实例句柄
        g_hHook = ::SetWindowsHookEx(
            WH_KEYBOARD,//键盘钩子标志
            KeyHookProc,//回调函数
            temp,
            dwThreadId//线程句柄
            );
        if(g_hHook!=NULL)
        {
            bOK = TRUE;
        }
        else
        {
            bOK = FALSE;
        }
    }
    else
    {
        bOK = ::UnhookWindowsHookEx(g_hHook);//卸载钩子
        g_hHook = NULL;
    }
    return bOK;
}

DLL项目的DEF文件

LIBRARY "gouzi"
EXPORTS
SetKeyHook
SECTIONS
MyShared Read Write Shared

 

注册钩子的工程

#include <windows.h>
#include <iostream>
#include "a1.h"//DLL中的头文件
using namespace std;
#pragma comment(lib,"gouzi")
 
 
void main()
{
    ::SetConsoleTitle("aaa");
    //HWND hWnd = ::FindWindow(NULL,"Our First Window");
    HWND hWnd = ::FindWindow("notepad",NULL);
    //::SendMessage(hWnd,HM_KEY,)
    if(!SetKeyHook(TRUE,0,hWnd))
    {
        cout<<"安装钩子失败"<<endl;
        return;
    }
    char a;
    while(true)
    {
        cin>>a;
        if(a == 'u')
        {
            SetKeyHook(FALSE,0,hWnd);
            return;
        }
    }
    return;
}
posted @   liulun  阅读(676)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
点击右上角即可分享
微信分享提示