Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;ToUnicodeEx()无法识别shift键,除非我有一个messgaebox()文件 在C++中编写一个键盘钩子有点麻烦。_C++_Visual Studio 2010_Hook - Fatal编程技术网

C++;ToUnicodeEx()无法识别shift键,除非我有一个messgaebox()文件 在C++中编写一个键盘钩子有点麻烦。

C++;ToUnicodeEx()无法识别shift键,除非我有一个messgaebox()文件 在C++中编写一个键盘钩子有点麻烦。,c++,visual-studio-2010,hook,C++,Visual Studio 2010,Hook,我可以读取击键,但我尝试在按下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_ICON

我可以读取击键,但我尝试在按下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键时,会弹出两个消息框,第一个是空白的Shift键,第二个显示“@”字符。这是意料之中的

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

另外,当我包括MsgBox行并使用CapLock时,我的字母也会相应地改变,但在我删除MsgBox行后,它只使用程序启动时cap lock的状态(程序启动时,大写字母锁定处于打开状态,所有字母都是大写字母,反之,程序启动时,大写字母关闭所有字母都是小字母,即使我更改了大写字母锁定状态)

有人知道为什么我的钩子只记得开始时的键盘状态,除非我包含msgbox

我的钩子是这样设置的:

theHook = SetWindowsHookEx ( WH_KEYBOARD_LL, (HOOKPROC) KeyEvent, exe, 0);
我的钩子回调函数是:

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);
}

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

在调用
ToUnicodeEx
之前,应将此数组设置为如下(伪代码):

设置keyState数组后,可以调用:

ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);
我一直在使用像这样的
ToUnicodeEx
函数,它工作得很好。

希望这能帮助您;)

GetKeyboardLayout和GetKeyState返回键盘布局和进程状态。不是那个会收到键盘信息的人。您不能可靠地使用ToUnicodeEx(),需要一个带有WH_键盘的全局钩子。@HansPassant我认为您可以。这是一个全局钩子,因此函数位于DLL中,并且该DLL被注入到原始进程中。所以这些函数应该按预期工作。@rodrigo-WH\u键盘\u LL不是全局钩子。没有注入DLL,Windows在您自己的进程中调用钩子回调,然后将消息添加到具有前景的窗口的消息队列中。OP发现MessageBox之所以有效,是因为它将焦点从窗口上移开了。@HansPassant-事实上,根据他的说法,WH_KEYBOARD_LL是一个全局唯一的钩子。可能低级钩子不同于其他全局钩子,并且不需要DLL(我没有测试它)。但我在文档中没有看到任何关于这方面的参考。谢谢,这很有效。我认为是与keyState变量有关,但我认为GetKeyboardState()更新了它。现在我只需要识别caps lock是否处于活动状态,但这不应该太难。
ToUnicodeEx(keyboard.vkCode, keyboard.scanCode, (PBYTE)&keyState, (LPWSTR)&keybuff, sizeof(keybuff) / 16, 0,keyboardlayout);