PDA

Ver la Versión Completa : Forms y Frames


Albano
07-12-2006, 20:56:46
Hola a todos, tengan un buen dia...
Estoy trabajando con delphi 2005, pero yo creo que la pregunta que voy a hacer es útil para cualquier otra version, pero lo aclaro en caso de que sea necesario.
Adjunto una imagen de la presentación de mi aplicación, lo que quiero es que en la parte izquierda me aparezca el menu, en la parte superior el nombre de mi aplicación (el que tengo ahorita es provisional, le vamos a poner uno entre mi socio y yo) y en el centro la ventana en la que se estaría trabajando... Hasta ahorita lo he hecho todo con panels (incluso cada módulo del programa es un panel separado), pero sé que no es la mejor opción, creo que debería usar frames y forms para cada módulo.
Aqui estan mis preguntas:

Con los componentes frames puedo hacer que siempre estén visibles las barras de menu y del titiulo?
Cómo puedo hacer para que en el centro aparezca una nueva forma, que no oculte las otras partes y que sea parte de la misma ventana?Creo que esto se hace con las MDI forms, pero no he usado ni frames ni MDI forms. Voy a estar investigando, pero quiero saber si voy por buen camino.
Gracias por su atencion.

roman
07-12-2006, 21:19:30
Para el formato que quieres no te conviene MDI. Necesitas:

1. Un panel con Align = alLeft para el menú lateral
2. Un panel con Align = alTop para el título
3. Un panel con Align = alClient para el resto

En el tercer panel es donde vas a colocar tus Frame. Desde luego, no conviene usar paneles para cada módulo porque tendrías que editar todo en el mismo formulario y eso puede terminar con la sanidad mental de uno :) En cambio un frame lo diseñas con sus propiedades, métodos y eventos en su propia ventana y unidad.

Lo que tienes que implementar es la forma de colocar uno u otro Frame según la opción del menú seleccionada. Yo he hecho esto, pero como he usado muy pocos Frame, opté por insertarlos todos de inicio y sólo cambio su visibilidad según me muevo por el menú. Pero si sin muchos módulos, lo mejor será crearlos bajo demanda.

// Saludos

Albano
07-12-2006, 21:44:52
Desde luego, no conviene usar paneles para cada módulo porque tendrías que editar todo en el mismo formulario y eso puede terminar con la sanidad mental de uno :)
Pues creo que por el momento voy bien en lo que propones, con excepción de no usar panels para cada módulo, lo hice y si esta terminando con mi salud mental, así que estoy buscando nuevas opciones.
Voy a empezar a trabajar con esto de los frames, nunca lo he hecho, haber cómo me va. Creo que voy a estar haciendo unas cuantas preguntas en este hilo. De cualquier modo voy a buscar en los foros, haber qué encuentro.
Gracias Roman.

Albano
14-12-2006, 02:07:18
Como lo dije anteriormente: "Voy a estar haciendo preguntas en este hilo"
No se cómo crear los frames en delphi 2005, de hecho no se hacerlo ni en delphi 7, que tambien lo he usado, nunca traté de crearlos.
En el foro me encontré que se pueden crear de la siguiente manera: File|New|Frame, pero no viene esa opción por ningun ladoen el delphi 2005.
¿Cómo creo el Frame en delphi 2005 y cómo lo pongo sobre el panel?

dec
14-12-2006, 23:07:53
Hola,

Creo que puedes probar en:


Menú -> File -> New -> Other... -> Delphi Projects -> Delphi Files -> Frame


Y luego puedes echar un vistazo en:


Menú -> File -> New -> Customize...


Podrás desde ahí personalizar el menú "New" de Delphi. Puedes buscar la "Frame" donde digo arriba y situarla en el lugar que prefieras.

Albano
15-12-2006, 00:17:16
Ya pude... lo que pasa es que el proyecto en el que estaba tratando de ponerlo es .Net y ahi no me aparece la opción, pero en un proyecto para Win32 si aparece...
Gracias Dec, hice lo que mencionaste.

dec
15-12-2006, 00:23:43
Hola,

Así es. Me parece que en .NET lo que hace las veces de los "Frames" son los "User controls".

Albano
15-12-2006, 00:27:58
Ah! ok, estaré investigando sobre esto... Gracias de nuevo.

Lepe
15-12-2006, 15:03:00
Quizás y solo quizás te convenga crear previamente un componente en la paleta....

Me explico:
Ahora tienes todo con paneles, al pasarlo a frames vas a tener que copiar y pegar mucho código y ahora si tu salud mental está en peligro:
- no está declarado ese evento
- me falta copiar el onclick del botón, en donde rayos está ese procedimiento
- etc.

Primero seleccionas el panel boton derecho y Add to Component Palete (o Add to repository, no recuerdo bien ainsss). Esto lo que hace es crear un nuevo icono en la paleta de componentes (como el que existe de un TEdit), pero lleva todo lo que tienes en el panel y además su código fuente asociado, ahora creas el frame, añades ese nuevo componente y voilá, ya tienes todo en el Frame.

Guarda el proyecto por si acaso ;).

Creo que ahora puedes mover todos los componentes desde el panel hasta el frame y eliminar el panel en sí (no creo que lo necesites, pero igual tampoco molesta) tú mismo.

Después de eso, puedes eliminar el componente de la paleta de delphi.Si no recuerdo mal creo que es así a grandes rasgos.

Saludos y suerte!!

roman
15-12-2006, 17:25:31
Hola,

Lepe, creo que es un poco distinto. Según entiendo de la ayuda de Delphi, el repository sólo acepta proyectos, forms, datamodules y frames.

En Delphi7 la opción que mencionas la obtienes seleccionando el panel y luego yendo al menú Component|Create Component Template...

El resto es igual, pero queda mejor si en lugar de seleccionar el panel, seleccionas todos los controles dentro del panel para que el panel en sí no se copie en la plantilla.

// Saludos

Albano
02-02-2007, 07:40:38
No se como poner el Frame dentro de la forma, la unica manera que encontré es siguiendo los pasos que me mencionaron, esos de poner el frame en la paleta de componentes y despues ponerlo en la forma, pero lo que quiero es poder hacerlo en tiempo de ejecución, quiero crear los frames y ponerle todos los componentes que quiera y despues solo mostrarlos en el panel que tengo en el centro, ¿como lo puedo hacer?
Gracias otra vez.

dec
02-02-2007, 09:22:03
Hola,

En realidad puedes hacerlo como con cualquier otro componente: utilizas su constructor para crear una instancia y luego, básicamente, le asignas a su propiedad "Parent" el componente que quieres que acoga a su ventana. Es decir, una secuencia similar a esta:


var
l: TLabel;
f: TFrame;
b: TButton;
begin
f := TFrame.Create(Self);
f.Parent := Self; // por Form1, por ejemplo
b := TButton.Create(Self);
b.Parent := f;
l := TLabel.Create(Self);
l.Parent := f;
{...}
end;



Ahora bien, me parece que los "frames" son más bien para tenerlos "armados" y listos para usar (en tiempo de diseño o en tiempo de ejecución) y no para andar añadiéndoles componentes. Son como una especie de plantilla que se supone (en mi opinión) está preparada para ser utilizada: contiene los componentes que sean menester, vaya.

Lepe
02-02-2007, 11:56:50
Suscribo lo dicho por dec. Aunque también puedes anidar Frames en tiempo de ejecución, colocar tantos frames como quieras y situarlos donde te apetezca.

Como ya sabes, solo con poner la propiedad Parent de un frame, puedes poner ese frame donde quieras.

Ejemplo:

var
l: TLabel;
f1, f2: TFrame;
b: TButton;
begin
f1 := TFrame.Create(Self);
f1.Parent := Self; // por Form1, por ejemplo

f2 := TFrame2.Create(Self);
f2.Parent := f1; // lo metemos dentro de frame1

f1.SetBounds( 0,0 100, 400); // lo hacemos mas alto para que quepa el segundo frame
f2.setBounds(300, 100, 100,100); // ajustamos el tamaño

Obviamente tendrás que jugar con los anchors para que todo cuadre y unos frames no se superpongan con otros.

Saludos

Albano
03-02-2007, 09:48:17
Ya hice lo que me mencionaron y funciona a la perfección, pero creo que no expliqué bien lo que queria en mi mensaje anterior...

Ahora bien, me parece que los "frames" son más bien para tenerlos "armados" y listos para usar (en tiempo de diseño o en tiempo de ejecución) y no para andar añadiéndoles componentes. Son como una especie de plantilla que se supone (en mi opinión) está preparada para ser utilizada: contiene los componentes que sean menester, vaya.
Esto es precisamente lo que quiero hacer, quiero tenerlos listos y solo ponerlos cuando de click en un botón, pero no se hacerlo, estoy tratando, pero no encuentro la manera... me pueden ayudar de nuevo?

dec
03-02-2007, 10:45:45
Hola,

Bueno. Lo primero que tienes que hacer es preparar un "frame". Inicia un nuevo proyecto de Delphi (7) y añade un nuevo "frame" al mismo: Menú File -> New -> Frame.

Tienes ante un "Frame" (similar a un formulario) vacío en el que puedes añadir los componentes que te sean menester. Añadiremos por ejemplo un "TEdit" y un "TButton".

Guarda a continuación todo el proyecto: File -> Save All

Sitúate en el formulario principal del proyecto. ¿Ya? Vale. En la paleta de componentes, en la pestaña "Standard", el primer componente que encuentras te da la posibilidad de insertar un "frame" en el formulario.

Pulsa sobre el icono del componente, pues, y a continuación sobre el formulario. Te aparecerá un cuadro de diálogo que muestra los "frames" conque contamos en el proyecto en el que trabajamos.

En nuestro caso hay sólo una y se llama (por defecto) "Frame2". Elige "Frame2" de la lista de "frames" disponibles y pulsa el botón "OK". Ya puedes ver el "frame" que anteriormente sobre el formulario: ves el botón y la casilla de edición.

El "frame" no lo ves, propiamente, es decir, este se confunde aparentemente con el propio formulario, de modo que cuando compiles y eches a andar el programa en el formulario pueda verse el botón y la casilla de edición, pero nada más.

Es decir, el "frame" nos proporciona varias cosas. Por un lado nos permite diseñar un componente compuesto de otros componentes de forma visual. Y por otro lado nos permite reutilizar dicho conjunto de componentes (que contiene el "frame") en diversos formularios y proyectos. Es una especie de plantilla que está a nuestra disposición.

Ahora bien. Nada nos impediría diseñar el "frame" visualmente (que creo que es lo suyo) y luego crear dicho "frame" en tiempo de ejecución y mostrarlo en el formulario que nos fuera menester. Al fin y al cabo el "frame" es un componente más, y los componentes no son sino clases con la particularidad de que un entorno de programación como Delphi permite su configuración y diseño visualmente.

Todo este rollo se resume de la siguiente forma:


unit Unit1;

interface

uses
Forms,

Unit2; // TFrame2

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
FFrame: TFrame2;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
FFrame := TFrame2.Create(Self);
FFrame.Parent := Self;
FFrame.SetBounds(10, 10, 300, 200);
end;

procedure TForm1.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
FFrame.Free;
end;

end.



Quita el "frame" que anteriormente insertamos en el formulario en tiempo de diseño. Sustituye el código del formulario tal como está ahora por el código anterior. Y ejecuta el proyecto de nuevo. Habrás creado un "frame" en tiempo de ejecución, le habrás dicho (con la propiedad "Parent") dónde tiene que mostrarse e incluso le habrás dado el tamaño (con "SetBounds") que has querido.

Y poco más me parece que puedo yo añadir sobre este tema. Si acaso decir que hasta ahora hemos creado y utilizado un "frame" en un proyecto en concreto, que puede contar con más "frames" (aunque tampoco creo que sea cuestión de utilizar "frames" a gogó), pero, lo que también es posible es utilizar "frames" que previamente hayamos situado en el "Repositorio de objetos" de Delphi. Esto nos ofrece la posibilidad de utilizar "frames" en distintos proyectos.

Sitúate de nuevo en el "Frame2" que creamos antes y pulsa con el botón derecho del ratón sobre el propio "frame". Verás un menú contextual que entre otras cosas te ofrece una opción para añadir la "frame" (ojo, también puedes añadir formularios, por ejemplo) al "Repositorio de objetos".

Hazlo. Añade el "Frame2" al "Repositorio" y a continuación inicia un nuevo proyecto en Delphi. Si a continuación tratas de añadir un "frame" en el formulario de nuestro nuevo proyecto verás aparecer un mensaje de error "No hay frames definidas en este proyecto. Si quiere puede usar File -> New -> Frames".

Pero nosotros no queremos eso exactamente ahora, no queremos crear un nuevo "frame" sino insertar nuestro "Frame2" creado anteriormente. Menú File -> New -> Others. Esto hace aparecer el "Repositorio de objetos" de Delphi. En mi caso guardé a "Frame2" en la pestaña "Forms" y la di de nombre "Perico" (verídico).

Pues bien, el resto es conocido: basta con seleccionar el icono correspondiente a nuestro "Frame2" (o cualquier otro que hubiéramos creado) para que automáticamente se inserte en el formulario dicho "Frame2". Cabría añadir el tema de la copia, herencia y uso de "frames". Verás en el "Repositorio de objetos" te permite insertar el "Frame2" copiándolo, heredándolo y haciendo uso de él, simplemente.

No hay que olvidar que "Frame2" se define he implementa en sendos archivos "pas" y "dfm" que antes guardamos junto al primer proyecto que creamos como ejemplo. Si queremos usar el "Frame2" en otro proyecto y optamos por "copiar" el "Frame2", cuando guardemos el proyecto en que usamos a "Frame2" se nos pedirá en qué ruta queremos guardar los archivos "pas" y "dfm" en que se define "Frame2": lo que tendremos por lo tanto será una copia de "Frame2" que usaremos en nuestro proyecto.

Ahora vayamos a "heredar" de "Frame2". En este caso lo que estamos indicando es que queremos crear un nuevo "frame" que herede de "Frame2", sencillamente. Es decir, si elegimos esta opción obtendremos un nuevo "frame" en cuya definición de tipo puede verse que:


type
TFrame3 = class(TFrame2)


Hay que tener en cuenta que heredar de "Frame2" conlleva que los cambios en "Frame2" van a afectar a "Frame3". ¿Me explico? :D Quiere decirse que ahora usaremos a "Frame2", cuyos archivos "pas" y "dfm" estarán donde se hubieran guardado en un principio:


program Project2;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in '..\Nueva carpeta\Unit2.pas' {Frame2: TFrame},
Unit3 in 'Unit3.pas' {Frame3: TFrame};

{...}


Y en último lugar podemos "usar" el "frame", no copiarlo ni heredarlo, sino sólamente usarlo. ¿Y esto qué significa realmente? Recordemos la secuencia: Menú File -> New -> Others -> Forms -> Perico... "usar".

Podríamos decir que "usar" no es ni "copiar" ni "heredar", pero, claro, esto no sé si deja muy diáfano el asunto. Pero hay que recordar que cuando "copiamos" el "frame" tuvimos que indicar una nueva ubicación para el mismo, de modo que usaríamos una copia del "frame", independientemente de lo que le ocurriera a la copia del "Repositorio de objetos".

Cuando heredamos el "frame", sin embargo, vimos que el asunto iba un poco más allá: si hacíamos cambios en "Frame2", "Frame3" se vería afectada (o mejor podría verse afectada) por dichos cambios. Pues bien. "Usar" el "Frame2" no significa sino eso, precisamente, usar los propios archivos donde se define "Frame2", lo que quiere decir que cualquier cambio que hagamos sobre "Frame2" será un cambio que afecte a todo proyecto que use "Frame2".

En fin. Voy a dejarlo aquí porque estoy justo en el punto en que uno piensa si tras tanta palabra no estará sino diciendo majaderías y además mal dichas. En todo caso si te he podido dar alguna idea pues mira, eso que has ganado tú y que no he perdido yo. Ya sabes. :)

Albano
03-02-2007, 19:18:59
estoy justo en el punto en que uno piensa si tras tanta palabra no estará sino diciendo majaderías y además mal dichas. En todo caso si te he podido dar alguna idea pues mira, eso que has ganado tú y que no he perdido yo. Ya sabes. :)

WOW!!! :eek:
Muchisisisimas gracias por esta clase de FRAMES dec, eso era precisamente lo que necesitaba y creo que será de utilidad para algunos foristas. Ya entendí el funcionamiento de los frames y veo que tienene muchisima utilidad, de hoy en adelante los usaré en la mayoría de mis proyectos.

Lepe
03-02-2007, 22:51:36
Yo suelo usarlo para los grids.

Creo un frame, añado un grid, lo configuro a mi gusto, añado algunas rutinas para ocultar columnas o lo que necesite... y listo. Ya tengo ese Frame para usar cada vez que necesito un grid en el proyecto.

Ahorra mucho código y tiempo, lo aconsejo.

dec, enhorabuena por el peaso artículo :cool: .

Saludos

Albano
31-03-2007, 03:04:29
Hola a todos! Otra vez con problemas referentes al tema de Frames, a continuación lo describo:
Por aqui anduve leyendo y me encontré con que, para destruir un componente de manera sencilla en alguna parte de mi aplicación, el owner tendría que ser yo o "nil", asi que tengo el siguiente código para crear mi frame:
FrameCamAlt := TFrameCamAlt.Create(nil);
FrameCamAlt.Parent := panelcontenido;
Aqui, como pueden ver, creo el frame con owner = nil y lo pongo sobre un panel (por lo menos eso es lo que creo que hago).
Después trato de destruir este frame con un botón que tengo en el mismo frame con el siguiente código:
procedure TFrameCamAlt.BtnSalirClick(Sender: TObject);
begin
FrameCamAlt.Free;
end;
En algunas ocaciones me han dicho que debo de tener cuidado al momento de destruír los componentes. que debo hacer que apunte a nil nuevamente, pero eso no lo entiendo, además, con lo que he hecho hasta ahora, me marca el error de Abstract Error
Qué tengo que hacer para destruir mi frame de manera correcta?
Gracias otra vez...

vtdeleon
31-03-2007, 04:48:53
Prueba con FreeAndNil(FrameCamAlt)

Saludos

Albano
31-03-2007, 23:19:46
Sigo teniendo el mismo problema, pero acabo de darme cuenta de que la primera vez que lo destruyo no pasa nada, solo aparece a partir de la segunda ocación que lo elimino. Es que este frame lo puedo mandar llamar varias veces sin necesidad de salirme del programa.
La solución que estoy pensando implementar es ocultar el frame cada vez que oprima el botón de salir y destruirlo al salirme de la aplicación, ¿hay otra solución?

Lepe
01-04-2007, 02:32:57
Problemas no hay ninguno mientras no solapes las 2 creaciones del objeto.
Esto es inaceptable:

procedure TFrameCamAlt.BtnSalirClick(Sender: TObject);
begin
FrameCamAlt.Free;
end;

Porque desde una clase TFRameCamAlt, estas intentando liberar la memoria del objeto que lo instancia.

Imagina un código así:

var x:TFrameCamAlt;
begin
x := TFrameCamalt.Create(nil);

end;
Cuando el usuario pulse el botón salir, se querrá liberar la variable FrameCamAlt que sabe dios si está creada o no.

La solución a tu problema, desde mi punto de vista, es crear al frame un evento OnSalir, cuando el usuario pulsa el botón salir, se lanza ese evento, que lo recoge la ventana donde se creó el Frame, y desde allí se destruye el Frame. Resultará complejo, pero deberías hacerlo así:


Definición del Frame:

TFrameCamAlt = class(Tframe)
...
private
FOnSalir : TnotifyEvent;
public
property OnSalir:TnotifyEvent read FOnSalir write FOnSalir;
end;

implementation

procedure TFrameCamAlt.BtnSalirclick(....);
begin
if Assigned(FOnSalir) then FOnSalir(Self);
end;


Ahora la ventana donde quieres incluir el frame en ejecución:

TForm1 = class (TForm);
...
private
CamAlt : TFRameCamAlt;
procedure RecibeEventoSalir(Sender:TObject);
....

implementation

procedure Tform1.FormCreate(...); supongo que creas el frame al crear el Form
begin
CamAlt := TFRameCamAlt.Create(nil);
CamAlt.OnSalir := RecibeEventoSalir;
end;

procedure TForm1.RecibeEventoSalir(Sender:TObject);
begin
FreeAndNil(CamAlt);
end;


Aquí está el detalle importante: La misma ventana que crea el frame es el que lo destruye. Además evitas dolores de cabeza, muy típico cuando depuras un programa: "El frame se crea en el form1... pero ¿donde se destruye? ahhh ... siii, en el Form25 cuando se pulsa el boton XXX"... demasiado lío compañero.


Saludos

Chris
16-04-2007, 22:42:36
No sé si para la plataforma Net exista una componente llamado TNotebook que en delphi 7 se dencuentra en la paleta win 3.1, es algo antiguo y por eso no estoy seguro. Si no exite todavía podrías utilizar el TpageControl y en cada página colocar un frame (modulo) distinto y cambiar la página activa como PageControl1.activepage := X

con esta forma te evitarás el enorme trabajo de estar ocultado y mostrando los frames. El PageControl lo puedes personalizar para no mostrar las ventanas, aún así yo en lo personal prefiero utilizar el TNoteBook porque obtengo una mejor apariencia, y creo que sería la mejor para tí. El problema con el PageControl es que a pesar de ocultar las pestañas, este se muestra de un forma 3D, que creo que no haría uniformidad con tu aplicación. Puedes buscar alternativas en internet.

La mejor alternativa que conozco es un componente que creo que se llama TNoteoBookForm o algo por el estilo, es del paquete LM Tools, tienen un paquete gratuito y otro comercial, talvez el componente que te mensiono sea parte del gratuito. Te aseguro que sería lo mejor que puedes obtener para tu apliación ya que carga formularios en páginas de un NoteBook. de esta formar ahorraría mucha memoría.

Albano
25-04-2007, 22:03:51
La solución a tu problema, desde mi punto de vista, es crear al frame un evento OnSalir, cuando el usuario pulsa el botón salir, se lanza ese evento, que lo recoge la ventana donde se creó el Frame, y desde allí se destruye el Frame.Ya seguí estos pasos y sigo teniendo el mismo problema... Voy a escribir lo que hice:
Puse todo el código que me recomendó Lepe nada mas que modifiqué un poco el procedimiento RecibeEventoSalir, lo puse de la siguiente manera:
procedure TForm2.RecibeEventoOnSalir(Sender: TObject);
begin
if FrameCamAlt <> nil then FreeAndNil(FrameCamAlt);
if FrameCliAlt <> nil then FreeAndNil(FrameCliAlt);
end;
Esto lo hice para poder usarlo con algunos Frames que tengo en la aplicación (ahí solo muestro 2, pero son mas).
El error que me marca es el de Abstract Error, después de la última línea del código que acabo de poner, pero la primera vez que lo ejecuto no, hasta la segunda pasa.

Aquí está el detalle importante: La misma ventana que crea el frame es el que lo destruye. Además evitas dolores de cabeza, muy típico cuando depuras un programa: "El frame se crea en el form1... pero ¿donde se destruye? ahhh ... siii, en el Form25 cuando se pulsa el boton XXX"... demasiado lío compañero.
Me gusta la idea, muchas gracias por el tiempo que tomaste para explicarmelo, espero que pueda hacerla funcionar.

con esta forma te evitarás el enorme trabajo de estar ocultado y mostrando los frames. El PageControl lo puedes personalizar para no mostrar las ventanas, aún así yo en lo personal prefiero utilizar el TNoteBook porque obtengo una mejor apariencia, y creo que sería la mejor para tí.
Lo malo de esta opción sería la cantidad de Frames que utilizo, son algunos y no es recomendable tenerlos todos creados. Pero muchas gracias por la opción, creo que la voy a usar en otro proyecto que tengo pensado hacer muy pronto.
Lo que tienes que implementar es la forma de colocar uno u otro Frame según la opción del menú seleccionada. Yo he hecho esto, pero como he usado muy pocos Frame, opté por insertarlos todos de inicio y sólo cambio su visibilidad según me muevo por el menú. Pero si sin muchos módulos, lo mejor será crearlos bajo demanda.

Lepe
26-04-2007, 02:14:00
Estas usando ese mismo evento para destruir varios frames, y debe tenerse en cuenta.

Por ejemplo:
- has creado 2 frames (para simplificar los nombres) uno es "Cam" y el otro "Cli".
- Ahora cierras un frame.
- Se ejecuta el evento TForm2.RecibeEventoOnSalir que liberará de memoria los dos frames ¿eso no importa?

Lo pregunto porque yo no sé la lógica de tu programa, pero al menos no lo veo del todo correcto.

Una posible solución sería esta:

procedure TForm2.RecibeEventoOnSalir(Sender: TObject);
begin
if (FrameCamAlt <> nil) and (Sender is TFrameCamAlt) then FreeAndNil(FrameCamAlt);
if (FrameCliAlt <> nil) and (Sender is TFrameCliAlt)then FreeAndNil(FrameCliAlt);
end;

El truco viene de la definición del frame, en la línea que se lanza el evento:

FOnSalir(Self);

como ves, se le pasa el parámetro "Self", que será un TFrameCamAlt o un TFrameCliAlt, según quien lance el evento. De esta forma solo liberamos el Frame donde se pulse el boton salir.

No lo he dicho, pero en el OnClose del TForm2 también tendrías que mirar si hay algún frame creado para liberarlo.

El "Abstract error" viene a decir que estamos ejecutando un método que está marcado como abstracto (abstract es una palabra reservada de delphi) que precisamente se pone para eso, para evitar un problema mayor del que estas teniendo. Imagina que el programa se cierra sin indicar ningún mensaje de error... ¿por donde empiezas a buscar?.

Ahora te muestra el mensajito de error y ya sabes que el problema está en la creación y destrucción de objetos, y es más que probable que hayas creado un método así:

constructor Create;
procedure Close;

cuando debería decir:

constructor Create;override;
procedure Close;override;

Para indicar que ese método que estas creando no es uno nuevo, sino que sustituye a uno existente en la clase de la que estas heredando (esa clase puede ser un Frame, un Form, etc).

Saludos y buena caza.

Albano
26-04-2007, 05:22:06
Hice eso que me mencionabas del "Sender", pero lo último que me propones no se donde ponerlo, la creación de los frames la hice como me indicaron Dec y tu, al darle click a un botón, pongo el siguiente código:
RecibeEventoOnSalir(Sender);
FrameCamAlt := TFrameCamAlt.Create(nil);
FrameCamAlt.OnSalir := RecibeEventoOnSalir;
FrameCamAlt.Parent := panelcontenido;
Donde se tiene que poner eso de override?

Lepe
26-04-2007, 12:03:44
Se hace cuando heredas de un frame o de una forma, normalmente usas estos 2 métodos especiales:


constructor Create(...); override;
destructor Destroy;


Si no has usado ni constructor ni destructor, pues.... el problema vendrá por otro sitio. Como ya ves es difícil de resolver, precisamente porque ese tipo de fallos son de concepto (crees que estas haciendo las cosas bien) y no detectas el fallo. La solución viene por estudiar (con F1 por ejemplo) todo aquello que puedas intuir que da fallos, y comprobar que está bien.

No sé si pueda ayudarte el Call Stack.

Primero activa tools- > options -> debugger "Stop on delphi exception", así al producirse la excepción "abstract error" el IDE de delphi se parará, a continuación mira en View -> Stack Call (llamadas de pila). Las primeras llamadas serán bastante raras y no te sonarán de nada, pero si sigues mirando, igual encuentras algún elemento de tu programa (un Form, un frame) etc, y muy probablemente se encuentre el error por ahí.

Suerte