mouldyBaguette
mouldyBaguette

Reputation: 33

How to pass a component as a parameter of a procedure in Delphi?

I want to be able to use one procedure to center all the components on a form. This is the kind of thing I'm going for:

procedure TForm4.centerComponent(x: Tobject);
begin
x.Left := (Form4.ClientWidth - x.Width) div 2;
end;

I would only be passing built in components (memo, label, edit etc...) I get the feeling this is either not possible or if it is its probably not best practice

Upvotes: 3

Views: 913

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108948

This is easy, but you must be careful about terminology:

  • A TObject is any Delphi object. It need not be a control. It doesn't even need to be something you can drop on a form.

  • A TComponent is an object you can drop on a form. It might be a visual control (like a button, a label, or an edit box), or it might be a non-visual component (like a TActionList).

  • A TControl is a visual control, like a button, a label, an edit box, or an animated analogue clock.

The above classes are ordered by inheritance.

So, you want a procedure that acts on TControls in general:

procedure Centre(AControl: TControl);
var
  Parent: TWinControl;
begin
  Parent := AControl.Parent;
  if Parent = nil then
    Exit;
  AControl.SetBounds(
    (Parent.ClientWidth - AControl.Width) div 2,
    (Parent.ClientHeight - AControl.Height) div 2,
    AControl.Width,
    AControl.Height
  );
end;

Every TControl has Top, Left, Width, and Height properties, as well as the SetBounds method, which we use above.

Notice that I centre the control in its parent window. (A control's Top and Left values are always relative to its parent.)

Now, there are two kinds of controls in Delphi:

  • Controls that are actual Win32 windows (with HWNDs).
  • Controls that are not actual Win32 windows.

Only the former kind of control can have child controls. These controls derive from TWinControl. That's the reason I declare Parent as a TWinControl. This is also the type of the TControl.Parent property.

Some notes about your code

x.Left := (Form4.ClientWidth - x.Width) div 2;

Here there are two issues (except for x: TObject not having any Width or Left properties):

  • Form4 is one particular instance of the form class. It is much better to write Self.ClientWidth or simply ClientWidth, so you refer to the current instance of the form class.

  • But even this is not good enough, because this only works if the form is the parent of x. x might well have a different parent. For instance, x might have a TPanel as its parent (the TPanel's parent being the form).

Upvotes: 12

Related Questions