Windows:如何查询低级键盘钩子中修饰键的状态? [英] Windows: How to query state of modifier keys within low level keyboard hook?

查看:285
本文介绍了Windows:如何查询低级键盘钩子中修饰键的状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于usb键盘配置工具,我需要截取所有键盘输入,并检测同时按下哪些修改键和正常键。因此,我使用一个Windows低级钩子(WH_KEYBOARD_LL),除非我不能确定是否WIN-Key(VK_LWIN / VK_RWIN)被按下(控制/ shift和alt正在工作),工作正常。

For a usb keyboard configuration tool I need to intercept all keyboard input and detect which modifier keys and normal keys are pressed simultaneously. Therefore I use a windows low level hook (WH_KEYBOARD_LL) which works fine except that I´m not able to determine if WIN-Key (VK_LWIN / VK_RWIN) is pressed (control / shift and alt is working).

我做了一个小命令行工具来显示问题:

I made a little commandline tool to show the problem:

#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,每个键都按swallowed除了CTRL + ALT + DEL和WIN + L)。如果我在回调函数的结尾调用下一个钩子的行为改变(和键显然不会再被吞噬)。然后,如果WIN键与另一个键一起被按下,我得到WIN键被按下的信息。

If I return "1" from LowLevelKeyboardProc every key press is "swallowed" (except for CTRL+ALT+DEL and WIN+L). If I call the next hook at the end of the callback function the behaviour changes (and the keys obviously aren´t swallowed any more). Then if WIN key is pressed together with another key I get the information that WIN key is pressed.

我必须做什么来拦截所有键盘输入和检测WIN键(使用GetAsyncKeyState)?

What do I have to do to intercept all keyboard input and detect a WIN-key press (using GetAsyncKeyState)? Or is there another way to get all (inkl. WIN) pressed modifier keys?

推荐答案

我没有找到为什么我不能从钩子内获得windows键的状态,但是我实现了一个简单的解决方法,我不想让你忘记。

I didn't find out why I can't get the state of the windows key from within the hook, but I implemented a simple workaround which I don't want to keep back from you.

回调函数被调用,如果我按/释放Windows键。因此,我只是自己保存键的状态,并在以下键按下使用此信息。

The callback function gets called if I press/release the windows key. So I just save the state of the key by myself and use this information on following key presses.

所以更改的回调函数看起来像:

So the changed callback function looks like:

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 这是奇怪的行为。但如果有人发现为什么会这样做,请让我知道。

To clean it up I will probably do this for all modifier keys and use a bit field to store the state of the modifier keys. So I'm not dependent on GetAsyncKeyState and it's weird behaviour. But if someone finds out why it behaves that way, please let me know.

这篇关于Windows:如何查询低级键盘钩子中修饰键的状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆