Reputation: 7042
I have a custom component of type TSpeedButton that has two extra properties defined:
CommentHeading: string;
CommentText: string;
I set CommentHeading at design time.
When the speed button is pressed a memo is shown with a button beneath it for saving its contents. The procedure that handles this:
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;
And the ViewComments procedure itself:
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;
The contents of the memo need to be assigned to the CommentText property of the custom SpeedButton.
What I was initially thinking was that I could pass the component name to a variable when the custom SpeedButton gets pressed and then retrieve that name when the save button on the memo is pressed and use it to assign the memo text to the speedbuttons CommentText property. But then I realized that to do this I'd have to use some kind of case..of statement that checked for each possible speedbutton name and then assign the memo value to its properties and this just seems ridiculously tedious.
Is there an easier way to assign the memo text to the speedbutton that opened the memo to begin with?
Upvotes: 1
Views: 3645
Reputation: 163257
Ultimately, you're asking how to tell the ViewComments
function which button's properties it's working with.
Do you understand what the Sender
parameter is doing in the OnClick
event? It's telling the event handler which object's event is being handled. It's serving precisely the role that you're looking to bring to the ViewComments
function.
That's what Mason was getting at in his answer. Rather than pass all the property values, pass the object itself:
procedure ViewComments(CommentButton: TCustomSpeedButton);
Then call it from all your buttons' event handlers:
procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
begin
ViewComments(CustomSpeedButton1);
end;
procedure TForm1.CustomSpeedButton2Click(Sender: TObject);
begin
ViewComments(CustomSpeedButton2);
end;
No strings, no case
statements, no lookups.
That should answer your question, but you can do it even better. Remember what I said before about the Sender
parameter? When someone clicks the first button, the Sender
parameter of that OnClick
handler will be the button, so we can rewrite the first event handler like this:
procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
begin
ViewComments(Sender as TCustomSpeedButton);
end;
And you can rewrite the second event handler like this:
procedure TForm1.CustomSpeedButton2Click(Sender: TObject);
begin
ViewComments(Sender as TCustomSpeedButton);
end;
Hmm. They're the same. Having two identical functions is wasteful, so get rid of one and rename the other so it doesn't sound button-specific:
procedure TForm1.CommentButtonClick(Sender: TObject);
begin
ViewComments(Sender as TCustomSpeedButton);
end;
Then set the OnClick
properties of both buttons to refer to that one event handler. You can't do that just by double-clicking the property in the Object Inspector. You'll need to either type the name yourself, choose it from the drop-down list, or assign the event property at run time:
CustomSpeedButton1.OnClick := CommentButtonClick;
CustomSpeedButton2.OnClick := CommentButtonClick;
I'd also like to encourage you to use more meaningful names for your controls. That Label15
is particularly egregious. How can you remember that the fifteenth label is the one that indicates that editing is in progress? Call it EditInProgressLabel
, for instance.
Upvotes: 2
Reputation: 47704
A small change to your code should do the trick:
procedure TForm1.CustomSpeedButton1Click(Sender: TObject);
var
btn: TCustomSpeedButton;
begin
btn := Sender as TCustomSpeedButton;
Receiver := btn.Name;
ViewComments(btn.CommentTitle, btn.CommentText);
end;
and after editing the comment:
procedure TForm1.StoreComments(comment: string);
var
btn: TCustomSpeedButton;
begin
btn := FindComponent(Receiver) as TCustomSpeedButton;
btn.CommentText := comment;
end;
You can also memorize the button itself instead of just it's name.
Upvotes: 0
Reputation: 84540
Since you're already passing extra variables around, why not just pass the SpeedButton itself? Then you won't need to look up the reference.
Upvotes: 2