Windows C++ GetKeyState 大写锁定检测器相反

时间:2021-03-06 21:49:18

标签: c++ winapi keyboard hook keylogger

我编写了一个简单的程序来监听大写锁定键,并显示一个消息框,说明当前大写锁定是打开还是关闭。 所以:用户按下大写锁定,程序确定大写锁定现在处于什么状态(打开或关闭)并显示一个消息框。 实际发生的情况是,当大写锁定打开时,程序会显示消息框说它关闭,反之亦然。

我已经阅读了函数的文档,但仍然不理解这种不需要的(相反的)行为,并想知道如何(以及是否)可以解决这个问题。

这是我的代码:


#include <Windows.h>

// Research/credits/references
// https://www.unknowncheats.me/forum/c-and-c-/83707-setwindowshookex-example.html
// http://www.rohitab.com/discuss/topic/38617-get-the-state-of-capslock/

HHOOK _hook;

// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code.
KBDLLHOOKSTRUCT kbdStruct;

// This is the callback function. Consider it the event that is raised when, in this case, 
// a key is pressed.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        // the action is valid: HC_ACTION.
        if (wParam == WM_KEYDOWN)
        {
            // lParam is the pointer to the struct containing the data needed, so cast and assign it to kdbStruct.
            kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
            // a key (non-system) is pressed.
            if (kbdStruct.vkCode == VK_CAPITAL)
            {
                if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0)
                    MessageBox(NULL, "Caps Lock ON!", "Caps Lock", MB_ICONINFORMATION);
                else
                    MessageBox(NULL, "Caps Lock OFF!", "Caps Lock", MB_ICONINFORMATION);
            }
        }
    }

    // call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

void SetHook()
{
    // Set the hook and set it to use the callback function above
    // WH_KEYBOARD_LL means it will set a low level keyboard hook. More information about it at MSDN.
    // The last 2 parameters are NULL, 0 because the callback function is in the same thread and window as the
    // function that sets and releases the hook. If you create a hack you will not need the callback function 
    // in another place than your own code file anyway. Read more about it at MSDN.
    if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)))
    {
        MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
    }
}

void ReleaseHook()
{
    UnhookWindowsHookEx(_hook);
}

int main()
{
    // Set the hook
    SetHook();

    // Don't mind this, it is a meaningless loop to keep a console application running.
    // I used this to test the keyboard hook functionality.
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {

    }
    
    return 0;
}

1 个答案:

答案 0 :(得分:1)

GetKeyState 返回处理当前按键并更新键盘状态之前的状态。例如,如果 CAPS LOCK 为 OFF 并且您按下 CAPS LOCK 键,钩子被调用并且 GetKeyState 报告当前状态为 OFF,然后按键被处理并打开 CAPS LOCK。

这在LowLevelKeyboardProc callback function中间接暗示:

<块引用>

注意: 当这个回调函数被调用以响应键状态的变化时,回调函数在异步状态之前被调用密钥已更新。因此,无法通过从回调函数中调用 GetAsyncKeyState 来确定键的异步状态。

由于 GetKeyState 反映了 GetAsyncKeyState 报告的物理状态之前的线程状态,因此间接暗示对 GetKeyState 的调用将返回前一个状态。

相关问题