【发布时间】:2021-06-05 05:18:49
【问题描述】:
我编写了一个简单的程序来监听大写锁定键,并显示一个消息框,说明大写锁定当前是打开还是关闭。 所以:用户按下大写锁定,程序确定大写锁定现在处于什么状态(打开或关闭)并显示一个消息框。 实际发生的情况是,当大写锁定打开on时,程序会显示消息框,说明它off,反之亦然。
我已经阅读了函数的文档,但仍然不理解这种不需要的(相反的)行为,并且想知道如何(以及是否)可以解决这个问题。
这是我的代码:
#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;
}
【问题讨论】:
-
GetKeyState反映上次从队列中检索输入消息时的键盘状态。GetAsyncKeyState反映了调用函数时的键盘状态。你的钩子在消息发布到消息队列之前被调用,所以从那里调用GetKeyState总是落后于真实状态。
标签: c++ winapi keyboard hook keylogger