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】:左移与右移显示在KBDLLHOOKSTRUCT
的vkCode
字段中。您正在使用扫描码的 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?