[英]Why would Windows hooks not receive certain messages?
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中收到的消息值与我的回调中的消息值不同。
我似乎无法在你原来的问题下添加评论,这是我更喜欢这样做的地方,但是:
从你想要做的事情来看,WH_KEYBOARD和WH_MOUSE钩子不是更合适吗?
我在这里聚会很晚,但我花了这么多时间搞清楚同样的问题,希望其他人会觉得这很有用。
我的实证结论是DispatchMessage不会触发WH_CALLWNDPROC挂钩。 换句话说,WH_CALLWNDPROC将不会捕获在线程的消息队列中发布并通过消息循环(GetMessage - > 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*
。
我曾经遇到过类似的问题。 我不太害羞它是什么(我认为它在PreTranslateMessage的某个地方被消耗但我并不害羞)但我知道我是如何发现它的:
我自己创建了一条消失的消息,然后通过MFC调试它。 如果我记得正确,我只是回到错误的BOOLEAN。 但是,这种方法可能会为您提供实际的线索。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.