因为要用到,所以特意添加了这么个方法,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;
