我在用C++编写键盘挂钩时遇到了一些麻烦。

我可以阅读击键,但是我想在按下Shift键时尝试使用ToUnicodeEx()转换击键。
到目前为止,我已经在代码中

i = ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);
MessageBox(MainnhWnd,keybuff, L"message", MB_OK | MB_ICONEXCLAMATION);

当我按Shift + 2时,在此“MessageBox”行中,我弹出两个消息框,第一个为Shift键为空白,第二个显示为“@”字符。这是预期的。

但是,如果我删除此消息框,则ToUnicodeEx()函数将转换击键,就好像未使用shift键一样。通过设置断点,命中计数器或将字符输出到程序窗口中的编辑框,我可以看到这一点。

另外,当我包括MsgBox行并使用CapLock时,我的字母也会相应更改,但是当我删除msgbox行之后,它仅在程序启动时使用大写锁定的状态(当programm启动时大写锁定处于打开状态,所有字母均为大写,反之亦然,即使我更改了大写锁定状态,在programm启动时,所有字母也都变小了

有人知道为什么我的钩子(Hook)只记得启动时的键盘状态,除非我包括msgbox?

我的钩子(Hook)设置为:
theHook = SetWindowsHookEx ( WH_KEYBOARD_LL, (HOOKPROC) KeyEvent, exe, 0);

我的钩子(Hook)回调函数是:
DLLEXPORT LRESULT CALLBACK KeyEvent(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode>=0) {
    int i = 0;
    KBDLLHOOKSTRUCT keyboard;
    WCHAR keybuff[256]= {0};

    if ((wParam == WM_KEYDOWN)|| (wParam == WM_SYSKEYDOWN)||(wParam == WM_SYSKEYUP)) {
        keyboard = *((KBDLLHOOKSTRUCT*)lParam);
        if (keyboard.vkCode == VK_RETURN) {
            i += wsprintf (((LPWSTR)keybuff + i),L"[Return]\r\n");
        }
        else {
            HKL keyboardlayout = GetKeyboardLayout(0);
            GetKeyboardState((PBYTE)&keyState);
            i = ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);

            MessageBox(MainnhWnd,keybuff, L"message", MB_OK | MB_ICONEXCLAMATION);
        }
        if (keybuff>0) {
            addToEditBox(keybuff);
        }
    }
}
return CallNextHookEx(theHook, nCode, wParam, lParam);
}

最佳答案

根据ToUnicodeEx function的文档,您应该提供一个指向包含当前键盘状态(const BYTE *lpKeyState)的256字节数组的指针。数组中的每个元素(字节)都包含一个键的状态。如果设置了字节的高位,则该键按下。

在调用ToUnicodeEx之前,应像下面这样设置该数组(伪代码):

enum Keys
{
    ShiftKey    = 16, // shift
    ControlKey  = 17, // ctrl
    Menu        = 18, // alt
    Capital     = 20, // caps lock
};

BYTE keyState[256]= {0};

if (Control key down)
    keyState[Keys::ControlKey] = 0x80;

if (Shift key down)
    keyState[Keys::ShiftKey] = 0x80;

if (Alt key down)
    keyState[Keys::Menu] = 0x80;

if (Caps lock ON)
    keyState[Keys::Capital] = 0x01;

并设置了keyState数组后,您可以调用:
ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);

我一直在使用ToUnicodeEx函数,并且效果很好。
希望这能够帮到你 ;)

09-06 11:32