Delphi 检测Windows是否关闭或应用程序是否尝试从系统菜单关闭(WM_close)
我正在做托盘申请 Onj FormCloseQuery我检查程序是否应该转到托盘,而不是关闭它,我把它放在托盘中(CanClose:=False) 但如果Windows因为Windows关闭而试图关闭我的应用程序,我不想将我的应用程序移动到任务栏中,而是想关闭它 Win7终止我的应用程序,但XP未关闭,因为我的应用程序仍在任务栏中 如何检测Windows是否处于某种“关闭”模式Delphi 检测Windows是否关闭或应用程序是否尝试从系统菜单关闭(WM_close),delphi,tray,Delphi,Tray,我正在做托盘申请 Onj FormCloseQuery我检查程序是否应该转到托盘,而不是关闭它,我把它放在托盘中(CanClose:=False) 但如果Windows因为Windows关闭而试图关闭我的应用程序,我不想将我的应用程序移动到任务栏中,而是想关闭它 Win7终止我的应用程序,但XP未关闭,因为我的应用程序仍在任务栏中 如何检测Windows是否处于某种“关闭”模式 谢谢 您的问题源于使用了OnCloseQuery,这是一个错误的事件。Remy的回答解释了如何解决Windows关机被
谢谢 您的问题源于使用了
OnCloseQuery
,这是一个错误的事件。Remy的回答解释了如何解决Windows关机被默认VCL结束会话消息处理阻止的问题。而这又是由在OnCloseQuery
事件中将CanClose
设置为False
引起的
这种变通方法可以完成工作,但有一种更简单的方法来处理这个问题。
与其阻止窗体关闭,不如让它继续并关闭。完全删除OnCloseQuery
事件。将其替换为OnClose
事件
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caNone;
Visible := False;
end;
当主窗体关闭时,这一微不足道的代码足以使您的应用程序最小化到托盘中。如果响应
WM\u QUERYENDSESSION
消息触发OnCloseQuery
事件,则设置CanClose=False
将导致消息返回False
在XP和更早版本上,这将取消Windows关机。到目前为止,任何收到WM_QUERYENDSESSION
消息的应用程序都将收到WM_ENDSESSION
消息,其wParam
值设置为FALSE
告诉这些应用程序不自行终止。这就是为什么你的应用会进入任务栏,在Windows关闭期间不会退出
Microsoft在Windows Vista中更改了此行为,因此应用程序无法再通过WM\u QUERYENDSESSION
取消Windows关机。这就是为什么Windows Vista及更高版本将终止您的应用程序。如果应用程序需要故意停止Windows关机,则会引入全新的API
这在MSDN上有记录:
要执行要求的操作,必须直接截获WM\u 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;
您是否试图捕获该消息?我已将我的注释移动到一个答案。这是因为您的代码未使用
OnCloseQuery
事件。它使用的是OnClose
事件,它与WM\u QUERYENDSESSION
消息没有关联,比如OnCloseQuery
is。@Remy是的,我的理解有点慢,不是吗?!在这里,OnClose似乎是正确的解决方案。卷入结束会话消息毫无意义。我需要WM_QUERYENDSESSION和WM_ENDSESSION-触发WM_CLOSE时,我已经使用OnCanCloseQuery将程序放入托盘中。不,您不需要。您只需要此答案中的代码作为主窗体的OnClose事件。摆脱OnCloseQuery,这是问题的根源。就这么简单。我们的应用程序也做同样的事情。我的使用一个两行事件处理程序。你也可以。你不需要知道它的用户是单击关闭按钮还是Windows关闭。当Windows关闭时,应用程序将运行其OnClose事件并使其主窗体不可见。然后它将被终止。然后窗户就会掉下来。你真的不需要做更多的事情了。我很抱歉继续说下去,但我真的相信这是更好更简单的选择。大卫,你和雷米的解决方案是一样的。我所需要的就是这些消息——以及系统何时发送它们。你们两个都帮了我,我给了你们额外的帮助,但雷米是以回答的形式做的,所以我接受了帮助。但这两种解决方案是相同的。想法(逻辑)几乎是一样的。不,我的答案非常不同。可能您还没有刷新页面。你在谈论我的评论。我相信这个答案中的雷米密码比你需要的要复杂得多。是的,我说的是你的建议,而不是答案。我不能用你们写的这个代码做任何事情,因为我已经用了相同的代码来检测关闭,而不是停止程序,我把它放进了任务栏。我需要其他事件,然后WM_关闭-我需要结束会话,甚至因为Win在退出时触发它。使用你的代码,我无法使diff Dod Close按钮显示此消息或赢得关机