【问题标题】:Receiving Keypresses While in Background在后台接收按键
【发布时间】:2013-08-01 18:01:44
【问题描述】:

我正在使用 winapi 开发一个 Win32 应用程序,我很好奇是否有办法在应用程序失焦/无窗口时接收键盘事件。

最初我正在读取应用程序消息队列并检查WM_KEYDOWN 消息,但是消息仅在窗口处于焦点时才发送到应用程序。我知道可以使用 DirectInput,但如果可能的话,我想避免让我的应用程序需要 DirectX。

除了使用 DirectInput 之外,还有其他方法可以在窗口失焦时接收键盘按下吗?

编辑:不,在你问我不是在写键盘记录器之前。应用程序需要在后台响应某些可重新绑定的键盘快捷键。

【问题讨论】:

    标签: c++ winapi


    【解决方案1】:

    这是由winapi直接支持的,你需要使用RegisterHotKey()

    【讨论】:

      【解决方案2】:

      实现这种行为的最佳方法是钩住键盘。

      这是一个解释基础知识的便捷教程:codeguru
      它还将钩子类型区分为 systemwideprocess specific

      【讨论】:

        【解决方案3】:

        稍后编辑:如果窗口失焦,即使WM_KILLFOCUS 被忽略,它也无法处理WM_KEYDOWN 消息。因此,您需要定期单独检查GetAsyncKeyState()

        您可以绕过WndProc() 消息中的WM_KILLFOCUS,这样应用就不会失去焦点。它仍然可以处理任何按键。

        类似:

        LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
        {
        
            switch (msg)
            {
        
            /* cases blah blah */
        
            case WM_KILLFOCUS:
                return 0;
        
            /* other cases' blah blah */
        
            }
            return DefWindowProc(hWindow, msg, wParam, lParam);
        }
        

        【讨论】:

        • 其实这样会更容易。但它安全吗?如果另一个应用试图获得焦点怎么办?
        • 这不会阻止任何其他应用程序获得焦点吗?这个想法是应用程序应该能够在其他应用程序正常运行时在后台接收按键。
        • @Bad Wolf 你应该挂上键盘。在未知行为的土地上徘徊并不理想。
        • @Bad Wolf:它不会阻止任何应用程序获得焦点。我有我的窗口和 Chrome 的这个例子,当我点击 RMB 时,Chrome 会在 RMB 上执行任何操作,而我的应用程序执行我告诉它在 RMB 上执行的操作 @TheOtherGuy 它不应该是 break;,因为它会返回 DefWindowProc()我们不希望这样
        • @losif M. 是否有任何文档支持?因为据我所知,当我使用 Windows 时,一次只关注一个应用程序。
        【解决方案4】:

        Microsoft DirectX 库包含一个可用于获取键盘状态的函数。它是 DirectInput API 的一部分。下面的代码演示了如何轮询键盘以获取按键状态信息。必须添加额外的逻辑来检测何时按下/释放键并将其转换为字符。

        请注意,这需要 Microsoft DirectX SDK 进行编译。

        //Public domain: no attribution required
        #include "stdafx.h"
        #include "dxlog.h"
        
        #pragma comment(lib, "dinput8")
        #pragma comment(lib, "dxguid")
        
        LPDIRECTINPUT8 din;
        LPDIRECTINPUTDEVICE8 dinkbd;
        BYTE keystate[256];
        DIDATAFORMAT dfi;
        
        void init_dinput(HINSTANCE hInst, HWND hWnd)
        {
            HRESULT hr;
            hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&din, NULL);
            hr = din->CreateDevice(GUID_SysKeyboard, &dinkbd, NULL);
            hr = dinkbd->SetDataFormat(&c_dfDIKeyboard);
            // share the keybdb and collect even when not the active application
            hr = dinkbd->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
        }
        
        void detect_input(void)
        {
            dinkbd->Acquire();
            dinkbd->GetDeviceState(256, keystate);
        }
        
        void clean_dinput(void)
        {
            dinkbd->Unacquire();
            din->Release();
        }
        
        void print_state()
        {
            WCHAR pState[4096] = L"";
            WCHAR temp[32];
        
            for (int i = 0; i < 256; i++)
            {
                if (keystate[i] != 0)
                {
                    wsprintf (temp, L"%d(%d) ", i, keystate[i]);
                    lstrcat(pState, temp);
                }
            }
            if (lstrlen(pState) != 0)
            {
                lstrcat(pState, L"\n");
                OutputDebugString(pState);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-03
          • 2020-01-05
          • 1970-01-01
          • 2013-01-14
          • 2011-05-13
          相关资源
          最近更新 更多