Firemonkey:如何定义包含另一个组件的组件?

时间:2016-08-16 21:53:47

标签: delphi firemonkey

在Delphi下,我想创建一个新的firemonkey控件,它将包含另一个firemonkey控件。这不是一个真正的问题,因为我可以这样做:

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  FBtn := Trectangle.create(self);
  FBtn.parent := self;
  FBtn.stored := false;
end;

但是现在我想允许最终用户修改 Object Inspector 中FBtn的属性!我不知道该怎么办:(

如果我删除FBtn.stored:= False,那么我将在结构资源管理器中有一些名称为<组件[7]>每当我将表单视为文本并返回查看为表单时,结构资源管理器中将出现一个新组件:(

2 个答案:

答案 0 :(得分:4)

您要在Objct Inspector中公开的任何内容都必须在published属性中声明,例如:

type
  TMyComponent = class(TComponent)
  private
    FBtn: TRectangle;
    procedure SetBtn(Value: TRectangle);
  published
    property Btn: TRectangle read FBtn write SetBtn;
  end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  FBtn := TRectangle.create(Self);
  FBtn.Parent := Self;
  FBtn.Stored := False;
  FBtn.SetSubComponent(True);
end;

procedure TMyComponent.SetBtn(Value: TRectangle);
begin
  FBtn.Assign(Value);
end;

答案 1 :(得分:3)

虽然雷米的答案在技术上会起作用,但我认为这不是合适的方法。这是因为当您将任何TComponent后代发布为属性时,这假设您将在外部创建外部控件,然后在对象检查器中对其进行分配。当然,您不希望允许这种情况发生,因为此控件是在内部创建的。您也可能只希望允许用户更改某些属性,而不是所有属性。

相反,我建议使用TPersistent,它只公开您实际想要提供访问权限的控件的那些属性。

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.