我正试图拦截并禁止
Alt+Tab
组合(对我来说,不仅禁止这种组合很重要),这样应用程序窗口就不会通过按下中的这些键来切换(例如,在某些情况下,这与游戏中的全屏模式有关)
Windows
操作系统(
Windows 10 22H2
,显然这与
DInput
版本,下面将对此进行详细介绍)。为了做到这一点,我
use
SetWindowsHookEx
具有
WH_KEYBOARD_LL
但是,如果应用程序使用API进行处理,则此挂钩不起作用
DirectInput
(
DInput8
)输入。值得注意的是,如果应用程序最小化(即使使用
直接输入
在中
DISCL_BACKGROUND
与上述行为相矛盾的模式)。
我看到上面立了一面旗
DISCL_FOREGROUND
帮助了一些人——我最初有这面旗帜,尝试了各种组合
CooperativeLevel
-这也于事无补。
此外,钩子和
直接输入
以前可能对很多人都有效,但现在它
seems
事实并非如此(中的处理逻辑之间存在差异
DInput7
和
DInput8
,以及在不同的Windows操作系统之间)。在这里,我只能假设
DInput7
使用较早,内部使用相同的钩子(
键盘钩子
),而不是
Raw Input
。
根据判断
documentation
直接输入
过程
原始输入
(即。
WM_INPUT
消息)。我试图拦截
WM_INPUT
使用
键盘钩子
钩与
WH_GETMESSAGE
-它没有帮助(在我的情况下,这个钩子根本不起作用
直接输入
已启用)。
我试图更改初始化的顺序,以防万一(至于
WH_KEYBOARD_LL
,所以对于
WH_get消息
)-没用。
在这里,我发现了许多同样的人面临着同样的问题,但我没有找到这些主题的解决方案:
example1
(Windows XP),
example2
(问题的焦点相似,但
原始输入
在这里使用,而不是
直接输入
),
example3
。
问题是:
-
为什么钩子
WH_KEYBOARD_LL
只有当窗口的焦点丢失时才能工作?有可能解决这个问题吗
直接输入
并且窗口焦点处于活动状态?
-
基于第1点:为什么钩子即使在
直接输入
当窗口焦点丢失时处于活动状态(
DISCL_BACKGROUND
)?
-
在的引擎盖下
直接输入
(谈论
DInput8
,参见上面的区别)是
原始输入
处理。如果是,为什么
键盘钩子
钩与
WH_get消息
拦截
WM_INPUT
不工作?
-
这个问题还有什么其他解决方案?至少我知道
there is
一
RegisterHotKey
。
一个重现问题的最小示例:
#include <Windows.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
HWND g_hWnd = {};
HHOOK g_LLKeyboardHook = {};
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
{
PostQuitMessage(EXIT_SUCCESS);
return ERROR_SUCCESS;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
return ERROR_SUCCESS;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
const auto hookStruct = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
switch (nCode)
{
case HC_ACTION:
{
// For tests ('A' key)
if (hookStruct->vkCode == 0x41)
{
// MessageBox(g_hWnd, TEXT("Pressed 'A' from Hook"), TEXT("Hook"), 0u);
// Block it
return TRUE;
}
// Alt + Tab
else if (hookStruct->flags & LLKHF_ALTDOWN && hookStruct->vkCode == VK_TAB)
{
// MessageBox(g_hWnd, TEXT("Pressed 'Alt + Tab' from Hook"), TEXT("Hook"), 0u);
// Block it
return TRUE;
}
}
}
return CallNextHookEx(g_LLKeyboardHook, nCode, wParam, lParam);
}
bool InitializeDirectInput(LPDIRECTINPUT8& di, LPDIRECTINPUTDEVICE8& diKeyboard, HINSTANCE hInstance)
{
if (!hInstance || !g_hWnd)
{
return false;
}
auto res = DirectInput8Create(
hInstance,
DIRECTINPUT_VERSION,
IID_IDirectInput8,
reinterpret_cast<void**>(&di),
NULL);
if (FAILED(res))
{
MessageBox(g_hWnd, TEXT("DirectInput8Create failed"), TEXT("Error"), 0u);
return false;
}
res = di->CreateDevice(
GUID_SysKeyboard,
&diKeyboard,
NULL);
if (FAILED(res))
{
MessageBox(g_hWnd, TEXT("CreateDevice failed"), TEXT("Error"), 0u);
return false;
}
res = diKeyboard->SetDataFormat(&c_dfDIKeyboard);
if (FAILED(res))
{
MessageBox(g_hWnd, TEXT("SetDataFormat failed"), TEXT("Error"), 0u);
return false;
}
res = diKeyboard->SetCooperativeLevel(g_hWnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(res))
{
MessageBox(g_hWnd, TEXT("SetCooperativeLevel failed"), TEXT("Error"), 0u);
return false;
}
return true;
}
void CloseDirectInput(LPDIRECTINPUT8& di, LPDIRECTINPUTDEVICE8& diKeyboard)
{
if (diKeyboard)
{
diKeyboard->Unacquire();
}
if (di)
{
di->Release();
}
}
void DetectKeys(LPDIRECTINPUTDEVICE8& diKeyboard)
{
BYTE keyState[256] = {};
HRESULT res = {};
res = diKeyboard->Acquire();
if (FAILED(res))
{
// When the application loses focus, capture cannot be performed
return;
}
res = diKeyboard->GetDeviceState(sizeof(keyState), static_cast<LPVOID>(keyState));
if (FAILED(res))
{
return;
}
if (keyState[DIK_A] & 0x80)
{
MessageBox(g_hWnd, TEXT("Pressed 'A' from DirectInput"), TEXT("DirectInput"), 0u);
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLine, int nCmdShow)
{
const wchar_t windowClassName[] = L"Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = windowClassName;
RegisterClass(&wc);
g_hWnd = CreateWindowEx(
0u, // Optional window styles.
windowClassName, // Window class
L"Low-level keyboard hook with DirectInput", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (!g_hWnd)
{
MessageBox(NULL, TEXT("CreateWindowEx failed"), TEXT("Error"), 0u);
return EXIT_FAILURE;
}
LPDIRECTINPUT8 di = nullptr;
LPDIRECTINPUTDEVICE8 diKeyboard = nullptr;
if (!InitializeDirectInput(di, diKeyboard, hInstance))
{
return EXIT_FAILURE;
}
g_LLKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, 0u);
if (!g_LLKeyboardHook)
{
MessageBox(g_hWnd, TEXT("SetWindowsHookEx failed"), TEXT("Error"), 0u);
CloseDirectInput(di, diKeyboard);
return EXIT_FAILURE;
}
ShowWindow(g_hWnd, nCmdShow);
MSG msg = {};
while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DetectKeys(diKeyboard);
}
UnhookWindowsHookEx(g_LLKeyboardHook);
CloseDirectInput(di, diKeyboard);
return EXIT_SUCCESS;
}