Recent

Author Topic: [workaround found] How to get the sender within a frame?  (Read 1823 times)

Nicole

  • Hero Member
  • *****
  • Posts: 1324
[workaround found] How to get the sender within a frame?
« on: July 02, 2025, 10:04:02 am »
There is a method, which I shifted into a frame:
Code: Pascal  [Select][+][-]
  1. // ruft die Berichterstellung und übergibt damit Modus Tag
  2. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  3. begin
  4.    Berichte_erstellen(self);
  5. end;

Bericht = report in English
The problem: "self" does not point at the calling Speedbutton any more, but on the frame, which holds it.

The thing generates different reports dependent to the button, which calls it.
It would be easy to give a parameter alike 'daily report' or so. Unfortunately the click event does now allow to pass parameters other than sender. Or does it?

How to solve it?
Yes, I can write a calling rountirne, but this becomes more and more ugly.
Is there a smart solution?

What I need:
A information of which button a certain report is asked for.
« Last Edit: July 02, 2025, 11:11:21 am by Nicole »

Fibonacci

  • Hero Member
  • *****
  • Posts: 1000
  • Behold, I bring salvation - FPC Unleashed
Re: How to get the sender within a frame?
« Reply #1 on: July 02, 2025, 10:10:18 am »
Am I missing something? Sender is the button, Self is the frame containing it.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

rvk

  • Hero Member
  • *****
  • Posts: 7045
Re: How to get the sender within a frame?
« Reply #2 on: July 02, 2025, 10:12:31 am »
Berichte_erstellen isn't an event so you can change it to receive multiple parameters.

So:
Code: Pascal  [Select][+][-]
  1. // ruft die Berichterstellung und übergibt damit Modus Tag
  2. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  3. begin
  4.    Berichte_erstellen(self, Sender);
  5. end;

In Berichte_erstellen you can examine the Sender and act accordingly.

Nicole

  • Hero Member
  • *****
  • Posts: 1324
Re: How to get the sender within a frame?
« Reply #3 on: July 02, 2025, 10:15:41 am »
I read "wrong number of parameters" and if I use a dot instead of a comma "does not have such a member".

rvk

  • Hero Member
  • *****
  • Posts: 7045
Re: How to get the sender within a frame?
« Reply #4 on: July 02, 2025, 10:18:22 am »
I read "wrong number of parameters" and if I use a dot instead of a comma "does not have such a member".
I said you needed to change the definition of the procedure Berichte_erstellen. Did you do that???
Berichte_erstellen doesn't seem to be a click event so you could change it.

(if it is a event then you need to show a lot more code)

So:
Code: Pascal  [Select][+][-]
  1. procedure Berichte_erstellen(Sender: TObject; ButtonPressed: TObject);

Thaddy

  • Hero Member
  • *****
  • Posts: 19268
  • Glad to be alive.
Re: How to get the sender within a frame?
« Reply #5 on: July 02, 2025, 10:38:29 am »
Isn't it simply:
Code: Pascal  [Select][+][-]
  1. // ruft die Berichterstellung und übergibt damit Modus Tag
  2. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  3. begin
  4.    Berichte_erstellen(sender);
  5. end;
objects are fine constructs. You can even initialize them with constructors.

Nicole

  • Hero Member
  • *****
  • Posts: 1324
Re: How to get the sender within a frame?
« Reply #6 on: July 02, 2025, 10:43:52 am »
@Thaddy, thank you for the solution, but this does not work, I tried before.
The sender is "TSpeedButton", but not the specific speed button.

In the meanwhile, I change it to a combination of all and special rvk's inspirations.
If I must change the function, I can change sender to string as well.

Code: Pascal  [Select][+][-]
  1. // ruft die Berichterstellung und übergibt damit Modus Tag
  2. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  3. begin
  4.    Berichte_erstellen('TagesberichtErstellen');
  5. end;

works.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12429
  • Debugger - SynEdit - and more
    • wiki
Re: How to get the sender within a frame?
« Reply #7 on: July 02, 2025, 10:49:24 am »
"Self" should never have been the speedbutton. (Unless you had subclassed TMySpeedbutton = class(TSpeedButton) )

"Self" most likely (almost certain) was the TForm.

"Sender" should be the clicked speedbutton. If not, then you must have something very unexpected somewhere else.

Nicole

  • Hero Member
  • *****
  • Posts: 1324
Re: How to get the sender within a frame?
« Reply #8 on: July 02, 2025, 11:10:58 am »
oh yes, this had worked for years.
After the re-shaping of panels and frames, I clicked the usual button and - nothing happened any more.

This "Sender" always has been mysteriously to me.
It does not behave in the usual way parameters do. And just deleting it brings troubles sometimes.
I bet it comes from the stone-age of programming.

rvk

  • Hero Member
  • *****
  • Posts: 7045
Re: How to get the sender within a frame?
« Reply #9 on: July 02, 2025, 11:19:07 am »
It does not behave in the usual way parameters do.
Sure it does. It's just that it you want to know who called the event and want to use it's parameters you need to cast it to the correct class.

And just deleting it brings troubles sometimes.
Why would you delete it? It's part of the defined procedures in event.
It's a parameter so you know who called the event.
You can delete is but then you also need to change a lot more from where it's called, usually a doclick in the inherited class which you then need to override. But it's not advised (even if you don't use the sender in your event handler).

I bet it comes from the stone-age of programming.
Nope, you just need to know why it's passed and how to use it.
I guess you skipped those parts of all the beginner guides you needed to read  ;)

egsuh

  • Hero Member
  • *****
  • Posts: 1800
Re: [workaround found] How to get the sender within a frame?
« Reply #10 on: July 02, 2025, 11:25:04 am »
Sender is TObject. So, if you want to do anything meaningful, you have to type case it.

For example,

Code: Pascal  [Select][+][-]
  1. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  2. begin
  3.     ShowMessage((Sender as TSpeedButton).caption);
  4.  
  5.      // or you may write as follows if you are reading caption, as property Caption is available from TControl in the inheritance tree.  
  6.  
  7.     ShowMessage((Sender as TControl).caption);
  8.  
  9.     Berichte_erstellen(Sender);
  10. end;

So if the Sender of Berichte_erstellen is always TSpeedButten, then you can define and call as :

Code: Pascal  [Select][+][-]
  1. procedure  Berichte_erstellen(SpeedButton:TSpeedButton);
  2. begin
  3.      with SpeedButton do begin
  4.          // do Something;
  5.       end;
  6. end;
  7.  
  8. // And calll
  9.  
  10. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  11. begin
  12.     Berichte_erstellen(Sender as TSpeedButton);
  13. end;

OR,

Code: Pascal  [Select][+][-]
  1. procedure  Berichte_erstellen(SpeedButton:TObject);
  2. begin
  3.      with SpeedButton as TSpeedButton do begin
  4.             // do Something
  5.      end;
  6. end;
  7.  
  8. // And calll
  9.  
  10. procedure TFrame_BerichteF.SpeedButton_TagesberichtErstellenClick(Sender: TObject);
  11. begin
  12.     Berichte_erstellen(Sender);
  13. end;
« Last Edit: July 02, 2025, 11:51:39 am by egsuh »

Thaddy

  • Hero Member
  • *****
  • Posts: 19268
  • Glad to be alive.
Re: [workaround found] How to get the sender within a frame?
« Reply #11 on: July 02, 2025, 11:44:44 am »
You can put that in concrete by also using
Code: Pascal  [Select][+][-]
  1. if sender is TSpeedButton then

I have to test that for actions, though: I always program through actions when writing a user interface and that does not work: Sender is TAction, not TSpeedButton.
You need to be aware of that.
« Last Edit: July 02, 2025, 11:55:42 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

creaothceann

  • Sr. Member
  • ****
  • Posts: 375
Re: [workaround found] How to get the sender within a frame?
« Reply #12 on: July 02, 2025, 12:15:01 pm »
Code: Pascal  [Select][+][-]
  1. if sender is TSpeedButton then
Would silently fail if some other component is calling that function by mistake.

egsuh

  • Hero Member
  • *****
  • Posts: 1800
Re: [workaround found] How to get the sender within a frame?
« Reply #13 on: July 02, 2025, 12:23:03 pm »
Quote
I always program through actions when writing a user interface and that does not work: Sender is TAction, not TSpeedButton.

Hmmm... I think I had experienced the same issue, and defined at ButtonClick, etc. instead of Action. I needed to recognize which button called the event handler.

Thaddy

  • Hero Member
  • *****
  • Posts: 19268
  • Glad to be alive.
Re: [workaround found] How to get the sender within a frame?
« Reply #14 on: July 02, 2025, 12:24:36 pm »
The name....
With actions that is basically irrelevant, otherwise:
Code: Pascal  [Select][+][-]
  1.  TSpeedButton(sender).name
« Last Edit: July 02, 2025, 12:32:08 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018