I WM_EXITSIZEMOVE trying to catch WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages for a window whose handle is a member of the class. To do this, use SetWindowsHookExA with the WH_GETMESSAGE parameter. The second parameter of the function ( HOOKPROC ) indicates the function inside my class:

 class WindowDisplayHelper : // public ... { public: // some other public methods here void SetMsgHook(); protected: LRESULT CALLBACK GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam); private: // some other private members there HWND m_windowHandle; bool m_isWindowResizing = false; static HHOOK m_msgHook; static WindowsDisplayHelperMasterWindow* m_pThis; }; 

.cpp file:

 WindowDisplayHelper* WindowDisplayHelper ::m_pThis = nullptr; HHOOK WindowDisplayHelper ::m_msgHook = NULL; void WindowDisplayHelper ::SetMsgHook() { m_pThis = this; m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0); } LRESULT CALLBACK WindowDisplayHelper::MsgPoc(int code, WPARAM wParam, LPARAM lParam) { if (m_pThis != nullptr) { return m_pThis->GetMsgProcHook(code, wParam, lParam); } return CallNextHookEx(0, code, wParam, lParam); } LRESULT CALLBACK WindowDisplayHelper::GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam) { DUMPER_INFO("Hooked"); if (code < 0) { return CallNextHookEx(0, code, wParam, lParam); } MSG* lpmsg = (MSG*)lParam; DUMPER_INFO("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle); if (lpmsg->hwnd != m_windowHandle) { return CallNextHookEx(0, code, wParam, lParam); } if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing) { DUMPER_INFO("Start window resizing"); m_isWindowResizing = true; } else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing) { DUMPER_INFO("Stop window resizing"); m_isWindowResizing = false; } return CallNextHookEx(0, code, wParam, lParam); } 

The process of creating a WindowDisplayHelper object:

 auto helper = boost::make_shared<WindowDisplayHelper>(windowHandle); helper->SetMsgHook(); AddDisplayHelper(displayId, helper); return true; 

And although I call SetMsgHook after creating the WindowDisplayHelper object, it looks like the hook is not installed: m_isWindowResizing all the time == false and no logs are visible. Because the hook handler is inside the class, then I had to resort to tricks with a static pointer to this, but something didn’t work. I tried to specify the thread id (the result of GetCurrentThreadId ), but this also did not help. Can you please tell me why my window message handling function doesn't work?

  • The code does not check the success of the installation of the hook. The last two null parameters in SetWindowsHookEx look suspicious. Not clearly, whence m_windowHandle undertakes? - VTT

1 answer 1

If I understand your question correctly, then this problem is usually solved a little differently. In particular, it is not the static field that is used to store the reference to the class instance, but the window itself.

The address of the class instance is specified when creating the window as the CreateWindowEx argument:

 m_hwndControl = ::CreateWindowEx(WS_EX_CLIENTEDGE, MY_WINDOW_CLASS, _TEXT(""), WS_CHILD | WS_TABSTOP | WS_VISIBLE, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hwndParent, (HMENU)uID, hInstance, this); 

A binding to an instance of a class is performed in a window procedure.

 // WndProc является статической функцией-членом! LRESULT CALLBACK MyWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get pointer to self MyWindow *pSelf; if (uMsg == WM_CREATE) { pSelf = (MyWindow*)(((CREATESTRUCT*)lParam)->lpCreateParams); ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pSelf); } else pSelf = (MyWindow*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); // Здесь вызываются классовые функции-обработчики, например так: // Dispatch message switch (uMsg) { HANDLE_MSG(hWnd, WM_CREATE, pSelf->OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, pSelf->OnDestroy); HANDLE_MSG(hWnd, WM_ERASEBKGND, pSelf->OnEraseBkgnd); HANDLE_MSG(hWnd, WM_PAINT, pSelf->OnPaint); . . . 

( HANDLE_MSG is the HANDLE_MSG message cracker. Of course, HANDLE_MSG is not necessary.)

In this form, everything will work correctly for multiple windows.

  • Thanks for the answer, but I have another case. My class is not a window, but rather a class that checks the state (minimized or not, blocked or not, the position and size of the window) of this window at a specific point in time. For this in my class there is an HWND of the window for which my class is collecting information. And the global challenge is to understand that at this particular moment in time the window is resized. That is, the task comes down to how having the window handle to understand that it is resized. - rudolfninja pm
  • That is, you simply do not call the procedure specified in SetWindowsHookEx ? And at you digit capacity will be coordinated? This is essentially a DLL implementation. - freim
  • Yes, but the problem is that I do not have a dll, but global hooks can only be done from dll - rudolfninja 7:49 pm
  • one
    @rudolfninja, are you trying to make a hook from a process in another process? Then it is not surprising that nothing comes out, the address spaces are different. Implement dll, and she already let with yours communicates. - freim 8:40 pm
  • Yes thank you. I already understood it. Most likely I will implement such a solution - rudolfninja