如何知道WinForms ListView滚动条何时到达底部? 当发生这种情况时,我希望列表视图中填充更多数据(在我的情况下,这在理论上是无穷无尽的。)
OnScroll事件从顶部给出了滚动值,但我无法知道用户是否可以进一步滚动。
答案 0 :(得分:3)
我使用伟大的ObjectListView代码项目中的一些代码找到了答案: http://www.codeproject.com/KB/list/ObjectListView.aspx
调用GetScrollInfo:
private const int SIF_RANGE = 0x0001;
private const int SIF_PAGE = 0x0002;
private const int SIF_POS = 0x0004;
private const int SIF_DISABLENOSCROLL = 0x0008;
private const int SIF_TRACKPOS = 0x0010;
private const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS);
private const int SB_HORZ = 0;
private const int SB_VERT = 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool GetScrollInfo(IntPtr hWnd, int fnBar, SCROLLINFO scrollInfo);
public static SCROLLINFO GetFullScrollInfo(ListView lv, bool horizontalBar) {
int fnBar = (horizontalBar ? SB_HORZ : SB_VERT);
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.fMask = SIF_ALL;
if (GetScrollInfo(lv.Handle, fnBar, scrollInfo))
return scrollInfo;
else
return null;
}
使用此数据结构:
[StructLayout(LayoutKind.Sequential)]
public class SCROLLINFO
{
public int cbSize = Marshal.SizeOf(typeof(SCROLLINFO));
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
nMax给出包含滚动句柄本身的总最大滚动值,因此实际有用的最大值是nMax - nPage,其中nPage是滚动句柄的大小。
这很棒!
答案 1 :(得分:0)
我无法直接回答您的问题,但根据您的描述,您似乎真的想要使用列表视图的虚拟模式来管理大型数据集。
http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode.aspx
答案 2 :(得分:0)
在有人需要的情况下,我借用了上面的代码,并且使用键盘上的下一页,下一页和结束键,拖动或单击滚动条并达到最大底部,使用了一些改进,以处理onMaximumBottomScroll事件鼠标滚轮垂直或水平旋转。这对我来说就像一种魅力。
public partial class OrganizationFilesListView : ListView
{
// Windows messages
private const int WM_VSCROLL = 0x0115;
private const int WM_MOUSEHWHEEL = 0x020E;
private const int WM_MOUSEWHEEL = 0x020A;
private const int WM_KEYDOWN = 0x0100;
// ScrollBar types
private const int SB_VERT = 1; // only for maximum vertical scroll position
// ScrollBar interfaces
private const int SIF_TRACKPOS = 0x10;
private const int SIF_RANGE = 0x01;
private const int SIF_POS = 0x04;
private const int SIF_PAGE = 0x02;
private const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
// variable to force to run only once the event
private bool runningOnMaximumBottomScroll = false;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (uint)ScrollInfoMask.SIF_ALL;
bool isMaximumButtomScroll = false;
switch (m.Msg)
{
case WM_VSCROLL:
isMaximumButtomScroll = GetScrollInfo(m.HWnd, SB_VERT, ref si) ? (si.nPage + si.nPos) >= si.nMax : false;
if (isMaximumButtomScroll && !runningOnMaximumBottomScroll)
{
runningOnMaximumBottomScroll = true;
onMaximumBottomScroll(this, new ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(this.Handle, SB_VERT)));
runningOnMaximumBottomScroll = false;
}
break;
case WM_MOUSEHWHEEL:
case WM_MOUSEWHEEL:
isMaximumButtomScroll = GetScrollInfo(m.HWnd, SB_VERT, ref si) ? (si.nPage + si.nPos) >= si.nMax : false;
bool isMouseWheelDown = m.Msg == WM_MOUSEWHEEL ? (int)m.WParam < 0 : (int)m.WParam > 0;
if (isMaximumButtomScroll && isMouseWheelDown && !runningOnMaximumBottomScroll)
{
runningOnMaximumBottomScroll = true;
onMaximumBottomScroll(this, new ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(this.Handle, SB_VERT)));
runningOnMaximumBottomScroll = false;
}
break;
case WM_KEYDOWN:
isMaximumButtomScroll = GetScrollInfo(m.HWnd, SB_VERT, ref si) ? (si.nPage + si.nPos) >= (si.nMax - 1) : false;
switch (m.WParam.ToInt32())
{
case (int)Keys.Down:
case (int)Keys.PageDown:
case (int)Keys.End:
if (isMaximumButtomScroll && !runningOnMaximumBottomScroll)
{
runningOnMaximumBottomScroll = true;
onMaximumBottomScroll(this, new ScrollEventArgs(ScrollEventType.EndScroll, GetScrollPos(this.Handle, SB_VERT)));
runningOnMaximumBottomScroll = false;
}
break;
}
break;
}
}
public event ScrollEventHandler onMaximumBottomScroll;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetScrollPos(IntPtr hWnd, int nBar);
[Serializable, StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
public enum ScrollInfoMask : uint
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS),
}
}
完成...享受它!