## 2010. május 29., szombat

### How to determine the absolute location of a control

Problem/Question/Abstract:

Is there a built-in method for getting the absolute location of a control or do I need to step through the hierarchy? E.g.: Form1...Group1...Button1 means that the absolute left of Button1 is Form1.Left+Group1.Left+Button1.Left

Solve 1:

You need to use the ClientToScreen and ScreenToClient methods, like this:

procedure TForm1.Button1Click(Sender: TObject);
var
P: TPoint;
begin
P := Point(Button1.Left, Button1.Top);
{Button1's coordinates are expressed relative to it's parent. Using Parent.ClientToScreen converts these client coordinates to screen coordinates, which are absolute, not relative.}
P := Button1.Parent.ClientToScreen(P);
{Using ScreenToClient here is the same as Self.ScreenToClient. Since Self is the current instance of TForm1, this statement converts the absolute screen coordinates back to coordinates relative to Self.}
P := ScreenToClient(P);
ShowMessage(Format('x: %d, y: %d', [P.X, P.Y]));
end;

Because this code uses the absolute screen coordinates in the conversion process, it will work regardless of how deeply nested the Button is. It could be on the form, on a group on the form, on a panel in a group on the form... it doesn't matter. The code will always return the same results, the coordinates expressed in the form's client system.

Solve 2:

I don't know if there is a simpler method, but this one works:

function GetScreenCoordinates(AControl: TControl): TPoint;
begin
if AControl.Parent <> nil then
begin
Result := AControl.Parent.ClientToScreen(Point(AContol.Left, AControl.Top));
end
else
begin
Result := Point(AContol.Left, AControl.Top);
end;
end;

The trick is: If a control has no parent, (Left, Top) should be the screen coordinates already (TForm). If it has a parent, the ClientToScreen function of the parent can be used to get it.

Solve 3:

Use TComponent.DesignInfo, which holds the Left and Top of the component. You can do this:

X := LongRec(MyComponent.DesignInfo).Lo;
Y := LongRec(MyComponent.DesignInfo).Hi;