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 -
