Search code examples
c#winformslistboxmouseover

C# ListBox.MouseEnter/MouseLeave and the scrollbar


I have a ListBox on the left side of my form. The user has the option of "auto-hiding" it so that it disappears off to the left, and only reappears while the user moves their mouse onto it.

If the ListBox has few items in it, this feature works beautifully.

However as soon as I put enough items into the ListBox such that there is now a scrollbar, funny things start to happen. The MouseEnter code is only triggered when the user has moved their mouse into the ListBox past the scrollbar. This means that I must have more then the width of the scroll bar peeking or they will never be able to show it.

Additionally, the user is not able to scroll at all if the ListBox is not in focus. If they try to click the scrollbar to scroll, the ListBox disappears. If they click inside the ListBox to focus it (so that they can scroll with the mouse wheel), then they lose their selection.

Is there any way I can extend the bounds of MouseEnter and MouseLeave to include the scrollbar?


Solution

  • This is by design, the scrollbar is not part of the client area of a control. It is in the non-client area, similar to caption bar on top of a form. Windows treats them differently, mouse move messages like WM_MOUSEMOVE get announced with WM_NCMOUSEMOVE instead. Winforms does not have events for non-client notifications. This is the way you'd normally want it, you wouldn't want to know about the scrollbar getting manipulated. Feature, not a bug. Except in this case.

    As a workaround, you could inherit from ListBox and override WndProc() to see the WM_NCMOUSEMOVE messages (m.Msg == 0xa0). Or a 200 msec Timer that checks where the mouse is located.