Recent

Author Topic: Triggering other events within OnCreate handler  (Read 888 times)

simsee

  • Full Member
  • ***
  • Posts: 240
Triggering other events within OnCreate handler
« on: March 08, 2024, 04:25:44 pm »
Consider the following program:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Shape1: TShape;
  16.     procedure FormCreate(Sender: TObject);
  17.     procedure Shape1ChangeBounds(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.  
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32.  
  33. procedure TForm1.FormCreate(Sender: TObject);
  34. begin
  35.   Shape1.Left:=Shape1.Left+100;
  36. end;
  37.  
  38. procedure TForm1.Shape1ChangeBounds(Sender: TObject);
  39. begin
  40.   Caption:='ok';
  41. end;
  42.  
  43. end.

Changing Shape1.Left within OnCreate does not trigger Shape1ChangeBounds.

Differently, changing Shape1.Left within OnShow triggers Shape1ChangeBounds, as in the following program:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Shape1: TShape;
  16.     procedure FormShow(Sender: TObject);
  17.     procedure Shape1ChangeBounds(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.  
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32.  
  33. procedure TForm1.FormShow(Sender: TObject);
  34. begin
  35.   Shape1.Left:=Shape1.Left+100;
  36. end;
  37.  
  38. procedure TForm1.Shape1ChangeBounds(Sender: TObject);
  39. begin
  40.   Caption:='ok';
  41. end;
  42.  
  43. end.

Why this different behavior?

I ask because I would need to intercept all changes to the Left and Top properties of a component I'm writing, even those that happen within OnCreate events of the parent control. Left and Top have getters and setters that are not virtual and this prevents me from redefining them in descending control.

Any suggestions? Thanks!

ASerge

  • Hero Member
  • *****
  • Posts: 2510
Re: Triggering other events within OnCreate handler
« Reply #1 on: March 08, 2024, 07:59:27 pm »
Why this different behavior?
Answer in procedure TControl.CheckOnChangeBounds (see my comment):
Code: Pascal  [Select][+][-]
  1. begin
  2. ...
  3.   if (not CompareRect(@FLastDoChangeBounds,@CurBounds)) or (ComparePoints(CurClientSize,FLastDoChangeClientSize)<>0) then begin
  4.     if FormIsUpdating then begin // <- This True in OnCreate and False in OnShow
  5.       Include(FControlFlags,cfOnChangeBoundsNeeded);
  6.       exit; // Exit when OnCreate
  7.     end;
  8.     FLastDoChangeBounds:=CurBounds;
  9.     FLastDoChangeClientSize:=CurClientSize;
  10.     DoOnChangeBounds; // So, not called when OnCreate
  11.   end;
  12.  


simsee

  • Full Member
  • ***
  • Posts: 240
Re: Triggering other events within OnCreate handler
« Reply #2 on: March 08, 2024, 09:58:10 pm »
Thanks ASerge. The code snippet makes it clear the reason for the different behavior.

Is there a way to ensure that all changes to Left,Top,Width and Height in a TControl derived component are also "intercepted" in the parent/owner's OnCreate event handlers?

simone

  • Hero Member
  • *****
  • Posts: 706
Re: Triggering other events within OnCreate handler
« Reply #3 on: March 08, 2024, 11:55:29 pm »
I would override TControl.Resize TControl.ChangeBounds method, which is virtual, as in the following code:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TShape }
  13.  
  14.   TShape=class(ExtCtrls.TShape)
  15.   protected
  16.     procedure ChangeBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer; KeepBase: Boolean); override;
  17.   end;
  18.  
  19.   { TForm1 }
  20.  
  21.   TForm1 = class(TForm)
  22.     Shape1: TShape;
  23.     procedure FormCreate(Sender: TObject);
  24.   private
  25.  
  26.   public
  27.  
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34.  
  35. {$R *.lfm}
  36.  
  37. { TShape }
  38.  
  39. procedure TShape.ChangeBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer; KeepBase: Boolean);
  40. begin
  41.   inherited;
  42.   writeln('ok');
  43. end;
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.FormCreate(Sender: TObject);
  48. begin
  49.   Shape1.Left:=Shape1.Left+100;
  50. end;
  51.  
  52. end.
« Last Edit: March 09, 2024, 11:31:04 am by simone »
Microsoft Windows 10/11 64 bit - Lazarus 4.8/4.6 FPC 3.2.2 x86_64-win64-win32/win64

 

TinyPortal © 2005-2018