C ++/Win32:键盘输入到非前台窗口 [英] C++/Win32: Keyboard input to a non-foreground window

查看:153
本文介绍了C ++/Win32:键盘输入到非前台窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标:

我希望我的应用程序能够响应特定的键盘快捷键/热键,而不管它是不是前台窗口 而不会干扰其他应用程序对这些快捷键的使用.

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.

我尝试过的无效的方法:

  1. WM_KEYDOWN消息仅发送到当前的前台窗口,因此我的应用程序未收到它们.
  2. GetKeyState(),根据 MS docs ,根据最近检索到的WM_KEY*消息返回密钥的状态,并且由于我的应用程序没有收到WM_KEYDOWN作为背景窗口,因此该状态不会更改.
  3. GetAsyncKeyState(),根据
  1. WM_KEYDOWN messages are only sent to the current foreground window, so my application does not receive them.
  2. GetKeyState(), according to the MS docs, returns the status of the key according to the most recently retrieved WM_KEY* messages, and because my application doesn't receive WM_KEYDOWN as background window, this status doesn't change.
  3. 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.

  1. GetKeyboardState()GetKeyState()一样,仅在检索消息时更改键状态.

  1. GetKeyboardState(), like GetKeyState(), 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆