在 Delphi 7中,我有一个TMainForm.FormClose过程,用于在程序退出时写出一些状态。这在手动关闭程序时工作正常。然而,我发现如果程序被Windows“强制”退出(例如在需要重新启动的Windows Update之后),则不会调用FormClose过程。
编辑-我是新来的,看起来我不能删除我自己的帖子。经过一番搜索,我找到了a solution。
在 Delphi 7中,我有一个TMainForm.FormClose过程,用于在程序退出时写出一些状态。这在手动关闭程序时工作正常。然而,我发现如果程序被Windows“强制”退出(例如在需要重新启动的Windows Update之后),则不会调用FormClose过程。
编辑-我是新来的,看起来我不能删除我自己的帖子。经过一番搜索,我找到了a solution。
4条答案
按热度按时间nnsrf1az1#
这是真实的困难。如果你在外部杀死一个进程,那就是即时终止。没有机会清理,时期。Windows Update的重新启动通常会通过发送WM_QUERYENDSESSION消息来“正确”关闭程序,但无论出于何种原因,它并不总是有效。特别是,如果你的程序延迟了很长时间(例如,在退出前询问用户是否要保存),关闭代码将终止进程。
因此,如果你想保证它总是调用那个事件处理程序,你必须保证你永远不会使用一个模态对话框或任何其他东西来阻止程序在收到WM_QUERYENDSESSION时立即退出。这可能是更多的麻烦比它的价值。
一个替代方案是做一些类似于Firefox所做的事情:当它还在运行时,将状态数据写入一个临时文件,然后当它重新启动时,检查该文件是否在那里,以及数据是否指示它仍处于“打开”状态。如果是这样,您的程序可以知道它的最后一个化身以某种方式被杀死,并采取任何适当的行动,例如用最后可用的数据更新状态日志(或您正在使用的任何内容)。
slsn1g292#
上面的一条评论建议我总结我找到的答案(link)。基本上,它说要为WM_QUERYENDSESSION提供自己的处理程序。这是推荐的代码:
我不确定在调用MyCleanUpProcedure之前调用Inherited是否完全正确。如果Inherited过程首先响应Windows,则Windows仍然可以在MyCleanUpProcedure完成之前关闭应用程序。我不确定Inherited对
WM_QUERYENDSESSION
消息做了什么-我假设它默认允许立即关闭。在我的应用程序中,MyCleanUpProcedure运行得非常快,所以它不会导致Windows显示“Not Responding”对话框,因为没有对WM_QUERYENDSESSION
消息的响应。为了确保我的过程运行完成,也许该过程应该看起来像这样:
或者这个?
ac1kyiln3#
随访信息:我不知道继承的过程除了返回“1”之外还做了什么,所以我尝试了return和inherited。首先运行我的关闭过程,然后返回1,然后继承。
我已经测试了这个代码的情况下,系统正在关闭(手动或由于Windows更新),我的应用程序仍在运行。以下代码已被验证在这种情况下正确工作- MyCleanUpProcedure在我的应用程序关闭之前运行。
我还没有针对应用程序被任务管理器杀死的情况进行测试--这与我的应用程序无关。
3phpmpom4#
不能保证会调用FormClose。
(详情来自Peter B,
https://groups.google.com/g/borland.public.delphi.objectpascal/c/82AG0_kHonU/m/ft53lAjxWRMJ)
通过一个名为“应用程序”的按钮关闭表单。
OnShow来电
毁灭召唤
OnHide打来电话
OnDestroy打电话来
通过调用Form1.Close的按钮关闭表单,在FormClose中使用Action:= caFree:
OnShow来电
OnCloseQuery已调用。
在关闭调用
毁灭召唤
OnHide打来电话
OnDestroy打电话来
通过系统菜单关闭表单:
OnShow来电
OnCloseQuery已调用。
在关闭调用
毁灭召唤
OnHide打来电话
OnDestroy打电话来
通过注销Win NT关闭应用程序:
OnShow来电
OnCloseQuery已调用。
两种解决方案: