|
Hola de nuevo.
Primero debo decir que los tips de Lepe me sirvieron de mucho, he hecho lo que ha propuesto él y todo funciona bien en esa parte.
Sin embargo lamento decir que el problema de fondo no se resolvió. Sucede que lo que yo creía que era el problema en realidad es solo un síntoma de un problema más profundo. En otras palabras el problema no está en la destrucción de la ventana modal como yo creía. El problema parte de un evento anterior a la creación de esa ventana.
Paso a explicar lo que sucede.
Como había dicho en mi primer mensaje, el programa presenta una lista de datos, esa lista es un TObjectList, uso esta clase porque necesito que cada nodo de la lista contenga un componente TLabel (que es el encargado de mostrar visualmente los datos). Para darle la opción al usuario a editar esos datos el nodo debe capturar el evento click de ese TLabel, en la clase TNodo he creado un evento nuevo que debe ejecutarse cuando se hace clic en el TLabel y que además pasa como parámetro el índice del nodo en la lista, así puedo saber en qué nodo se hizo clic. En el formulario principal asigno código a ese evento y allí creo la ventana modal para editar ese nodo.
En circunstancias normales todo funciona bien. Pero cuando la lista se destruye debido a que todos los datos son invalidados (como expliqué en mi primer mensaje), el contexto del evento click en el nodo no ha terminado aún cuando la ventana modal está abierta. En ocaciones, y supongo que se debe a cómo Delphi administra la sicronización de eventos, el contexto del evento termina antes que se destruya la lista y entonces no ocurre ningún error, pero a veces termina después de que la lista ha sido destruida y por lo tanto se trata de finalizar un evento de un componente que ya no existe, el resultado es un 'Access Violation'.
Cuando tengo que destruir la lista y volver a crearla con datos nuevos procedo de esta manera.
1.- Ocurre el evento de sicronización de datos.
2.- Verifico si hay una ventana modal abierta.
3.- Si la hay procedo a cerrarla.
4.- Llamo al método Clear de TObjectList eliminando todos los nodos incluyendo los TLabels.
Pero si hay una ventana modal abierta es porque ha sucedido lo siguiente.
1.- El usuario hace clic en el TLabel del nodo.
2.- Ejecuto el evento.
3.- Se crea la ventana modal lista para editar los datos del nodo.
4.- (1) Ocurre el evento de sicronización de datos.
5.- (2) Verifico si hay una ventana modal abierta.
6.- (3) Si la hay procedo a cerrarla.
7.- (4) Llamo al método Clear de TObjectList.
8.- El evento clic del TLabel del nodo debe terminar.
9.- Tal TLabel no existe = Access Violation.
Para complicar las cosas el OnClick del TLabel no es el único evento que se ejecuta, Delphi llama a tres eventos en total: OnClick, OnMouseDown y OnMouseUp. Es este último donde aparece el Access Violation aún cuando no tengo ningún código para ese evento Delphi aún así tiene que verificar eso.
Poner un Application.ProcessMessage; junto antes de destruir la ventana modal no soluciona el problema.
Revolviendo el código de la VCL llegué a la línea 4759 del Controls.pas, es una llamada al procedimiento DoMouseUp() de los TControls. Me siento muy inclinado a encerrar esa llamada en un try ... except para que no aparezca ante el usuario el mensaje de error :P. Pero sé que esa no es solución.
¿Alguna idea?.
Si es necesario que ponga código no tengo problemas en escribir uno que reproduzca el problema, aunque quedará medio largo.
Gracias por su atención.
|