我试图阻止我的应用程序被Windows关闭.该应用程序在Windows 8上运行并以XE6编写.我尝试了下面的代码,但它似乎完全被忽略了.为了测试它,我只需通过任务管理器向其发送"结束任务".我需要的是一种方法,让我的应用程序完成它在用户关闭应用程序时所执行的操作,由Windows关闭的任务管理器完成.正常关闭不是问题,这由FormCloseQuery事件处理.但其他两种方法我都无法工作.直到windows XP,通过捕获wm_endsession和wm_queryendsession很容易,从vista开始你需要使用ShutDownBlockReasonCreate,它返回true但似乎无论如何都不起作用.
procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QUERYENDSESSION;
procedure WMEndSession(var Msg: TWMEndSession); message WM_ENDSESSION;
function ShutdownBlockReasonCreate(hWnd: HWND; Reason: LPCWSTR): Bool; stdcall; external user32;
function ShutdownBlockReasonDestroy(hWnd: HWND): Bool; stdcall; external user32;
procedure TForm1.WMEndSession(var Msg: TWMEndSession);
begin
inherited;
Msg.Result := lresult(False);
ShutdownBlockReasonCreate(Handle, 'please wait while muting...');
Sleep(45000); // do your work here
ShutdownBlockReasonDestroy(Handle);
end;
procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
inherited;
Msg.Result := lresult(False);
ShutdownBlockReasonCreate(Handle, 'please wait while muting...');
Sleep(45000); // do your work here
ShutdownBlockReasonDestroy(Handle);
end;
Run Code Online (Sandbox Code Playgroud)
更新
将消息结果更改为true并删除睡眠不会改变任何内容.
procedure TForm1.WMEndSession(var Msg: TWMEndSession);
begin
inherited;
Msg.Result := lresult(True);
ShutdownBlockReasonDestroy(Application.MainForm.Handle);
ShutdownBlockReasonCreate(Application.MainForm.Handle, 'please wait while muting...');
end;
procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
inherited;
Msg.Result := lresult(True);
ShutdownBlockReasonDestroy(Application.MainForm.Handle);
ShutdownBlockReasonCreate(Application.MainForm.Handle, 'please wait while muting...');
end;
Run Code Online (Sandbox Code Playgroud)
Dav*_*nan 10
根据阻止关闭的文档,您需要返回FALSE以响应WM_QUERYENDSESSION.
更重要的是,你不能在这个消息处理程序中工作.这项工作必须在别处进行.如果您未及时回复此消息,系统将不会等待您.
ShutdownBlockReasonCreate在开始工作之前打电话.FALSE的时候WM_QUERYENDSESSION.处理此消息时请勿工作.马上回来.ShutdownBlockReasonDestroy.处理程序WM_QUERYENDSESSION可以如下所示:
procedure TMainForm.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
if Working then
Msg.Result := 0
else
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
然后执行工作的代码需要ShutdownBlockReasonCreate在工作开始之前调用,ShutdownBlockReasonDestroy当工作结束时,并确保Working上面使用的属性True在工作期间进行评估.
如果你的工作阻止主线程,那你就麻烦了.主线程必须是响应式的,否则系统不会等你.将工作放在一个线程中往往是前进的方向.如果您的主窗口不可见,那么您将无法阻止关闭.详细信息请参见此处:http://msdn.microsoft.com/en-us/library/ms700677.aspx
如果你被送到目前为止WM_ENDSESSION已经太晚了.系统正在下降.
为了测试它,我只需通过任务管理器向其发送"结束任务".
这与关闭阻塞无关.测试关闭阻塞的方法是注销.如果用户坚持要求杀死您的流程,那么您无能为力.Sertac的答案详细介绍了这一点.
最后,忽略API调用的返回值也是非常差的形式.不要那样做.
您的代码似乎完全被忽略,因为您没有对其进行测试.您通过任务管理器向其发送"结束任务",您发布的代码仅在系统关闭时才有效.
Windows 8的不同之处似乎是任务管理器的行为方式.在Windows 8之前,任务管理器的结束任务将首先尝试正常关闭应用程序(发送一个WM_CLOSE),这是您正在处理的OnCloseQuery.但是当应用程序拒绝关闭时,任务管理器将强制结束该过程.这个,你无法处理.如果从任务管理器中选择"结束进程",则相同.
Windows 8任务管理器不提供强制关闭应用程序的附加对话框,但在应用程序拒绝关闭时立即执行此操作.
| 归档时间: |
|
| 查看次数: |
2512 次 |
| 最近记录: |