[fpc-pascal] WriteComponent not outputting a hierarchy of components?

Graeme Geldenhuys graemeg.lists at gmail.com
Thu Jun 3 17:09:14 CEST 2010


I'm using FPC 2.4.1

I'm experimenting with streaming (read & write) components to build a form
and runtime from an external file (something like GTK2 has with Glade). I
have a ReadForm() method very similar to the SaveForm below, and it works
pretty well. All components placed directly on the form are loaded and
displayed correctly, except if you have nested components. eg: a Panel on
the Form and then components inside the Panel.

I thought that maybe I am creating the *.frm files (text object format of
form) incorrectly, so wrote the code below to see what the RTL does
automatically for me.

procedure SaveForm(AForm: TComponent);
var
  f, f2: TStream;
  Filename: string;
  TextStream, BinStream: TStream;
begin
  Filename    := LowerCase(Copy(AForm.ClassName, 2, 255)) + '.frm';
  BinStream   := TMemoryStream.Create;
  TextStream  := TFileStream.Create(Filename, fmCreate);
  BinStream.WriteComponent(AForm);
  BinStream.Position := 0;
  ObjectBinaryToText(BinStream, TextStream);
  TextStream.Free;
  BinStream.Free;
end;


For some reason a call:  SaveForm(self)
 ... in a button click, creates the *.frm file, but in only writes the
TfpgForm published properties. It doesn't write any information about the
other components on the form, or nested components.

-------[ actual content of *.frm file ]-----------------------
object CheckBoxForm: TCheckBoxForm
  Height = 400
  Left = 520
  MaxHeight = 0
  MaxWidth = 0
  MinHeight = 32
  MinWidth = 32
  ModalResult = mrNone
  Sizeable = True
  Top = 166
  Width = 400
  WindowPosition = wpOneThirdDown
  WindowTitle = 'Check box test'
end
----------------[ end ]----------------------


What is WriteComponent() looking for to traverse a Form?

I quickly put together the code shown below. It traverses components on the
form and writes each components name width indentation to show
relationships to the console. I also use ComponentCount and Components[],
and the output looks fine (output also shown below). So I really don't know
what WriteComponent() is struggling with. Any clues?

------------------------------------
procedure TTestForm.Button1Click(Sender: TObject);
var
  ind: string;

  procedure TraverseComponents(AComponent: TComponent);
  var
    p: string;
    i: integer;
  begin
    p := ind;
    for i := 0 to AComponent.ComponentCount-1 do
    begin
      writeln(ind + AComponent.Components[i].Name);
      if AComponent.Components[i].ComponentCount > 0 then
      begin
        ind := ind + '  ';
        TraverseComponents(AComponent.Components[i]);
        ind := p;
      end;
    end;
  end;

begin
//  SaveForm(self);
  ind := '';
  TraverseComponents(self);
end;
------------------------------------


-------[ output of above code ]-----------
CheckBox1
CheckBox2
CheckBox3
GroupBox1
  Label1
  Edit1
Button1
--------------------


Regards,
  - Graeme -

-- 
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/




More information about the fpc-pascal mailing list