9

ばかげた単純な質問のように思えるかもしれませんが、満足のいく答えを見つけることができませんでした. 基本的に、データを含むTListview (スタイル = vsReport) があります。時々、更新する必要があるため、リストビューをクリアして、更新されたデータを再度入力する必要があります。

ただし、それを行うと、スクロールバーの位置が0にリセットされます。クリアする前にスクロールバーの位置を取得し、以前の位置に戻せるようにしたいと考えています。更新されたデータの行数が古いデータとまったく同じである場合、スクロールバーを以前とまったく同じ位置に配置する必要があります。そうでない場合は、以前とほぼ同じ場所にある必要があります。

簡単そうですよね?それでも、私が見つけたのは、TopItemMakeVisibleを使ったハックまたは微調整だけです。それを行う適切な方法はありますか?

ありがとう!

4

2 に答える 2

15

クリア前に一番上のアイテムをセーブして、

FSaveTop := ListView1.TopItem;

更新後、リストビューをスクロールして、保存された一番上のアイテムの 'y' 位置が 0 (+ ヘッダーの高さ) になるようにします。

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;

実際には、リストビューを再作成しているため、参照を保存するのではなく、一番上にしたいアイテムを見つけるメカニズムを考案する必要があります。


SetScrollInfoのような関数SetScrollPosはコントロールのクライアント領域を更新しないため、「トップ項目」を介してスクロール位置を変更したくない場合は、リストをクリアする前GetScrollInfoに a の「nPos」を取得し、それを送信することができます。入力後に「SB_LINEDOWN」を含むTScrollInfo多くのメッセージ。WM_VSCROLL

スクロール位置を保存:

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

データを入力したら、スクロールします (スクロール位置が 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);
于 2013-12-29T23:28:16.200 に答える
-2
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
于 2015-05-23T16:48:05.363 に答える