Delphi 2009:传递组件名称 onclick 事件然后设置属性

Posted

技术标签:

【中文标题】Delphi 2009:传递组件名称 onclick 事件然后设置属性【英文标题】:Delphi 2009: Pass component name onclick event then set property 【发布时间】:2010-11-23 05:13:53 【问题描述】:

我有一个 TSpeedButton 类型的自定义组件,它定义了两个额外的属性:

CommentHeading: string;
CommentText: string;

我在设计时设置了 CommentHeading。

按下速度按钮时,会显示一个备忘录,其下方有一个按钮,用于保存其内容。处理这个的过程:

procedure CustomSpeedButton1Click(Sender: TObject);
begin
   Receiver := CustomSpeedButton1.Name; // possibly used to save the memo text back to this speedbuttons property after comments are submitted
   ViewComments(CustomSpeedButton1.CommentTitle,CustomSpeedButton1.CommentText);
end;

以及 ViewComments 过程本身:

procedure ViewComments(comment_caption:string; comment_text:string);
begin
  label15.Hide; // label showing editing in progress, hidden until user begins typing
  Button1.Enabled     := false; // the button for saving the memo text, hidden until user begins typing
  CommentsBox.Visible := true; // pop up the comment box at the bottom of the form
  CommentsBox.Caption := 'Comments: ' + comment_caption;
  CommentsMemo.Text   := comment_text; // if there are existing comments assign them to memo
end;

备忘录的内容需要赋值给自定义 SpeedButton 的 CommentText 属性。

我最初的想法是,我可以在按下自定义 SpeedButton 时将组件名称传递给变量,然后在按下备忘录上的保存按钮时检索该名称,并使用它将备忘录文本分配给 speedbuttons评论文本属性。但后来我意识到,要做到这一点,我必须使用某种 case..of 语句来检查每个可能的 speedbutton 名称,然后将 memo 值分配给它的属性,这看起来非常乏味。

有没有一种更简单的方法可以将备忘录文本分配给打开备忘录的快速按钮?

【问题讨论】:

【参考方案1】:

最终,您要问的是如何告诉 ViewComments 函数它正在使用哪个按钮的属性。

您了解Sender 参数在OnClick 事件中的作用吗?它告诉事件处理程序正在处理哪个对象的事件。它正是您希望为ViewComments 功能带来的角色。

这就是梅森在他的回答中所要表达的。与其传递所有属性值,不如传递对象本身

procedure ViewComments(CommentButton: TCustomSpeedButton);

然后从所有按钮的事件处理程序中调用它:

procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
begin
  ViewComments(CustomSpeedButton1);
end;

procedure TForm1.CustomSpeedButton2Click(Sender: TObject);
begin
  ViewComments(CustomSpeedButton2);
end;

没有字符串,没有 case 语句,没有查找。

这应该可以回答您的问题,但您可以做得更好。还记得我之前说过的关于Sender 参数的内容吗?当有人点击第一个按钮时,OnClick 处理程序的Sender 参数将成为按钮,因此我们可以像这样重写第一个事件处理程序:

procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
begin
  ViewComments(Sender as TCustomSpeedButton);
end;

您可以像这样重写第二个事件处理程序:

procedure TForm1.CustomSpeedButton2Click(Sender: TObject);
begin
  ViewComments(Sender as TCustomSpeedButton);
end;

嗯。他们是一样的。拥有两个相同的功能是浪费,所以去掉一个并重命名另一个,这样听起来就不是特定于按钮的:

procedure TForm1.CommentButtonClick(Sender: TObject);
begin
  ViewComments(Sender as TCustomSpeedButton);
end;

然后设置 both 按钮的OnClick 属性以引用该事件处理程序。您不能仅通过双击 Object Inspector 中的属性来做到这一点。您需要自己输入名称,从下拉列表中选择它,或者在运行时分配事件属性:

CustomSpeedButton1.OnClick := CommentButtonClick;
CustomSpeedButton2.OnClick := CommentButtonClick;

我还想鼓励您为控件使用更有意义的名称。 Label15 特别令人震惊。你怎么记得第十五标签是表示正在编辑的标签?例如,称之为EditInProgressLabel

【讨论】:

Rob,你是德尔福神!!!这正是我正在寻找的信息!梅森,如果你正在阅读这篇文章,我很抱歉第一次没有理解你的意思,但我在 2002 年左右离开 Delphi 后的一个月内才再次拿起德尔福,所以我仍在努力记住所有概念、技巧等 Rob,感谢您对标签命名的说明 - 该特定标签只是一个快速放置的“黑客”,以向用户显示他们实际上处于编辑模式。在发布编译之前,我总是调整标签等以反映它们的实际使用情况。【参考方案2】:

既然您已经传递了额外的变量,为什么不直接传递 SpeedButton 本身呢?这样您就不需要查找参考了。

【讨论】:

这仍然引出了一个问题,即如何告诉“保存”按钮哪个 SpeedButton 打开了备忘录,而不必使用 case..of 语句?我试图避免任何形式的大量查找,因为表单上会有数百个这样的评论按钮。 我不太明白问题出在哪里。将一个 SpeedButton 引用与每个评论相关联,当您打开评论时,为其提供对打开它的按钮的引用。然后,当您保存时,您拥有的任何参考都是将其分配回的按钮。无需查找。【参考方案3】:

对您的代码稍作改动即可解决问题:

procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
var
  btn: TCustomSpeedButton;
begin
   btn := Sender as TCustomSpeedButton;
   Receiver := btn.Name; 
   ViewComments(btn.CommentTitle, btn.CommentText);
end;

编辑评论后:

procedure TForm1.StoreComments(comment: string);
var
  btn: TCustomSpeedButton;
begin
  btn := FindComponent(Receiver) as TCustomSpeedButton;
  btn.CommentText := comment;
end;

您还可以记住按钮本身,而不仅仅是它的名称。

【讨论】:

只是想补充一点,这实际上是解决方案的第二部分!使用上面 Rob 的代码修剪多个 onclick 事件是问题的一部分,但保存 cmets 是问题的另一半,稍微摆弄一下这段代码就可以了!谢谢 Uwe!

以上是关于Delphi 2009:传递组件名称 onclick 事件然后设置属性的主要内容,如果未能解决你的问题,请参考以下文章

Delphi 2009 - 在自定义 Delphi 组件中设置默认属性值

如何在 Delphi 2010 ( UniSynEdit Package ) 中安装 Delphi 2009 组件包?

Delphi 2009 - 检测是不是安装了组件

如何在 Delphi 2009 中为我的组件设置 Tool Palette 组件图标?

如何在 Delphi 2009 中对自定义组件进行鼠标平移

在 Delphi 2009 中显示 PDF 文件的最佳方法是啥[关闭]