Link to home
Start Free TrialLog in
Avatar of gipa
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 .
Avatar of DonBartholomew
DonBartholomew

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
Avatar of gipa

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.
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
Avatar of gipa

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.
Avatar of gipa

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.
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
Avatar of gipa

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.
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.DefineProperties(Filer: TFiler);

  function DoWrite: Boolean;
  begin
    Result := determine somehow whether there is to write something or not;
  end;

begin
  Filer.DefineProperty('OutlookBar', 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
Avatar of gipa

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.LoadCompProperty(Reader: TReader);
begin
  if Reader.ReadBoolean then
    FOutBar:= TDCOutBar(Reader.ReadComponent(nil));
end;

procedure TBrowser32.StoreCompProperty(Writer: TWriter);

begin
  Writer.WriteBoolean(FOutBar <> nil);
  if FOutBar <> nil then
    Writer.WriteComponent(FOutBar);
end;

procedure TBrowser32.DefineProperties(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('MyCompProperty', LoadCompProperty, StoreCompProperty, DoWrite);
end;
Avatar of gipa

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
Avatar of gipa

ASKER

Mike,

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
Avatar of gipa

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.
Well, I would change the read procedure so:

procedure TBrowser32.LoadCompProperty(Reader: TReader);
begin
  if Reader.ReadBoolean then
  begin
    FOutBar:= TDCOutBar(Reader.ReadComponent(nil));
    FOutBar.Parent := Self;
  end;
end;

Ciao, Mike
Avatar of gipa

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.
ASKER CERTIFIED SOLUTION
Avatar of Lischke
Lischke

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gipa

ASKER

Thanks for helping me sorting this problem out.