12

トレイアプリケーションを使用しています。

Onj FormCloseQueryプログラムをトレイに移動する必要があるかどうかを確認し、プログラムを閉じる代わりにトレイに配置します(CanClose:= False)

しかし、WindowsがシャットダウンしたためにWindowsがアプリケーションを閉じようとした場合、アプリをトレイに移動するのではなく、閉じたいと思います。

Win7はアプリを終了しますが、アプリがトレイに残っているため、XPは閉じません。

Windowsが「シャットダウン」モードであるかどうかをどのように検出できますか?

ありがとう!

4

2 に答える 2

16

OnCloseQueryメッセージに応答してイベントがトリガーされた場合WM_QUERYENDSESSION、設定CanClose=Falseするとメッセージが返されFALSEます。

XP以前では、Windowsのシャットダウンがキャンセルされます。その時点まで、メッセージを受信したアプリは、それらのアプリに終了しないように指示する値が設定されたメッセージWM_QUERYENDSESSIONを受信します。これが、アプリがトレイに移動し、Windowsのシャットダウン中に終了しない理由です。WM_ENDSESSIONwParamFALSE

MicrosoftはWindowsVistaでこの動作を変更したため、アプリはWindowsのシャットダウンをキャンセルできなくなりWM_QUERYENDSESSIONました。これが、WindowsVista以降でアプリが終了する理由です。アプリが意図的にWindowsのシャットダウンを停止する必要がある場合は、まったく新しいAPIが導入されています。

これはMSDNに文書化されています:

WindowsVistaでのアプリケーションシャットダウンの変更

WM_QUERYENDSESSION求めていることを実行するには、メッセージを直接インターセプトして、OnCloseQueryWindowsのシャットダウンが原因で呼び出されているかどうかを判断できるようにする必要があります。例えば:

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;
于 2012-05-24T22:07:54.177 に答える
9

OnCloseQueryあなたの問題は、使用するのが間違ったイベントであることに起因します。Remyの回答は、デフォルトのVCL終了セッションメッセージ処理によってブロックされているWindowsシャットダウンを回避する方法を説明しています。そして、これは、イベントでに設定CanCloseすることによって発生します。FalseOnCloseQuery

この回避策で作業は完了しますが、これに対処するためのはるかに簡単な方法があります。フォームが閉じるのを止めるのではなく、先に進んで閉じます。OnCloseQueryイベントを完全に削除します。イベントに置き換えますOnClose

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  Visible := False;
end;

このかなり些細なコードで、メインフォームを閉じたときにアプリをトレイに最小化するのに十分です。

于 2012-05-24T21:29:11.137 に答える