如果您要传递给函数的每个表单都有一个名为“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;
不过,这是一个相当弱的编程接口。如果你不小心忽略了在表单上放置一个计时器,或者你给了它错误的名字,或者你给了它一个不同的可见性,你直到运行时才发现你的错误(当断言失败)。即使表单确实符合要求的界面,也不能保证它是故意的。可能有很多表单已经发布了名为Timer1 的TTimer 字段,但它们并不都适用于这个Slide 函数。他们可能已经将他们的计时器用于其他目的,因此对他们调用 Slide 会破坏程序的其他部分,可能会以难以调试的方式。
如果您给计时器起一个更具描述性的名称,例如SlideTimer,这将是一个稍微强大的界面。 Timer1 只是说这是您在该表单上创建的第一个 TTimer,一旦您离开表单设计器,这将不再是一个有意义的名称。您不需要使用 IDE 的命名选项。
另一个更好的选择是让所有可滑动表单都有一个公共基类,并将计时器放在该基类中。然后,更改Slide 中的参数类型以采用该表单类,而不仅仅是TForm。
type
TSlidableForm = class(TForm)
Timer1: TTimer;
end;
procedure Slide(Form: TSlidableForm; Show: Boolean);
您似乎担心必须在 Slide 单元中包含对 Form2 单元的引用,这通常是一个很好的考虑。你不希望你的代码耦合得太紧,因为这个Slide 函数应该能够在一个项目中使用不止一种形式。但是如果它太松,那么你就会遇到我上面描述的问题。这个TSlidableForm 类是一种妥协;您的 Slide 函数未直接绑定到 TForm2 或其单元。将TForm2 更改为TSlidableForm 的后代。
The_Fox's second suggestion 是我第一个的变体,但还有另一个变体。您可以传递对组件本身的引用,而不是传递计时器组件的名称:
procedure Slide(Form: TForm; Timer: TTimer; Show: Boolean);
现在您不需要使用FindComponent 来搜索要使用的计时器;您提供了对它的直接引用。组件的名称甚至无关紧要,因此不同的表单可以使用不同的名称。你可以这样称呼它:
Slide(Form2, Form2.Timer1, True);
Slide(AnotherForm, AnotherForm.SlideTimer, False);
一旦您走到这一步,您可能会超越最初的问题,并意识到计时器甚至不再需要属于表单。您可以专门为调用Slide 创建它,或者计时器可以完全属于其他东西(如数据模块)。但是,如果您要为 Slide 调用创建计时器,那么您可以使用 David 的建议,即在例程本身中创建计时器,而根本不需要调用者或表单处理它:
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;