Henrik Bergstrm writes:
Quote
TPers is in itself not interesting in this example, but in the component I'm
trying to build its corresponding class should maintain a list of components
(here called TComp, se below). These components are not children of
TExempelComp. The only reason why they are components at all is to allow
them to occure in the object inspector.
It is enough to derive them from TPersistent. This saves a bit overhead.
Quote
So, whenever an instance of TExempelComp need to be saved it naturally need
to save these components manually since they are internal to TPers. Since
they are maintained by TPers, but not published properties I added
functionality to TPers to store and retrieve them I thought.
Here is how I do it:
1) The outer class (component) has the DefineProperties method overriden as usual.
2) The write method is:
type
TWriterCast = class(TWriter); // Enabled access to protected methods.
procedure TCustomColorPicker.WriteWidgets(Writer: TWriter);
var
I: Integer;
OldAncestor: TPersistent;
begin
with TWriterCast(Writer) do
begin
OldAncestor := Ancestor;
Ancestor := nil;
try
WriteValue(vaCollection);
for I := 0 to FWidgets.Count - 1 do
begin
WriteListBegin;
WritePropName('WidgetClass');
WriteString(FWidgets[I].ClassName);
WriteProperties(FWidgets[I]);
WriteListEnd;
end;
WriteListEnd;
finally
Ancestor := OldAncestor;
end;
end;
end;
I use a collection here hence the vaCollection identification at the start. I suppose you don't need this, but I recommend that you look in Classes.pas how Borland did the streaming with other property kinds.
3) The read method is then:
type
TReaderCast = class(TReader); // Enabled access to protected methods.
procedure TCustomColorPicker.ReadWidgets(Reader: TReader);
var
I: Integer;
S: string;
Widget: TColorPickerWidget;
ClassFound: Boolean;
begin
FWidgets.Clear;
with TReaderCast(Reader) do
begin
// Skip vaCollection indicator.
ReadValue;
while not EndOfList do
begin
ReadListBegin;
// Determine class to create. Skip 'WidgetClass' property name.
ReadStr;
S := ReadString;
ClassFound := False;
for I := 0 to RegisteredWidgets.Count - 1 do
if RegisteredWidgets[I].ClassName = S then
begin
ClassFound := True;
Widget := TColorPickerWidgetClass(RegisteredWidgets[I]).Create(Self);
while not EndOfList do
ReadProperty(Widget);
FWidgets.Add(Widget);
Break;
end;
if not ClassFound then
ColorPickerError('Color picker widget class ''%s'' not found.'#13#10 +
'Is the widget unit included in the uses clause?', [S]);
ReadListEnd;
end;
ReadListEnd;
end;
end;
The result looks like:
WidgetCollection = <
item
WidgetClass = 'TColorSwatchWidget'
BoxSize = 8
CMYKProfileFile = 'EuroscaleCoated.icc'
DisplayGamma = 1.000000000000000000
Spacing = -1
SwatchFile =
'ANPA Colors.aco'
StreamedSelectedColor = ''
end
item
WidgetClass = 'TDelphiColorsCpWidget'
DisplayGamma = 1.000000000000000000
StreamedSelectedColor = ''
end
item
WidgetClass = 'TColorCompareCpWidget'
DisplayGamma = 1.000000000000000000
Options = [woHotColorAsSelected, woTrackHotColor]
StreamedSelectedColor = '(1.00, 0.74, 0.07)'
StreamedAlternativeColor = '(0.00, 0.00, 0.00)'
end>
HTH
Mike
--
www.delphi-gems.com
www.delphi-unicode.net
www.lischke-online.de