C# 是否强制在ListView中显示滚动条?
背景:我们大多数人都知道.NET Framework提供的C# 是否强制在ListView中显示滚动条?,c#,winforms,listview,pinvoke,scrollbars,C#,Winforms,Listview,Pinvoke,Scrollbars,背景:我们大多数人都知道.NET Framework提供的SysListView32公共控件和等价的包装器ListView类。稍微深入了解一下它的内部结构,就会发现它为滚动其内容提供的滚动条不是控件本身,而是由SysListView32控件管理的 目标:始终绘制滚动条,即使它没有要显示的列表视图项,或者滚动条很少,因此不需要滚动条;有点像模仿RichTextBox类,其滚动条属性设置为ForcedBoth。或者类似这样的列表框: 问题: .NET对于列表视图中的滚动条,根本没有糖 W
SysListView32
公共控件和等价的包装器ListView
类。稍微深入了解一下它的内部结构,就会发现它为滚动其内容提供的滚动条不是控件本身,而是由SysListView32
控件管理的
列表视图项
,或者滚动条很少,因此不需要滚动条;有点像模仿RichTextBox
类,其滚动条
属性设置为ForcedBoth
。或者类似这样的列表框
:
- 问题:
- .NET对于
,根本没有糖列表视图中的滚动条
- Win32文档没有说明何时显示/隐藏和/或启用/禁用滚动条
- 我的解决方案:
重写派生类中的
,并按照步骤2和3处理其WndProc
和WM\u HSCROLL
消息WM\u VSCROLL
- 调用
对滚动功能执行实际需要的处理base.WndProc
- 创建一个类似于
的方法,并在WmScroll
返回后立即对其进行base.WndProc
处理
- 这包括对
的p/invoke调用。确定是否确实需要滚动条。如果没有,则使用所需值调用GetScrollInfo
和showcollbar
,以绘制明显禁用的滚动条enableCollbar
- 解决方法的问题:
- 它几乎不起作用。滚动条显示和禁用,但与Windows经典主题下的滚动条类似
- 它隐藏了每个
列表视图组的折叠按钮,使它们毫无用处李>
期待已久的实际问题: 如何强制滚动条在
列表视图
中始终可见,而不考虑列表视图项的数量
,并在不需要滚动条时禁用滚动条,同时避免大小计算错误(显示列表视图组的折叠按钮)和主题退化?
不带代码的答案,以及在C#、VB.NET和C++/CLR中带代码的答案都是受欢迎的。如果您使用.NET支持的任何其他语言发布代码,请同时留下一个链接,指向代码转换网站,如果代码看起来,呃,不可理解,我可能会使用该网站。信息:
- 首先,我必须承认这是一个不错的答案,但不是最好/最有效的答案。如果你的答案与我的不同,请发布它
- 其次,这个答案要归功于的,我通过实验了解到,默认情况下,
ListView
的样式中没有设置wshscroll | WS_VSCROLL
标志。
- 这就是为什么我以前的解决方案在主题方面存在问题
- 这些经典滚动条是Windows提供给未设置这些标志的控件的滚动条
- 更改
CreateParams
也不起作用。您必须使用SetWindowLong
在OnHandleCreated
方法中手动设置它
- 我发布的解决方案没有使用上述技术。显然,为每个窗口消息调用
showcollbar
,会强制设置这些标志
- 解决方案:
- 定义您的
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 :(
}
受保护的覆盖无效WndPoc(参考消息m)
{
//调用base.WndProc之前的自定义代码
基准WndProc(参考m);
//base.WndProc返回后的自定义
WmScroll();//效率很低,为每条消息调用:(
}
- 定义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);
}
受保护的虚拟卷
{
显示滚动条(Handle、SB_和true);
//si.fMask=SIF_页面| SIF_范围
- 信息:
- 首先,我必须承认这是一个不错的答案,但不是最好/最有效的答案。如果你的答案与我的不同,请发布它
- 其次,这个答案要归功于的,我通过实验了解到,默认情况下,
ListView
的样式中没有设置wshscroll | WS_VSCROLL
标志。
- 这就是为什么我以前的解决方案在主题方面存在问题
- 这些经典滚动条是Windows提供给未设置这些标志的控件的滚动条
- 更改
CreateParams
也不起作用。您必须使用SetWindowLong
在OnHandleCreated
方法中手动设置它
- 我发布的解决方案没有使用上述技术。显然,为每个窗口消息调用
showcollbar
,会强制设置这些标志
- 解决方案:
- 定义您的
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 :(
}
受保护的覆盖无效WndPoc(参考消息m)
{
//调用base.WndProc之前的自定义代码
基准WndProc(参考m);
//base.WndProc返回后的自定义
WmScroll();//效率很低,为每条消息调用:(
}
- 定义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);
}
受保护的虚拟卷
{
显示滚动条(Handle、SB_和true);
//si.fMask=SIF_PAGE | SIF_RANGE显示了一系列与ListView相关的滚动条操作,包括指向ShowScrollBar
@puropoix尼斯链接的Pinvoke,但我没有