By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,669 Members | 1,540 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,669 IT Pros & Developers. It's quick & easy.

Forcing a ListView to scroll

P: n/a
Hello,
I'm trying to force a listView to scroll to some location when a
certain button is clicked on. I've found that the SendMessage function
seems to be the choice way of doing it. Here's what I've put in my
button handler:

//somewhere else in my code:
private const int WM_VSCROLL = 277; // Vertical scroll
..
..
..
//inside button click handler:
SendMessage(myListView.Handle,WM_VSCROLL,IntPtr.Ze ro,
(IntPtr)scrollAmt);

The application compiles and runs fine, and when I click on the scroll
button, the method is invoked (I stepped through in the debugger), but
the listview never scrolls to scrollAmt.
I think I may be using SendMessage incorrectly, but I just can't
figure out how.
Can anyone help with this?
Jun 27 '08 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Tue, 24 Jun 2008 21:32:09 -0700, Lord Zoltar <lo*********@gmail.com>
wrote:
Hello,
I'm trying to force a listView to scroll to some location when a
certain button is clicked on. I've found that the SendMessage function
seems to be the choice way of doing it.
Minor hint: in C#/.NET, unmanaged code is _never_ "the choice way" of
doing anything. It is sometimes the only way, but it's never a choice.
It's something you do because you have to.

In this particular case, the ListView class has the TopItem property and
the EnsureVisible() method that can be used to accomplish what you seem to
be trying to do, but without having to mess with the unmanaged API.

Hope that helps.

Pete
Jun 27 '08 #2

P: n/a
>
Minor hint: in C#/.NET, unmanaged code is _never_ "the choice way" of *
doing anything. *It is sometimes the only way, but it's never a choice.*
It's something you do because you have to.

In this particular case, the ListView class has the TopItem property and *
the EnsureVisible() method that can be used to accomplish what you seem to *
be trying to do, but without having to mess with the unmanaged API.

Hope that helps.

Pete
I had a look at TopItem. It gave me trouble because my ListView
displays in LargeIcon mode. Using EnsureVisible() gave me some odd
behaviour:
I have several dynamically generated groups in my listview and a
button for each group. The button should scroll the listview to the
top of the group. Using EnsureVisible() caused ALL the buttons to
scroll to the first item that had EnsureVisible() invoked on it.
I know the height of each item and each group header, so determining
the exact amount to scroll wouldn't be hard. Is there any other way to
do this besides the SendMessage method?
Jun 27 '08 #3

P: n/a
On Wed, 25 Jun 2008 19:46:02 -0700, Lord Zoltar <lo*********@gmail.com>
wrote:
I had a look at TopItem. It gave me trouble because my ListView
displays in LargeIcon mode. Using EnsureVisible() gave me some odd
behaviour:
I have several dynamically generated groups in my listview and a
button for each group. The button should scroll the listview to the
top of the group. Using EnsureVisible() caused ALL the buttons to
scroll to the first item that had EnsureVisible() invoked on it.
I don't understand your problem description. A concise-but-complete code
sample that illustrates what you're talking about would probably help.
I know the height of each item and each group header, so determining
the exact amount to scroll wouldn't be hard. Is there any other way to
do this besides the SendMessage method?
Yes, there is. Use TopItem or EnsureVisible().

Pete
Jun 27 '08 #4

P: n/a
On Fri, 27 Jun 2008 21:00:16 -0700, Lord Zoltar <lo*********@gmail.com>
wrote:
[...] It really does have to scroll so that the group
header is right at the top of the visible part of the listView. The
effect should be the same as if I did my ListView in HTML, put an
anchor at each group, then provided a link to all the anchors. The
browser should scroll down the page so that anchor is right at the top
of the browser's content area.
But in a browser, you are not guaranteed that the anchor will wind up at
the top. Nor is that exactly the scenario you described here anyway.
Maybe the ListView is not the right
container for this? I'd be open to trying something else if someone
knows a container that can do this better.
It's hard to say without knowing the rest of your criteria. Personally, I
find the particular requirement you're trying to address sort of
pointless, so I can't say that there's necessarily any value in you
describing the rest of the requirements. :)
I've seen a few examples of subclassing ListView and overriding
WndProc so I'll have to give those a try. but I'm still open to any
suggestion that does not use SendMessage()...
If you can involve WndProc() at all for this purpose, it would be simply
to call it. But I don't know whether the managed WndProc() method winds
up near the top or the bottom of the window message processing chain. It
may be that if you really want to use the window message approach, you
have to go with the unmanaged SendMessage().

Pete
Jun 28 '08 #5

P: n/a
Well, I did finally get it working. As it turns out, WM_VSCROLL is the
wrong message. I should have been using LVM_SCROLL... it seems there's
a whole bunch of messages just for listviews:
http://msdn.microsoft.com/en-us/libr...08(VS.85).aspx
for anyone who's interested in the solution, the core of it looks
something like this:

int prevScrollPos = 0;
SCROLLINFO currentInfo = new SCROLLINFO();
currentInfo.cbSize = Marshal.SizeOf(currentInfo);
currentInfo.fMask = (int)ScrollInfoMask.SIF_ALL;

GetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_VERT, ref
currentInfo)

prevScrollPos = currentInfo.nPos;

//The LVM_SCROLL message will take a delta-x and delta-y which tell
the list view how
//much to scroll, relative to the current scroll positions. We are
getting the scroll
//position as an absolute position, so some adjustments are necessary:
scrollPos -= prevScrollPos;
//Send the LVM_SCROLL message to scroll the list view.
SendMessage(new HandleRef(null, this.Handle),
(uint)ListViewMessages.LVM_SCROLL, (IntPtr)0, (IntPtr)scrollPos);
....The key here is that scrollPos is the location of the group header.
I found that someListViewGroup.Items[0].Position.Y - 30 seemed to work
fine (but I would still like to find a better way than hardcoding
"30").
Hope this helps anyone else who has to scroll to groups in ListViews.
Jul 5 '08 #6

This discussion thread is closed

Replies have been disabled for this discussion.