Discussion:
Getting and Restoring Listview Scrolling Position
(too old to reply)
Brandon
2004-08-03 05:13:14 UTC
Permalink
I have a program that displays an LVS_OWNERDATA listview and when the
user selects an item and presses a button, the selected item is
removed from the list, and the listview is "updated" with calls to
ListView_DeleteAllItems() and ListView_SetItemCount(). The contents
of the listview are wide, requiring the user to scroll left or right
and up or down. The problem is that when the list is updated, the
listview defaults back to the top left corner of the listview. Is
there any way get get the scroll position of the listview before the
update and restore the position after?

-Brandon
Severian
2004-08-03 19:33:21 UTC
Permalink
Post by Brandon
I have a program that displays an LVS_OWNERDATA listview and when the
user selects an item and presses a button, the selected item is
removed from the list, and the listview is "updated" with calls to
ListView_DeleteAllItems() and ListView_SetItemCount(). The contents
of the listview are wide, requiring the user to scroll left or right
and up or down. The problem is that when the list is updated, the
listview defaults back to the top left corner of the listview. Is
there any way get get the scroll position of the listview before the
update and restore the position after?
For vertical position only, ListView_GetTopIndex() and _SetTopIndex().

Perhaps ListView_GetOrigin() and ListView_Scroll() will do both, but I
don't know for sure and MSDN is kind of sparse.

--
Sev
Brandon
2004-08-04 04:46:42 UTC
Permalink
Post by Severian
For vertical position only, ListView_GetTopIndex() and _SetTopIndex().
Perhaps ListView_GetOrigin() and ListView_Scroll() will do both, but I
don't know for sure and MSDN is kind of sparse.
I want/need to get both the horizontal and vertical scroll so
ListView_GetTopIndex() and ListView_SetTopIndex() won't quite work...
not by themselves anyway.

I gave ListView_GetOrigin() and ListView_Scroll() a try.
ListView_Scroll() seems to be just what I'm looking for but,
unfortunately, ListView_GetOrigin() doesn't work in report view. Does
anyone know of a similar function that will work in a report view
listview? I read through the listview macros on MSDN a few times but
can't seem to find anything. MSDN specifically mentions how
ListView_Scroll() behaves in report view when the vertical scroll
value isn't evenly divisible by the height of a row, so I know there
has to be a way to get the scroll values in report view. There can't
be a way to set the values without a way to get them first.

-Brandon
Severian
2004-08-04 05:25:21 UTC
Permalink
Post by Brandon
Post by Severian
For vertical position only, ListView_GetTopIndex() and _SetTopIndex().
Perhaps ListView_GetOrigin() and ListView_Scroll() will do both, but I
don't know for sure and MSDN is kind of sparse.
I want/need to get both the horizontal and vertical scroll so
ListView_GetTopIndex() and ListView_SetTopIndex() won't quite work...
not by themselves anyway.
I gave ListView_GetOrigin() and ListView_Scroll() a try.
ListView_Scroll() seems to be just what I'm looking for but,
unfortunately, ListView_GetOrigin() doesn't work in report view. Does
anyone know of a similar function that will work in a report view
listview? I read through the listview macros on MSDN a few times but
can't seem to find anything. MSDN specifically mentions how
ListView_Scroll() behaves in report view when the vertical scroll
value isn't evenly divisible by the height of a row, so I know there
has to be a way to get the scroll values in report view. There can't
be a way to set the values without a way to get them first.
I don't use ListViews all that much, and especially not in the way you
are, but here's what I'd try:

1) GetTopIndex, GetScrollInfo(hview, SC_HORZ). (fMask = SIF_POS)

2) SetTopIndex, SetScrollInfo(hview, SC_HORZ). (fMask = SIF_POS)

If (2) didn't work, I'd try sending scroll messages directly:

SendMessage(hview, WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, pos), 0)

Another possibility would be to use the nPos results of GetScrollInfo
horz & vert to seed the ListView_Scroll(), but I may be just talking
out of my ass, since I don't know what units are used for scrolling,
and whether they are equivalent.
--
Sev
Brandon
2004-08-04 00:07:56 UTC
Permalink
I found some info on MSDN, other places online, and this newsgroup but
none of the info I've found seems to work for me. As it is now,
before calling ListView_DeleteAllItems() and ListView_SetItemCount(),
I save the scroll positions (both vertical and horizontal) and then
restore afterwards. If anyone could point out an error in the code
below, I would appreciate it. I have tried a few different fMask
values, tried with and without the WM_SETREDRAW messages, and tried
passing both true and false as the last parameter of SetScrollInfo()
but nothing seems to work. Depending on which combination I try from
the options above, the scroll bar thumbs will be restored but the
contents of the listview still defaults to the beginning of the list
and when I try to scroll using the scroll wheel on my mouse, the
thumbs move back to the top (to match the true position of the
listview contents.) Also depending on which combination of options I
use, sometimes the scrollbars won't appear at all after restoring the
position until I start scrolling using the mouse's scroll wheel. I
have to admit that this time I am completely lost. And,
unfortunately, I can't seem to find any good examples specific to
listviews and none the listview tutorial code I have found so far uses
LVS_OWNERDATA listviews (when not using LVS_OWNERDATA, the position
doesn't "reset" like it does with LVS_OWNERDATA listviews.) Does
anyone know what's going on? Am I even using the right approach?


SCROLLINFO prevHScrollPos;
SCROLLINFO prevVScrollPos;
...
ZeroMemory(&prevHScrollPos,sizeof(prevHScrollPos));
prevHScrollPos.cbSize = sizeof(SCROLLINFO);
prevHScrollPos.fMask = SIF_ALL;
ZeroMemory(&prevVScrollPos,sizeof(prevVScrollPos));
prevVScrollPos.cbSize = sizeof(SCROLLINFO);
prevVScrollPos.fMask = SIF_ALL;
...
GetScrollInfo(hWndListview, SB_HORZ, &prevHScrollPos);
GetScrollInfo(hWndListview, SB_VERT, &prevVScrollPos);
SendMessage(hWndListview, WM_SETREDRAW, false, 0);
ListView_DeleteAllItems(hWndListview);
ListView_SetItemCount(hWndListview, itemCount);
SendMessage(hWndListview, WM_SETREDRAW, true, 0);
SetScrollInfo(hWndListview, SB_HORZ, &prevHScrollPos, true);
SetScrollInfo(hWndListview, SB_VERT, &prevVScrollPos, true);
Brandon
2004-08-04 05:22:39 UTC
Permalink
Nevermind, I found a solution. This could be considered my own dumb
fault. No wonder I couldn't find any info about it online. The
problem was that I was using ListView_SetItemCount() instead of
ListView_SetItemCountEx(). Using ListView_SetItemCountEx() with
LVSICF_NOSCROLL and removing the ListView_DeleteAllItems() call (left
over from before I change the listview to LVS_OWNERDATA) fixed the
problem. I never would have thought that using the non-extended-style
call would have caused all this trouble. Thanks to all of you who
gave suggestions.

-Brandon
scs0
2004-09-03 18:45:18 UTC
Permalink
I don't see what ListView_SetItemCountEx() has to do with caching and
restoring the scrolled position. I am currently stuck on this issue
as well: I can cache the scroll position, then delete the contents of
the listview, restore the contents, and restore the scroll position
and sometimes the listview scrolls properly and sometimes it does not.

Between the caching and restore of the listview I will use the
listview for other things. I think when I restore my cache the
listview's scrollbars are still set for the previous ranges and
therefore scroll to the incorrect points when restored. I've
confirmed part of that theory by reading the scroll information
immediately after restoring the contents and it's still set to the old
values.

Oh well. I guess if the API worked as documented it wouldn't be
Windows.

Loading...