What is correct way to structure delphi compound components for stream reading?

。_饼干妹妹 提交于 2020-01-04 04:54:22

问题


I am having trouble reloading a saved compound component in Delphi where the subcomponent (a TChart) appears to be being created twice. When I create my component in code, it works fine.

My component is a TPanel hosting a client aligned TChart and I create the single series and its data myself. Here is my code:

type

  TMyChart = class( TPanel )
  PRIVATE
    FChart : TChart;
  PROTECTED
    procedure Notification( AComponent : TComponent; Operation : TOperation ); override;
  PUBLIC
    constructor Create( AOwner : TComponent ); override;
    destructor  Destroy; override;
  PUBLISHED
    property Chart : TChart
               read FChart;
  end;


{ TMyChart }

constructor TMyChart.Create(AOwner: TComponent);
begin
  inherited;
  Width := 400;
  Height := 150;
  FChart := TChart.Create( Self );
  FChart.Name := '';
  FChart.SetSubComponent( True );
  FChart.FreeNotification( Self );
  FChart.Parent := Self;
  FChart.Align := alClient;
  FChart.AddSeries( TLineSeries.Create( FChart ));
  FChart.Series[0].FillSampleValues(100);
end;

destructor TMyChart.Destroy;
begin
  FreeAndNil( FChart );
  inherited;
end;

procedure TMyChart.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent = FChart) and (Operation = opRemove) then
    FChart := nil;
end;

initialization

  RegisterClass( TMyChart );
  RegisterClass( TChart );
  RegisterClass( TLineSeries );

end.

I've followed the example in ExtCtrls 'TLabeledEdit' to include a FreeNotification for the subcomponent TChart.

I stream this out using TStream.WriteComponent and get the following DFM:

object Mychart1: TMyChart
  Left = 0
  Top = 0
  Width = 400
  Height = 150
  Caption = 'Mychart1'
  TabOrder = 3
  Chart.Left = 1
  Chart.Top = 1
  Chart.Width = 398
  Chart.Height = 148
  Chart.Align = alClient
  Chart.TabOrder = 0
  Chart.ColorPaletteIndex = 13
  object TChart
    Left = 1
    Top = 1
    Width = 398
    Height = 148
    Align = alClient
    TabOrder = 0
    ColorPaletteIndex = 13
    object TLineSeries
      Marks.Arrow.Visible = True
      Marks.Callout.Brush.Color = clBlack
      Marks.Callout.Arrow.Visible = True
      Marks.ShapeStyle = fosRoundRectangle
      Marks.Visible = False
      Brush.BackColor = clDefault
      Pointer.InflateMargins = True
      Pointer.Style = psRectangle
      Pointer.Visible = False
      XValues.Name = 'X'
      XValues.Order = loAscending
      YValues.Name = 'Y'
      YValues.Order = loNone
    end
  end
end

Everything I require is there. I reload this DFM using ReadComponent as follows:

procedure LoadComponentFromFile( var AComponent : TComponent );
var
  MS : TMemoryStream;
  SS : TStringStream;
begin
  MS := TMemoryStream.Create;
  SS := TStringStream.Create;
  try
    SS.LoadFromFile( GetSpecialFolderPath( CSIDL_DESKTOP ) + '\test.txt' );
    SS.Position := 0;
    ObjectTextToBinary( SS, MS );
    MS.Position := 0;
    AComponent := MS.ReadComponent( nil );
  finally
    MS.Free;
    SS.Free;
  end;
end;

procedure TForm8.Button3Click(Sender: TObject);
begin
  FreeAndNil( FMyChart );

  LoadComponentFromFile( TComponent(FMyChart) );

  FMyChart.Parent := Self;
end;

After this I seem to get TWO TCharts created - one with the correct series data (constructed by TMyChart.Create) and another (in front of this) with empty axes, presumably where ReadComponent is constructing 'object TChart'. I have proven this by placing a breakpoint in 'TMyChart.Create' and another in the source code for TChart in 'TCustomChart.Create'. When calling the loader code it hits the TMyChart.Create breakpoint once, first, and then hits the TCustomChart.Create breakpoint twice. I can see that I need to tell TStream.ReadComponent not to recreate my subcomponent TChart but after many trials and reading of documentation on component streaming I cant see how to structure it. Can anyone comment please? Many thanks.

来源:https://stackoverflow.com/questions/14802179/what-is-correct-way-to-structure-delphi-compound-components-for-stream-reading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!