Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.1k views
in Technique[技术] by (71.8m points)

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

I am new to delphi and pascal and was wondering if there was a way to get/access a property of the component that the Sender is referencing within the procedure.

More specifically I would like to make a procedure that changes the caption property of a label, that label being the component that Sender is referencing. I imagine that procedure looking something like:

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

Naturally this wouldn't work but can something like or something similar to this be done?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Although the example in your question doesn't really make sense (it incorrectly suggests that a TLabel has an OnEdit event), it is very much possible to use the Sender parameter to obtain information about the sender object.

Create a new VCL application and drop a number of TLabel controls on the form. Give them different captions (like Dog, Cat, Rabbit, Horse etc.).

Now select them all in the form designer and then use the Object Inspector to create a common OnClick handler for them. You can name it LabelClick (write LabelClick in the edit field next to OnClick and press Enter).

This will create the following empty method:

procedure TForm1.LabelClick(Sender: TObject);
begin

end;

It has a Sender parameter of type TObject. Now, depending on how this method is called, Sender can be any TObject (a button, a form, a bitmap, ...), or nil (no object at all).

But in our case, we expect this method mainly to be called in response to the labels being clicked on, and in these cases, the Sender will be the corresponding TLabel object.

Let's try to display the caption of the clicked label in a message box!

We try

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

But this doesn't even compile! The problem is that TObject has no public Caption member. But TLabel does, so we can write

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

Here we are telling the compiler that we know Sender will always be a TLabel, and we ask it to assume that it is.

But this will crash or do other bad things if somehow this method is called with a non-TLabel Sender. So it is safer to do

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

This does the same, except that the compiler will now create code that checks at runtime that Sender really is a TLabel object. If not, the code will raise an exception. That's much better than the kind of memory corruption/AV issues you may get with the unsafe cast above.

Arguably even better is

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

This will also test the type of Sender at runtime. If it is a label, we display its caption. Otherwise, we choose to do nothing. Notice that there is no point in using a safe (and slightly, slightly, slower) as cast here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...