Delphi - Get and Set Scrollbar Position of a ListView

怎甘沉沦 提交于 2019-12-03 13:45:44

Save the top item before clearing,

FSaveTop := ListView1.TopItem;

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.


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.

Save scroll position:

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

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));

or,

var
  i: Integer;
begin
  ...
  for i := 1 to FPos do
    SendMessage(ListView1.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
type
  TForm1 = class(TForm)
    ListView1: TListView;
    Timer1: TTimer;
    Timer2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
    pb:array [0..20] of Tprogressbar;
    i:integer;
      mintop,spacetop,readtop:integer;
    implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);


begin

mintop:=19;
spacetop:=14;
for i:=0 to 20 do
begin
listview1.AddItem('Item no'+inttostr(i),nil);
pb[i]:=Tprogressbar.create(self);
pb[i].Parent:=listview1;
pb[i].width:=120;
pb[i].height:=14;
pb[i].top:=mintop+i*spacetop;
pb[i].position:=i*5;
pb[i].Left:=listview1.Column[0].Width;



end;


end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  z,FPos: Integer;
  SInfo: TScrollInfo;
begin
  SInfo.cbSize := SizeOf(SInfo);
  SInfo.fMask := SIF_ALL;
  GetScrollInfo(ListView1.Handle, SB_VERT, SInfo);
  FPos := SInfo.nPos;
  form1.caption:='FPOS='+inttostr(fpos);
if fpos>0 then
begin
for z:=0 to 11 do
begin
pb[z+fpos-1].Top:=mintop+z*spacetop;
form1.caption:=form1.caption+' Z='+inttostr(z)+' !';
     end;
     end;

 end;
procedure TForm1.Timer2Timer(Sender: TObject);
var x:integer;
begin
  for  x:=0 to 20 do
  begin
  pb[x].Position:=Pb[x].position+1;
  end;


end;

end.


/// Code by BRTH1 - Simao Coelho - Portugal
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!