getKeyboardState一个密钥延迟

GetKeyboardState one key delay

本文关键字:一个 密钥 延迟 getKeyboardState      更新时间:2023-10-16

我正在从事ToUnicodeEx功能,并且需要键盘状态为输入参数。因此,我使用GetKeyboardState函数来做到这一点。但是我注意到当我使用修饰符键键入 shift> shift a 时,有一个字符延迟。这是一个例子。

aaa(holding shift 现在)aaaaaaaa(版本 shift> shift )aaaa

当我调试此问题时,我注意到GetKeyboardState造成了此延迟。我如何处理或防止此延迟?

这是我的整个键盘挂钩Proc。

void proc(KBDLLHOOKSTRUCT kbdStruct) {

    fdebug = fopen("debug.txt", "a");
    foutput= fopen("output.txt", "a");
    WCHAR pwszBuff[9];
    WCHAR key[9];
    char str[8];
    BOOL isDead = FALSE;
    BYTE lpKeyState[256];
    HWND currentHwnd = GetForegroundWindow();
    LPDWORD currentProcessID = 0;
    DWORD currentWindowThreadID = GetWindowThreadProcessId(currentHwnd, currentProcessID);
    DWORD thisProgramThreadId = GetCurrentThreadId();
    hkl = GetKeyboardLayout(thisProgramThreadId);
    if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, TRUE))
    {
        GetKeyboardState(lpKeyState);
        AttachThreadInput(thisProgramThreadId, currentWindowThreadID, FALSE);
    }
    else
    {
        GetKeyboardState(lpKeyState);
    }
    int ret = ToUnicodeEx(kbdStruct.vkCode, kbdStruct.scanCode, lpKeyState, pwszBuff, 8, 0, hkl);
    fprintf(fdebug, "vkCode: %dn", (int)kbdStruct.vkCode);
    fprintf(fdebug, "ret: %dn", (int)ret);
    fprintf(fdebug, "lastIsDead: %dn", (int)lastIsDead);
    fprintf(fdebug, "lastIsMod: %dn", (int)lastIsMod);
    fprintf(fdebug, "lastVKCode: %dn", (int)lastVKCode);
    if (ret == -1) {
        isDead = TRUE;
        ClearKeyboardBuffer(kbdStruct.vkCode, kbdStruct.scanCode, hkl);
    }
    else if (ret == 0) {
    }
    else {
        memcpy(&key, &pwszBuff, sizeof(pwszBuff));
        WideCharToMultiByte(CP_UTF8, 0, key, -1, str, sizeof(str), NULL, NULL);
        fprintf(fdebug, "str: %sn", str);
    }
    if (lastVKCode != 0 && lastIsDead == TRUE) {
        ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, pwszBuff, 4, 0, hkl);
        memcpy(&key, &pwszBuff, sizeof(pwszBuff));
        WideCharToMultiByte(CP_UTF8, 0, key, -1, str, sizeof(str), NULL, NULL);
        fprintf(fdebug, "str: %sn", str);
        lastVKCode = 0;
    }
    fprintf(fdebug, "%s", "---------------------------------------------------n");
    fprintf(foutput, "LSHIFT: %dn", (int)lpKeyState[160]);
    fprintf(foutput, "RSHIFT: %dn", (int)lpKeyState[161]);
    fprintf(foutput, "%s", "---------------------------------------------------nn");
    lastVKCode = kbdStruct.vkCode;
    lastScanCode = kbdStruct.scanCode;
    lastIsDead = isDead;
    fclose(fdebug);
    fclose(foutput);
}

这是hookcallback的更新版本,谢谢Ton Plooij。但是,我仍然有同样的问题。

LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    LRESULT ret = CallNextHookEx(_hook, nCode, wParam, lParam);
    if (nCode >= 0)
    {
        if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
        {
            hookStruct = *((KBDLLHOOKSTRUCT*)lParam);
            proc(hookStruct);
        }
    }
    return ret;
}
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, FALSE);

这并不能做您希望做的事情。有时。当您致电GetKeyboardState()时,这是一项英勇而必要的努力。花了我一段时间来找到故障模式,这一点并不明显,我无法以相同的方式使代码失败。当GUI过程处于前景时,它可以正常工作,例如,使用记事本或VS。

但是不是当它是控制台模式过程时。

解释有点令人费解的是,实际上是返回误导信息的getWindowThreadProcessid()。它试图保持幻想,即拥有控制台窗口的控制台过程。它不是,实际上是拥有它的关联的conhost.exe过程。Windows 7中添加了conhost.exe在旧的Windows版本上的CSRSS.exe,以求解由UIPI引起的拖放 下降问题。

但没有任何不错的方法来发现拥有该窗口的特定conhost.exe过程,更不用说线程ID了。此Q a的主题。非常怀疑它将为您提供帮助。

只有体面的建议是众所周知的令人不愉快的建议:如果您需要可靠地翻译击键,那么您需要使用wh_keyboard挂钩而不是wh_keyboard_ll。因此,getKeyboardState()始终是准确的,挂钩回调在进程中运行。

lowlevelkeyboardproc在其WPARAM中接收WM_KEYUP和WM_KEYDOWN消息。在这种情况下,您可以自己跟踪按压修饰符键,以检测到向下移动。将密钥状态信息存储在静态变量中,并使用它在处理其他键而不是使用getKeyState时测试是否按下移位。

您可以尝试getAsyncKeystate()。我的键盘钩模块中的此功能完美地工作。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms646293(v = vs.85).aspx

在按键时,似乎可以捕获硬件中断。

,您的GetKeyboardState与Windows注册表有关。它似乎与Belows有关:

" hkey_users default controlpanel 键盘",修改"键盘delay"值为0 default 1)并将"键盘匹配"值更改为48(Dafault 31)。

根据Hans Passant的答案,我搜索了我如何从GetWindowThreadProcessId()获得正确的值并成功地获得了hWndwindowThreadID,我每次都在Hook回调中获得这些值,我将这些值仅获得全局变量程序启动和使用的变量后,在钩回调中。