TPersistent
RTLがプロパティをストリーミングする必要があるかどうかを決定するときは、要件のリストを詳しく見てください。
if (PropInfo^.GetProc <> nil) and
((PropInfo^.SetProc <> nil) or
((PropInfo^.PropType^.Kind = tkClass) and
(TObject(GetOrdProp(Instance, PropInfo)) is TComponent) and
(csSubComponent in TComponent(GetOrdProp(Instance, PropInfo)).ComponentStyle))) then
ChildObj
プロパティは読み取り専用プロパティであるため、PropInfo^.SetProc <> nil
要件を満たしていません。また、派生TComponent
サブコンポーネントではないため、isis TComponent
およびcsSubComponent
要件を満たしていません。そのため、プロパティがDFMから欠落しています。
最も簡単な解決策は、ChildObj
プロパティを読み取り専用ではなく読み取り/書き込みにすることです(必要な場合をTComponent
除いて、この状況では使用しないでください)。
また、オブジェクトTTest
を解放するためのデストラクタがありません。TChildObj
また、適切な方法として、ハンドラーを割り当てることがTChildObj
できるOnChange
イベントを指定して、サブプロパティTTest
への変更に対応できるようにする必要があります。TChildObj
これを試して:
type
TChildObj = class(TPersistent)
private
FVisible : Boolean;
FColor : TColor;
FOnChange : TNotifyEvent;
procedure Changed;
procedure SetVisible(Value : Boolean);
procedure SetColor(Value : TColor);
public
procedure Assign(Source : TPersistent); override;
property OnChange : TNotifyEvent read FOnChange write FOnChange;
published
property Visible : Boolean read FVisible write SetVisible;
property Color : TColor read FColor write SetColor;
end;
TTest = class(TComponent)
private
FChildObj : TChildObj;
FOne : integer;
procedure ChildObjChanged(Sender : TObject);
procedure SetChildObj(Value : TChildObj);
protected
procedure Loaded; override;
public
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
published
property One : integer read FOne write FOne;
property ChildObj : TChildObj read FChildObj write SetChildObj;
end;
。
procedure TChildObj.Assign(Source: TPersistent);
begin
if Source is TChildObj then
begin
FVisible := TChildObj(Source).Visible;
FColor := TChildObj(Source).Color;
Changed;
end else
inherited;
end;
procedure TChildObj.Changed;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TChildObj.SetVisible(Value : Boolean);
begin
if FVisible <> Value then
begin
FVisible := Value;
Changed;
end;
end;
procedure TChildObj.SetColor(Value : TColor);
begin
if FColor <> Value then
begin
FColor := Value;
Changed;
end;
end;
constructor TTest.Create(AOwner : TComponent);
begin
inherited;
FChildObj := TChildObj.Create;
FChildObj.OnChange := ChildObjChanged;
end;
destructor TTest.Destroy;
begin
FChildObj.Free;
inherited;
end;
procedure TTest.ChildObjChanged(Sender : TObject);
begin
if csLoading in ComponentState then Exit;
// use ChildObj values as needed...
end;
procedure TTest.Loaded;
begin
inherited;
ChildObjChanged(nil);
end;
procedure TTest.SetChildObj(Value : TChildObj);
begin
if FChildObj <> Value then
FChildObj.Assign(Value);
end;
アプローチする場合は、TComponent
代わりにこれを試してください。
type
TChildObj = class(TComponent)
private
FVisible : Boolean;
FColor : TColor;
FOnChange : TNotifyEvent;
procedure Changed;
procedure SetVisible(Value : Boolean);
procedure SetColor(Value : TColor);
public
procedure Assign(Source : TPersistent); override;
property OnChange : TNotifyEvent read FOnChange write FOnChange;
published
property Visible : Boolean read FVisible write SetVisible;
property Color : TColor read FColor write SetColor;
end;
TTest = class(TComponent)
private
FChildObj : TChildObj;
FOne : integer;
procedure ChildObjChanged(Sender : TObject);
procedure SetChildObj(Value : TChildObj);
protected
procedure Loaded; override;
public
constructor Create(AOwner : TComponent); override;
published
property One : integer read FOne write FOne;
property ChildObj : TChildObj read FChildObj write SetChildObj;
end;
。
procedure TChildObj.Assign(Source: TPersistent);
begin
if Source is TChildObj then
begin
FVisible := TChildObj(Source).Visible;
FColor := TChildObj(Source).Color;
Changed;
end else
inherited;
end;
procedure TChildObj.Changed;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TChildObj.SetVisible(Value : Boolean);
begin
if FVisible <> Value then
begin
FVisible := Value;
Changed;
end;
end;
procedure TChildObj.SetColor(Value : TColor);
begin
if FColor <> Value then
begin
FColor := Value;
Changed;
end;
end;
constructor TTest.Create(AOwner : TComponent);
begin
inherited;
FChildObj := TChildObj.Create(Self);
FChildObj.SetSubComponent(True);
FChildObj.OnChange := ChildObjChanged;
end;
procedure TTest.ChildObjChanged(Sender : TObject);
begin
if csLoading in ComponentState then Exit;
// use ChildObj values as needed...
end;
procedure TTest.Loaded;
begin
inherited;
ChildObjChanged(nil);
end;
procedure TTest.SetChildObj(Value : TChildObj);
begin
if FChildObj <> Value then
FChildObj.Assign(Value);
end;