Under Delphi, i want to create a new firemonkey control that will contain another firemonkey control. This is not really a problem because i can do like this :
constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited;
FBtn := Trectangle.create(self);
FBtn.parent := self;
FBtn.stored := false;
end;
But now i would like to permit end-user to modifie the properties of the FBtn in the Object Inspector also! i don't know how to do :(
if i remove the FBtn.stored := False then i will have in the structure explorer some component with name like < Components[7] > and every time i will do view the form as text and back to view as form then a new component will appear in the structure explorer :(
While Remy's answer technically will work, I wouldn't consider it the appropriate approach. This is because when you publish any TComponent
descendant as a property, this presumes that you would create such a control externally and then assign it within the object inspector. Surely you don't want to allow this to happen, since this control is created internally. You also presumably only want to allow the user to change certain properties, not all of them.
Instead, I would recommend using a TPersistent
which exposes only those properties of the control you actually want to provide access to.
unit MyComponentUnit;
interface
uses
System.Classes, System.SysUtils,
Fmx.Controls, FMX.StdCtrls, FMX.Objects;
type
TMyComponentButton = class(TPersistent)
private
FBtn: TRectangle;
function GetXRadius: Single;
function GetYRadius: Single;
procedure SetXRadius(const Value: Single);
procedure SetYRadius(const Value: Single);
//And any other property getters/setters you wish to wrap
public
constructor Create(ABtn: TRectangle);
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
published
property XRadius: Single read GetXRadius write SetXRadius;
property YRadius: Single read GetYRadius write SetYRadius;
//And any other properties you wish to wrap
end;
TMyComponent = class(TControl)
private
FBtn: TRectangle;
FMyComponentButton: TMyComponentButton;
procedure SetMyComponentButton(const Value: TMyComponentButton);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property MyComponentButton: TMyComponentButton
read FMyComponentButton write SetMyComponentButton;
end;
implementation
{ TMyComponentButton }
constructor TMyComponentButton.Create(ABtn: TRectangle);
begin
inherited Create;
FBtn:= ABtn;
end;
destructor TMyComponentButton.Destroy;
begin
inherited;
end;
procedure TMyComponentButton.Assign(Source: TPersistent);
begin
if Source is TMyComponentButton then begin
XRadius:= (Source as TMyComponentButton).XRadius;
YRadius:= (Source as TMyComponentButton).YRadius;
//And everything else you need to assign
end else
inherited;
end;
function TMyComponentButton.GetXRadius: Single;
begin
Result:= FBtn.XRadius;
end;
function TMyComponentButton.GetYRadius: Single;
begin
Result:= FBtn.YRadius;
end;
procedure TMyComponentButton.SetXRadius(const Value: Single);
begin
FBtn.XRadius:= Value;
end;
procedure TMyComponentButton.SetYRadius(const Value: Single);
begin
FBtn.YRadius:= Value;
end;
{ TMyComponent }
constructor TMyComponent.Create(AOwner: TComponent);
begin
inherited;
FBtn:= TRectangle.Create(Self);
FBtn.Parent:= Self;
FBtn.Stored:= False;
FMyComponentButton:= TMyComponentButton.Create(FBtn);
end;
destructor TMyComponent.Destroy;
begin
FreeAndNil(FMyComponentButton);
FreeAndNil(FBtn);
inherited;
end;
procedure TMyComponent.SetMyComponentButton(const Value: TMyComponentButton);
begin
FMyComponentButton.Assign(Value);
end;
end.