Search code examples
c++windowswinapiwin32gui

The procedure of control subclassed does not work. Why?


I recently tried to subclass a control using the SetWindowSubclass() function. And to my surprise, it worked smoothly at first. I created the control procedure, but it doesn't receive messages like WM_LBUTTONDOWN or WM_KEYDOWN, and I don't understand why! I searched all my time yesterday and I confess that I am losing hope.

Here is my code, simplified (very long in normal times!):

HWND button = CreateWindow("BUTTON", NULL, WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 100, 200, 250, 50, hwnd, (HMENU)ID_B_JOUER, instance, NULL);
SetWindowSubclass(boutton, ControlProc, ID_B_JOUER, 0);

And here is the control procedure:

LRESULT CALLBACK ControlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch(msg)
    {
        case WM_...:
        {
            MessageBox(hwnd, "Bonjour!", "Message", MB_ICONINFORMATION); // Here it does not work!!! Something be the message.
            break;
        }
        default:
        {
            DefSubclassProc(hwnd, msg, wParam, lParam);
        }
    }

    return 0;
}

I want to clarify that I am using the GetLastError() function and it returned 0 (no problem). I hope someone has a solution because it's very weird.


Solution

  • You are creating a new BUTTON control and assigning it to a variable named button, but you are subclassing using a different variable named boutton instead.

    Assuming that is just a typo, your ControlProc() is returning 0 for every message, it is ignoring the return value of DefSubclassProc(), which may not be 0. You MUST return what DefSubclassProc() returns for unhandled messages.

    HWND button = CreateWindow("BUTTON", NULL, WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, 100, 200, 250, 50, hwnd, (HMENU)ID_B_JOUER, instance, NULL);
    SetWindowSubclass(button, &ControlProc, ID_B_JOUER, 0);
    
    ...
    
    LRESULT CALLBACK ControlProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
    {
        switch (msg)
        {
            case WM_LBUTTONDOWN:
            case WM_KEYDOWN:
            {
                MessageBox(hwnd, "Bonjour!", "Message", MB_ICONINFORMATION);
                break;
            }
    
            default:
            {
                return DefSubclassProc(hwnd, msg, wParam, lParam);
            }
        }
    
        return 0;
    }