うならぼ

申し訳程度のアフィリエイトとか広告とか解析とかは/aboutを参照

WM_QUERYENDSESSIONでどこまでやるべきか

unarist.hatenablog.com

その後色々読んでました。

ところで、WM_QUERYENDSESSIONというのは本来、Windowsを終了してもよいか、各アプリケーションにお伺いを立てるために存在しているメッセージであり、ここで即座にDestroyWindow()してしまうのは誤りです。

本当は、WM_QUERYENDSESSIONに対しては、終了してよいかどうかの値をリターン値として返すのみにとどまり、その後のWM_ENDSESSIONを受け取ったときに、Windows終了時の対処を書くのが正解です。

WM_QUERYENDSESSIONのマイブームと最近のWindowsでの注意点: INASOFT 管理人のひとこと

うーん、確かに。

MSDNにはどう書かれているか

色んな記事に書かれていてややこしいですが・・・。

最後の記事に載ってる Best Practices を参考にまとめると、

  • そもそもブロックするな。できると思うな。
  • WM_QUERYENDSESSION にはすぐ返事し(当然TRUEが望ましい)、 WM_ENDSESSION が届くのを待って、終了処理を行う。
  • 例えば今中断するとシステムが壊れるとか、ディスク焼いてるときとか、どうしても無理な場合にだけ ShutdownBlockReasonCreate を使う。

って感じなので、はなっから 「ユーザーさんに聞いてみないとわっかんないですね~」 保存確認ダイアログを出すなんて想定していないご様子。

ところで、 WM_QUERYENDSESSION の説明には

If any application returns zero, the session is not ended. The system stops sending WM_QUERYENDSESSION messages as soon as one application returns zero.

として「誰かがブロックしたらQUERY中断するよ」とか書いてある割に、

When an application returns TRUE for this message, it receives the WM_ENDSESSION message, regardless of how the other applications respond to the WM_QUERYENDSESSION message.

「QUERYにTRUE返したら、他のアプリがどう答えようとWM_ENDSESSION送るよ」とも書かれている。だからこそ、ブロックする予定なら SetProcessShutdownParameters で順番早めておくべき、と言われるんでしょうね。

まとめ

理想

  • ブロックしない。

使い分けを守るパターン

  • 「はい」で保存、「いいえ」直後の WM_ENDSESSION で終了(メモ帳)
  • 「はい」で保存、「いいえ」でdirtyフラグクリア(例えば秀丸はその後ウィンドウを閉じる際にも保存確認が出ない)

守らないけど、ウィンドウ閉じたときと挙動が一致する

  • 「はい」で保存、「いいえ」で終了

「いいえ」だけでも「シャットダウンがブロックされています」画面で回答できるようになったら私が喜びます。