检查滚动条可见性
Posted
技术标签:
【中文标题】检查滚动条可见性【英文标题】:Check Scrollbar Visibility 【发布时间】:2011-06-02 01:51:52 【问题描述】:有没有办法检查垂直滚动条在某个 ListView 对象上是否可见?
我有一个带有 listView 的 Windows 窗体,如果 listview 的垂直滚动条可见,我想捕捉到 resize 事件!
【问题讨论】:
@thephpdeveloper 我不相信他的意思是 ListView 对象...而是实际的 ListView,将其还原... 【参考方案1】:如果这是 WPF,则此处为 sample exist,它在解决方案的基础上连接到 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 code exists 使用 GetWindowLong
检查是否存在可以移植到 C# 的 ScrollBar。
【讨论】:
@Cloaky - 最好在你的问题中写下尽可能多的细节。您可以点击编辑链接来编辑您的问题 =) 不,您没有...问题中仍然没有任何内容可以说明您在谈论 Windows 窗体。我以为你也在谈论 WPF。 问题是,您真的需要这些信息吗?如果要适合列,最好只使用 ClientRectangle;它总是在滚动条内提供可用区域。【参考方案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 的多台显示器时
【讨论】:
以上是关于检查滚动条可见性的主要内容,如果未能解决你的问题,请参考以下文章
当可见性发生变化时,IFrame滚动条会在Chrome上消失