1

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

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

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

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

4

4 回答 4

7

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

于 2013-08-01T19:45:29.953 回答
1

The best way you can achieve such behaviour is to hook the keyboard.

This is a handy tutorial explaining the basics: codeguru
It also differentiates the hook types into systemwide and process specific.

于 2013-08-01T18:07:50.923 回答
0

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

WM_KILLFOCUS您可以绕过WndProc()消息中的 ,以免应用程序失焦。它仍然可以处理任何按键。

就像是:

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);
}
于 2013-08-01T18:10:55.107 回答
0

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);
    }
}
于 2017-03-07T18:19:14.393 回答