因此,当您双击一个按钮并自动完成按钮单击过程时,我很好奇编译器如何知道该函数链接到哪个按钮。例如它会使 TForm1.Button1Click(Sender: TObject);
那么编译器如何知道链接的按钮呢?它是否只是解析过程名称以查看它是什么按钮?
因此,当您双击一个按钮并自动完成按钮单击过程时,我很好奇编译器如何知道该函数链接到哪个按钮。例如它会使 TForm1.Button1Click(Sender: TObject);
那么编译器如何知道链接的按钮呢?它是否只是解析过程名称以查看它是什么按钮?
您可以将方法命名为任何名称,Delphi 不会解析或使用方法名称来识别关联的组件或事件。
如果您在设计时执行此操作,则与事件处理程序的事件关联存储在 DFM 文件中,您可以在其中找到如下内容:
object Button1: TButton
Left = 104
Top = 64
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
这OnClick = Button1Click
使您的程序在创建表单时,在运行时将方法(也称为事件处理程序)与对象的事件(一种特殊的属性)相关联。
您还可以在运行时将事件与任何兼容的方法相关联,例如使用以下代码:
type
TForm1 = class(TForm)
Button1: TButton;
private
procedure MyClick(Sender: TObject);
procedure MyOtherClick(Sender: TObject);
....
procedure TForm1.AssociateClickHandler;
begin
Button1.OnClick := MyClick;
end;
procedure TForm1.MyClick(Sender: TObject);
begin
Button1.OnClick := MyOtherClick; //from now, the other method with handle the event.
end;
在设计时,您可以直接在 ObjectInspector 中为事件处理程序编写所需的名称,然后按 Enter 键,Delphi 将为您创建具有该名称的方法。如果您不提供名称,Delphi 会使用组件名称以及不带“On”的事件名称自动生成方法名称。如果该方法已经存在,IDE 只需将事件与该方法相关联。
编写所需的方法名称:
按回车:
您可以将相同的方法关联到同一对象的不同事件,或关联到不同对象的同一事件。
例如,您可以将上面显示的 MyOwnMethodName 与任意数量的按钮的 OnClick 相关联。通常,Sender 参数包含对触发事件的对象的引用。
编译器不参与其中。IDE 正在处理所有事情。
当您在设计时双击控件时,表单设计器会知道单击的是哪个控件,因为它是内存中的活动对象。
表单设计器使用控件的 RTTI 和注册TComponentEditor
实现(如果未注册用户定义的实现,VCL 提供默认实现)来确定该类类型的哪个事件是默认事件(在 的情况下TButton
,即OnClick
事件) ,然后使用 RTTI 检查该事件是否已经分配了处理程序。
如果尚未分配处理程序,则表单设计器使用 RTTI 读取控件的Name
属性和事件的声明名称,将它们连接在一起(删除On
事件名称的部分),并在源代码中查找该名称的过程的控件Owner
。如果未找到该过程,则在那时创建它。
一旦表单设计器找到该过程,它就会使用 RTTI 来验证该过程是否与事件的签名匹配,然后如果需要,将该过程分配为新的事件处理程序,然后最终跳转到代码编辑器中的过程实现。
如果您在对象检查器中单击控件的事件并重命名处理程序,源代码中的相应过程将被重命名以匹配新名称,并且任何其他事件,即使是在其他组件中,链接到同一过程也会更新通过他们的 RTTI 来匹配新名称。
编译项目时,IDE 首先利用 RTTI 和注册的组件流式处理例程来创建包含所有各种组件属性/事件值的 .DFM 文件。然后它调用编译器,编译器将 .DFM 文件中的源代码和链接作为二进制资源编译到最终的可执行文件中。
在运行时,RTL 解析 DFM 资源,使用 RTTI 和注册的自定义组件流式处理例程,以定位各种组件并根据需要连接它们的属性/事件值。