3

I'm calling the HtmlHelpA winapi method to display the .chm of my app. This method returns a HWND immediatelly, and the help window is shown as a separate window.

Along with the window, I set a timer for this hwnd. My problem is that I need to know when this window gets closed to kill the timer.

My first approach was trying to register the WndProc callback, but I couldn't do that because I'm not creating the window, I only have a reference to the hwnd.

Then I tried with a hook (SetWindowsHookEx) but the HOOKPROC won't bring the HWND as a parameter to the callback. Besides, I need to know the thread for this hwnd.

Is there any way to register a callback when a HWND gets closed or having a WndProc to wait for the WM_CLOSE message?

Rodrigo Rivera
  • 157
  • 1
  • 9

2 Answers2

2

If required you can register a new window procedure for an existing window. Check out the documentation on SetWindowLongPtr().

Invoking it like this:

SetWindowLongPtr(hwnd, GWLP_WNDPROC, &MyCustomHelpWindowProc);

Just remember that window subclassing is very delicate. You might want to store the old window procedure somewhere and invoke that rather than DefWindowProc() for messages you are not interested in.

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • 2
    It's not that easy. The window you're modifying belongs to the hh.exe process, not your own, so the code address you store for that window won't be valid. – Rob Kennedy Dec 14 '11 at 18:52
  • Thanks! Using a global map to hold the old WndProc for each hwnd I've been able to call the former WndProc from My_WndProc that checks the WM_CLOSE in a sort of "inheritance" – Rodrigo Rivera Dec 14 '11 at 19:06
  • @RobKennedy: My help (both via the built in help handling in VB6 and the `HtmlHelpA` function) are in process. Only when launched from Explorer do they use their own hh.exe host. – Deanna Dec 15 '11 at 09:03
1

You want to subclass the help window. Subclassing gives you a chance to spy on all the messages going to the window proc. You do whatever additional work you need when you see a message of interest, and then pass the message on to the original window procedure for normal processing.

LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);

WNDPROC fnOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hwndHelp, GWLP_WNDPROC, &MyWndProc));


LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    if (msg == WM_CLOSE) {
        // Kill your timer here.
    }
    return CallWindowProc(fnOldProc, hwnd, msg, wp, lp);
}
Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175