huidong

首页 | 会员登录 | 关于争取 2022 寒假做出汇东网 Ver3.0.0 !
搜索文章


https://blog.csdn.net/qq_42789677/article/details/120364014


总结重点:

一般钩子在 Win32 程序里面跑,所以运行正常。但是我之前的尝试都是基于控制台窗口的,而钩子回调只能在调用 GetMessage()(或 PeekMessage())时发生,也就是 Windows 能够控制的时候发生,但由于我是控制台应用,自然地没有写 GetMessage(),所以一直没有成功。直到看到这篇文章,我才明白了问题所在。

 

备注,钩子上的 "WH_KEYBOARD_LL" 中的 "_LL" 说明是全局的。


#include<Windows.h>
#include<iostream>

std::string get_time()
{
    SYSTEMTIME sys;
    GetLocalTime(&sys);
    char time[1024] = { 0 };
    sprintf_s(time, "[%4d/%02d/%02d %02d:%02d:%02d]", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond);

    return std::string(time);
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    /*
    typedef struct tagKBDLLHOOKSTRUCT {
    DWORD     vkCode;        // 按键代号
    DWORD     scanCode;        // 硬件扫描代号,同 vkCode 也可以作为按键的代号。
    DWORD     flags;        // 事件类型,一般按键按下为 0 抬起为 128。
    DWORD     time;            // 消息时间戳
    ULONG_PTR dwExtraInfo;    // 消息附加信息,一般为 0。
    }KBDLLHOOKSTRUCT,*LPKBDLLHOOKSTRUCT,*PKBDLLHOOKSTRUCT;
    */
    KBDLLHOOKSTRUCT* ks = (KBDLLHOOKSTRUCT*)lParam;        // 包含低级键盘输入事件信息

    char data[1024];

    DWORD code = ks->vkCode;

    std::string t = get_time();
    char state[20];


    if (wParam == WM_KEYDOWN)
    {
        strcpy_s(state, "按下");
    }
    else if (wParam == WM_KEYUP)
    {
        strcpy_s(state, "抬起");
    }

    sprintf_s(data, "%s 键代码:%d %s", t.c_str(), code, state);

    std::cout << data << std::endl;


    return 1;    // 吃掉消息
    //return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    /*
    typedef struct tagMOUSEHOOKSTRUCT {
        POINT   pt;                    // Point数据
        HWND    hwnd;                // 接收鼠标消息的窗体的句柄
        UINT    wHitTestCode;        // 指定点击测试值
        ULONG_PTR dwExtraInfo;        // 指定和该消息相关联的附加信息。
    } MOUSEHOOKSTRUCT, FAR* LPMOUSEHOOKSTRUCT, * PMOUSEHOOKSTRUCT;
    */

    std::string t = get_time();
    char data[1024];

    MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
    POINT pt = ms->pt;

    char state[20] = "未识别";

    if (wParam == WM_LBUTTONDOWN)    // 其余回到文档去找
    {
        strcpy_s(state, "左键按下");
    }
    else if (wParam == WM_LBUTTONUP)
    {
        strcpy_s(state, "左键抬起");
    }
    else if (wParam == WM_MOUSEMOVE)
    {
        strcpy_s(state, "移动");
    }
    else if (wParam == WM_RBUTTONDOWN)
    {
        strcpy_s(state, "右键按下");
    }
    else if (wParam == WM_RBUTTONUP)
    {
        strcpy_s(state, "右键抬起");
    }

    sprintf_s(data, "%s 键代码:x:%d y:%d %s", t.c_str(), pt.x, pt.y, state);

    std::cout << data << std::endl;

    //return 1;    // 吃掉消息
    return CallNextHookEx(NULL, nCode, wParam, lParam);

}

int main()
{
    HINSTANCE hM = GetModuleHandle(NULL), hK = GetModuleHandle(NULL);
    HHOOK g_Hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hK, 0);
    HHOOK g_Hook2 = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, hM, 0);

    // 消息循环是必须的,Windows 直接在你自己的进程中调用你的 hook 回调.要做这个工作,
    // 需要一个消息循环.没有其他机制可以让您的主线程进行回调,
    // 回调只能在您调用 GetMessage()(或 PeekMessage())以使 Windows 可以控制时发生.

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    UnhookWindowsHookEx(g_Hook);

    return 0;
}




返回首页


Copyright (C) 2018-2024 huidong