Here is a quick solution, how to synchronize scrolling of two TListViews. All you have to do is to write a code for
OnAdvancedCustomDraw event for both lists.
Suppose, you have two lists of TListView type --
fNewList. Write code for first one (
procedure TMainForm.fListAdvancedCustomDraw(Sender: TCustomListView; const ARect: TRect; Stage: TCustomDrawStage; var DefaultDraw: Boolean); var dY: Integer; begin if(fList.TopItem <> nil) and (fNewList.Items.Count > fList.TopItem.Index) then begin dY := fNewList.TopItem.DisplayRect(drBounds).Bottom - fNewList.TopItem.DisplayRect(drBounds).Top; dY := (fList.TopItem.Index - fNewList.TopItem.Index) * dY; fNewList.Scroll(0, dY); end; end;
Code for second one (
fNewListAdvancedCustomDraw event) is quite similar:
procedure TMainForm.fNewListAdvancedCustomDraw(Sender: TCustomListView; const ARect: TRect; Stage: TCustomDrawStage; var DefaultDraw: Boolean); var dY: Integer; begin if(fNewList.TopItem <> nil) and (fList.Items.Count > fNewList.TopItem.Index) then begin dY := fList.TopItem.DisplayRect(drBounds).Bottom - fList.TopItem.DisplayRect(drBounds).Top; dY := (fNewList.TopItem.Index - fList.TopItem.Index) * dY; fList.Scroll(0, dY); end; end;
And that's it.
Of course, there are penalities for being lazy ass! :] Performance is killing you and everyone around as you're using drawing event to catch scrolling (madness! :]) and you can actually clearly see, when your lists are refreshed. But since I needed a really quick solution, without playing around window messages and aligning, this was the best I could get. It was enough for me.
If you're looking for harder to good, but much more performance full, then you have to look around for subclassing and catching window's messages, as there are not specific events published for catching scroll of an TListView. I suppose, you can start with StackOverflow articles: TListView scroll event and Catching ListView BeginScroll and EndScroll Events.