检查滚动条可见性。

4

有没有办法检查特定ListView对象上的垂直滚动条是否可见?

我有一个Windows表单,上面有一个listView,在调整大小事件中,我想捕获listview是否有其垂直滚动条可见!


@thephpdeveloper 我不相信他的意思是 ListView 对象,而是实际的 ListView,将其恢复回来... - Aaron McIver
2个回答

3
如果这是WPF,可以参考这里的示例,该示例通过钩取ListView.LayoutUpdated来实现。如果这是WinForms,您可以使用pinvoke和GetWindowLong...
  static public class WndInfo
  {
    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    ...
    public static bool IsWindowTopMost(IntPtr Handle)
    {
      return (GetWindowLong(Handle, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
    }
    ...
  }

VB代码存在,使用GetWindowLong来检查是否存在一个滚动条,您可以将其移植到C#。


1
@Cloaky - 最好在你的问题中写下尽可能多的细节。你可以点击编辑链接来编辑你的问题 =) - mauris
不,你没有...问题中仍然没有任何内容指定你在谈论Windows Forms。我假设你也在谈论WPF。 - Josh
问题是,你真的需要那个信息吗?如果是为了适应列,最好只使用ClientRectangle;它总是提供滚动条内可用区域。 - Nyerguds
请更新已损坏的链接。 - rory.ap
C#代码检查滚动条可见性 https://www.csharp-examples.net/check-scrollbars-visibility/ - Ahmed Osama

2

我有几种方法在使用Winforms时获取信息,这些方法基于我想要从哪种类型的控件中获取信息。这是我的类。

public static class NativeMethods
{
    const Int32 LVM_FIRST = 0x1000;
    const Int32 LVM_SCROLL = LVM_FIRST + 20;

    [DllImport("user32")]
    static extern IntPtr SendMessage(IntPtr Handle, Int32 msg, IntPtr wParam, IntPtr lParam);


    // offset of window style value
    const int GWL_STYLE = -16;

    // window style constants for scrollbars
    const int WS_VSCROLL = 0x00200000;
    const int WS_HSCROLL = 0x00100000;

    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);


    static ScrollBars GetControlVisibleScrollbars(Control ctl)
    {
        int wndStyle = GetWindowLong(ctl.Handle, GWL_STYLE);
        bool hsVisible = (wndStyle & WS_HSCROLL) != 0;
        bool vsVisible = (wndStyle & WS_VSCROLL) != 0;

        if(hsVisible)
            return vsVisible ? ScrollBars.Both : ScrollBars.Horizontal;
        else
            return vsVisible ? ScrollBars.Vertical : ScrollBars.None;
    }

    public static ScrollBars GetVisibleScrollbars(this ListView lv)
    {
        if(lv is null)
        {
            throw new ArgumentNullException(nameof(lv));
        }

        return GetControlVisibleScrollbars(lv);
    }


    public static ScrollBars GetVisibleScrollbars(this ScrollableControl ctl)
    {
        if(ctl is null)
        {
            throw new ArgumentNullException(nameof(ctl));
        }

        if(ctl.HorizontalScroll.Visible)
            return ctl.VerticalScroll.Visible ? ScrollBars.Both : ScrollBars.Horizontal;
        else
            return ctl.VerticalScroll.Visible ? ScrollBars.Vertical : ScrollBars.None;
    }


    private static void ScrollHorizontal(Form form, int pixelsToScroll)
    {
        SendMessage(form.Handle, LVM_SCROLL, (IntPtr)pixelsToScroll, IntPtr.Zero);
    }

    public static void EnsureVisible(this ListViewItem item, int subItemIndex, int margin=10)
    {
        if(item is null)
        {
            throw new ArgumentNullException(nameof(item));
        }

        if( subItemIndex > item.SubItems.Count - 1)
        {
            throw new IndexOutOfRangeException($"ListView {item.ListView.Name} does not have a SubItem on index {subItemIndex}");
        }

        // scroll to the item row.
        item.EnsureVisible();
        Rectangle bounds = item.SubItems[subItemIndex].Bounds;
        bounds.Width = item.ListView.Columns[subItemIndex].Width;
        ScrollToRectangle(item.ListView,bounds,margin);
    }



    private static void ScrollToRectangle(ListView listView, Rectangle bounds, int margin)
    {
        int scrollToLeft = bounds.X + bounds.Width + margin;
        if(scrollToLeft > listView.Bounds.Width)
        {
            ScrollHorizontal(listView.FindForm(),scrollToLeft - listView.Bounds.Width);
        }
        else
        {
            int scrollToRight = bounds.X - margin;
            if(scrollToRight < 0)
            {
                ScrollHorizontal(listView.FindForm(),scrollToRight);
            }
        }
    }

假设您的用例中有一个分割面板,您希望左侧面板足够宽,不需要水平滚动条,则可以执行以下操作:

var bar= MyListView.GetVisibleScrollbars();
while(bar== ScrollBars.Horizontal || bar== ScrollBars.Both)
{
    progressPanels.SplitterDistance += 5;
    bar = MyListView.GetVisibleScrollbars();
}

我并不是说这是最好的方法,我只是说这是一个选项,特别是在处理不同DPI的多个监视器时


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接