因为要用到,所以特意添加了这么个方法,FMX 的 TCustomScrollBox 没有提供,或者是我没有找到正确的,所以特意加了一个。另外,针对 TControl 加了一个 LocalToParent 函数用于将指针的坐标转换为指定级别的父控件的坐标。
完整源码奉上,但声明下,我只测试了一部分我用到的情况,其它情况没测试,如果你发现有问题,欢迎改正好发我更新下。
type TControlHelper = class helper for TControl function OffsetOf(AParent: TControl): TPointF; function LocalToParent(AParent: TControl; APoint: TPointF) : TPointF; overload; function LocalToParent(AParent: TControl; R: TRectF): TRectF; overload; end; TScrollBoxHelper = class helper for TCustomScrollBox public procedure ScrollInView(ACtrl: TControl); end; { TScrollBoxHelper } procedure TScrollBoxHelper.ScrollInView(ACtrl: TControl); var R, LR: TRectF; dx, dy: Single; begin R := ACtrl.LocalToParent(Self, ACtrl.LocalRect); LR := LocalRect; if not LR.Contains(R) then begin if R.Left > LR.Right then dx := LR.Right-R.Right else if R.Right < R.Left then dx := R.Left else dx := 0; if R.Top > LR.Bottom then dy := LR.Bottom-R.Bottom else if R.Bottom < LR.Top then dy := R.Top else dy := 0; ScrollBy(dx, dy); end; end; { TControlHelper } function TControlHelper.LocalToParent(AParent: TControl; APoint: TPointF): TPointF; var AOffset: TPointF; begin AOffset := OffsetOf(AParent); Result.X := APoint.X + AOffset.X; Result.Y := APoint.Y + AOffset.Y; end; function TControlHelper.LocalToParent(AParent: TControl; R: TRectF): TRectF; var AOffset: TPointF; begin AOffset := OffsetOf(AParent); Result := R; Result.Offset(AOffset.X, AOffset.Y); end; function TControlHelper.OffsetOf(AParent: TControl): TPointF; var ACtrl: TControl; begin ACtrl := Self; Result.X := 0; Result.Y := 0; while (ACtrl <> nil) and (ACtrl <> AParent) do begin Result.X := Result.X + ACtrl.Position.X; Result.Y := Result.Y + ACtrl.Position.Y; ACtrl := ACtrl.ParentControl; end; if not Assigned(ACtrl) then raise Exception.CreateFmt('指定的控件 %s 不是 %s 的子控件', [Name, AParent.Name]); end;