The*_*802 1 c++ windows keyboard winapi keyboard-shortcuts
我的目标:
我希望我的应用程序能够响应特定的键盘快捷键/热键,而不管它是否是前台窗口,而不会干扰其他应用程序对这些快捷键的使用。
例如,如果另一个进程有前台窗口并且用户按下该VK_MEDIA_PLAY_PAUSE键,我希望我的应用程序和当前前台窗口做出响应。
此功能是用户设置,因此我不担心不受欢迎的行为。
我尝试过但没有奏效的事情:
WM_KEYDOWN 消息仅发送到当前前台窗口,因此我的应用程序不会收到它们。GetKeyState(),根据MS docs,根据最近检索到的WM_KEY*消息返回密钥的状态,并且因为我的应用程序没有WM_KEYDOWN作为后台窗口接收,所以这个状态不会改变。GetAsyncKeyState(),根据MS 文档,在以下情况下返回零:前台线程属于另一个进程,桌面不允许钩子或日志记录。
我不确定这的后半部分是什么意思,但是GetAsyncKeyState()当我的窗口不是前景窗口时返回零。
GetKeyboardState(),如GetKeyState(),仅在检索消息时更改密钥状态。
RegisterHotKey()/ UnregisterHotKey():与其他选项不同,我的应用程序能够响应热键,即使它不是前台窗口;但是,当前的前景窗口不再响应。似乎这些热键仅重定向到我的应用程序,而其他应用程序根本不再看到它们。
我唯一的(凌乱的)想法:
我能想到的唯一方法是那些我相当肯定会让我被 Win32 社区回避的方法。
我可以使用RegisterHotKey()/UnregisterHotKey()来获得热键的通知,然后将按键模拟到当前的前景窗口。看到SendInput()可能会进入循环,我需要先取消注册热键:
case WM_HOTKEY:
UnregisterHotKey(...); // unregister the hotkey to avoid looping
SendInput(...); // send keyboard input
RegisterHotKey(...); // restore it
Run Code Online (Sandbox Code Playgroud)
或直接模拟它SendMessage():
case WM_HOTKEY:
SendMessage(GetForegroundWindow(), WM_KEYDOWN, ...);
// send WM_KEYUP ?
Run Code Online (Sandbox Code Playgroud)
这两个似乎都是 Win32 架构并非为之设计的一种黑客行为。
是否有任何(其他)方法可以在不干扰其他应用程序的情况下从非前台窗口读取/接收键盘输入?
您可以使用SetWindowsHookEx与WH_KEYBOARD_LL参数:
这是一个示例:
#include <windows.h>
#include <iostream>
HHOOK _k_hook;
LRESULT __stdcall k_Callback1(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
//a key was pressed
if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
{
switch (key->vkCode)
{
case VK_ESCAPE:
puts("ESC pressed");
break;
case 'A':
puts("A pressed");
break;
case VK_RETURN:
puts("RETURN pressed");
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
int main()
{
_k_hook = SetWindowsHookEx(WH_KEYBOARD_LL, k_Callback1, NULL, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (_k_hook)
UnhookWindowsHookEx(_k_hook);
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理如下:
| 归档时间: |
|
| 查看次数: |
428 次 |
| 最近记录: |