Reputation: 2619
I wonder why, but I can not simply debug my simple program. Loaded method is ignored, it is never executed. No idea why. Look:
TGridObj = class (TComponent)
private
FPen1:TPen;
FBrush1:TBrush;
FChange:TNotifyEvent;
protected
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnChange:TNotifyEvent read FChange write FChange;
property Pen1:TPen read FPen1 write FPen1;
property Brush1:TBrush read FBrush1 write FBrush1;
end;
. . .
constructor TGridObj.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPen1:=TPen.Create;
FPen1.OnChange:=FChange;
FBrush1:=TBrush.Create;
FBrush1.OnChange:=FChange;
end;
destructor TGridObj.destroy;
begin
FPen1.Free;
FBrush1.Free;
inherited;
end;
procedure TGridObj.Loaded();
begin
inherited Loaded;
ShowMessage(''); // this is never executed;
FPen1.OnChange:=FChange;
FBrush1.OnChange:=FChange;
end;
. .
procedure TForm1.FormCreate(Sender: TObject);
begin
Grid:=TGridObj.Create(nil);
Grid.OnChange:=ev1.OnChange;
Form1.InsertComponent(Grid);
end;
Thanx
Upvotes: 2
Views: 1721
Reputation: 36664
OnLoaded will only be executed if the component is loaded from a form resource (dfm file).
If the component is created at run time in code only, it will not be executed.
Update:
I recommend to design components so that they can be created and configured at run time too - which means I avoid overriding OnLoaded. The advantage is that no package installation / component registration is needed.
Upvotes: 1
Reputation: 613302
Loaded
is only called when the component's properties are streamed from the form file. Since you are creating it at runtime, Loaded
does not get called. This is by design.
Your code needs some work anyway to allow for the OnChange
event to be modified at runtime and have that change filter down to the pen and brush. I'd do it like this:
TGridObj = class (TComponent)
private
FPen1: TPen;
FBrush1: TBrush;
FChange: TNotifyEvent;
procedure DoChange(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnChange: TNotifyEvent read FChange write FChange;
property Pen1: TPen read FPen1;
property Brush1: TBrush read FBrush1;
end;
constructor TGridObj.Create(AOwner: TComponent);
begin
inherited;
FPen1 := TPen.Create;
FPen1.OnChange := DoChange;
FBrush1 := TBrush.Create;
FBrush1.OnChange := DoChange;
end;
destructor TGridObj.Destroy;
begin
FBrush1.Free;
FPen1.Free;
inherited;
end;
procedure TGridObj.DoChange(Sender: TObject);
begin
if Assigned(FChange) then
FChange(Sender);
end;
Now there's no need for Loaded
or anything like that. Because you wait until the OnChange
events of the pen and brush actually fire before accessing FChange
.
By the way, in your code it's a mistake to add property setters for Pen1
and Brush1
that modify the underlying fields. That leads to leaks and all sorts of mess. Also, be warned that exposing the pen and brush as public properties allows clients of TGridObj
to change the OnChange
event. And that subverts TGridObj.OnChange
.
Upvotes: 8