Jump to content
plumothy

Sender of TAction.OnHint Event?

Recommended Posts

In the Object Inspector, if you double-click the OnHint event of a TAction then you get a procedure like this:

procedure TForm1.Action1Hint(var HintStr: string; var CanShow: Boolean);

There is no Sender parameter (like most other events have) so how can I tell which TAction made the call if several TActions share this event?

Share this post


Link to post
On 11/9/2022 at 12:49 AM, plumothy said:

how can I tell which TAction made the call if several TActions share this event? 

Unfortunately, you can't, at least not from the event itself, anyway.  You will have to instead use a different event handler for each action, making them call a common method if they need to share code, eg:

procedure TForm1.Action1Hint(var HintStr: string; var CanShow: Boolean);
begin
  DoActionHint(Action1, HintStr, CanShow);
end;

procedure TForm1.Action2Hint(var HintStr: string; var CanShow: Boolean);
begin
  DoActionHint(Action2, HintStr, CanShow);
end;

procedure TForm1.DoActionHint(Sender: TObject; var HintStr: string; var CanShow: Boolean);
begin
  ...
end;

.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

Thanks Remy - I suspected as much. I wonder why they did it that way? 

Just about every other event I have ever used has a Sender parameter.

 

I actually want to use OnHint for my Dataset Actions so I can customise the Hints depending on which dataset the Action is working on. Then the Hint can be more meaningful - eg "Delete order item" rather than a generic "Delete record".

Your suggestion will work of course, but I might investigate creating my own descendant Dataset Action.

Share this post


Link to post

There is another possibility.  If you don't mind assigning the OnHint events in code at runtime (or at least looping through the actions at runtime to update their OnHint handlers that are assigned at design-time), then you can use the TMethod record to alter the event handler's Self pointer to point at each TAction object instead of the TForm object.  Then you can just type-cast the Self pointer inside the handler.  For example:

procedure TForm1.FormCreate(Sender: TObject);
var
  Evt: THintEvent;
begin
  ...

  Evt := Action1.OnHint;
  // or:
  Evt := @ActionHint;

  TMethod(Evt).Data := Action1; // instead of Form1
  Action1.OnHint := Evt;

  ...
  // repeat for all TAction objects that share ActionHint()...
end;

procedure TForm1.ActionHint(var HintStr: string; var CanShow: Boolean);
begin
  // use TAction(Self) as needed...
end;

 

  • Like 1

Share this post


Link to post
21 hours ago, plumothy said:

That looks interesting

When, in a few years, you or someone else comes across that code, "interesting" will not be the word used to describe it.

  • Haha 1

Share this post


Link to post

It's a hack. Go for the pragmatic solution instead; It's easier to maintain.

 

For something as simple as this it's simply not worth it to use an obscure hack that requires a 20 line comment explaining to your future self what the hell is going on and why it was necessary.

Share this post


Link to post

Anders,

 

Thanks for clarifying.

 

Yes you’re right, it’s a hack - but that is exactly what makes it interesting to me. :classic_smile: 

(Although I think a single line of comments would be enough to explain it - “hack to get at sending Action in OnHint event”.)

 

I really enjoy discovering how things work and what is “under the hood” (whether it’s how to build a Delphi application or how to build a house).

 

I now have 3 possible answers to my original question and I will try them all (not just the hack) and then decide which to deploy in my project.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×