PDA

Ver la Versión Completa : Guardar los cambios de componentes nuevos


oesteve
11-06-2003, 09:57:22
Hola a todos:

Queria saber como puedo guardar los cambios realizados en tiempo de ejecucion sobre una aplicacion, es decir tengo una aplicacion y le añado componentes en tiempo de ejecucion, pero quiero que esos cambios se mantengan la siguiente vez que abra la alicacion.

Gracias.

delphi.com.ar
11-06-2003, 16:43:31
Desconozco si hay algo para automatizar esto, pero no es muy difícil hacerlo, vas a tener que prolijamente guardar en una base de datos / archivo / registro / ini todos los componentes que vas creando, te recomendaría trabajar con un TList dónde vayas asignando los componentes creados, o que siempre los agregues sobre un mismo contenedor, para poder recorrer los componentes contenidos por éste e ir guardándolos.

Saludos!

roman
12-06-2003, 00:08:25
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:

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:

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:

initialization
RegisterClasses([TEdit, TLabel, TMemo, TComboBox]);


// Saludos

delphi.com.ar
12-06-2003, 17:19:22
La solución que te propone Román es fenomenal, lo que si tu no dejas en claro si quieres guardar todos los componentes del form o solo una parte, si es solo una parte. Si es solo una parte, no se que tan práctico puede ser esto, pero podrías crear un forms sin bordes e insertarlo en tu form, y hacer que este form sea el que guarde los datos de la forma que te sugerieron anteriormente.

Saludos!

roman
12-06-2003, 18:09:27
Posteado originalmente por delphi.com.ar
...lo que si tu no dejas en claro si quieres guardar todos los componentes del form o solo una parte, si es solo una parte. Si es solo una parte, no se que tan práctico puede ser esto, pero podrías crear un forms sin bordes e insertarlo en tu form...


En las pruebas que hice ayer intenté guardar sólo las componentes dentro de, digamos, un panel pero no me funcionaba. Estudiándole más entendí porque:

El método WriteComponent de TStream trabaja con las subcomponentes, no con los subcontroles. Normalmente, cuando se insertan componentes en tiempo de diseño, todos tienen como "owner" al formulario, incluso cuando se insertan dentro de un control contenedor como un panel. WriteComponent(Panel) guardará el panel y todos los compoenentes que posea-- ninguno en el caso normal.

Pero dado que la intención es guardar los componentes que se creen durante la ejecución bastará pasarle al constructor del componente el panel como parámetro pare que sea éste el "owner". Creo que esta sería la solución ideal.

Por otro lado, es posible usar las rutinas ObjectTextToBinary y ObjectBinaryToText de la unidad "Clases" para que podamos guardar las componentes en formato de texto, tal como se ven cuando escogemos la opción "View as text" en un formulario.

En estos momentos no tengo mucho tiempo pero creo que no sería muy difícil crear una componente TStoreComponent que englobe estas ideas y facilite su uso. La componente tendría la siguiente interfaz:


TStoreComponent = class(TComponent)
public
procedure LoadFromFile(FileName: String);
procedure SaveToFile(FileName: String);

published
property Component: TComponent;
end;


La insertaríamos en un formulario, asignaríamos la propiedad Component a la componente que desemos guardar y ¡listo!

Si esto lo combinamos con la componente TSizeControl (no estoy seguro del nombre, hace no mucho puse aquí el enlace) que nos permite cambiar tamaño y posición de controles durante la ejecución, tendríamos un modesto editor de formularios.

En fin, sólo algunas ideas.

// Saludos

fabianbbg
20-12-2005, 21:08:54
Estimado Roman:

He probado tu ejemplo y la verdad es que ha acelerado bastante mi aplicación, pues lo que hago es crear en tiempo de ejecución una suerte de form de "ABM" genérico, de esta forma crea los controles necesarios para dicho abm segun los campos de la Base de Datos.

Pero tenia un pequeño retardo para las tablas grandes.. pues cada vez que se abria se creaba de nuevo.

Con la forma que sugeris, se crean solo una vez y luego levantan la configuración del archivo si este existe.. lo que es bastante mas rapido.

Ahora bien a continuación el problema:
En ese ABM generico hay un grid, el cual tambien se "formatea" con los nombres de columnas y demás. Pero cuando guardo el form en el archivo ( destroy) . Guarda la configuración del grid solo si tiene algun ragistro, es decir si el dataset que alimenta al grid esta vacio (eof) No guarda los "titles" que yo habia configurado.
Pero cuando tiene por lo menos algun registro si los guarda..

Tenés idea de que puede ser? Desde ya te agradezco cualquier ayuda

fabián