English 中文(简体)
检测 Windows 关闭窗口或应用程序是否试图关闭系统菜单( WM_CLOSE)
原标题:Detect if Windows closing or application tries to close from system menu (WM_CLOSE)
  • 时间:2012-05-24 20:56:40
  •  标签:
  • delphi
  • tray

我有托盘应用程序。

Onj FormClose 查询我检查程序是否应该转到托盘,而不是关闭它,我把它放在托盘中(CanClose:= False)

但如果 Windows 因 Windows 关闭而试图关闭我的应用程序,

Win7 终止了我的应用程序, 但XP没有关闭,因为我的应用程序仍然在托盘中。

我怎样才能察觉 Windows是不是某种"休眠"模式?

谢谢!

最佳回答

您的问题来自使用 OnCloseQuery 的错误事件。 Remy S 的回答解释了如何在默认 VCL 终端会话处理中屏蔽 Windows 关闭窗口 。 这反过来又由于在 OnCloseQuery 事件中设置 CanClose False 造成。

That workaround will get the job done but there s a much simpler way to deal with this. Instead of stopping the form from closing, let it go ahead and close. Remove your OnCloseQuery event altogether. Replace it with an OnClose event.

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  Visible := False;
end;

当主窗体关闭时, 这个相当小的代码位足以让您的应用程序 < em> 最小化到托盘

问题回答

如果 onCloseQuery 事件是因响应 WMUERYENDESSION 消息而触发的,设定 CanClose=False 将使消息返回 FALSE

在 XP 上和之前, 这将取消 Windows 关闭 。 到此点为止, 收到 < code> WUUERYENDSSISION < /code> 消息的任何应用程序都会收到 < code> WM_ENDSSION < /code > 消息, 其 < code> wParam 值被设置为 < code> FALSE , 告诉这些应用程序 < strong > NOT 自己终止。 这就是为什么您的应用程序会进入托盘, 并在 Windows 关闭时不退出 。

微软在 Windows Vista 中改变了此行为, 所以应用程序无法通过 < code> WM UERYENDSSISION 取消 Windows 关闭 。 这就是为什么 Windows Vista 和 以后将终止您的应用程序。 如果应用程序需要停止 Windows 关闭, 将会引入一个全新的 API 。

这在MSDN上有记载:

< a href=>""http://msdn.microsoft.com/en-us/library/ms700677.aspx" rel=“ noreferrer" >Windows Vista 中应用的关闭更改

要按您的要求行事, 您必须直接拦截 < code> WMUIULYENDSSISION 消息, 这样您才能确定 < code> OnCloseQuery < /code> 是否因 Windows 关闭被调用 。 例如 :

type
  TForm1 = class(TForm)
  private
    procedure WMQueryEndSession(var Message: TWMQueryEndSession); message WM_QUERYENDSESSION;
    procedure WMEndSession(var Message: TWMEndSession); message WM_ENDSESSION;
  end;

var
  ShuttingDown: Boolean = False;

procedure TForm1.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
  ShuttingDown := True;
  inherited;
end;

procedure TForm1.WMEndSession(var Message: TWMEndSession);
begin
  ShuttingDown := Message.EndSession;
  inherited;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := ShuttingDown;
  if not ShuttingDown then
  begin
    // your Tray logic here ...
  end;
end;




相关问题
determining the character set to use

my delphi 2009 app has a basic translation system that uses GNUGetText. i had used some win API calls to prepare the fonts. i thought it was working correctly until recently when someone from Malta ...

Help with strange Delphi 5 IDE problems

Ok, I m going nuts here. For the last (almost) four years, I ve been putting up with some extremely bad behavior from my Delphi 5 IDE. Problems include: Seemingly random errors in coride50.bpl ...

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How convert string to integer in Oxygene

In Delphi, there is a function StrToInt() that converts a string to an integer value; there is also IntToStr(), which does the reverse. These functions doesn t appear to be part of Oxygene, and I can ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签