gipa
asked on
Compound component and properties
I created a component assembled from different other components.
Where some components have again childcomponents.
Now my problem is: How can I stream all properties from those components and subcomponents to a *.dfm .
Where some components have again childcomponents.
Now my problem is: How can I stream all properties from those components and subcomponents to a *.dfm .
If you want to tell Luc about EE, he already knows.
Hi gipa,
all published properties and classes are automatically saved into the DFM file. If you have classes which are only public then you need to override DefineProperties in the particular container and stream out explicitely the classes in question.
Ciao, Mike
all published properties and classes are automatically saved into the DFM file. If you have classes which are only public then you need to override DefineProperties in the particular container and stream out explicitely the classes in question.
Ciao, Mike
ASKER
Mike,
If I understand you well, I should stream out every property from a class I use.
But can’t I stream the whole subcomponent out, I don’t want to write a Read and a write for each property.
Patrick.
If I understand you well, I should stream out every property from a class I use.
But can’t I stream the whole subcomponent out, I don’t want to write a Read and a write for each property.
Patrick.
No no, you don't need to stream all properties of all subcomponents. Depending on what you want to have saved you can either make the particular property/class published or you save them yourself. Can you give us a snippet of the container class with some of the properties to be saved? Then we can discuss this on the "living" example...
Ciao, Mike
Ciao, Mike
ASKER
Mike,
Type
MyBrowser = class(TCustomPanel)
private
FOutBar: TDCOutBar;
FGrid: TDbGrid;
public
property OutLookBar: TDCOutBar
read GetOutLookBar
write SetOutLookBar;
published
end;
One of the props of FOutBar is
FOutBar.Groups[i] //(TDCOutBarGroup)
// this could be
// DCOutBarGroup.Caption
// DCOutBarGroup.Align and ……
So I want to stream every Group from FOutbar.
If there are 5 groups then I want per group all the props in the *.dfm.
Is this possible?
// Dream OutBar
// This is Something like a Outlookbar and has subcomponents like Groups, Listviews and ...
// http://www.dream- com.com
Patrick.
Type
MyBrowser = class(TCustomPanel)
private
FOutBar: TDCOutBar;
FGrid: TDbGrid;
public
property OutLookBar: TDCOutBar
read GetOutLookBar
write SetOutLookBar;
published
end;
One of the props of FOutBar is
FOutBar.Groups[i] //(TDCOutBarGroup)
// this could be
// DCOutBarGroup.Caption
// DCOutBarGroup.Align and ……
So I want to stream every Group from FOutbar.
If there are 5 groups then I want per group all the props in the *.dfm.
Is this possible?
// Dream OutBar
// This is Something like a Outlookbar and has subcomponents like Groups, Listviews and ...
// http://www.dream- com.com
Patrick.
ASKER
Mike,
Type
MyBrowser = class(TCustomPanel)
private
FOutBar: TDCOutBar;
FGrid: TDbGrid;
public
property OutLookBar: TDCOutBar
read GetOutLookBar
write SetOutLookBar;
published
end;
One of the props of FOutBar is
FOutBar.Groups[i] //(TDCOutBarGroup)
// this could be
// DCOutBarGroup.Caption
// DCOutBarGroup.Align and ……
So I want to stream every Group from FOutbar.
If there are 5 groups then I want per group all the props in the *.dfm.
Is this possible?
// Dream OutBar
// This is Something like a Outlookbar and has subcomponents like Groups, Listviews and ...
// http://www.dream- com.com
Patrick.
Type
MyBrowser = class(TCustomPanel)
private
FOutBar: TDCOutBar;
FGrid: TDbGrid;
public
property OutLookBar: TDCOutBar
read GetOutLookBar
write SetOutLookBar;
published
end;
One of the props of FOutBar is
FOutBar.Groups[i] //(TDCOutBarGroup)
// this could be
// DCOutBarGroup.Caption
// DCOutBarGroup.Align and ……
So I want to stream every Group from FOutbar.
If there are 5 groups then I want per group all the props in the *.dfm.
Is this possible?
// Dream OutBar
// This is Something like a Outlookbar and has subcomponents like Groups, Listviews and ...
// http://www.dream- com.com
Patrick.
Patrick,
well, I don't see why this should not be possible. You have not published the Outlookbar class. Is there a reason why you want to have it only public? I ask because this way you cannot modify it at design time. If you publish it then all problems should be gone, because it's published properties are automatically saved.
Ciao, Mike
well, I don't see why this should not be possible. You have not published the Outlookbar class. Is there a reason why you want to have it only public? I ask because this way you cannot modify it at design time. If you publish it then all problems should be gone, because it's published properties are automatically saved.
Ciao, Mike
ASKER
Mike,
I Edit the properties with a ComponentEditor at design-time.
If I publish this component all what I can see in the object Inspector is the name of the component.
So if you can tell me how to stream this component, that would be very nice.
Patrick.
I Edit the properties with a ComponentEditor at design-time.
If I publish this component all what I can see in the object Inspector is the name of the component.
So if you can tell me how to stream this component, that would be very nice.
Patrick.
Patrick, for non-standard components published as properties of other components you need to write a property editor (for the property being a component) and override the GetAttributes method. There you need to return the flag paSubProperties (among others if appropriate). This is the way to make it working in the object inspector saving you work to stream your component.
The other way is to override DefineProperties in your container component.
TMyBrowser = class(TCustomPanel)
protected
procedure DefineProperties(Filer: TFiler); override;
end;
procedure TMyBrowser.DefinePropertie s(Filer: TFiler);
function DoWrite: Boolean;
begin
Result := determine somehow whether there is to write something or not;
end;
begin
Filer.DefineProperty('Outl ookBar', ReadData, WriteData, DoWrite);
end;
This method will be called by the streaming system of the VCL when loading or storing your browser component. There's a good example in the online help which shows all you need. Look in the index for DefineProperties. The first entry in the sublist is the example.
Ciao, Mike
The other way is to override DefineProperties in your container component.
TMyBrowser = class(TCustomPanel)
protected
procedure DefineProperties(Filer: TFiler); override;
end;
procedure TMyBrowser.DefinePropertie
function DoWrite: Boolean;
begin
Result := determine somehow whether there is to write something or not;
end;
begin
Filer.DefineProperty('Outl
end;
This method will be called by the streaming system of the VCL when loading or storing your browser component. There's a good example in the online help which shows all you need. Look in the index for DefineProperties. The first entry in the sublist is the example.
Ciao, Mike
ASKER
Mike,
Something is written to the dfm file.
But it is unreadable, and i got a stream read error.
// this is the code i used
procedure TBrowser32.LoadCompPropert y(Reader: TReader);
begin
if Reader.ReadBoolean then
FOutBar:= TDCOutBar(Reader.ReadCompo nent(nil)) ;
end;
procedure TBrowser32.StoreCompProper ty(Writer: TWriter);
begin
Writer.WriteBoolean(FOutBa r <> nil);
if FOutBar <> nil then
Writer.WriteComponent(FOut Bar);
end;
procedure TBrowser32.DefinePropertie s(Filer: TFiler);
function DoWrite: Boolean;
begin
if Filer.Ancestor <> nil then { check Ancestor for an inherited value }
begin
if TBrowser32(Filer.Ancestor) .FOutBar = nil then
Result := FOutBar <> nil
else if (FOutBar = nil) or
(TBrowser32(Filer.Ancestor ).FOutBar. Name <> FOutBar.Name) then
Result := True
else Result := False;
end
else { no inherited value -- check for default (nil) value }
Result := FOutBar <> nil;
end;
begin
inherited; { allow base classes to define properties }
Filer.DefineProperty('MyCo mpProperty ', LoadCompProperty, StoreCompProperty, DoWrite);
end;
Something is written to the dfm file.
But it is unreadable, and i got a stream read error.
// this is the code i used
procedure TBrowser32.LoadCompPropert
begin
if Reader.ReadBoolean then
FOutBar:= TDCOutBar(Reader.ReadCompo
end;
procedure TBrowser32.StoreCompProper
begin
Writer.WriteBoolean(FOutBa
if FOutBar <> nil then
Writer.WriteComponent(FOut
end;
procedure TBrowser32.DefinePropertie
function DoWrite: Boolean;
begin
if Filer.Ancestor <> nil then { check Ancestor for an inherited value }
begin
if TBrowser32(Filer.Ancestor)
Result := FOutBar <> nil
else if (FOutBar = nil) or
(TBrowser32(Filer.Ancestor
Result := True
else Result := False;
end
else { no inherited value -- check for default (nil) value }
Result := FOutBar <> nil;
end;
begin
inherited; { allow base classes to define properties }
Filer.DefineProperty('MyCo
end;
ASKER
Adjusted points from 200 to 500
Mmmh, strange. Your code looks ok. Are you using D5? I ask because with D5 you have to possibility to save a DFM in text form, not only binary. From what I can see in Classes.pas all TWriter methods write binary data only. Perhaps this is your problem? See, if your form is saved as text DFM and switch it if so...
Ciao, Mike
Ciao, Mike
ASKER
Mike,
Yes it is saved as Text.
Patrick.
Yes it is saved as Text.
Patrick.
Aha, then switch the flag so that the DFM is saved in binary form (right click, switch off "text DFM"). Then change something in the form and save it. Does this work?
Ciao, Mike
Ciao, Mike
ASKER
Mike,
Yes it works partly.
But now there is an other problem my outlookbar changed is parent, the component isn’t the parent anymore but the form is.
Patrick.
Yes it works partly.
But now there is an other problem my outlookbar changed is parent, the component isn’t the parent anymore but the form is.
Patrick.
Well, I would change the read procedure so:
procedure TBrowser32.LoadCompPropert y(Reader: TReader);
begin
if Reader.ReadBoolean then
begin
FOutBar:= TDCOutBar(Reader.ReadCompo nent(nil)) ;
FOutBar.Parent := Self;
end;
end;
Ciao, Mike
procedure TBrowser32.LoadCompPropert
begin
if Reader.ReadBoolean then
begin
FOutBar:= TDCOutBar(Reader.ReadCompo
FOutBar.Parent := Self;
end;
end;
Ciao, Mike
ASKER
Mike,
I tried that already, bot its not solving the whole problem because now then outlookbar lay’s on top of the component and I can delete it from my component.
Patrick.
I tried that already, bot its not solving the whole problem because now then outlookbar lay’s on top of the component and I can delete it from my component.
Patrick.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for helping me sorting this problem out.