我编写了一个简单的程序,它监听大写锁键,并显示一个消息框,说明当前大写锁是打开还是关闭。因此:用户按下caps-lock,程序确定caps-lock现在处于什么状态(开或关)并显示一个消息框。实际发生的情况是,当打开时,,程序显示消息框,提示关闭反之亦然
我已经阅读了函数的文档,但是仍然不理解这种不必要的(相反的)行为,并且想知道如何(以及是否)可以修复。
下面是我的代码:
#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
返回在当前按键被处理并更新键盘状态之前的状态。例如,如果CAPS LOCK是OFF,你按下CAPS LOCK键,钩子被调用,GetKeyState
报告当前状态为OFF,然后按键被处理,CAPS LOCK被打开。
这在LowLevelKeyboardProc回调函数中间接暗示:
注意: 当此回调函数被调用以响应密钥状态的更改时,回调函数在密钥的异步状态更新之前被调用。因此,键的异步状态不能通过在回调函数中调用GetAsyncKeyState来确定。
由于GetKeyState
反映了GetAsyncKeyState
报告的物理状态之前的一个线程状态,因此间接暗示调用GetKeyState
将返回先前的状态。