Author: Tomas Rutkauskas
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
Answer:
Solve 1:
You need to use the ClientToScreen and ScreenToClient methods, like this:
1 procedure TForm1.Button1Click(Sender: TObject);
2 var
3 P: TPoint;
4 begin
5 P := Point(Button1.Left, Button1.Top);
6 {Button1's coordinates are expressed relative to it's parent. Using
7 Parent.ClientToScreen converts these client coordinates to screen coordinates,
8 which are absolute, not relative.}
9 P := Button1.Parent.ClientToScreen(P);
10 {Using ScreenToClient here is the same as Self.ScreenToClient. Since Self is the
11 current instance of TForm1, this statement converts the absolute screen coordinates
12 back to coordinates relative to Self.}
13 P := ScreenToClient(P);
14 ShowMessage(Format('x: %d, y: %d', [P.X, P.Y]));
15 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:
16 function GetScreenCoordinates(AControl: TControl): TPoint;
17 begin
18 if AControl.Parent <> nil then
19 begin
20 Result := AControl.Parent.ClientToScreen(Point(AContol.Left, AControl.Top));
21 end
22 else
23 begin
24 Result := Point(AContol.Left, AControl.Top);
25 end;
26 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:
27 X := LongRec(MyComponent.DesignInfo).Lo;
28 Y := LongRec(MyComponent.DesignInfo).Hi;
|