Windows se está cerrando
Cómo el proceso de WM_ENDSESSION etc
Colaborador: HALLVARD VASSBOTN
{
En un anterior por correo con el asunto '[Delphi] Serias error a la hora de cierre
windows???' [email protected](Por Bakkendorff) escribe:
>Cuando usted tiene una aplicación delphi en funcionamiento, y que están cerrando ventanas,
>(no cierre su aplicación en primer lugar), NINGUNO de sus destructores se llama!!!!
Al principio pensé que el problema era del programador de código, pero luego me di cuenta de que realmente es un bug o al menos una muy perezoso 'característica'.
El problema parece ser que al cerrar Windows, primero enviar un mensaje WM_QueryEndSession mensaje a todas las ventanas de nivel superior. Esto es manejado y procesado correctamente por el TForm objeto en la VCL.
a Continuación, suponiendo que todas las aplicaciones se indicaba que era aceptar para cerrar, Windows enviará WM_EndSession mensajes a todas las ventanas. Este mensaje no es manejado por la VCL. La aplicación simplemente es derribado con una explosión.
Ninguna de las ventanas están cerradas, no destructor llamado y no los procedimientos de salida de llama.
La solución es controlar la WM_EndSession mensaje a ti mismo. Hay varias formas de manejo de los mensajes en Delphi, pero la única manera confiable para el manejo de la WM_ENDSESSION es el uso de la HookWindow método de Aplicación.
En el controlador de mensajes, comprobar para ver si el mensaje es una WM_ENDSESSION. Si es así, se debe cerrar la aplicación. Podemos llamar al método Close de la ventana principal, pero la documentación de API de Windows indica que el sistema podría pasar en cualquier momento después de regresar de la WM_ENDSESSION, y publicó un mensaje WM_QUIT podría no llegar nunca a la aplicación.
La solución es simplemente llame a Detener en su lugar. Esto llamará a todos los registrados los procedimientos de salida, incluyendo aquellos en los Controles y unidades DB. Estos se libre de la aplicación y de los objetos de la pantalla y tomar el BDE correctamente.
a continuación Un ejemplo sencillo:
}
unidad de Tst2u
interfaz
usos
& nbsp & nbsp SysUtils, WinTypes, unidades winprocs, Mensajes, Clases, Gráficos, Controles,
& nbsp & nbsp Formas, cuadros de diálogo, las redes, DBGrids, DB, DBTables
tipo
& nbsp & nbsp TForm1 = class(TForm)
& nbsp & nbsp & nbsp & nbsp DataSource1: TDataSource
& nbsp & nbsp & nbsp & nbsp Tabla1: TTable
& nbsp & nbsp & nbsp & nbsp DBGrid1: TDBGrid
& nbsp & nbsp & nbsp & nbsp procedimiento FormCreate(Sender: TObject)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp { Private declarations }
& nbsp & nbsp & nbsp & nbsp función HookProc(var Message: TMessage): boolean
& nbsp & nbsp pública
& nbsp & nbsp & nbsp & nbsp { Public declarations }
& nbsp & nbsp final
var
& nbsp & nbsp Form1: TForm1
aplicación
{$R *.DFM}
const
& nbsp & nbsp FlagFileName = 'C:/Flag.Fil'
procedimiento CreateFlagFile
var
& nbsp & nbsp F: Sistema.Texto
begin
& nbsp & nbsp Sistema.Assign(F, FlagFileName)
& nbsp & nbsp Sistema.Rewrite(F)
& nbsp & nbsp Writeln(F, 'Esto es una falsa bandera archivo')
& nbsp & nbsp Sistema.Cierre(F)
fin
procedimiento KillFlagFile
var
& nbsp & nbsp F: Archivo
begin
& nbsp & nbsp Sistema.Assign(F, FlagFileName)
& nbsp & nbsp Sistema.Borrar(F)
fin
procedimiento MyExitProc lejos
begin
& nbsp & nbsp KillFlagFile
fin
procedure TForm1.FormCreate(Sender: TObject)
begin
& nbsp & nbsp Aplicación.HookMainWindow(HookProc)
fin
función TForm1.HookProc(var Message: TMessage): boolean
begin
& nbsp & nbsp Resultado := false
& nbsp & nbsp si el Mensaje.Msg = WM_EndSession, a continuación,
& nbsp & nbsp empezar
& nbsp & nbsp & nbsp & nbsp si WordBool(Mensaje.wParam), a continuación,
& nbsp & nbsp & nbsp & nbsp empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Windows se está cerrando - limpiar!! }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Esto debe ejecutar todos los ExitProcs, cierre las ventanas y llamar a los destructores... }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Detener { Esto funciona! }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Esto debe cerrar las cosas correctamente,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp pero, ¿tenemos el tiempo suficiente para manejar cualquier publicado mensajes antes de que Windows
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ya está abajo?? Esto resultará en un PostQuitMessage que podría
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp nunca llega!}
{ Cerrar } { Esto no siempre funciona - evitar }
& nbsp & nbsp & nbsp & nbsp final
& nbsp & nbsp final
fin
inicialización
& nbsp & nbsp CreateFlagFile
& nbsp & nbsp AddExitProc(MyExitProc)
final.
Esta unidad se demuestra que los procedimientos de salida se llama al cerrar la app normalmente y cuando el cierre de las Ventanas y el uso de HookMainWindow. Sin HookMainWindow llamada, la salida proc no se llama. Esto es especialmente importante para la DB. Sin Parar, LCK archivos no se eliminarán, búferes posible que no se vacían, los cambios publicados y así sucesivamente.
Windows se esta cerrando
Windows se esta cerrando : Multi-millones de consejos para hacer su vida mas facil.
Como el proceso de WM_ENDSESSION etc
Colaborador: HALLVARD VASSBOTN
{
En un anterior por correo con el asunto '[Delphi] Serias error a la hora de cierre
windows???' [email protected](Por Bakkendorff) escribe:
>Cuando usted tiene una aplicacion delphi en funcionamiento, y que estan cerrando ventanas,
>(no cierre su aplicacion en primer lugar), NINGUNO de sus destructores se llama!!!!
Al principio pense que el problema era del programador de codigo, pero luego me di cuenta de que realmente es un bug o al menos una muy perezoso 'caracteristica'.
El problema parece ser que al cerrar Windows, primero enviar un mensaje WM_QueryEndSession mensaje a todas las ventanas de nivel superior. Esto es manejado y procesado correctamente por el TForm objeto en la VCL.
a Continuacion, suponiendo que todas las aplicaciones se indicaba que era aceptar para cerrar, Windows enviara WM_EndSession mensajes a todas las ventanas. Este mensaje no es manejado por la VCL. La aplicacion simplemente es derribado con una explosion.
Ninguna de las ventanas estan cerradas, no destructor llamado y no los procedimientos de salida de llama.
La solucion es controlar la WM_EndSession mensaje a ti mismo. Hay varias formas de manejo de los mensajes en Delphi, pero la unica manera confiable para el manejo de la WM_ENDSESSION es el uso de la HookWindow metodo de Aplicacion.
En el controlador de mensajes, comprobar para ver si el mensaje es una WM_ENDSESSION. Si es asi, se debe cerrar la aplicacion. Podemos llamar al metodo Close de la ventana principal, pero la documentacion de API de Windows indica que el sistema podria pasar en cualquier momento despues de regresar de la WM_ENDSESSION, y publico un mensaje WM_QUIT podria no llegar nunca a la aplicacion.
La solucion es simplemente llame a Detener en su lugar. Esto llamara a todos los registrados los procedimientos de salida, incluyendo aquellos en los Controles y unidades DB. Estos se libre de la aplicacion y de los objetos de la pantalla y tomar el BDE correctamente.
a continuacion Un ejemplo sencillo:
}
unidad de Tst2u
interfaz
usos
& nbsp & nbsp SysUtils, WinTypes, unidades winprocs, Mensajes, Clases, Graficos, Controles,
& nbsp & nbsp Formas, cuadros de dialogo, las redes, DBGrids, DB, DBTables
tipo
& nbsp & nbsp TForm1 = class(TForm)
& nbsp & nbsp & nbsp & nbsp DataSource1: TDataSource
& nbsp & nbsp & nbsp & nbsp Tabla1: TTable
& nbsp & nbsp & nbsp & nbsp DBGrid1: TDBGrid
& nbsp & nbsp & nbsp & nbsp procedimiento FormCreate(Sender: TObject)
& nbsp & nbsp privada
& nbsp & nbsp & nbsp & nbsp { Private declarations }
& nbsp & nbsp & nbsp & nbsp funcion HookProc(var Message: TMessage): boolean
& nbsp & nbsp publica
& nbsp & nbsp & nbsp & nbsp { Public declarations }
& nbsp & nbsp final
var
& nbsp & nbsp Form1: TForm1
aplicacion
{$R *.DFM}
const
& nbsp & nbsp FlagFileName = 'C:/Flag.Fil'
procedimiento CreateFlagFile
var
& nbsp & nbsp F: Sistema.Texto
begin
& nbsp & nbsp Sistema.Assign(F, FlagFileName)
& nbsp & nbsp Sistema.Rewrite(F)
& nbsp & nbsp Writeln(F, 'Esto es una falsa bandera archivo')
& nbsp & nbsp Sistema.Cierre(F)
fin
procedimiento KillFlagFile
var
& nbsp & nbsp F: Archivo
begin
& nbsp & nbsp Sistema.Assign(F, FlagFileName)
& nbsp & nbsp Sistema.Borrar(F)
fin
procedimiento MyExitProc lejos
begin
& nbsp & nbsp KillFlagFile
fin
procedure TForm1.FormCreate(Sender: TObject)
begin
& nbsp & nbsp Aplicacion.HookMainWindow(HookProc)
fin
funcion TForm1.HookProc(var Message: TMessage): boolean
begin
& nbsp & nbsp Resultado := false
& nbsp & nbsp si el Mensaje.Msg = WM_EndSession, a continuacion,
& nbsp & nbsp empezar
& nbsp & nbsp & nbsp & nbsp si WordBool(Mensaje.wParam), a continuacion,
& nbsp & nbsp & nbsp & nbsp empezar
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Windows se esta cerrando - limpiar!! }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Esto debe ejecutar todos los ExitProcs, cierre las ventanas y llamar a los destructores... }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Detener { Esto funciona! }
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp { Esto debe cerrar las cosas correctamente,
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp pero, ¿tenemos el tiempo suficiente para manejar cualquier publicado mensajes antes de que Windows
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp ya esta abajo?? Esto resultara en un PostQuitMessage que podria
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp nunca llega!}
{ Cerrar } { Esto no siempre funciona - evitar }
& nbsp & nbsp & nbsp & nbsp final
& nbsp & nbsp final
fin
inicializacion
& nbsp & nbsp CreateFlagFile
& nbsp & nbsp AddExitProc(MyExitProc)
final.
Esta unidad se demuestra que los procedimientos de salida se llama al cerrar la app normalmente y cuando el cierre de las Ventanas y el uso de HookMainWindow. Sin HookMainWindow llamada, la salida proc no se llama. Esto es especialmente importante para la DB. Sin Parar, LCK archivos no se eliminaran, buferes posible que no se vacian, los cambios publicados y asi sucesivamente.
Windows se está cerrando
By Consejos Y Trucos
Windows se está cerrando : Multi-millones de consejos para hacer su vida más fácil.