home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / delphi.swg / 0055_Process WM_ENDSESSION.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-11-24  |  3.8 KB  |  128 lines

  1. {
  2. In a previous mailed with the subject "[Delphi] Serios bug when closing
  3. windows???" bimmer@ibm.net(Per Bakkendorff) writes:
  4. >When you have a delphi application running, and you are shutting down windows,
  5. >(don't close your app first), NONE of your destructors are called!!!!
  6.  
  7. At first I thought the problem was programmer's code, but then I realized
  8. that it really is a bug or at least a very lazy "feature".
  9.  
  10. The problem seems to be that when you close down Windows, it will first
  11. send a WM_QueryEndSession message to all running top-level windows. This
  12. is handled and processed correctly by the TForm object in VCL.
  13.  
  14. Then assuming that all applications indicated that it was ok to close down,
  15. Windows will send WM_EndSession messages to all windows. This message is
  16. not handled by VCL. The application is simply brought down with a bang.
  17. No windows are closed, no destructor called and no exit procedures called.
  18.  
  19. The solution is to handle the WM_EndSession message yourself. There are
  20. several ways of handling messages in Delphi, but the only reliable way
  21. of handling the WM_ENDSESSION is to use the HookWindow method of
  22. Application.
  23.  
  24. In the message handler, check to see if the message is a WM_ENDSESSION.
  25. If so, we should close down the application. We could have called the
  26. Close method of the main window, but the Windows API documentation states
  27. that the system might go down anytime after return from the WM_ENDSESSION,
  28. and a posted WM_QUIT message might never arrive to the application.
  29.  
  30. The solution is to simply call Halt instead. This will call all registred
  31. exit procedures, including the ones in Controls and DB units. These will
  32. free the application and screen objects and take the BDE down correctly.
  33.  
  34. A simple example follows:
  35. }
  36.  
  37. unit Tst2u;
  38.  
  39. interface
  40.  
  41. uses
  42.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  43.   Forms, Dialogs, Grids, DBGrids, DB, DBTables;
  44.  
  45. type
  46.   TForm1 = class(TForm)
  47.     DataSource1: TDataSource;
  48.     Table1: TTable;
  49.     DBGrid1: TDBGrid;
  50.     procedure FormCreate(Sender: TObject);
  51.   private
  52.     { Private declarations }
  53.     function HookProc(var Message: TMessage): boolean;
  54.   public
  55.     { Public declarations }
  56.   end;
  57.  
  58. var
  59.   Form1: TForm1;
  60.  
  61. implementation
  62.  
  63. {$R *.DFM}
  64.  
  65. const
  66.   FlagFileName = 'C:\Flag.Fil';
  67.  
  68. procedure CreateFlagFile;
  69. var
  70.   F: System.Text;
  71. begin
  72.   System.Assign(F, FlagFileName);
  73.   System.Rewrite(F);
  74.   Writeln(F, 'This is a dummy flag file');
  75.   System.Close(F);
  76. end;
  77.  
  78. procedure KillFlagFile;
  79. var
  80.   F: File;
  81. begin
  82.   System.Assign(F, FlagFileName);
  83.   System.Erase(F);
  84. end;
  85.  
  86. procedure MyExitProc; far;
  87. begin
  88.   KillFlagFile;
  89. end;
  90.  
  91. procedure TForm1.FormCreate(Sender: TObject);
  92. begin
  93.   Application.HookMainWindow(HookProc);
  94. end;
  95.  
  96. function TForm1.HookProc(var Message: TMessage): boolean;
  97. begin
  98.   Result := false;
  99.   if Message.Msg = WM_EndSession then
  100.   begin
  101.     if WordBool(Message.wParam) then
  102.     begin
  103.       { Windows is closing down - clean up!! }
  104.  
  105.       { This should execute all ExitProcs, close windows and call destructors... }
  106.        Halt; { This works! }
  107.  
  108.       { This should close things down properly,
  109.         but do we have enough time to handle any posted messages before Windows
  110.         is already down??  This will result in a PostQuitMessage that might
  111.         never arrive!}
  112. {      Close;} { This doesn't always work - avoid it }
  113.     end;
  114.   end;
  115. end;
  116.  
  117. initialization
  118.   CreateFlagFile;
  119.   AddExitProc(MyExitProc);
  120. end.
  121.  
  122. This unit demonstrates that the exit procedures are called when closing
  123. the app normally and when closing down Windows and using HookMainWindow.
  124. Without the HookMainWindow call, the exit proc will not be called. This
  125. is specially important for DB applications. Without the Halt, LCK files
  126. will not be deleted, buffers might not be flushed, changes posted and
  127. so on.
  128.