C ++/Win32:键盘输入到非前台窗口 [英] C++/Win32: Keyboard input to a non-foreground window
问题描述
我的目标:
我希望我的应用程序能够响应特定的键盘快捷键/热键,而不管它是不是前台窗口 而不会干扰其他应用程序对这些快捷键的使用.
I want my application to be able to respond to specific keyboard shortcuts/hotkeys regardless of whether it is the foreground window without interfering with other applications' use of these shortcuts.
例如,如果另一个进程有前台窗口,并且用户按下VK_MEDIA_PLAY_PAUSE
键,我希望我的应用程序和当前前台窗口进行响应.
For instance, if another process has the foreground window and the user presses the VK_MEDIA_PLAY_PAUSE
key, I want my application and the current foreground window to respond.
此功能是用户设置,因此我不必担心不想要的行为.
This function is a user setting, so I'm not concerned about undesired behavior.
我尝试过的无效的方法:
-
WM_KEYDOWN
消息仅发送到当前的前台窗口,因此我的应用程序未收到它们. -
GetKeyState()
,根据 MS docs ,根据最近检索到的WM_KEY*
消息返回密钥的状态,并且由于我的应用程序没有收到WM_KEYDOWN
作为背景窗口,因此该状态不会更改. -
GetAsyncKeyState()
,根据
WM_KEYDOWN
messages are only sent to the current foreground window, so my application does not receive them.GetKeyState()
, according to the MS docs, returns the status of the key according to the most recently retrievedWM_KEY*
messages, and because my application doesn't receiveWM_KEYDOWN
as background window, this status doesn't change.GetAsyncKeyState()
, according to the MS docs, returns zero when:
前台线程属于另一个进程,并且桌面不允许挂钩或日志记录.
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.
我不确定这意味着后半段是什么,但是当我的窗口不是前台窗口时,GetAsyncKeyState()
返回零.
I'm not sure what the second half of this means, but GetAsyncKeyState()
returns zero when my window is not the foreground window.
-
GetKeyboardState()
与GetKeyState()
一样,仅在检索消息时更改键状态.
GetKeyboardState()
, likeGetKeyState()
, only changes key status as messages are retrieved.
RegisterHotKey()
/UnregisterHotKey()
:与其他选项不同,我的应用程序即使不是前台窗口,也能够响应热键;但是,当前的前台窗口不再响应.这些热键似乎仅重定向到我的应用程序,其他应用程序再也看不到它们.
RegisterHotKey()
/UnregisterHotKey()
: Unlike the other options, my application is able to respond to hotkeys even when it's not the foreground window; however, the current foreground window no longer responds. It appears that these hotkeys are redirected to only my application, and other applications no longer see them at all.
我唯一的想法:
我能想到的唯一方法是,我肯定可以使Win32社区回避我.
The only approaches I can think of are ones that I'm fairly certain would have me shunned by the Win32 community.
我可以使用RegisterHotKey()
/UnregisterHotKey()
来通知热键,然后将按键模拟为当前的前台窗口.看到SendInput()
可能会进入循环,我需要先注销热键:
I could use RegisterHotKey()
/UnregisterHotKey()
to be notified of the hotkey, and then emulate the keypress to the current foreground window. Seeing as SendInput()
would likely enter a loop, I would need to either unregister the hotkey first:
case WM_HOTKEY:
UnregisterHotKey(...); // unregister the hotkey to avoid looping
SendInput(...); // send keyboard input
RegisterHotKey(...); // restore it
或直接用SendMessage()
进行仿真:
case WM_HOTKEY:
SendMessage(GetForegroundWindow(), WM_KEYDOWN, ...);
// send WM_KEYUP ?
这两种方法似乎都是Win32架构不是为之而设计的.
Both of these seem like a hack that the Win32 architecture was not designed for.
是否可以通过其他方式从非前台窗口读取/接收键盘输入而不会干扰其他应用程序?
推荐答案
You can use SetWindowsHookEx
with WH_KEYBOARD_LL
parameter:
以下是示例:
#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;
}
它的工作原理如下:
这篇关于C ++/Win32:键盘输入到非前台窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!