This is the code I'm using. It will work for any TWinControl descendant: list, tree view, list view, etc.
type TAutoScrollTimer = class(TTimer) private FControl: TWinControl; FScrollCount: Integer; procedure InitialiseTimer; procedure Timer(Sender: TObject); public constructor Create(Control: TWinControl); end; { TAutoScrollTimer } constructor TAutoScrollTimer.Create(Control: TWinControl); begin inherited Create(Control); FControl := Control; InitialiseTimer; end; procedure TAutoScrollTimer.InitialiseTimer; begin FScrollCount := 0; Interval := 250; Enabled := True; OnTimer := Timer; end; procedure TAutoScrollTimer.Timer(Sender: TObject); procedure DoScroll; var WindowEdgeTolerance: Integer; Pos: TPoint; begin WindowEdgeTolerance := Min(25, FControl.Height div 4); GetCursorPos(Pos); Pos := FControl.ScreenToClient(Pos); if not InRange(Pos.X, 0, FControl.Width) then begin exit; end; if Pos.Y<WindowEdgeTolerance then begin SendMessage(FControl.Handle, WM_VSCROLL, SB_LINEUP, 0); end else if Pos.Y>FControl.Height-WindowEdgeTolerance then begin SendMessage(FControl.Handle, WM_VSCROLL, SB_LINEDOWN, 0); end else begin InitialiseTimer; exit; end; if FScrollCount<50 then begin inc(FScrollCount); if FScrollCount mod 5=0 then begin //speed up the scrolling by reducing the timer interval Interval := MulDiv(Interval, 3, 4); end; end; if Win32MajorVersion<6 then begin //in XP we need to clear up transient "fluff"; results in flickering so only do it in XP where it is needed FControl.Invalidate; end; end; begin if Mouse.IsDragging then begin DoScroll; end else begin Free; end; end;
Then, to use it, you add an OnStartDrag event OnStartDrag for the control and implement it as follows:
procedure TMyForm.SomeControlStartDrag(Sender: TObject; var DragObject: TDragObject); begin TAutoScrollTimer.Create(Sender as TWinControl); end;
David heffernan
source share