对于USB键盘配置工具,我需要拦截所有键盘输入并检测同时按下哪些修改键和普通键。因此我使用Windows低级挂钩(WH_KEYBOARD_LL),除了我无法确定是否按下了WIN-Key(VK_LWIN / VK_RWIN)(控制/移位和alt工作)之外,它工作正常。
我制作了一个小命令行工具来显示问题:
#include <Windows.h>
#include <iostream>
using namespace std;
HHOOK hKeyboardHook;
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
if (nCode < 0 || nCode != HC_ACTION )
return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);
KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
// working
if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
cout << "CONTROL" << endl;
if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
cout << "SHIFT" << endl;
if(GetAsyncKeyState(VK_MENU) & 0x8000) // ALT
cout << "ALT" << endl;
// VK_xWIN not working at all
if((GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000))
cout << "WIN" << endl;
// working for ALTGR/right-handed ALT
if((GetAsyncKeyState(VK_LCONTROL) & 0x8000) || (GetAsyncKeyState(VK_RCONTROL) & 0x8000))
cout << "LRCONTROL" << endl;
// not working at all
if((GetAsyncKeyState(VK_LSHIFT) & 0x8000) || (GetAsyncKeyState(VK_RSHIFT) & 0x8000))
cout << "LRSHIFT" << endl;
if((GetAsyncKeyState(VK_LMENU) & 0x8000) || (GetAsyncKeyState(VK_RMENU) & 0x8000))
cout << "LRMENU" << endl;
}
//return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);
return 1;
}
int main(int argc, char* argv[])
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
MSG message;
while (GetMessage(&message,NULL,0,0)) {
TranslateMessage( &message );
DispatchMessage( &message );
}
UnhookWindowsHookEx(hKeyboardHook);
return 0;
}
如果我从LowLevelKeyboardProc返回“1”,则每次按键都被“吞下”(除了CTRL + ALT + DEL和WIN + L)。如果我在回调函数结束时调用下一个钩子,行为就会改变(并且键显然不会被吞下)。然后,如果将WIN键与另一个键一起按下,我将获得按下WIN键的信息。
我需要做什么来拦截所有键盘输入并检测WIN键按下(使用GetAsyncKeyState)?或者是否有其他方法可以获得所有(墨水.WIN)按下的修改键?
答案 0 :(得分:0)
LowLevelKeyboardProc
的文档说明了返回值:
如果钩子过程处理了消息,它可能会返回非零值 阻止系统将消息传递给其余的挂钩 链或目标窗口程序。
所以,return 1
说“我已经处理了这些信息,而且这些密钥没有别的办法”。
我不确定你是如何通过检测自己的WIN键来解决问题的 - 我怀疑系统只是在没有键盘事件的情况下才转发,直到按下第二个键。
答案 1 :(得分:0)
我没有找到为什么我无法从钩子中获取Windows键的状态,但是我实现了一个简单的解决方法,我不想让你退缩。
如果我按下/释放Windows键,则会调用回调函数。所以我只是自己保存密钥的状态,并在按下按键时使用这些信息。
所以改变后的回调函数如下:
bool leftWinKeyPressed = false;
bool rightWinKeyPressed = false;
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
if (nCode < 0 || nCode != HC_ACTION )
return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam);
KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
// save state of win keys manually... (needs to be tested some more)
if(p->vkCode == VK_LWIN)
leftWinKeyPressed = (wParam == WM_KEYDOWN)?true:false;
else if(p->vkCode == VK_RWIN)
rightWinKeyPressed = (wParam == WM_KEYDOWN)?true:false;
if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
// not beautifull but working...
if(leftWinKeyPressed || rightWinKeyPressed)
cout << "WIN" << endl;
// for example
if(leftWinKeyPressed && p->vkCode == 68 )
cout << "LEFT WINDOWS + D";
}
return 1;
}
要清理它,我可能会对所有修改键执行此操作,并使用位字段来存储修改键的状态。所以我不依赖于GetAsyncKeyState
,这是奇怪的行为。但如果有人发现它为什么会这样,请告诉我。