如何访问 Sender 参数引用的组件的 属性(触发事件的组件)

How to access a property of the component that the Sender parameter is referencing (the component that fired the event)

我是 delphi 和 pascal 的新手,想知道是否有办法 get/access 发件人在程序中引用的组件的 属性。

更具体地说,我想创建一个程序来更改标签的标题 属性,该标签是 Sender 所引用的组件。 我想象这个过程看起来像:

procedure TForm1.LabelEdit(Sender: TObject);
begin
    Sender.caption := 'Sample Text';
end;

这当然行不通,但是可以做类似或类似的事情吗?

您将 Sender 转换为事件连接的类型。

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Assigned(Sender) then
    (Sender as TButton).Caption := 'Clicked';
end;

如果你在不同类型的控件之间共享事件,你可以先测试看看它是什么类型:

procedure TForm1.ControlClick(Sender: TObject);
begin
  if (Sender is TEdit) then
    TEdit(Sender).Text := 'Clicked'
  else if (Sender is TButton) then
    TButton(Sender).Caption := 'Clicked';
end;
  
end;

尽管您问题中的示例并没有真正意义(它错误地表明 TLabel 有一个 OnEdit 事件),但很有可能使用 Sender参数获取发件人信息object.

创建一个新的 VCL 应用程序并在窗体上拖放一些 TLabel 控件。给他们不同的标题(如 DogCatRabbitHorse 等)。

现在 select 它们都在表单设计器中,然后使用 Object Inspector 为它们创建一个通用的 OnClick 处理程序。您可以将其命名为 LabelClick(在 OnClick 旁边的编辑字段中写入 LabelClick,然后按 Enter)。

这将创建以下空方法:

procedure TForm1.LabelClick(Sender: TObject);
begin

end;

它有一个 Sender 类型的 TObject 参数。现在,根据调用此方法的方式,Sender 可以是任何 TObject(按钮、表单、位图...),或 nil(没有 object)。

但在我们的例子中,我们希望这个方法主要是在标签被点击时被调用,在这些例子中,Sender 将是对应的 TLabel object.

让我们尝试在消息框中显示点击标签的标题!

我们试试

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage(Sender.Caption); // won't compile!
end;

但这甚至无法编译!问题是 TObject 没有 public Caption 成员。但是 TLabel 可以,所以我们可以写成

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage(TLabel(Sender).Caption);
end;

这里我们告诉编译器我们知道Sender将永远是TLabel,我们要求它假设它是。

但是如果以某种方式使用非TLabel Sender调用此方法,这将崩溃或做其他坏事。所以这样做比较安全

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage((Sender as TLabel).Caption);
end;

除了编译器现在将创建在运行时检查 Sender 确实是 TLabel object 的代码外,这也是一样的。否则,代码将引发异常。这比上面的不安全转换可能遇到的内存 corruption/AV 问题要好得多。

可以说更好的是

procedure TForm1.LabelClick(Sender: TObject);
begin
  if Sender is TLabel then
    ShowMessage(TLabel(Sender).Caption);
end;

这也将在运行时测试 Sender 的类型。如果它是一个标签,我们会显示它的标题。否则,我们选择什么都不做。请注意,在此处使用安全的(并且稍微、稍微、更慢)as 转换没有意义。