问题
The background: Most of us know the
SysListView32common control and the equivalent wrapperListViewclass provided by the .NET Framework. A little depth into its internals show that the scroll bars it provides for scrolling its contents are NOT controls themselves, but are managed by theSysListView32control.The goal: Always draw scroll bars even if it has no
ListViewItemsto display or has very few such that no scroll bars are needed anyway; sort of like mimicking theRichTextBoxclass with itsScrollBarsproperty set toForcedBoth. Or kinda like thisListBox:
The problem(s):
- .NET has NO sugar at all for scroll bars within a
ListView. - Win32 documentation does not state when to show/hide and/or enable/disable scrollbars.
- .NET has NO sugar at all for scroll bars within a
My workaround(s):
overridetheWndProcin a derived class and handle itsWM_HSCROLLandWM_VSCROLLmessages as per steps 2 and 3.- Call
base.WndProcto do the actually required processing of the scroll functionality. - Create a method like
WmScrolland do my processing on it immediatelyafterbase.WndProchas returned. - This consists of a p/invoke call to
GetScrollInfo. Determine if a scroll bar is actually needed. If it's not then callShowScrollBarandEnableScrollBarwith required values to draw visibly disabled scroll bars.
Problems with the workaround:
- It barely works. The scroll bars are displayed and disabled but are like the ones under Windows Classic Theme.
- It hides the collapse buttons of each
ListViewGroup, rendering them useless!
The descriptive image:
The long awaited actual question:
How do I force scroll bars to always be Visible within a ListView irrespective of the number of ListViewItems and disable them if they are unnecessary, at the same time avoiding size miscalculation (to display collapse buttons of the ListViewGroups) and theme deterioration?
Answers without code, and answers with code in C#, VB.NET and C++/CLR are welcome. If you post code in any other language supported by .NET, please also leave a link to a code conversion website I may use if the code seems, uh, incomprehensible.
回答1:
Information:
- Firstly, I have to admit this is an okay answer and not the best/most efficient one. If you have a different answer from mine, please post it.
- Secondly, this answer owes some credit to Plutonix's answer, experimenting with which I learned that by default
ListViewdoes not haveWS_HSCROLL | WS_VSCROLLflags set in its styles.- This is why my previous workaround had problem with themes.
- These Classic scroll bars are ones Windows provides to
Controls that do not have these flags set. - Changing the
CreateParamsdoes not work either. You have to set it manually in theOnHandleCreatedmethod usingSetWindowLong. - The solution I am posting does not use the above technique. Apparently, calling
ShowScrollBarfor each window message forces these flags to be set.
The Solution:
Define your
WndProclike the following:protected override void WndPoc(ref Message m) { //custom code before calling base.WndProc base.WndProc(ref m); //custom after base.WndProc returns WmScroll(); //VERY INEFFICIENT, called for each message :( }Define WmScroll() as follows:
protected virtual void WmScroll() { NativeMethods.ShowScrollBar(Handle, SB_BOTH, true); //si.fMask = SIF_PAGE | SIF_RANGE <- initialized in .ctor NativeMethods.GetScrollInfo(Handle, SB_HORZ, ref si); if(si.nMax < si.nPage) NativeMethods.EnableScrollBar(Handle, SB_HORZ, ESB_DISABLE_BOTH); else NativeMethods.EnableScrollBar(Handle, SB_HORZ, ESB_ENABLE_BOTH); NativeMethods.GetScrollInfo(Handle, SB_VERT, ref si); if(si.nMax < si.nPage) NativeMethods.EnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH); else NativeMethods.EnableScrollBar(Handle, SB_VERT, ESB_ENABLE_BOTH); }- Output:
It now, looks like:
These are with another item added featuring the horizontal scroll and working ListViewGroup collapse button:
- Imperfection, yes there is:
- A call to
AutoResizeColumnsis required if group collapse changes effective text width, otherwise the vertical scroll bar hides the collapse buttons.
- A call to
来源:https://stackoverflow.com/questions/39057774/force-the-display-of-scroll-bars-in-a-listview