Search code examples
clistviewwinapisubclasswin32gui

Win32 C++ How to handle LVM_SETCOLUMNWIDTH in a ListView subclass?


I have a ListView whose columns I'd like to resize in relation to the size of the ListView itself (which is sized based on the window size). The ListView is subclassed with a seperate WNDPROC in which WM_NOTIFY is being used to handle other messages.

To size the header columns I'm using ListView_SetColumnWidth(), however this only works when I deactivate the seperate ListView WNDPROC or remove from it the WM_NOTIFY handling.

I've tried handling LVM_SETCOLUMNWIDTH manually in both the WNDPROC for both the ListView and its header to see if the message is getting passed through, but to no avail.

I'm not quite sure how to proceed; any help would be greatly appreciated.

For reference, the WM_NOTIFY in my ListView WNDPROC:

    case WM_NOTIFY:
    {
        UINT debugval = (((LPNMHDR)lParam)->code);
        switch (((LPNMHDR)lParam)->code)
        {
            case HDN_BEGINTRACK:
            {
                return TRUE;  //Prevent manual resizing.
                break;
            }
            case LVM_SETCOLUMNWIDTH:
            {
                ::MessageBox(hwnd, L"test", L"test", MB_OK);
                break;
            }
        }
        break;
    }

Solution

  • LVM_SETCOLUMNWIDTH is its own separate message, it is NOT carried through WM_NOTIFY, like you have coded for. You need to move case LVM_SETCOLUMNWIDTH into the outer switch instead. And make sure you are calling CallWindowProc() or DefSubclassProc() (depending on how you are creating the subclass) for ALL messages you don't want to discard.

    Try something more like this:

    switch (uMsg)
    {
        case WM_NOTIFY:
        {
            UINT code = (((LPNMHDR)lParam)->code);
            switch (code)
            {
                case HDN_BEGINTRACK:
                {
                    return TRUE;  //Prevent manual resizing.
                }
            }
            break;
        }
    
        case LVM_SETCOLUMNWIDTH:
        {
            ...
            break;
        }
    }
    
    return CallWindowProc(..., hwnd, uMsg, wParam, lParam);
    or
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);