Delphi-获取和设置ListView的滚动条位置 [英] Delphi - Get and Set Scrollbar Position of a ListView

查看:749
本文介绍了Delphi-获取和设置ListView的滚动条位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎很愚蠢&一个简单的问题,但是,我一直找不到令人满意的答案.基本上,我有一个带有数据的 TListview (样式= vsReport).有时,我必须对其进行更新,因此,我必须清除列表视图,并用更新的数据再次填充它.

It might seem like a silly & simple question, and yet, I've been unable to find a satisfying answer. Basically, I have a TListview (style = vsReport) with data. Sometimes, I have to update it, and therefore, I have to clear the listview and fill it again with the updated data.

但是,当我这样做时,滚动条的位置将重置为0.我希望能够在清除之前获得滚动条的位置并将其设置回原来的位置.如果更新后的数据与旧数据的行数完全相同,则我需要滚动条与以前的位置完全相同;如果没有的话,我只需要它和以前在同一个地方差不多即可.

However, when I do that, the scrollbar position is reseted to 0. I would like to be able to get the scrollbar position before the clearing and set it back to what it was before. If the updated data has the exact same amount of rows as the old data, I need the scrollbar to be at the exact same position as before; if not, I just need it to be more-or-less at the same place as before.

似乎很容易,对吧?但是,我发现的只是对 TopItem MakeVisible 的修改或调整.有什么合适的方法吗?

Seems easy, right? Yet, all I've found are hacks or tweaks with TopItem and MakeVisible. Is there any appropriate method to do that?

谢谢!

推荐答案

清除前保存顶部项目,

FSaveTop := ListView1.TopItem;

更新后,滚动列表视图,以使保存的首要项目的y位置为0(+标题高度):

After updating, scroll the listview so that the saved top item's 'y' position will be 0 (+ header height):

var
  R: TRect;
begin
  if Assigned(FSaveTop) then begin
    // account for header height
    GetWindowRect(ListView_GetHeader(ListView1.Handle), R);
    ListView1.Scroll(0, FSaveTop.Position.Y - (R.Bottom - R.Top));
  end;
end;

实际上,由于要重新填充列表视图,因此必须设计一种机制来查找要放在顶部的项目,而不是保存对其的引用.

Actually, since you're re-populating the listview, you have to devise a mechanism to find which item you want to be at the top instead of saving a reference to it.


如果您不喜欢通过'top item'修改滚动位置,由于SetScrollInfoSetScrollPos之类的功能不会更新控件的客户区,您可以使用GetScrollInfo来在清除列表之前获取TScrollInfo的'nPos',然后在填充后使用'SB_LINEDOWN'发送许多WM_VSCROLL消息.


If you don't like modifying scroll position through 'top item', since functions like SetScrollInfo, SetScrollPos won't update the client area of the control, you can use GetScrollInfo to get the 'nPos' of a TScrollInfo before clearing the list, and then send that many WM_VSCROLL messages with 'SB_LINEDOWN` after populating.

保存滚动位置:

var
  FPos: Integer;
  SInfo: TScrollInfo;
begin
  SInfo.cbSize := SizeOf(SInfo);
  SInfo.fMask := SIF_ALL;
  GetScrollInfo(ListView1.Handle, SB_VERT, SInfo);
  FPos := SInfo.nPos;
  ...

填充后,滚动(假设滚动位置为0):

After populating, scroll (assuming scroll position is 0):

var
  R: TRect;
begin
  ...
  R := ListView1.Items[0].DisplayRect(drBounds);
  ListView1.Scroll(0, FPos * (R.Bottom - R.Top));

var
  i: Integer;
begin
  ...
  for i := 1 to FPos do
    SendMessage(ListView1.Handle, WM_VSCROLL, SB_LINEDOWN, 0);

这篇关于Delphi-获取和设置ListView的滚动条位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆