PDA

Ver la Versión Completa : Comportamiento extraño de la aplicacion con los Dialogs


Edwardfeliz
27-07-2022, 00:07:05
Saludos, le comento algo extraño que me está pasando,
Tengo un programa desallorado en delphi 10.4 Community edition (Solo para informar).
Resulta que, en un panel, muestro algunos formularios ahí, como por ejemplo uno que se abre desde que el programa inicia, colocas una información y con un botón se cierra.
Lo muestro de forma automática de la siguiente forma:

FVerificacion := TFVerificacion.Create(Self);
FVerificacion.Parent := PNCentral;
FVerificacion.Align := alClient;
FVerificacion.Show;


y al final me deshago de él simplemente con un "close", todo bien hasta aquí, resulta que abro otro formulario (En el mismo panel), y dentro de ese formulario, utilizo un savedialog...
para guardar un archivo, luego de mostrarse la ventana y todo y guardar el archivo, se abre solo el formulario de verificación, y desaparece incluso el otro formulario que habia abierto en el panel, solo me pasa eso luego de comenzar a usar el savedialog en el programa.
:eek:

dec
27-07-2022, 08:40:45
Hola a todos,

Si te vuelve a aparecer el formulario de verificación, diría yo que debe estar relacionado con su "Parent" y con el hecho de que no liberes el formulario al cerrarlo. Podrías probar situando el siguiente código en el evento "OnClose" del formulario de verificación:


Action := caFree;


Con eso estaríamos liberando el formulario de verificación cuando se cierre, y, de este modo, no debería poderte "aparecer" de nuevo, si no lo vuelves a crear. Podrías probar con esto a ver si te soluciona el asunto... y acaso también usar el mismo código en el resto de formularios que sitúas en el panel.

P.D. Dicho lo anterior, he intentado reproducir el problema y no he sido capaz, de modo que a lo mejor hay algo que se escapa y que esté causando el asunto. En todo caso prueba lo dicho anteriormente, puesto que un formulario que ha sido liberado no puede volver a mostrarse sin más.

Neftali [Germán.Estévez]
27-07-2022, 12:48:49
En estos casos, lo más sencillo es crear un pequeño proyecto de ejemplo con un par de formularios vacíos, donde se reproduzca el problema, y adjuntarlo al mensaje (ZIP).
De esa forma es más sencillo de probar y "tocar" el proyecto.

Edwardfeliz
27-07-2022, 15:20:42
Hola a todos,

Si te vuelve a aparecer el formulario de verificación, diría yo que debe estar relacionado con su "Parent" y con el hecho de que no liberes el formulario al cerrarlo. Podrías probar situando el siguiente código en el evento "OnClose" del formulario de verificación:


Action := caFree;


Con eso estaríamos liberando el formulario de verificación cuando se cierre, y, de este modo, no debería poderte "aparecer" de nuevo, si no lo vuelves a crear. Podrías probar con esto a ver si te soluciona el asunto... y acaso también usar el mismo código en el resto de formularios que sitúas en el panel.

P.D. Dicho lo anterior, he intentado reproducir el problema y no he sido capaz, de modo que a lo mejor hay algo que se escapa y que esté causando el asunto. En todo caso prueba lo dicho anteriormente, puesto que un formulario que ha sido liberado no puede volver a mostrarse sin más.

Esto no funcionó....


;547612']En estos casos, lo más sencillo es crear un pequeño proyecto de ejemplo con un par de formularios vacíos, donde se reproduzca el problema, y adjuntarlo al mensaje (ZIP).
De esa forma es más sencillo de probar y "tocar" el proyecto.

Hola, Gracias por Responder....
Efectivamente intente replicarlo y no hace el problema :confused:, parece que es el proyecto en si, (Puede pasar porque el programa es muy visual? con muchos recursos esteticos y eso?)
lo que hice fue hacer un video del problema y subirlo a un enlace que les comparto a continuacion...
https://youtu.be/XCYZjovh9qI

La unica solucion Inmediata mientras descubro la causa, es luego de ejecutar el Dialog, mandar a cerrar dicho formulario de Verificacion. Con un Close.

Casimiro Notevi
27-07-2022, 17:10:25
Poco te pueden ayudar si no pones el código que usas.
Y aparte de eso ya han comentado antes que liberes el formulario, pues en el código lo creas:
FVerificacion := TFVerificacion.Create(Self);
¿Pero dónde lo destruyes?

duilioisola
27-07-2022, 19:56:44
Además del Action := caFree en el OnClose, quizás deberías limpiar la variable que apunta al formulario.

FVerificacion := TFVerificacion.Create(Self);
FVerificacion.Parent := PNCentral;
FVerificacion.Align := alClient;
FVerificacion.Show;
FVerificacion := nil; // Esta variable podría estar apuntando a un formulario ya liberado.


Yo lo que haría es:
with TFVerificacion.Create(Self) do
begin
Parent := PNCentral;
Align := alClient;
Show;
end;
Esto evita tener que definir una variable y luego tener que acordarte de liberarla.

Edwardfeliz
27-07-2022, 20:23:40
Poco te pueden ayudar si no pones el código que usas.
Y aparte de eso ya han comentado antes que liberes el formulario, pues en el código lo creas:
FVerificacion := TFVerificacion.Create(Self);
¿Pero dónde lo destruyes?

Referente al codigo explique como llamo al formulario y para cerrarlo habia dicho que uso un close.
Cuando libero el formulario mediante un Free por ejemplo se produce un access_violation c0000005.
El mismo error cuando utilizo esta forma como sugirió duilioisola.

with TFVerificacion.Create(Self) do
begin
Parent := PNCentral;
Align := alClient;
Show;
end;
Ambas formas dan el Access Violation.


Además del Action := caFree en el OnClose, quizás deberías limpiar la variable que apunta al formulario.

FVerificacion := TFVerificacion.Create(Self);
FVerificacion.Parent := PNCentral;
FVerificacion.Align := alClient;
FVerificacion.Show;
FVerificacion := nil; // Esta variable podría estar apuntando a un formulario ya liberado.


Yo lo que haría es:
with TFVerificacion.Create(Self) do
begin
Parent := PNCentral;
Align := alClient;
Show;
end;
Esto evita tener que definir una variable y luego tener que acordarte de liberarla.

Colocando solo el Action := caFree en el close, hace el mismo efecto. No cambia el comportamiento.
y liberandolo causa el access violation.


Explicare nuevamente como se relacionan los formularios y como se llaman y utilizan.

- El formulario principal tiene un panel donde se muestran los demas formularios, algunos formularios simplemente se muestran fuera del panel con un tipo de borde simple.
Caracteristicas del formulario principal:
BorderStyle BsSizeable.
Con sus 3 border icons.

- El Formulario de Verificacion se muestra dentro del panel del formulario principal esto sucede desde que el programa inicia se muestra el principal ya con el de verificacion dentro, es solo para colocar usuario y contraseña y se muestra con el siguiente codigo:

Verificacion := TVerificacion.Create(Self);
Verificacion.Parent := PNCentral;
Verificacion.Align := alClient;
Verificacion.Show;

Cuando se colocan los datos, para cerrarlo solo se utiliza un Close. Si utilizo un free me produce un access violation.
Caracteristicas de este formulario:
Sin iconos en los bordes y el borderstyle es None.

- El formulario de configuracion al igual que el de verificacion no tiene bordes ni los iconos, y se muestra dentro del panel del formulario principal.
Es un formulario solo con botones de opciones. Por el cual se llama al formulario de Comprobantes donde esta el boton con el SaveDialog.
Para abrirlo se hace de la siguiente forma.


FConfiguracion := TFConfiguracion.Create(Self);
FConfiguracion.Parent := PNCentral;
FConfiguracion.Align := alClient;
FConfiguracion.Show;


(Lo cambie por el que me recomendaron pero no es la razon del problema).

with TFConfiguracion.Create(Self) do
begin
Parent := PNCentral;
Align := alClient;
Show;
end;


y Para liberarlo se hace con un Close.

- El formulario de comprobantes se abre desde el formulario de Configuracion. Es una ventana que no se muestra dentro del panel, la llamo de la siguiente forma:
FComprobantes := TFComprobantes.Create(self);
try
FComprobantes.ShowModal;
Finally
FComprobantes.Free;
end;

En este formulario es que esta el Dialog, que cuando se ejecuta y se cierra causa que el formulario de verificacion se vuelva a mostrar en el panel principal.
para abrir el dialg simplemente es un
if dlgguardar.Execute then
nada fuera de lo normal ni antes ni despues de este codigo.

Espero haber aclarado mas el asunto.

Neftali [Germán.Estévez]
28-07-2022, 08:54:25
...se abre solo el formulario de verificación, y desaparece incluso el otro formulario que habia abierto en el panel,

=> Verificación, entiendo que es el de Usuario/Contraseña
=> Otro, entiendo que es el de BACKUP, ROLES, USUARIOS,...


Lo único que se me ocurre es que hagas LOG de eventos importantes a ver si adivinas qué está pasando con los formularios de Visualización y el Otro.
O estás cerrando el Otro (de forma involuntaria), o estás abriendo un segundo form de Visualización (que tapa el otro) o el Otro está perdiendo el padre y deja de verse...

(1) Por ejemplo, graba en un log, los eventos de Create, Close, Destroy,... de todos los forms, para ver el ciclo de vida de cada uno de ellos.
=> Te permitirá saber si alguno se está destruyendo sin tú saberlo (o ha quedado oculto, o sin parent,..)

(2) Haz un procedimiento que utilice Screen.Forms (https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Forms.TScreen.Forms), y coloca un botón en el Main para llamarlo. De forma que en cualquier momento te permita conocer (ya sea mostrando un ShowMessage o volcando al LOG) los formularios abiertos en cada momento.
=> Te permitirá saber si el form Otro, realmente está destruído o es que no lo estás viendo...

Edwardfeliz
30-07-2022, 05:02:35
;547631']=> Verificación, entiendo que es el de Usuario/Contraseña
=> Otro, entiendo que es el de BACKUP, ROLES, USUARIOS,...


Lo único que se me ocurre es que hagas LOG de eventos importantes a ver si adivinas qué está pasando con los formularios de Visualización y el Otro.
O estás cerrando el Otro (de forma involuntaria), o estás abriendo un segundo form de Visualización (que tapa el otro) o el Otro está perdiendo el padre y deja de verse...

(1) Por ejemplo, graba en un log, los eventos de Create, Close, Destroy,... de todos los forms, para ver el ciclo de vida de cada uno de ellos.
=> Te permitirá saber si alguno se está destruyendo sin tú saberlo (o ha quedado oculto, o sin parent,..)

(2) Haz un procedimiento que utilice Screen.Forms (https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Forms.TScreen.Forms), y coloca un botón en el Main para llamarlo. De forma que en cualquier momento te permita conocer (ya sea mostrando un ShowMessage o volcando al LOG) los formularios abiertos en cada momento.
=> Te permitirá saber si el form Otro, realmente está destruído o es que no lo estás viendo...

Entiendo tu planteamiento y analisis, Gracias por las ideas, probare con calma y dejo saber cualquier descubrimiento.