SetWindowsHookEx WH_KEYBOARD_LL 在右移时没有响应

Posted

技术标签:

【中文标题】SetWindowsHookEx WH_KEYBOARD_LL 在右移时没有响应【英文标题】:SetWindowsHookEx WH_KEYBOARD_LL not responding on right shift 【发布时间】:2013-09-19 17:02:03 【问题描述】:

我尝试在 c++ 中使用 Windows API,而 SetWindowsHookEx WH_KEYBOARD_LL 似乎没有从右侧的 Shift 键(Shift 键在qwerty 键盘右侧,Enter 键下方)。它确实适用于左 Shift 键。我该如何解决这个问题???

#include "stdafx.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <string> 
#include <shlobj.h>
#include <Shlwapi.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <future>
#include <stdlib.h>
#include <random>
#include <ctime>
#include <time.h>       
#include <Lmcons.h>



HHOOK   kbdhook;    /* Keyboard hook handle */
bool    running;    /* Used in main loop */


__declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp)

        static bool capslock = false;
        static bool shift = false;
        char tmp[0xFF] = 0;
        std::string str;
        DWORD msg = 1;
        KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);



        msg += (st_hook.scanCode << 16);
        msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
        GetKeyNameText(msg, tmp, 0xFF);
        str = std::string(tmp);


    if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN )) 
        MessageBox(NULL,str.c_str(),NULL,MB_OK);

return CallNextHookEx(kbdhook, code, wp, lp);


LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)

    switch (msg) 
        case WM_CLOSE: case WM_DESTROY:
            running = false;
            break;
        default:
            /* Call default message handler */
            return DefWindowProc(hwnd, msg, wp, lp);
    

    return 0;


int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance,
        LPSTR cmdline, int ncmdshow)



    HWND        hwnd;
    HWND        fgwindow = GetForegroundWindow(); 
    MSG     msg;
    WNDCLASSEX  windowclass;
    HINSTANCE   modulehandle;

    modulehandle = GetModuleHandle(NULL);
    kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, NULL);
    running = true;






    while (running) 

        if (!GetMessage(&msg, NULL, 0, 0))
            running = false; 
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    

    return 0;

右移在警报中显示一个 blanco 字符串。然而,左移在警报中显示“SHIFT”字符串。谁有线索???

PS:

如果我删除带有“ msg += ((st_hook.flags & LLKHF_EXTENDED) “RIGHT SHIFT”现在确实出现了,但是当按下“Windows 键”时出现 undefined

【问题讨论】:

@paulm 右移在警报中显示一个 blanco 字符串。然而,左移会在警报中显示“SHIFT”字符串。 这是 GetKeyNameText() 中的一个怪癖。 shift 键有点特殊,它们生成相同的虚拟键码,但扫描码不同。它只是没有正确处理右移键的扫描码。您必须解决此限制。 @HansPassant 正在删除“msg += (st_hook.scanCode @HansPassant 但是...如果我删除带有“ msg += ((st_hook.flags & LLKHF_EXTENDED) “RIGHT SHIFT”现在确实出现了,但是当按下“Windows 键”时出现了 undefined 【参考方案1】:

左移与右移显示在KBDLLHOOKSTRUCTvkCode 字段中。您正在使用扫描码的 name 键;右 Shift 键被命名为“Shift”,就像它在键盘上所说的那样。

显然,右移最终会设置扩展标志,这会导致 GetKeyNameText 查找错误的表。删除扩展标志最终会得到一个键名“右移”。

    msg += (st_hook.scanCode << 16);
    if (st_hook.scanCode != 0x3a)
    
        msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
    
    GetKeyNameText(msg, tmp, 0xFF);

【讨论】:

未定义字符或结果中的“blanco”为 NULL。 但是...如果我删除与“msg += ((st_hook.flags & LLKHF_EXTENDED) “RIGHT SHIFT”现在确实出现了,但是当按下“Windows 键”时出现了 undefined 并且它混合了上、左、右、下箭头和“插入”、“删除”、“结束”数字(1,2,3,4,5,6,7,8,9,0)......顺便说一句。你是怎么知道那些 Windows API 的? @user10056 所以答案是明确地忽略右移的扩展标志(扫描代码0x3a)。其他键(插入、删除等)需要扩展标志才能获得正确的行为。我知道这些 API 是因为我在 Windows 上工作。 要明确:“if (st_hook.scanCode != 0x3a)”没有解决问题。 | “我在 Windows 上工作” 看起来我的右移标记为扫描码“54” if (st_hook.scanCode != 54) 似乎工作得更好......但它显示“Alt Gr”为“ ctrl+alt" 不知何故..【参考方案2】:

此解决方案不依赖特定代码

if (st_hook.vkCode != VK_RSHIFT)
  msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);

【讨论】:

以上是关于SetWindowsHookEx WH_KEYBOARD_LL 在右移时没有响应的主要内容,如果未能解决你的问题,请参考以下文章

为啥必须将 SetWindowsHookEx 与 Windows 消息队列一起使用

在我的线程上下文中调用“SetWindowsHookEx”函数

用于 DeviceIOControl 的 SetWindowsHookEx,要使用啥 hookid?

增加 Windows 7 中的 SetWindowsHookEx 限制

SetWindowsHookEx c#

SetWindowsHookEx 其他进程的 记录