M
Michael J. Salamone
I have a listview whose contents are constantly being refreshed. When a
refresh occurs, I delete all the items and add back. I want to maintain the
scroll position before deleting all the items, and then want to restore it
once the items are added back.
I'm using P/Invoke Get/SetScrollInfo to get and restore the scroll
information. GetScrollInfo is working fine - it returns expected
information. SetScrollInfo has no effect - the scroll positions are
unchanged (both horz and vert are 0).
I also tried Get/SetScrollPos - no luck there, either.
Is this the correct way to do this? Anyone know what might be wrong?
Here's some of my code:
private void RefreshList()
{
User32.SCROLLINFO hsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_HORZ);
User32.SCROLLINFO vsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_VERT);
MyListView.BeginUpdate();
MyListView.Items.Clear();
// Add new items here...
User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_HORZ, false, hsi);
User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_VERT, false, vsi);
MyListView.EndUpdate();
}
public class Constants
{
public const int SB_HORZ = 0;
public const int SB_VERT = 1;
public const int SB_CTL = 2;
public const int SB_BOTH = 4;
public const int SIF_RANGE = 0x0001;
public const int SIF_PAGE = 0x0002;
public const int SIF_POS = 0x0004;
public const int SIF_DISABLENOSCROLL = 0x0008;
public const int SIF_TRACKPOS = 0x0010;
public const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS |
SIF_TRACKPOS);
}
public class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct SCROLLINFO
{
public UInt32 cbSize;
public UInt32 fMask;
public Int32 nMin;
public Int32 nMax;
public UInt32 nPage;
public Int32 nPos;
public Int32 nTrackPos;
}
[DllImport("user32.dll", EntryPoint = "GetScrollInfo", SetLastError =
true)]
private static extern int GetScrollInfoWnd(uint hWnd, int nBar, ref
SCROLLINFO si);
public static SCROLLINFO GetScrollInfo(uint hWnd, int nBar)
{
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint) System.Runtime.InteropServices.Marshal.SizeOf(si);
si.fMask = Constants.SIF_ALL;
// also tried si.fMask = Constants.SIF_PAGE | Constants.SIF_POS |
Constants.SIF_RANGE
GetScrollInfoWnd(hWnd, nBar, ref si); // returns correct data
return si;
}
[DllImport("user32.dll", EntryPoint = "SetScrollInfo", SetLastError =
true)]
private static extern int SetScrollInfoWnd(uint hWnd, int nBar, bool
bRedraw, ref SCROLLINFO si);
public static int SetScrollInfo(uint hWnd, int nBar, bool bRedraw,
SCROLLINFO si)
{
int rc = SetScrollInfoWnd(hWnd, nBar, bRedraw, ref si);
return rc; // return is 0 - presumably previous scroll position
}
}
Thanks
refresh occurs, I delete all the items and add back. I want to maintain the
scroll position before deleting all the items, and then want to restore it
once the items are added back.
I'm using P/Invoke Get/SetScrollInfo to get and restore the scroll
information. GetScrollInfo is working fine - it returns expected
information. SetScrollInfo has no effect - the scroll positions are
unchanged (both horz and vert are 0).
I also tried Get/SetScrollPos - no luck there, either.
Is this the correct way to do this? Anyone know what might be wrong?
Here's some of my code:
private void RefreshList()
{
User32.SCROLLINFO hsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_HORZ);
User32.SCROLLINFO vsi = User32.GetScrollInfo((uint)
MyListView.Handle.ToInt32(), Constants.SB_VERT);
MyListView.BeginUpdate();
MyListView.Items.Clear();
// Add new items here...
User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_HORZ, false, hsi);
User32.SetScrollInfo((uint)MyListView.Handle.ToInt32(),
Constants.SB_VERT, false, vsi);
MyListView.EndUpdate();
}
public class Constants
{
public const int SB_HORZ = 0;
public const int SB_VERT = 1;
public const int SB_CTL = 2;
public const int SB_BOTH = 4;
public const int SIF_RANGE = 0x0001;
public const int SIF_PAGE = 0x0002;
public const int SIF_POS = 0x0004;
public const int SIF_DISABLENOSCROLL = 0x0008;
public const int SIF_TRACKPOS = 0x0010;
public const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS |
SIF_TRACKPOS);
}
public class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct SCROLLINFO
{
public UInt32 cbSize;
public UInt32 fMask;
public Int32 nMin;
public Int32 nMax;
public UInt32 nPage;
public Int32 nPos;
public Int32 nTrackPos;
}
[DllImport("user32.dll", EntryPoint = "GetScrollInfo", SetLastError =
true)]
private static extern int GetScrollInfoWnd(uint hWnd, int nBar, ref
SCROLLINFO si);
public static SCROLLINFO GetScrollInfo(uint hWnd, int nBar)
{
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint) System.Runtime.InteropServices.Marshal.SizeOf(si);
si.fMask = Constants.SIF_ALL;
// also tried si.fMask = Constants.SIF_PAGE | Constants.SIF_POS |
Constants.SIF_RANGE
GetScrollInfoWnd(hWnd, nBar, ref si); // returns correct data
return si;
}
[DllImport("user32.dll", EntryPoint = "SetScrollInfo", SetLastError =
true)]
private static extern int SetScrollInfoWnd(uint hWnd, int nBar, bool
bRedraw, ref SCROLLINFO si);
public static int SetScrollInfo(uint hWnd, int nBar, bool bRedraw,
SCROLLINFO si)
{
int rc = SetScrollInfoWnd(hWnd, nBar, bRedraw, ref si);
return rc; // return is 0 - presumably previous scroll position
}
}
Thanks