Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: ListView.UpdateItems scrolls to bottom


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 16 - Last Post: Mar 11, 2018 7:07 AM Last Post By: Rudy Velthuis (...
Bart Kindt

Posts: 33
Registered: 12/16/07
ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2018 3:39 PM
I use a virtual Windows TListview.

When I try to update an entry in the TListview, no matter what I try, it jumps to the end of the list.

ListView.UpdateItems(2,2);

Will actually update the list entry, but then jumps to the end of the list.

It should not do that, and it happens with all Windows versions.

procedure TVirtualItemList.Update(VirtualItem: TVirtualItem);
var ATop, ABottom, AIndex: integer;
begin
  if Updating then exit;
  try
    ListView_SetItemCountEx(FListView.Handle, Count, LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL);
    ATop := 0; ABottom := 0;
 
    if VirtualItem = nil then
    begin
      Log('VirtualItemList.Update: VirtualItem = nil! FListView.Count='+IntToStr(FListView.Items.Count)+'  VirtualList.Count='+IntToStr(Count));
    end;
 
    AIndex := self.IndexOf(VirtualItem);
    if AIndex = -1 then
    begin
      Log('VirtualItemList.Update: Index not found of VirtualItem!',d_error);
    end;
 
    FListView.SortType := stNone; // Debug: Make sure its not on.
 
    Log('VirtualItemList.Update: Updating Index '+IntToStr(AIndex));
    FListView.UpdateItems(AIndex,AIndex);
    {if FListView.Items.Count > 0 then
    begin
      ATop := ListView_GetTopIndex(FListView.Handle);
      ABottom := ATop + FListView.VisibleRowCount;
    end;
    Log('VirtualItemList.Update: Top='+IntToStr(ATop)+' Bottom='+IntToStr(ABottom),d_4);
    FListView.UpdateItems(ATop,ABottom);
    }
  except
    on E:Exception do Log('VirtualItemList.Update: '+E.Message,d_error);
  end;
end;
 

--
---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz

Mark Marks

Posts: 269
Registered: 9/11/00
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 3, 2018 5:39 PM   in response to: Bart Kindt in response to: Bart Kindt
SWAG

Did you try lockwindow update on the control, make the update and then
lockwindow(0) to release the lock?
Bart Kindt

Posts: 33
Registered: 12/16/07
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 2:33 AM   in response to: Mark Marks in response to: Mark Marks
hanks, something I will look into, it may help with other issues.

In the meantime I found the problem, it was an invisible call to the ListView which I missed, and cause this to happen.

Thanks for your reply,

Bart

Mark Marks wrote:
SWAG

Did you try lockwindow update on the control, make the update and then
lockwindow(0) to release the lock?

--
---
Bart Kindt
CEO & Developer
SARTrack Limited New Zealand
http://www.sartrack.nz
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 11:17 AM   in response to: Mark Marks in response to: Mark Marks
Mark Marks wrote:

Did you try lockwindow update on the control, make the update and
then lockwindow(0) to release the lock?

DO NOT use LockWindowUpdate() for this! Raymond Chen from MSDN has a
series of blog articles about how that function should and should not
be used:

What does LockWindowUpdate do?
https://blogs.msdn.microsoft.com/oldnewthing/20070219-00/?p=27963

How is LockWindowUpdate meant to be used?
https://blogs.msdn.microsoft.com/oldnewthing/20070220-07/?p=27953

With what operations is LockWindowUpdate not meant to be used?
https://blogs.msdn.microsoft.com/oldnewthing/20070222-01/?p=27913

Final remarks on LockWindowUpdate
https://blogs.msdn.microsoft.com/oldnewthing/20070223-00/?p=27893

The correct way to temporarily disable screen updates on a control is
to use the WM_SETREDRAW message:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd145219.aspx

Which the TListItems.BeginUpdate() and TListItems.EndUpdate() methods
handle for you.

--
Remy Lebeau (TeamB)
Mark Marks

Posts: 269
Registered: 9/11/00
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 12:01 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

DO NOT use LockWindowUpdate() for this!

Wow, shouting and an exclamation mark.

After reading all the blog post, he provides examples of
possible issues. Some folks might call them "corner cases".

I have used both LockWindowUpdate and begin/end update without issue.

LockWindowUpdate might have been a train wreck for others.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 1:05 PM   in response to: Mark Marks in response to: Mark Marks
Mark Marks wrote:

Wow, shouting and an exclamation mark.

Yup, to make the point clear. This situation is NOT what
LockWindowUpdate() is intended for:

Actually, the intended purpose of LockWindowUpdate can be captured in
one word: dragging. But we'll get to that a little later.

The purpose of LockWindowUpdate is to allow a program to temporarily
take over the responsibility of drawing a window.

People see the "the window you lock won't be able to redraw itself"
behavior of LockWindowUpdate and use it as a sort of lazy version of
the WM_SETREDRAW message...

As we noted earlier, only one window in the system can be locked for
update at a time. If your intention for calling LockWindowUpdate is
merely to prevent a window from redrawing, say, because you're updating
it and don't want the window continuously refreshing until your update
is complete, then just disable redraw on that window. If you use
LockWindowUpdate, you create a whole slew of subtle problems.

After reading all the blog post, he provides examples of
possible issues. Some folks might call them "corner cases".

They are not just corner cases, though. A lot of things that Raymond
blogs about are real world issues that people have actually run across.

I have used both LockWindowUpdate and begin/end update without issue.

Good for you. LockWindowUpdate() is simply the wrong solution for this
situation, plain and simple.

--
Remy Lebeau (TeamB)
Mark Marks

Posts: 269
Registered: 9/11/00
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 1:22 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

LockWindowUpdate() is simply the wrong solution for
this situation, plain and simple.

Many things had one purpose when designed and are used for other
purposes without detrimental results.

As is so much in programming, subjective.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2018 11:10 AM   in response to: Mark Marks in response to: Mark Marks
Mark Marks wrote:

As is so much in programming, subjective.

It is not subjective when a highly visible and respected Microsoft
employee, who works on the Windows dev team and knows the APIs inside
and out, says to (not) use a given API in a particular way. And that
is the case here. Whether LockWindowsUpdate() can or cannot be
used to address the issue of unwanted window refreshes, it should not
be used to solve that issue, because that is not what it was designed
or intended to solve. There is another API (WM_SETREDRAW) that is
specifically designed and intended to solve that very issue instead.

--
Remy Lebeau (TeamB)
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 6, 2018 4:02 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

Mark Marks wrote:

As is so much in programming, subjective.

It is not subjective when a highly visible and respected Microsoft
employee, who works on the Windows dev team and knows the APIs inside
and out, says to (not) use a given API in a particular way.

Indeed. Not just anyone, it was Raymond Chen who said it.

--
Rudy Velthuis http://www.rvelthuis.de

"This is very true; for my words are my own, and my actions are
my ministers."
-- Charles II

Mike Margerum

Posts: 590
Registered: 12/1/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 8, 2018 10:24 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
On 3/5/18 4:05 PM, Remy Lebeau (TeamB) wrote:
Mark Marks wrote:

Wow, shouting and an exclamation mark.

Yup, to make the point clear. This situation is NOT what
LockWindowUpdate() is intended for:

How does it make your point more clear?
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 10, 2018 3:59 AM   in response to: Mike Margerum in response to: Mike Margerum
Mike Margerum wrote:

On 3/5/18 4:05 PM, Remy Lebeau (TeamB) wrote:
Mark Marks wrote:

Wow, shouting and an exclamation mark.

Yup, to make the point clear. This situation is NOT what
LockWindowUpdate() is intended for:

How does it make your point more clear?

It inreases its visibility. I do that too. bold is not always very
visible, e.g. in the font I use (Courier New) but UPPERCASE is. And
well, an exclamation point is an exclamation point.

--
Rudy Velthuis http://www.rvelthuis.de

"I'll be more enthusiastic about encouraging thinking outside the
box when there's evidence of any thinking going on inside it."
-- Terry Pratchett
Mike Margerum

Posts: 590
Registered: 12/1/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 10, 2018 4:40 AM   in response to: Rudy Velthuis (... in response to: Rudy Velthuis (...
How does it make your point more clear?

It inreases its visibility. I do that too. bold is not always very
visible, e.g. in the font I use (Courier New) but UPPERCASE is. And
well, an exclamation point is an exclamation point.

Bolding indicates yelling and condescension. There's almost never a
good reason to use it.
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 10, 2018 11:23 AM   in response to: Mike Margerum in response to: Mike Margerum
Mike Margerum wrote:

How does it make your point more clear?

It inreases its visibility. I do that too. bold is not always very
visible, e.g. in the font I use (Courier New) but UPPERCASE is. And
well, an exclamation point is an exclamation point.

Bolding indicates yelling and condescension.

Since when does bolding indicate condescension or yelling? It merely
indicates strength or emphasis. Think of HTML .

Did you mean using ALL CAPS? But even if you meant that, it does not
indicate condescension either. It does mean speaking louder, which is
what you do when people don't seem to understand you otherwise.

<shrug>
--
Rudy Velthuis http://www.rvelthuis.de

"In matters of conscience, the law of majority has no place."
-- Mohandas Gandhi
Mark Marks

Posts: 269
Registered: 9/11/00
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 10, 2018 11:58 AM   in response to: Rudy Velthuis (... in response to: Rudy Velthuis (...
Rudy Velthuis (TeamB, MVP) wrote:

It does mean speaking louder, which is
what you do when people don't seem to understand you otherwise.

Do you sound hoarse and are hard of hearing? :)
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 11, 2018 7:07 AM   in response to: Mark Marks in response to: Mark Marks
Mark Marks wrote:

Rudy Velthuis (TeamB, MVP) wrote:

It does mean speaking louder, which is
what you do when people don't seem to understand you otherwise.

Do you sound hoarse and are hard of hearing? :)

Was that an attempt to be funny?

--
Rudy Velthuis http://www.rvelthuis.de

"Technology: No Place for Wimps!" -- Scott Adams
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 5, 2018 11:11 AM   in response to: Bart Kindt in response to: Bart Kindt
Bart Kindt wrote:

I use a virtual Windows TListview.

When I try to update an entry in the TListview, no matter what I try,
it jumps to the end of the list.

ListView.UpdateItems(2,2);

Will actually update the list entry, but then jumps to the end of the
list.

It should not do that, and it happens with all Windows versions.

I can't reproduce the issue in XE2. What version of Delphi are you
using? I've been using TListView in virtual mode for years, and never
had a problem with jumping (not with UpdateItems(), anyway).

I just now did a simple test, and it does not jump at all:

unit Unit1;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls;
 
type
  TForm1 = class(TForm)
    ListView1: TListView;
    Button1: TButton;
    procedure ListView1Data(Sender: TObject; Item: TListItem);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    Data: TStringList;
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Data[2] := IntToStr(GetTickCount);
  ListView1.UpdateItems(2, 2);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  Data := TStringList.Create;
  for I := 0 to 100 do
    Data.Add(IntToStr(I+1));
  ListView1.Items.Count := Data.Count;
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  Data.Free;
end;
 
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
  Item.Caption := Data[Item.Index];
end;
 
end.


Every time I press the button, the 3rd list item is updated, and no
matter where the ListView is scrolled to, the update does not make the
ListView jump anywhere else at all.

{code}
procedure TVirtualItemList.Update(VirtualItem: TVirtualItem);
var ATop, ABottom, AIndex: integer;
begin
if Updating then exit;
try

ListView_SetItemCountEx(FListView.Handle, Count,
LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL);

I see you already discovered that one :-) The fact that the
TListItems.SetCount() setter does not use the LVSICF_NOSCROLL flag is
very annoying.

FListView.SortType := stNone; // Debug: Make sure its not on.

Why are you using the SortType property at all? You shouldn't be
sorting the ListView itself, you should be sorting your data storage
instead.

--
Remy Lebeau (TeamB)
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: ListView.UpdateItems scrolls to bottom  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 10, 2018 3:59 AM   in response to: Bart Kindt in response to: Bart Kindt
Bart Kindt wrote:

I use a virtual Windows TListview.

When I try to update an entry in the TListview, no matter what I try,
it jumps to the end of the list.

ListView.UpdateItems(2,2);

Will actually update the list entry, but then jumps to the end of the
list.

It should not do that, and it happens with all Windows versions.

procedure TVirtualItemList.Update(VirtualItem: TVirtualItem);
var ATop, ABottom, AIndex: integer;
begin
  if Updating then exit;
  try
    ListView_SetItemCountEx(FListView.Handle, Count,
LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL);     ATop := 0; ABottom :=
0;
 
    if VirtualItem = nil then
    begin
      Log('VirtualItemList.Update: VirtualItem = nil!
FListView.Count='+IntToStr(FListView.Items.Count)+'
VirtualList.Count='+IntToStr(Count));     end;
 
    AIndex := self.IndexOf(VirtualItem);
    if AIndex = -1 then
    begin
      Log('VirtualItemList.Update: Index not found of
VirtualItem!',d_error);     end;
 
    FListView.SortType := stNone; // Debug: Make sure its not on.
 
    Log('VirtualItemList.Update: Updating Index '+IntToStr(AIndex));
    FListView.UpdateItems(AIndex,AIndex);
    {if FListView.Items.Count > 0 then
    begin
      ATop := ListView_GetTopIndex(FListView.Handle);
      ABottom := ATop + FListView.VisibleRowCount;
    end;
    Log('VirtualItemList.Update: Top='+IntToStr(ATop)+'
Bottom='+IntToStr(ABottom),d_4);
FListView.UpdateItems(ATop,ABottom);     }
  except
    on E:Exception do Log('VirtualItemList.Update:
'+E.Message,d_error);   end;
end;
 

Unlike what others say, don't use LockWindowUpdate for this.
LockWindowUpdate is global and you want to modify the local redrawing
state only.

So use a WM_SETREDRAW message. But beware:
http://fgaillard.com/2011/02/the-unfortunate-effect-of-wm_setredraw/

--
Rudy Velthuis http://www.rvelthuis.de

"War is hell and all that, but it has a good deal to recommend
it. It wipes out all the small nuisances of peacetime."
-- Ian Hay
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02