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