2

因此,当您双击一个按钮并自动完成按钮单击过程时,我很好奇编译器如何知道该函数链接到哪个按钮。例如它会使 TForm1.Button1Click(Sender: TObject);

那么编译器如何知道链接的按钮呢?它是否只是解析过程名称以查看它是什么按钮?

4

2 回答 2

10

您可以将方法命名为任何名称,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 参数包含对触发事件的对象的引用。

于 2013-01-11T19:26:58.423 回答
4

编译器不参与其中。IDE 正在处理所有事情。

当您在设计时双击控件时,表单设计器会知道单击的是哪个控件,因为它是内存中的活动对象。

表单设计器使用控件的 RTTI 和注册TComponentEditor实现(如果未注册用户定义的实现,VCL 提供默认实现)来确定该类类型的哪个事件是默认事件(在 的情况下TButton,即OnClick事件) ,然后使用 RTTI 检查该事件是否已经分配了处理程序。

如果尚未分配处理程序,则表单设计器使用 RTTI 读取控件的Name属性和事件的声明名称,将它们连接在一起(删除On事件名称的部分),并在源代码中查找该名称的过程的控件Owner。如果未找到该过程,则在那时创建它。

一旦表单设计器找到该过程,它就会使用 RTTI 来验证该过程是否与事件的签名匹配,然后如果需要,将该过程分配为新的事件处理程序,然后最终跳转到代码编辑器中的过程实现。

如果您在对象检查器中单击控件的事件并重命名处理程序,源代码中的相应过程将被重命名以匹配新名称,并且任何其他事件,即使是在其他组件中,链接到同一过程也会更新通过他们的 RTTI 来匹配新名称。

编译项目时,IDE 首先利用 RTTI 和注册的组件流式处理例程来创建包含所有各种组件属性/事件值的 .DFM 文件。然后它调用编译器,编译器将 .DFM 文件中的源代码和链接作为二进制资源编译到最终的可执行文件中。

在运行时,RTL 解析 DFM 资源,使用 RTTI 和注册的自定义组件流式处理例程,以定位各种组件并根据需要连接它们的属性/事件值。

于 2013-01-11T20:27:57.280 回答