【问题标题】:How to have a hook and have a timer running at the same time?如何同时运行一个钩子和一个计时器?
【发布时间】:2020-12-12 15:14:40
【问题描述】:

我正在尝试用 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() 功能在特定时间按下一系列键。 当 while 循环设置为无限时,不再调用 WH_KEYBOARD_LL 挂钩。 同样使用GetMessage(&amp;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)) {}
}

【问题讨论】:

  • 我对Windows不熟悉,但查了“winapi timers using messages”,发现docs.microsoft.com/en-us/windows/win32/winmsg/using-timers,看起来应该是对的。
  • 您想使用SetTimer() 就像上面发布的@Ry- 一样,但是您想使用它并填写第四个参数(TIMERPROC)。这将是对带有此的方法的回调签名:docs.microsoft.com/en-us/windows/win32/api/winuser/…
  • SetTimer 失败了吗?打完SetTimer之后可以打GetLastError()吗? SetTimer 返回什么?
  • 使用 DWORD dw = GetLastError(); printf("Error code is %X", dw); 我得到 7E,这与删除 SetTimer 时相同。

标签: c while-loop timer setwindowshookex keyhook


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 2013-12-10
    • 2015-07-18
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多