Windows - descobrir se esta fechando

Top  Previous  Next

   procedure EndSession(var Message: TWMEndSession); message WM_ENDSESSION;  // ocorre quando dá logoff

 

procedure TBartForm.EndSession(var Message: TWMEndSession);

begin

  inherited;

  Message.Result := 1;

end;

 

------------------------ another way --------------------

Performing an action when Windows shuts down a Delphi app

 

I did a little investigation, and here is what seems to be happening:

 

Normally, when you exit a Delphi application by using the system menu or by calling the Form's Close method, the following event handlers are called:

 

FormCloseQuery - the default action sets the variable CanClose=TRUE so form close will continue. 

FormClose 

FormDestroy 

If the application is active and you attempt to exit Windows, the event handlers are called in the following sequence:

 

FormCloseQuery 

FormDestroy 

The FormClose method never seems to be called.

 

Here is the flow of events when the user chooses to end the Windows session:

 

Windows sends out a WM_QUERYENDSESSION message to all application windows one by one and awaits a response 

Each application window receives the message and returns a non-zero value if it is OK to terminate, or 0 if it is not OK to terminate. 

If any application returns 0, the Windows session is not ended, otherwise, Windows sends a WM_ENDSESSION message to all application windows 

Each Application Window responds with a TRUE value indicating that Windows can terminate any time after all applications have returned from processing this message. This appears to be the location of the Delphi problem: Delphi applications seem to return TRUE and the FormDestroy method is called immediately, bypassing the FormClose method. 

Windows exits 

One solution is to respond to the WM_QUERYENDSESSION message in the Delphi application and prevent Windows from exiting by returning a 0 result. This can't be done in the FormCloseQuery method because there is no way to determine the source of the request (it can either be the result of the WM_QUERYENDSESSION message or the user just simply closing the application). 

 

Another solution is to respond to the WM_QUERYENDSESSION message by calling the same cleanup procedure you call in the FormClose method.

 

Example:

 

 

--------------------------------------------------------------------------------

 

unit Unit1;

interface

uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,

Dialogs;

type

  TForm1 = class(TForm)

    procedure FormClose(Sender: TObject; var Action: TCloseAction);

  private

  {---------------------------------------------------------------}

  { Custom procedure to respond to the WM_QUERYENDSESSION message }

  {---------------------------------------------------------------}

  procedure WMQueryEndSession(

             var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;

  public

    { Public declarations }

  end;

var

  Form1    : TForm1;

 

implementation

{$R *.DFM}

 

{---------------------------------------------------------------}

{ Custom procedure to respond to the WM_QUERYENDSESSION message }

{ The application will only receive this message in the event   }

{ that Windows is requesing to exit.                            }

{---------------------------------------------------------------}

procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);

begin

  inherited;         { let the inherited message handler respond first }

  {--------------------------------------------------------------------}

  { at this point, you can either prevent windows from closing...      }

  { Message.Result:=0;                                                 }

  {---------------------------or---------------------------------------}

  { just call the same cleanup procedure that you call in FormClose... }

  { MyCleanUpProcedure;                                                }

  {--------------------------------------------------------------------}

end;

 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  MyCleanUpProcedure;

end;

 

end.