Microsoft不建议使用DirectInput进行键盘和鼠标输入。因此,我编写了一个输入管理器类,它使用SetWindowsHookEx挂钩到WndProc和GetMsg。我认为钩子设置得恰当,但它们看起来是各种问题的原因。
我的WndProc和GetMsg挂钩都没有收到实际WndProc正在接收的任何消息。我的输入管理器永远不会收到它需要的WM_INPUT,WM_ BUTTON ,WM_MOUSEWHEEL和WM_KEY *消息。
是什么给出了?
部分标题:
namespace InputManager
{
class CInputManager
{
HWND m_Window;
HHOOK m_WndProcHook;
HHOOK m_GetMessageHook;
static LRESULT CALLBACK WindowsProcedureHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter);
static LRESULT CALLBACK GetMessageHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter);
static LRESULT CALLBACK MessageHandler(HWND Window, UINT Message, WPARAM wParameter, LPARAM lParameter);
};
}
部分来源:
namespace InputManager
{
bool CInputManager::Initialize(HWND Window)
{
m_Window = Window;
// Hook into the sent messages of the target window to intercept input messages.
m_WndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, &(WindowsProcedureHookProcedure), NULL, GetCurrentThreadId());
// Hook into the posted messages of the target window to intercept input messages.
m_GetMessageHook = SetWindowsHookEx(WH_GETMESSAGE, &(GetMessageHookProcedure), NULL, GetCurrentThreadId());
// Register mouse device for raw input.
RAWINPUTDEVICE RawInputDevice;
RawInputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC;
RawInputDevice.usUsage = HID_USAGE_GENERIC_MOUSE;
RawInputDevice.dwFlags = RIDEV_INPUTSINK;
RawInputDevice.hwndTarget = m_Window;
return RegisterRawInputDevices(&(RawInputDevice), 1, sizeof(RawInputDevice));
}
void CInputManager::Shutdown()
{
// Unhook from the posted messages of the target window.
UnhookWindowsHookEx(m_GetMessageHook);
// Unhook from the sent messages of the target window.
UnhookWindowsHookEx(m_WndProcHook);
}
LRESULT CALLBACK CInputManager::WindowsProcedureHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter)
{
if(nCode == HC_ACTION)
{
// Forward to message handler.
CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter);
MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam);
}
return CallNextHookEx(NULL, nCode, wParameter, lParameter);
}
LRESULT CALLBACK CInputManager::GetMessageHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter)
{
if(nCode == HC_ACTION)
{
// Forward to message handler.
CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter);
MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam);
}
return CallNextHookEx(NULL, nCode, wParameter, lParameter);
}
}
我没有包含消息处理程序的代码,因为它包含149行,其中大多数是消息类型的开关。 WndProc中收到的消息值与我的回调中的消息值不同。
答案 0 :(得分:6)
我似乎无法在您的原始问题下添加评论,而我希望将其放在此处,但是:
从你想要做的事情来看,WH_KEYBOARD和WH_MOUSE钩子不是更合适吗?
答案 1 :(得分:4)
我来这里参加派对已经很晚了,但我花了这么多时间来解决同样的问题,希望其他人会觉得这很有用。
我的实证结论是DispatchMessage不会触发WH_CALLWNDPROC挂钩。换句话说,WH_CALLWNDPROC将不会捕获在线程的消息队列中发布并通过消息循环(GetMessage - &gt; DispatchMessage)的消息。它只会使用SendMessage等将消息发送直接捕获到窗口过程中。当你查看文档时,它就是它所说的:
与SetWindowsHookEx函数一起使用的应用程序定义或库定义的回调函数。系统在调用窗口过程之前调用此函数以处理消息已发送到该线程。
当然,WH_GETMESSAGE钩子的情况恰恰相反。它将捕获已发布的消息,但不会发送消息。要获取所有消息,您必须使用两个钩子,或使用子类直接挂钩窗口过程:
WNDPROC realProc;
LRESULT CALLBACK hookProc(HWND h, UINT msg, WPARAM wp, LPARAM lp)
{
return CallWindowProc(realProc, h, msg, wp, lp);
}
...
realProc = (WNDPROC)SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)hookProc);
此外,OP的GetMessage挂钩无效的原因可能是因为lParameter
应该投放到MSG*
而不是CWPSTRUCT*
。
答案 2 :(得分:0)
我曾经遇到过类似的问题。我不太害羞它是什么(我认为它在PreTranslateMessage的某个地方被消耗了,但我并不害羞)但我知道我是如何发现它的:
我自己创建了一条消失的消息,然后通过MFC调试它。如果我记得正确,我只是回到错误的BOOLEAN。但是,这种方法可能会为您提供实际的线索。