Как передать компонент в качестве параметра процедуры в Delphi?

#delphi

#delphi

Вопрос:

Я хочу иметь возможность использовать одну процедуру для центрирования всех компонентов в форме. Это то, к чему я стремлюсь:

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

Я бы передавал только встроенные компоненты (memo, label, edit и т.д.)
У меня такое чувство, что это либо невозможно, либо, вероятно, это не лучшая практика

Ответ №1:

Это просто, но вы должны быть осторожны с терминологией:

  • TObject — это любой объект Delphi. Это не обязательно должен быть элемент управления. Это даже не обязательно должно быть чем-то, что вы можете поместить в форму.

  • TComponent — это объект, который вы можете поместить в форму. Это может быть визуальный элемент управления (например, кнопка, метка или поле редактирования), или это может быть невизуальный компонент (например, TActionList ).

  • TControl — это визуальный элемент управления, такой как кнопка, метка, окно редактирования или анимированные аналоговые часы.

Вышеуказанные классы упорядочены по наследованию.

Итак, вам нужна процедура, которая действует на TControl s в целом:

 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 имеет Top , Left , Width и Height свойства, а также SetBounds метод, который мы использовали выше.

Обратите внимание, что я центрирую элемент управления в его родительском окне. ( Top И Left значения элемента управления всегда относятся к его родительскому элементу.)

Итак, в Delphi есть два вида элементов управления:

  • Элементы управления, которые являются настоящими окнами Win32 (с HWND).
  • Элементы управления, которые не являются настоящими окнами Win32.

Только первый тип элемента управления может иметь дочерние элементы управления. Эти элементы управления являются производными от TWinControl . Вот почему я объявляю Parent как TWinControl . Это также тип TControl.Parent свойства.

Несколько замечаний о вашем коде

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

Здесь есть две проблемы (за исключением x: TObject отсутствия каких-либо свойств Width или Left ):

  • Form4 является одним конкретным экземпляром класса form. Гораздо лучше написать Self.ClientWidth или просто ClientWidth , чтобы вы ссылались на текущий экземпляр класса form.

  • Но даже этого недостаточно, потому что это работает, только если форма является родительской для x . x вполне может иметь другого родителя. Например, у x может быть TPanel родительский элемент (родительским элементом TPanel является форма).