Recent

Author Topic: [SOLVED] Components override event  (Read 1602 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 951
[SOLVED] Components override event
« on: November 01, 2020, 10:07:46 am »
In the attached simple component I have three buttons, each with it's own OnClick event.

My question is this - How do I execute some code before the respective OnClick event?

Thanks in advance.
« Last Edit: November 01, 2020, 06:22:50 pm by pcurtis »
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

wp

  • Hero Member
  • *****
  • Posts: 11906
Re: Components override event
« Reply #1 on: November 01, 2020, 11:57:19 am »
You can write an internal event handler for the BitBtns where you execute your stuff and then call the user event handler at the end:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyButton = class(TCustomControl)
  3.   private
  4.     FBtnCancel: TBitBtn;
  5.     FOnCancelClick: TNotifyEvent;
  6.     ...
  7.   protected
  8.     procedure InternalCancelClick(Sender: TObject);
  9.     ...
  10.   public
  11.     constructor Create(AOwner: TComponent); override;
  12.     ...
  13.   published
  14.     property OnCancelClick: TNotifyEvent read FOnCancelClick write FOnCancelClick;
  15.    ...
  16.   end;
  17.  
  18. constructor TMyButton.Create(AOwner: TComponent);
  19. begin
  20.   inherited;
  21.   FCancelBtn := TBitBtn.Create(self);
  22.   FCancelBtn.OnClick := @InternalCancelClick;
  23.   ...
  24. end;
  25.  
  26. procedure TMyButton.InternalCancelClick(Sender: TObject);
  27. begin
  28.   //... your stuff here....
  29.   if Assigned(FOnCancelClick) then FOnCancelClick(Self);  // This executes the user handler
  30. end;
 
BTW: If you use the component yourself only then you can do what you want, of course. But if you plan to make the component publicly available you should follow naiming conventions. A class named "TMyButton" is expected by everybody to belong to the TCustomButton class family, but it is not - it inherits from the much more general TCustomControl. A better name would be, in my opinion, TButtonGroup, or better, T<your initials>ButtonGroup because TButtonGroup is very general and there might be a chance that some other library might use this name too.

Moreover, it is convention to use an "On" prefix for events (in my opinion it was a bad idea of Delphi  to name the dataset events without it).

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Components override event
« Reply #2 on: November 01, 2020, 02:22:09 pm »
I can't get it to work.

If OnCancel is assigned then InternalCancelClick does not get called. Source attached.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Sieben

  • Sr. Member
  • ****
  • Posts: 310
Re: Components override event
« Reply #3 on: November 01, 2020, 02:43:50 pm »
This is a different approach to assigning the OnClick events. If you do it directly as suggested in that other thread of yours (btw why didn't you continue that one?) you won't have a place to execute own code in between. You got to drop those Getter/Setter methods. And did you have a look at the suggestion I posted in your former thread?
« Last Edit: November 01, 2020, 03:17:19 pm by Sieben »
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

wp

  • Hero Member
  • *****
  • Posts: 11906
Re: Components override event
« Reply #4 on: November 01, 2020, 03:03:44 pm »
I can't get it to work.

If OnCancel is assigned then InternalCancelClick does not get called. Source attached.
It is working for me, I see the message box. I am attaching my modifined version of your test program which does not require the new component to be installed. BTW, this is the recommended way to work with new components until they are fully complete; if you don't do it this way you probably must recompile the IDE after many changes, and get a risk of crashing the IDE when your new component is defective.

Did you recompile the IDE after you changed the sources?

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Components override event
« Reply #5 on: November 01, 2020, 03:49:59 pm »
Yes, but I only see one message 'lll'.

I wanted to see 'kkk' then 'lll'

@Sieben - Yes, but I should learn to walk before I start to run  :)
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Sieben

  • Sr. Member
  • ****
  • Posts: 310
Re: Components override event
« Reply #6 on: November 01, 2020, 04:46:29 pm »
By assigning the original BitBtn.OnClick to the InternalClick event - like wp posted or as with my former approach - you have a place to add own code, in said InternalClick, which then calls FOnClick. But if you combine this with setting the TBitBtn.OnClick with those Setter/Getter methods you disconnect (or 'override') InternalClick again and InternalClick 'hangs loose'.
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Components override event
« Reply #7 on: November 01, 2020, 05:02:21 pm »
Does that mean it can't be done?
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Sieben

  • Sr. Member
  • ****
  • Posts: 310
Re: Components override event
« Reply #8 on: November 01, 2020, 05:17:02 pm »
No, it just means that you cannot combine those two approaches. Leave out the Setter/Getter methods that connect directly to the BitBtn's OnClick and publish it like this instead (from wp's post):

Code: Pascal  [Select][+][-]
  1.   published
  2.     property OnCancelClick: TNotifyEvent read FOnCancelClick write FOnCancelClick;
  3.    ...
  4.   end;

Or have another look at my approach. But don't mix them up with the Setter/Getter approach.
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

wp

  • Hero Member
  • *****
  • Posts: 11906
Re: Components override event
« Reply #9 on: November 01, 2020, 05:28:29 pm »
You must not use your OnCancelClick setters and getters because they remove the InternalClick handler. Delete SetCancelClick and GetcancelClick and declare the event as

Code: Pascal  [Select][+][-]
  1.     property CancelClick: TNotifyEvent read FOnCancelClick write FOnCancelClick;

The logics is as follows:
- The user clicks on the OnCancel button.
- Since TMyButton had assigned the InternalCancelClick hander to the BitBtn's OnClick, this procedure is executed.
- The InternalCancelClick at first executes your code (ShowMessage ('kkk')), and then calls FOnCancelClick handler provided by the user.

[EDIT]
Too late, Sieben already has explained it...

Sieben

  • Sr. Member
  • ****
  • Posts: 310
Re: Components override event
« Reply #10 on: November 01, 2020, 05:36:41 pm »
Two explanations are always better than one...  :)
Lazarus 2.2.0, FPC 3.2.2, .deb install on Ubuntu Xenial 32 / Gtk2 / Unity7

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Components override event
« Reply #11 on: November 01, 2020, 06:21:51 pm »
Job done. Thanks.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

 

TinyPortal © 2005-2018