首页 > 解决方案 > 如何同时运行一个钩子和一个计时器?

问题描述

我正在尝试用 C 编写一个宏程序,并且我已经设法使用以下代码获取密钥:

#include <windows.h>
#include <stdio.h>

HHOOK _hook;

KBDLLHOOKSTRUCT kbdStruct;

LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode >= 0) {
        kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
            printf("Key %lu pressed.\n", kbdStruct.vkCode);
        } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
            printf("Key %lu released.\n", kbdStruct.vkCode);
        }
    }

    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

void main() {
    if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0))) {
        MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
    }

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

我希望程序在按下特定键时在特定时间按下一系列键并具有SendInput()功能。当WH_KEYBOARD_LLwhile 循环设置为无限时,不再调用钩子。对我来说,使用GetMessage(&msg, NULL, 0, 0)似乎也不干净。

我已经搜索了一个钩子方法来在给定的时间间隔内调用一个函数,但没有成功。

我使用 GNU GCC 编译器。

我几乎没有在计算机上用 C 语言编程的经验,但我确实有用 C 语言为微控制器编程的经验。

编辑:

我已经尝试过使用 SetTimer() 的方法,但它没有被调用。我使用了此页面中的示例:http: //www.equestionanswers.com/vcpp/set-timer.php

#include <windows.h>
#include <stdio.h>

#define TimerID 85

HHOOK _hook;

KBDLLHOOKSTRUCT kbdStruct;

VOID __stdcall MyTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime) {
    printf("Timer call\n");
}

LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode >= 0) {
        kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
            printf("Key %lu pressed.\n", kbdStruct.vkCode);
        } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) {
            printf("Key %lu released.\n", kbdStruct.vkCode);
        }
    }

    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

void main() {
    if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0))) {
        MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
    }

    SetTimer(NULL, TimerID, 1000, MyTimerProc);

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

标签: cwhile-looptimersetwindowshookexkeyhook

解决方案


我没有使用过它,但据我SetTimer所知,它依赖于查找WM_TIMER消息的 Wndproc 或 Timerproc 回调。不过,“Windows 计时器”总体上相当粗糙,所以我会远离它们。

相反,您应该做的是创建一个完成这项工作的线程。你可以让它在大多数时候有效地睡着WaitForMultipleObjects,这样你就可以定义一个超时。当它超时时,执行应该循环重复的任务。您还应该创建两个自定义事件(CreateEvent等),一个从钩子回调发送,通知线程更新(“下次你工作,做工作 x”),另一个告诉威胁优雅地关闭自己(程序结束等)。有了这种设计,您也不必担心重新进入。


推荐阅读