在Delphi中如何将组件作为过程的参数传递?

3

我希望能够使用一个过程来将表单上的所有组件居中。这就是我所追求的类型:

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

我只会传递内置组件(memo、label、edit等)。 我有一种感觉,这要么不可能,要么即使可能也不是最佳实践。

1个回答

12
这很简单,但你必须小心术语:
- 一个是任何Delphi对象。它不一定是控件。它甚至不需要是可以放在窗体上的东西。 - 是一个可以放在窗体上的对象。它可能是可视控件(如按钮、标签或编辑框),也可能是非可视组件(如)。 - 是一个可视控件,例如按钮、标签、编辑框或模拟钟表。
以上类按继承顺序排序。
因此,你想要一个作用于总体的过程:
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;

每个TControl都有TopLeftWidthHeight属性,以及SetBounds方法,正如我们上面使用的那样。

请注意,我将控件居中在其父窗口中。(控件的TopLeft值始终相对于其父控件。)

现在,在Delphi中有两种控件:

  • 真正的Win32窗口(具有HWNDs)的控件。
  • 不是真正的Win32窗口的控件。

只有前一种类型的控件可以拥有子控件。这些控件派生自TWinControl。这就是我将Parent声明为TWinControl的原因。这也是TControl.Parent属性的类型。

关于您的代码的一些注释

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

这里有两个问题(除了x:TObject没有任何WidthLeft属性):

  • Form4是表单类的一个特定实例。更好的做法是写成Self.ClientWidth或者简单地写成ClientWidth,这样你就引用了该表单类的当前实例。

  • 但即使这样还不够好,因为这只适用于表单是x的父容器的情况。 x可能有不同的父容器。例如,x可能有一个TPanel作为其父容器(TPanel的父容器是该表单)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接