Если каждая форма, которую вы собираетесь передать в свою функцию, будет иметь опубликованное поле с именем «Timer1», то вы можете использовать метод FindComponent
, чтобы получить ссылку на нее:
procedure Slide(Form: TForm; Show: Boolean);
var
TimerObj: TComponent;
Timer: TTimer;
begin
TimerObj := Form.FindComponent('Timer1');
Assert(Assigned(TimerObj), 'Form has no Timer1');
Assert(TimerObj is TTimer, 'Form.Timer1 is not a TTimer');
Timer := TTimer(TimerObj);
// Continue using Form and Timer
end;
Это довольно слабый интерфейс для программирования. Если вы случайно не указали таймер в вашей форме, или вы дали ему неправильное имя, или если вы дали ему другую видимость, вы не обнаружите свою ошибку до времени выполнения (когда утверждения потерпеть поражение). И даже если форма соответствует требуемому интерфейсу, нет гарантии, что он был намеренным. Может быть много форм, которые опубликовали TTimer
поля с именем Timer1
, но не все они предназначены для использования с этой функцией Slide
. Возможно, они уже используют свои таймеры для других целей, поэтому вызов Slide
для них может сломать другие части вашей программы, возможно, трудными для отладки способами.
Было бы немного более сильным интерфейсом, если бы вы дали таймеру более описательное имя, такое как SlideTimer
. Timer1
просто говорит, что это был первый TTimer
, который вы создали в этой форме, и как только вы покидаете конструктор форм, он перестает быть значимым обозначением. Вы не обязаны использовать варианты именования в среде IDE.
Другой, более лучший вариант - сделать так, чтобы все скользящие формы имели общий базовый класс, и поместили таймер в этот базовый класс. Затем измените тип параметра в Slide
, чтобы взять этот класс формы, а не просто TForm
.
type
TSlidableForm = class(TForm)
Timer1: TTimer;
end;
procedure Slide(Form: TSlidableForm; Show: Boolean);
Вы, похоже, обеспокоены тем, что вам придется включить ссылку на устройство Form2 в ваше устройство Slide
, и это, как правило, полезно. Вы не хотите, чтобы ваш код был слишком тесно связан, так как эта функция Slide
должна работать с более чем одной формой в одном проекте. Но если он слишком свободный, то вы столкнетесь с проблемами, которые я описал выше. Этот класс TSlidableForm
является компромиссом; Ваша Slide
функция не привязана напрямую к TForm2
или ее устройству. Измените TForm2
, чтобы сойти с TSlidableForm
.
Второе предложение The_Fox - это вариант моего первого, но есть еще один вариант. Вместо передачи имени компонента таймера вы можете передать ссылку на сам компонент:
procedure Slide(Form: TForm; Timer: TTimer; Show: Boolean);
Теперь вам не нужно использовать FindComponent
для поиска таймера; Вы предоставили прямую ссылку на это. Имя компонента даже не имеет значения, поэтому разные формы могут использовать разные имена. Вы можете назвать это так:
Slide(Form2, Form2.Timer1, True);
Slide(AnotherForm, AnotherForm.SlideTimer, False);
Как только вы зайдете так далеко, вы сможете выйти за рамки своего первоначального вопроса и понять, что таймеру даже не нужно больше принадлежать форме. Вы можете создать его специально для вызова Slide
, или таймер может полностью принадлежать чему-то другому (например, модулю данных). Но если вы собираетесь создать таймер только для вызова Slide
, то вы можете воспользоваться предложением Дэвида о создании таймера внутри самой подпрограммы и вообще не иметь дело с вызывающим абонентом или формой:
procedure Slide(Form: TForm; Show: Boolean);
var
Timer: TTimer;
begin
Timer := TTimer.Create(nil);
try
Timer.OnTimer := ...;
Timer.Interval := 500;
Timer.Enabled := True;
// Put your normal Slide stuff here
finally
Timer.Free;
end;
end;