I have a virtual listview, which I'm planning on using to display things from a rather large log file.
Any time a line is added or removed and I have a row selected or focused (or both) in the listbox, it will automatically scroll back to it, which is very annoying.
Feels like something makes a call for the MakeVisible (or something that does the same thing) when the item count is modified.
Very simplified example to reproduce it:
procedure TForm1.FormCreate(Sender: TObject);
var
Col: TListColumn;
begin
ListView1.OwnerData := True;
ListView1.ViewStyle := vsReport;
ListView1.RowSelect := True;
Col := ListView1.Columns.Add;
Col.Caption := 'LineNum';
Col.Alignment := taLeftJustify;
Col.Width := 70;
end;
// listview onData event
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := IntToStr(Item.Index+1);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
ListView1.Items.Count := ListView1.Items.Count + 10;
end;
Edit: Testing different ViewStyles, this only happens with vsReport and vsList
The problem is that the TListItems.Count
property setter calls ListView_SetItemCountEx()
without the LVSICF_NOSCROLL
flag:
The list-view control will not change the scroll position when the item count changes.
procedure TListItems.SetCount(Value: Integer);
begin
if Value <> 0 then
ListView_SetItemCountEx(Handle, Value, LVSICF_NOINVALIDATEALL)
else
ListView_SetItemCountEx(Handle, Value, 0);
end;
That is why the ListView scrolls whenever the Count
changes. You will have to call ListView_SetItemCountEx()
yourself directly so that you can specify the LVSICF_NOSCROLL
flag.
uses
..., CommCtrl;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//ListView1.Items.Count := ListView1.Items.Count + 10;
ListView_SetItemCountEx(ListView1.Handle, ListView1.Items.Count + 10, LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL);
end;