Why does Windows intercept undefined messages?

Microsoft does not recommend DirectInput for keyboard and mouse input. So I wrote an input manager class that uses SetWindowsHookEx to connect to WndProc and GetMsg. I believe that the hooks are properly installed, although they look to cause various problems.

Neither my WndProc nor GetMsg hooks receive any messages that a real WndProc receives. My input manager never receives the WM_INPUT, WM_BUTTON, WM_MOUSEWHEEL and WM_KEY * messages that he needs.

What gives?

Partial header:

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); }; } 

Partial Source:

 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); } } 

I do not include code for the message handler, as it consists of 149 lines, most of which are keys for message types. The message values ​​received in WndProc do not match the values ​​in my callbacks.

+6
windows hook messages wndproc setwindowshookex
source share
3 answers

I'm late to the party here, but I spent so many hours figuring out the same problem, and hopefully someone else finds this helpful.

My empirical conclusion is that DispatchMessage does not call WH_CALLWNDPROC hooks. In other words, messages that are placed in the thread message queue and pass through the message loop (GetMessage β†’ DispatchMessage) will not be infected by WH_CALLWNDPROC. It only catches messages sent directly to the window procedure using SendMessage, etc. And when you look at the documentation, this is what it says:

A library-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function before calling the window procedure to process the message sent to the stream.

And, of course, the opposite is true for the WH_GETMESSAGE hook. It will capture messages, but will not send messages. To get all the messages, you need to either use both hooks or use subclasses to directly connect the window procedure:

 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); 

Also, the reason the OP GetMessage hook did not work is probably because lParameter should be added to MSG* rather than CWPSTRUCT* .

+4
source share

I cannot add a comment on your original question in which I would prefer to put this, but:

What does it look like, what are you trying to do, is WH_KEYBOARD and WH_MOUSE suitable?

+6
source share

I had a similar problem. I did not quite understand what it was (I think he was absorbed somewhere in PreTranslateMessage, but I am not shure), but I know how I noticed him:

I created one of these disappearing messages myself and debugged my way through MFC. If I remember correctly, I just returned the wrong BOOLEAN somewhere. However, this approach can give you a real clue.

0
source share

All Articles