在ListView中强制显示滚动条?

Force the display of scroll bars in a ListView?


描述图片:


期待已久的真题:

如何强制滚动条始终在Visible内aListView不考虑ListViewItems[=59=的个数]并在不需要时禁用它们,同时避免大小计算错误 (显示 ListViewGroups)和主题恶化?

没有代码的答案,以及 C#VB.NETC++/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,否则垂直滚动条会隐藏折叠按钮。