Safely remove window subclassing?

Posted by Vegard Larsen on Stack Overflow See other posts from Stack Overflow or by Vegard Larsen
Published on 2010-03-15T10:07:33Z Indexed on 2010/03/15 10:09 UTC
Read the original article Hit count: 466

Filed under:
|
|

I am trying to subclass the currently focused window on a Windows system using a global CBT hook. This is related to what happens in this question, but the bug is different.

What happens when this subclassing is in effect, is that Opera's (version 10.50) main window is prevented from displaying. Opera has a "splash screen" where you are required to click "Start" for the main window to show that appears after Opera has not shut down properly. Whenever this window pops up, Opera's main window won't show. If Opera was shut down properly, and this splash screen does not show, the main window displays as it should.

HHOOK hHook;
HWND hWndSubclass = 0;

void SubclassWindow(HWND hWnd)
{
    Unsubclass();
    FARPROC lpfnOldWndProc = (FARPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)SubClassFunc);
    SetProp(hWnd, L"PROP_OLDWNDPROC", lpfnOldWndProc);
    hWndSubclass = hWnd;
}

void Unsubclass()
{
    if (hWndSubclass != 0 && IsWindow(hWndSubclass))
    {
        FARPROC lpfnOldWndProc = (FARPROC)GetProp(hWndSubclass, L"PROP_OLDWNDPROC");
        RemoveProp(hWndSubclass, L"PROP_OLDWNDPROC");
        SetWindowLongPtr(hWndSubclass, GWLP_WNDPROC, (LPARAM)lpfnOldWndProc);
        hWndSubclass = 0;
    }
}

static LRESULT CALLBACK SubClassFunc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_MOVING)
    {
        // do something irrelevant
    }
    else if (message == WM_DESTROY)
    {
        Unsubclass();
    }
    FARPROC lpfnOldWndProc = (FARPROC)GetProp(hWndSubclass, L"PROP_OLDWNDPROC");
    return CallWindowProc((WNDPROC)lpfnOldWndProc, hWndSubclass, message, wParam, lParam);
}

static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_SETFOCUS && hWndServer != NULL)
    {
        SubclassWindow((HWND)wParam);
    }
    if (nCode < 0)
    {
        return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
    return 0;
}

BOOL APIENTRY DllMain( HINSTANCE hInstance, 
                   DWORD  Reason, 
                   LPVOID Reserved
                 )
{
    switch(Reason)
    { 
        case DLL_PROCESS_ATTACH:
            hInst = hInstance;
            return TRUE;
        case DLL_PROCESS_DETACH:
            Unsubclass();
            return TRUE;
    }
    return TRUE;
}

My suspicion is that Opera's main window is somehow already subclassed. I imagine the following is happening:

  1. The window is created with it's own basic WndProc, and is given focus
  2. My application subclasses the window, storing the original WndProc
  3. Opera subclasses its own window
  4. When the window loses focus, I restore the original WndProc, thus ignoring the second WndProc

Can this really be the case? Are there any other explanations?

© Stack Overflow or respective owner

Related posts about win32

Related posts about c++