关于 OnCloseQuery: 顺序、不能关机等(所有的windows的广播消息都是逐窗口传递的)——如果一个窗体的OnCloseQuery事件中如果写了代码那么WM_QUERYENDSESSION消息就传不过去了msg.result会返回0,关机事件也就停止了

时间:2024-03-24 15:34:20

系统关闭窗体的事件顺序为:

OnCloseQuery ----> OnClose ----> OnDestroy

下面的代码说明问题:

  1. unit Unit3;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  5. Dialogs;
  6. type
  7. TForm3 = class(TForm)
  8. procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  9. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  10. procedure FormDestroy(Sender: TObject);
  11. private
  12. { Private declarations }
  13. public
  14. { Public declarations }
  15. end;
  16. var
  17. Form3: TForm3;
  18. implementation
  19. {$R *.dfm}
  20. procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
  21. begin
  22. MessageBox(Handle,'正在关闭窗体!','提示',MB_OK or MB_ICONWARNING);
  23. end;
  24. procedure TForm3.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  25. begin
  26. if MessageBox(Handle,'你确定要关闭该窗体吗?','提示',MB_YESNO or MB_ICONINFORMATION) = IDYES then
  27. CanClose:=True
  28. else
  29. CanClose:=False;
  30. end;
  31. procedure TForm3.FormDestroy(Sender: TObject);
  32. begin
  33. // 必须用Application的方法了
  34. Application.MessageBox('释放窗体','提示');
  35. end;

另外 从网友 http://echocancer.spaces.live.com/blog/cns!97776b41bf0a7f5d!141.entry 出摘的 文章:

程序不能关机?看看你在OnCloseQuery里是不是写了代码!

今天终于解决了程序不能关机的问题,都是OnCloseQuery惹得祸!
程序里有多个窗体,其中有两个在OnCloseQuery里写了处理代码,导致程序不能关机。
一开始我安网上找到的办法试图在主窗口中截获WM_QUERYENDSESSION消息然后返回Msg.Result=1。发现这个消息根本就没有传到主窗口来,后来我又怀疑是不是Application.OnMessage把这个消息给拦截掉了,后来发现也不是的。最后才弄清楚如果一个窗体的OnCloseQuery事件中如果写了代码那么WM_QUERYENDSESSION消息就传不过去了msg.result会返回0,关机事件也就停止了。因为程序中有两个窗体的OncloseQuery中都写了代码所以WM_QUERYENDSESSION消息根本就传不到主窗口。最后在那两个窗口中拦截WM_QUERYENDSESSION消息,强制将msg.result返回1就解决了问题。
这次的问题让我对windows的消息机制又有了更深的了解,所有的windows的广播消息都是逐窗口传递的。
http://blog.csdn.net/procedure1984/article/details/5418279