Ver Mensaje Individual
  #8  
Antiguo 10-10-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
No sé qué entiendes por aplicación residente. Ya no estamos en la era del DOS .

Controlador.exe no es más que una aplicación como cualquier otra cuyo formulario principal tiene forma de barra y la coloco en la parte superior. La parte "difícil" es lograr que el sistema reconozca al formulario como una barra para que ventanas de otras aplicaciones no se monten sobre ella. En esto también te puedo ayudar pero lo mejor es que primero programes lo fundamental.

Detalles a tener en cuenta:

Lógicamente querrás impedir que cierren tu aplicación, para lo cual usas el evento OnCloseQuery del formulario. Sin embargo esto impedirá que se pueda cerrar la sesión de Windows pues tu aplicación no lo permitirá.

Para remediar lo anterior debes crear manejadores para los mensajes WM_QUERYENDSESSION y WM_ENDSESSION usando una variable booleana que le indique al evento OnCloseQuery si se está cerrando la sesión de Windows.

Yo lo tengo así:

Código Delphi [-]
(* Al recibir la petición para cerrar la sesión de Windows debemos ajustar *)
(* la bandera WinSessionEnding a true para permitir al evento CloseQuery   *)
(* cerrar la ventana.                                                      *)
procedure TMainForm.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
  WinSessionEnding := true;
  inherited;
end;

procedure TMainForm.WMEndSession(var Msg: TWMEndSession);
begin
  (* Terminar sólo si se confirma el cierre de sesión *)
  WinSessionEnding := Msg.EndSession;
  inherited;
end;

{
  En este evento impedimos que el usuario pueda cerrar la aplicación
  excepto cuando termine la sesión de Windows.
}
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if WinSessionEnding then
  begin
    (* Marcar la sesión en MySql como cerrada *)
    DmData.ZQuery.SQL.Text := Format(sCloseSession, [SesionId]);
    DmData.ZQuery.ExecSQL;
  end
  else
    CanClose := false;
end;

Hay otro problema concerniente a cómo Windows envía estos mensajes:

Anteriormente el proceso era el siguiente:

Cuando el usuario pide cerrar la sesión, el sistema manda el mensaje WM_QUERYENDSESSION a todas las aplicaciones abiertas para preguntarles si aceptan el final de la sesión.

Si todas las aplicaciones aceptan, entonces el sistema manda el mensaje WM_ENDSESSION nuevamente a todas las aplicaciones para que cada una realice las rutinas necesarias antes de cerrarse (p. ej. grabar la hora de salida en tu caso)

Si una aplicación no acepta, el sistema deja de enviar el mensaje WM_QUERYENDSESSION y ya no manda el mensaje WM_ENDSESSION.

De esta forma, cuando recibes WM_ENDSESSION tienes la seguridad de que el sistema se va a cerrar.

Sin embargo, actualmente el procesamiento es distinto:

El sistema manda WM_QUERYENDSESSION a todas las aplicaciones. En cuanto una contesta que sí acepta, el sistema inmediatamente le manda WM_ENDSESSION sin esperar a ver qué contestan las demás.

El problema entonces es el siguiente:

Cuando recibes WM_ENDSESSION actuas como si el sistema se va a cerrar, pero suponte que hay otra aplicación, después de la tuya, que no acepta el cierre de sesión.

El efecto será que el sistema no se cierra pero tu aplicación sí.

Para evitar esto yo uso la sigueinte línea al comienzo del dpr de mi aplicación:

Código Delphi [-]
SetProcessShutDownParameters($100, 0);

Básicamente, esta línea le dice a Windows en qué orden quiere recibir WM_ENDSESSION. Los de parámetro más bajo reciben el mensaje al último (uso $100 en lugar de 0 porque abajo de $100 está reservado para procesos del sistema)

Ahora, todo esto se basa en que para mi el final de mi sistema coincide con el de la sesión de Windows. A mi me funciona bien pero no sé si te cause conflictos por lo que mencionaste antes:

Cita:
Empezado por desve
Resultaria dificil utilizar el cuadro de login de windows, ya que las computadoras de laboratorio de una universidad despues de un tiempo de uso se vuelven lentas, y existiria demasiado tiempo muerto en apagar y prender.
Aquí no se debe apagar la pc pero sí cerrar la sesión de Windows y esto lleva un tiempo.

// Saludos
Responder Con Cita