我正在使用winapi在Win32应用程序上工作,我很好奇是否有一种方法可以在应用程序失焦或无窗口时接收键盘事件。
最初我正在读取应用程序消息队列并检查WM_KEYDOWN
消息,但是当窗口处于焦点时,消息才会发送到应用程序。我知道可以使用DirectInput,但如果可能的话我想避免让我的应用程序需要DirectX。
除了使用DirectInput之外,还有其他方法可以在窗口失焦时接收键盘按下吗?
编辑:不,在你问我不是在写一个键盘记录器之前。应用程序需要在后台响应某些可重新绑定的键盘快捷键。
答案 0 :(得分:5)
这是winapi直接支持的,您需要使用RegisterHotKey()。
答案 1 :(得分:0)
您可以实现此类行为的最佳方式是挂钩键盘。
这是一个方便的教程,解释了基础知识: codeguru
它还将钩子类型区分为系统范围和特定于流程的。
答案 2 :(得分: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);
}
答案 3 :(得分: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);
}
}