When I build this component and place it on a form, all appears fine. However, when I run the program, the control duplicates all of its children. It appears to be calling the initialize components twice, although I cannot see why.
Code from TWinControl Component
unit Payments_Test;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AdvSmoothButton, EBSGrid,
Vcl.StdCtrls, Vcl.ExtCtrls, Data.DB, MemDS, EBS3DataClass,
DBAccess, AdvUtil, Vcl.Grids, AdvObj, BaseGrid, AdvGrid,AdvStyleIF;
type
TEBSPayments_Test = class(TWinControl)
private
{ Private declarations }
fDeletePayment, fNewPayment : TNotifyEvent;
PYLabel33: TLabel;
lblOverPayment: TLabel;
cmdAddPayment: TAdvSmoothButton;
cmdDeletePayment: TAdvSmoothButton;
PYPanel1: TPanel;
PyGrid1: TEBSGrid;
FBackgroundColor, FPanelColor: TColor;
procedure cmdDeletePaymentClick(Sender: TObject);
procedure cmdAddPaymentClick(Sender: TObject);
procedure SetBackgroundColor(const Value: TColor);
procedure SetPanelColor(const Value: TColor);
procedure InitializeComponents;
Protected
procedure SetParent(AParent: TWinControl); override;
Published
property Anchors default [akLeft, akTop];
property Align default alNone;
property AutoSize Default True;
property PanelColor: TColor read FPanelColor write SetPanelColor default clSkyBlue;
property BackgroundColor: TColor read FBackgroundColor write
SetBackgroundColor default clSkyBlue;
property DeletePayment: TNotifyEvent read FDeletePayment write FDeletePayment;
property NewPayment: TNotifyEvent read FNewPayment write FNewPayment;
public
{ Public declarations }
procedure Initialise;
procedure CloseControl;
constructor Create(AOwner: TComponent); override;
Destructor Destroy; Override;
end;
Procedure Register;
implementation
Uses EBS3DataUtils;
procedure TEBSPayments_Test.SetBackgroundColor(const Value: TColor);
begin
if FBackgroundColor <> Value then
begin
FBackgroundColor := Value;
Color := FBackgroundColor;
end;
end;
procedure TEBSPayments_Test.SetPanelColor(const Value: TColor);
begin
if FPanelColor <> Value then
begin
FPanelColor := Value;
Color := FPanelColor;
end;
end;
constructor TEBSPayments_Test.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 428;
Height := 224;
end;
procedure TEBSPayments_Test.InitializeComponents;
begin
PYPanel1 := TPanel.Create(Self);
PYPanel1.Parent := Self;
PYPanel1.Height := 22;
PYPanel1.Align := alTop;
PYPanel1.Caption := '';
PyGrid1 := TEBSGrid.Create(Self);
PYGrid1.Parent := Self;
PYGrid1.AutoSize := False;
PYGrid1.Align := alBottom;
PYGrid1.Height := ClientHeight - PYPanel1.Height;
PYGrid1.FctlGrid.FixedCols := 0;
FBackgroundColor := clSkyBlue;
FPanelColor := clMoneyGreen;
PYPanel1.Color := FPanelColor;
Color := FBackgroundColor;
cmdDeletePayment := TAdvSmoothButton.Create(Self);
cmdDeletePayment.Parent := PYPanel1;
cmdDeletePayment.SetBounds(182,1,54,20);
cmdDeletePayment.UIStyle := tsCustom;
cmdDeletePayment.Caption := 'Delete';
cmdDeletePayment.Color := clBlue;
cmdDeletePayment.Appearance.Font.Color := clWhite;
cmdDeletePayment.Appearance.Rounding := 8;
cmdDeletePayment.Bevel := True;
cmdDeletePayment.BevelColor := clWhite;
cmdAddPayment := TAdvSmoothButton.Create(Self);
cmdAddPayment.Parent := PYPanel1;
cmdAddPayment.SetBounds( 127,1,49,20);
cmdAddPayment.UIStyle := tsCustom;
cmdAddPayment.Caption := 'New';
cmdAddPayment.Color := clBlue;
cmdAddPayment.Appearance.Font.Color := clWhite;
cmdAddPayment.Appearance.Rounding := 8;
cmdAddPayment.Bevel := True;
cmdAddPayment.BevelColor := clWhite;
lblOverPayment := TLabel.Create(Self);
lblOverPayment.Parent := PYPanel1;
lblOverPayment.SetBounds(483,5,116,13);
lblOverPayment.Font.Color := clRed;
lblOverPayment.Font.Style := [fsBold];
PYLabel33 := TLabel.Create(Self);
PYLabel33.Parent := PYPanel1;
PYLabel33.SetBounds(8,6,66,13);
PYLabel33.Font.Color := clGreen;
PYLabel33.Font.Style := [fsBold];
end;
procedure TEBSPayments_Test.SetParent(AParent: TWinControl);
begin
inherited SetParent(AParent);
if Assigned(AParent) then InitializeComponents;
end;
Destructor TEBSPayments_Test.Destroy;
begin
PYLabel33.Free;
lblOverPayment.Free;
cmdAddPayment.Free;
cmdDeletePayment.Free;
PYPanel1.Free;
PyGrid1.Free;
Inherited Destroy;
end;
procedure TEBSPayments_Test.Initialise;
begin
end;
procedure TEBSPayments_Test.CloseControl;
begin
PYGrid1.SaveGridSettings;
end;
procedure TEBSPayments_Test.cmdAddPaymentClick(Sender: TObject);
begin
if Assigned(FNewPayment) then
FNewPayment(Self);
end;
procedure TEBSPayments_Test.cmdDeletePaymentClick(Sender: TObject);
begin
if Assigned(FDeletePayment) then
FDeletePayment(Self);
end;
procedure Register;
begin
RegisterComponents('EBSH', [TEBSPayments_Test]);
end;
end.
Code from the TForm
unit ComponentTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils,
System.Variants, System.Classes,Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,AdvUtil, Vcl.Grids, AdvObj,
BaseGrid, AdvGrid, UniProvider, SQLServerUniProvider,
Vcl.StdCtrls, JvExStdCtrls, JvMemo, Vcl.ExtCtrls,
Notes, ContactPanel, Payments_Test;
type
TfrmCompTest = class(TForm)
Button1: TButton;
EBSPayments_Test1: TEBSPayments_Test;
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmCompTest: TfrmCompTest;
implementation
{$R *.dfm}
end.
I checked the code for multiple calls to initialize components. At one stage it was doing it just by pasting to the form. This was caused by two calls to initialize components Now it only does it at run time. A breakpoint triggers twice but I cant figure where that second call comes from
As your container component is handling the lifetime of its subcomponents, you need to mark those as subcomponents so the streaming system can handle them properly. To do that call SetSubComponent(True)
on each of the subcomponents right after its creation.
For example:
PYPanel1 := TPanel.Create(Self);
PYPanel1.SetSubComponent(True);
PYPanel1.Parent := Self;
PYPanel1.Height := 22;
PYPanel1.Align := alTop;
PYPanel1.Caption := '';