Buscando aquí y allá encontré una manera de hacer lo que quieres sin necesidad de llevar registro de todas las componentes que se creen durante la ejecución. La idea es utilizar el mismo mecanismo que utiliza el IDE de Delphi para construir un formulario en tiempo de diseño a partir del archivo DFM.
Define los siguientes métodos de tu formulario:
Código:
function TForm1.FormFileName: String;
begin
Result := ExtractFilePath(Application.ExeName) + ClassName + '.bin';
end;
procedure TForm1.Load;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FormFileName, fmOpenRead or fmShareDenyWrite);
try
Stream.ReadComponent(Self);
finally
Stream.Free;
end;
end;
procedure TForm1.Save;
var
Stream: TFileStream;
begin
Stream := TFileStream.Create(FormFileName, fmCreate);
try
Stream.WriteComponent(Self);
finally
Stream.Free;
end;
end;
y redefine el constructor y destructor del formulario como sigue:
Código:
constructor TForm1.Create(AOwner: TComponent);
begin
if FileExists(FormFileName) then
begin
CreateNew(AOwner);
Load;
end
else
inherited Create(AOwner);
end;
destructor TForm1.Destroy;
begin
Save;
inherited;
end;
El destructor creará el archivo "TForm1.bin" con todas las componentes que haya en ese momento así como sus propiedades y el constructor buscará este archivo y, si lo encuentra, construirá el formulario a partir de él.
Ya lo probé y parece funcionar bien (el código no es de mi cosecha) Puedes crear y destruir componentes en tiempo de ejecución y alterar sus propiedades. Todos los cambios se guardan.
Sólo debes tener cuidado con dos cosas:
Cada vez que agregues componentes en tiempo de diseño deberás borrar el archivo "TForm1.bin", de lo contrario al ejecutar la aplicación leerá las componentes del archivo que aún no tiene las nuevas. Esto es hasta cierto punto un problema ya que si tu aplicación está ya siendo usada y decides modificarla seperderán las componentes que el usuario ya tenga creadas.
El segundo punto es que debes registrar manualmente todas las clases que desees instanciar durante la ejecución. Lo más conveniente es hacerlo en la sección
initialization del formulario:
Código:
initialization
RegisterClasses([TEdit, TLabel, TMemo, TComboBox]);
// Saludos