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).