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

Answer:

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;

Nincsenek megjegyzések:

Megjegyzés küldése