その後色々読んでました。
ところで、WM_QUERYENDSESSIONというのは本来、Windowsを終了してもよいか、各アプリケーションにお伺いを立てるために存在しているメッセージであり、ここで即座にDestroyWindow()してしまうのは誤りです。
本当は、WM_QUERYENDSESSIONに対しては、終了してよいかどうかの値をリターン値として返すのみにとどまり、その後のWM_ENDSESSIONを受け取ったときに、Windows終了時の対処を書くのが正解です。
うーん、確かに。
MSDNにはどう書かれているか
色んな記事に書かれていてややこしいですが・・・。
- WM_QUERYENDSESSION message (Windows)
- WM_ENDSESSION message (Windows)
- Logging Off (Windows)
- Shutting Down (Windows)
- Shutdown Changes for Windows Vista (Windows)
最後の記事に載ってる 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フラグクリア(例えば秀丸はその後ウィンドウを閉じる際にも保存確認が出ない)
守らないけど、ウィンドウ閉じたときと挙動が一致する
- 「はい」で保存、「いいえ」で終了
「いいえ」だけでも「シャットダウンがブロックされています」画面で回答できるようになったら私が喜びます。