Search code examples
winapiheadercursormouseenter

Disable cursor changing to SizeWE for some items in Win32 header


I need to prevent resizing of some items in a Win32 header control. No problem to process the HDN_BEGINTRACK notification message and cancel it - the problem is in the cursor indicating that the item can be resized. For instance, if the first item can't be resized, I see this:

enter image description here

, but I'd prefer to see this:

enter image description here

I can ignore the cursor change by suppressing the WM_SETCURSOR message, but the problem is how to know the header item WM_SETCURSOR is generated for. I can detect the item under the mouse pointer in WM_MOUSEMOVE using the HDM_HITTEST message, but WM_MOUSEMOVE is sent to window procedure only after WM_SETCURSOR. I analyzed all notification messages for the Win32 header control, and it seems, it does not have an equivalent of the MouseEnter event that is sent to the window procedure before WM_SETCURSOR.

Any ideas how to solve this problem?


Solution

  • You need to sub-class the header control if you haven't already.

    In the sub-class, intercept the WM_SETCURSOR message, and use GetMessagePos() to get the coordinates of the mouse. These are in screen coordinates, so you need to convert them to client coordinates for the header control hit test.

    // in the window sub-class
    if (uMsg == WM_SETCURSOR)
    {
        DWORD dwPos = GetMessagePos();
        HDHITTESTINFO hti;
        hti.pt.x = GET_X_LPARAM(dwPos);
        hti.pt.y = GET_Y_LPARAM(dwPos);
        ScreenToClient(hWnd, &hti.pt);
        SendMessage(hWnd, HDM_HITTEST, 0, reinterpret_cast<LPARAM>(&hti));
    
        if (...) // test for items we want to block
        {
            SetCursor(LoadCursor(0, IDC_ARROW));
            return TRUE;
        }
    
        // pass through to regular WndProc
    }