You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Windows全局键盘钩子代码实现扫码输入内容替换?

解决方案思路

核心是缓存扫描器的连续输入字符,识别到目标字符串后拦截原始输入,仅模拟输出需要的部分。因为扫描器是模拟键盘快速输入,可通过输入间隔或结束符(如回车)判断扫描完成。

关键代码修改步骤

假设你已有全局键盘钩子的基础框架,以下是KeyboardHookProc的修改逻辑:

  1. 定义全局变量缓存输入、记录输入时间戳:
std::wstring inputBuffer;
DWORD lastKeyTime = 0;
const std::wstring TARGET_STRING = L"abc,def";
const std::wstring OUTPUT_STRING = L"def";
  1. 在钩子回调中处理按键:
LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode >= 0 && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) {
        KBDLLHOOKSTRUCT* pKeyBoard = (KBDLLHOOKSTRUCT*)lParam;
        DWORD currentTime = GetTickCount();
        
        // 若两次按键间隔超过200ms,视为新的输入,清空缓冲区(区分手动输入和扫描器快速输入)
        if (currentTime - lastKeyTime > 200) {
            inputBuffer.clear();
        }
        lastKeyTime = currentTime;

        // 获取按键对应的字符(处理Shift等修饰键)
        wchar_t ch = 0;
        BYTE keyState[256] = {0};
        GetKeyboardState(keyState);
        ToUnicode(pKeyBoard->vkCode, pKeyBoard->scanCode, keyState, &ch, 1, 0);

        if (ch != 0) {
            inputBuffer += ch;

            // 检查是否匹配目标字符串(含可能的回车结束符)
            if (inputBuffer == TARGET_STRING || inputBuffer == TARGET_STRING + L"\r") {
                // 模拟输出"def"
                INPUT inputs[3] = {0};
                for (int i = 0; i < OUTPUT_STRING.length(); i++) {
                    inputs[i].type = INPUT_KEYBOARD;
                    inputs[i].ki.wVk = 0;
                    inputs[i].ki.wScan = OUTPUT_STRING[i];
                    inputs[i].ki.dwFlags = KEYEVENTF_UNICODE;
                }
                SendInput(OUTPUT_STRING.length(), inputs, sizeof(INPUT));
                
                // 清空缓冲区并拦截原始输入
                inputBuffer.clear();
                return 1;
            }
            // 若缓冲区前缀不匹配目标,正常传递消息并清空缓存
            else if (TARGET_STRING.find(inputBuffer) != 0) {
                inputBuffer.clear();
            }
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
针对三种尝试的问题分析
  • 若第一种是逐字符拦截:没有缓存完整字符串就提前处理,无法识别完整的"abc,def",易出现误拦截或放行。
  • 若第二种是直接替换单个字符:扫描器输入是连续按键,单个字符无法判断是否属于目标前缀,容易误替换普通输入。
  • 若第三种是未正确拦截原始消息:即使模拟输出了"def",原始的"abc,def"仍会被输入,导致内容重复。
注意事项
  • 处理扫描器结束符:部分扫描器会在扫描后自动添加回车(\r或\n),需在目标判断中包含该情况。
  • 权限要求:全局键盘钩子需要程序以管理员权限运行,避免被系统拦截。
  • 修饰键兼容:ToUnicode会自动处理Shift等按键,确保正确获取输入字符(如大写字母)。

内容的提问来源于stack exchange,提问作者Ari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 04:22:53