winapi - 带有 RIDEV_NOHOTKEYS 的原始输入键盘显示经典的 Alt+Tab 菜单
问题描述
我正在尝试为使用 RawInput 处理键盘事件的窗口禁用 Windows 键。执行此操作的常用方法是安装低级键盘挂钩并在那里过滤掉 Windows 键事件。为了让它与 RawInput 一起工作,我必须用 RIDEV_NOHOTKEYS 初始化键盘设备。但是,当我这样做时,如果我从应用程序中使用 Alt+Tab,出于某种原因,Windows 10 会显示经典的 Alt+Tab 内容:
我没有在低级键盘挂钩中过滤掉 Alt 或 Tab 事件,如果我根本不安装低级键盘挂钩,也会发生这种情况,只需使用 RIDEV_NOHOTKEYS 初始化键盘设备即可。我尝试为 WM_INPUT 消息返回 0,并尝试调用默认窗口 proc,似乎没有任何帮助...以前有人遇到过这个问题吗?
解决方案
添加一个低级挂钩(WH_KEYBOARD_LL)可以防止 Alt 键消息传递到其他窗口。参考“ LowLevelKeyboardProc 回调函数”。
WH_KEYBOARD_LL 挂钩只能在全局范围内设置。
// Register hook
hinstDLL = LoadLibrary(TEXT("sysmsg.dll"));
hkprcSysMsg = (SYSMESSAGEPROC)GetProcAddress(hinstDLL, "SysMessageProc");
HHOOK hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)hkprcSysMsg, hinstDLL, 0);
DLL中的挂钩回调函数:
__declspec(dllexport)
LRESULT __cdecl SysMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) // do not process message
return CallNextHookEx(NULL, nCode,
wParam, lParam);
if (wParam == WM_SYSKEYDOWN)
{
if(((tagKBDLLHOOKSTRUCT*)lParam)->vkCode == VK_LMENU || ((tagKBDLLHOOKSTRUCT*)lParam)->vkCode == VK_RMENU)
return 1;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
更多参考:“使用 Hooks ”“键盘输入”“ WM_SYSKEYDOWN 消息”“ KBDLLHOOKSTRUCT 结构”“虚拟键代码”
笔记
挂钩往往会减慢系统速度,因为它们会增加系统必须为每条消息执行的处理量。您应该仅在必要时安装挂钩,并尽快将其移除。
您应该仅将全局挂钩用于调试目的;否则,您应该避免使用它们。全局挂钩会损害系统性能并导致与实现相同类型全局挂钩的其他应用程序发生冲突。
推荐阅读
- github-actions - GitHub Actions:秘密环境为空
- azure - 如何从现有 Azure 服务主体获取客户端密码
- php - SMTP 错误:无法连接到服务器:使用 phpmailer 时连接超时 (110)
- timeline - ThreeJs - 在 ThreeJS 中构建时间轴组件
- javascript - 为什么我无法在命令处理程序中捕获 Discord.js 错误?
- sql - 哪个 SQL 成本更高,为什么?
- java - 异常后JPA关闭连接并且没有重新连接
- variables - Nginx if 运算符
- assembly - 如何使用 lea 指令实现 shr 指令?
- node.js - 带有 apollo-express-server v2.xx 的 App Engine 服务静态地为 React 应用程序提供服务