在ListView中强制显示滚动条?
Force the display of scroll bars in a ListView?
背景:我们大多数人都知道SysListView32
公共控件和ListView
class提供的等效包装器通过 .NET Framework。深入了解其内部结构可以看出,它提供的用于滚动其内容的滚动条 不是 自己控制 ,而是由 SysListView32
控制.
目标: 始终绘制滚动条,即使它没有 ListViewItems
可显示或很少以至于不需要滚动条反正;有点像模仿 RichTextBox
class 并将其 ScrollBars
属性 设置为 ForcedBoth
。或者有点像这样 ListBox
:
问题:
- .NET NO sugar [=11] 内的滚动条=].
- Win32 文档没有说明何时 show/hide and/or enable/disable 滚动条。
我的解决方法:
override
派生的 class 中的 WndProc
并按照步骤 2 和 3 处理其 WM_HSCROLL
和 WM_VSCROLL
消息。
- 调用
base.WndProc
执行实际需要的滚动功能处理。
- 创建一个类似
WmScroll
的方法并立即对其进行 my 处理 after
base.WndProc
已返回。
- 这包括对
GetScrollInfo
的 p/invoke 调用。确定是否确实需要滚动条。如果不是,则使用所需值调用 ShowScrollBar
和 EnableScrollBar
以绘制明显禁用的滚动条。
解决方法有问题:
- 几乎没用。滚动条显示和禁用,但与 Windows 经典主题.
下的滚动条类似
- 它隐藏了每个
ListViewGroup
的折叠按钮,使它们无用!
描述图片:
期待已久的真题:
如何强制滚动条始终在Visible
内aListView
不考虑ListViewItems
[=59=的个数]并在不需要时禁用它们,同时避免大小计算错误 (显示 ListViewGroup
s)和主题恶化?
没有代码的答案,以及 C#、VB.NET 和 C++/CLR 中的代码答案 欢迎。如果您 post 使用 .NET 支持的任何其他语言编写代码,也请将 link 留给代码转换网站,如果代码看起来,呃,难以理解,我可能会使用。
信息:
- 首先,我不得不承认这是一个 还可以 的答案,而不是 best/most 有效的 答案。如果你和我有不同的答案,请post它。
- 其次,这个答案归功于 Plutonix's answer,通过实验我了解到默认情况下
ListView
在其样式中没有设置 WS_HSCROLL | WS_VSCROLL
标志。
- 这就是我之前的解决方法出现主题问题的原因。
- 这些 Classic 滚动条是 Windows 提供给
Control
没有设置这些标志的滚动条。
- 更改
CreateParams
也不起作用。您必须使用 SetWindowLong
. 在 OnHandleCreated
方法中手动设置它
- 我正在 post 的解决方案没有使用上述技术。显然,为每个 window 消息调用
ShowScrollBar
会强制设置这些标志。
解决方案:
定义您的 WndProc
,如下所示:
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 :(
}
定义WmScroll()如下:
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);
}
- 输出:
现在看起来像:
这些是添加的另一个项目,具有水平滚动和工作 ListViewGroup
折叠按钮:
- 不完美,是的:
- 如果组折叠更改有效文本宽度,则需要调用
AutoResizeColumns
,否则垂直滚动条会隐藏折叠按钮。
背景:我们大多数人都知道
SysListView32
公共控件和ListView
class提供的等效包装器通过 .NET Framework。深入了解其内部结构可以看出,它提供的用于滚动其内容的滚动条 不是 自己控制 ,而是由SysListView32
控制.目标: 始终绘制滚动条,即使它没有
ListViewItems
可显示或很少以至于不需要滚动条反正;有点像模仿RichTextBox
class 并将其ScrollBars
属性 设置为ForcedBoth
。或者有点像这样ListBox
:
问题:
- .NET NO sugar [=11] 内的滚动条=].
- Win32 文档没有说明何时 show/hide and/or enable/disable 滚动条。
我的解决方法:
override
派生的 class 中的WndProc
并按照步骤 2 和 3 处理其WM_HSCROLL
和WM_VSCROLL
消息。- 调用
base.WndProc
执行实际需要的滚动功能处理。 - 创建一个类似
WmScroll
的方法并立即对其进行 my 处理after
base.WndProc
已返回。 - 这包括对
GetScrollInfo
的 p/invoke 调用。确定是否确实需要滚动条。如果不是,则使用所需值调用ShowScrollBar
和EnableScrollBar
以绘制明显禁用的滚动条。
解决方法有问题:
- 几乎没用。滚动条显示和禁用,但与 Windows 经典主题. 下的滚动条类似
- 它隐藏了每个
ListViewGroup
的折叠按钮,使它们无用!
描述图片:
期待已久的真题:
如何强制滚动条始终在Visible
内aListView
不考虑ListViewItems
[=59=的个数]并在不需要时禁用它们,同时避免大小计算错误 (显示 ListViewGroup
s)和主题恶化?
没有代码的答案,以及 C#、VB.NET 和 C++/CLR 中的代码答案 欢迎。如果您 post 使用 .NET 支持的任何其他语言编写代码,也请将 link 留给代码转换网站,如果代码看起来,呃,难以理解,我可能会使用。
信息:
- 首先,我不得不承认这是一个 还可以 的答案,而不是 best/most 有效的 答案。如果你和我有不同的答案,请post它。
- 其次,这个答案归功于 Plutonix's answer,通过实验我了解到默认情况下
ListView
在其样式中没有设置WS_HSCROLL | WS_VSCROLL
标志。- 这就是我之前的解决方法出现主题问题的原因。
- 这些 Classic 滚动条是 Windows 提供给
Control
没有设置这些标志的滚动条。 - 更改
CreateParams
也不起作用。您必须使用SetWindowLong
. 在 - 我正在 post 的解决方案没有使用上述技术。显然,为每个 window 消息调用
ShowScrollBar
会强制设置这些标志。
OnHandleCreated
方法中手动设置它
解决方案:
定义您的
WndProc
,如下所示: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 :( }
定义WmScroll()如下:
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); }
- 输出:
现在看起来像:
这些是添加的另一个项目,具有水平滚动和工作 ListViewGroup
折叠按钮:
- 不完美,是的:
- 如果组折叠更改有效文本宽度,则需要调用
AutoResizeColumns
,否则垂直滚动条会隐藏折叠按钮。
- 如果组折叠更改有效文本宽度,则需要调用