我正在使用托盘申请。
Onj FormCloseQuery我检查程序是否应该转到托盘而不是关闭它我把它放在托盘中(CanClose:= False)
但是如果Windows由于Windows关闭而尝试关闭我的应用程序,我想不要将我的应用程序移动到托盘中,而是关闭它。
Win7终止我的应用程序,但XP没有关闭,因为我的应用程序仍然在托盘中。
如何检测Windows是否处于某种“关闭”模式?
谢谢!
答案 0 :(得分:13)
如果针对OnCloseQuery
消息触发WM_QUERYENDSESSION
事件,则设置CanClose=False
将导致消息返回FALSE
。
在XP及更早版本中,这将取消Windows关机。到目前为止,任何收到WM_QUERYENDSESSION
消息的应用都会收到WM_ENDSESSION
消息,其wParam
值设置为FALSE
,告知这些应用 NOT 强>终止自己。这就是为什么你的应用程序进入托盘并且在Windows关闭期间不退出的原因。
Microsoft在Windows Vista中更改了此行为,因此应用无法再通过WM_QUERYENDSESSION
取消Windows关闭。这就是Windows Vista及更高版本将终止您的应用程序的原因。如果应用程序需要故意停止Windows关闭,则会引入全新的API。
这在MSDN上有记录:
Application Shutdown Changes in Windows Vista
要执行您要求的操作,您必须直接拦截WM_QUERYENDSESSION
消息,以便确定是否因Windows关闭而调用OnCloseQuery
。例如:
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;
答案 1 :(得分:8)
您的问题源于OnCloseQuery
的使用,这是一个错误的事件。 Remy的答案解释了如何解决Windows关闭被默认VCL结束会话消息处理阻止的问题。而这又是由CanClose
事件中的False
设置为OnCloseQuery
引起的。
这种解决方法将完成工作,但有一种更简单的方法来解决这个问题。
不要让表格停止关闭,而是让它继续前进并关闭。完全删除您的OnCloseQuery
活动。将其替换为OnClose
事件。
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caNone;
Visible := False;
end;
这个相当简单的代码足以让您的应用在主窗体关闭时最小化到托盘。