INASOFT 管理人のひとこと


フリーソフトダウンロードサイト「INASOFT」の管理人 矢吹拓也 が日々の「ひとこと」を語るページです。
2021年1月1日より、旧ブログ(blog.inasoft.org)からお引越ししました。
・INASOFT Webサイト: https://www.inasoft.org/
・管理人のふたこと(長文記事/寄稿文): https://www.inasoft.org/talk/
本業の方のお仕事が再び忙しくなりつつあるので、断続的にしばらく更新が止まることがあります。

目次 | ←前へ / 2015-05-27 00:00 / 次へ→ / 最新へ⇒

■WM_QUERYENDSESSIONのマイブームと最近のWindowsでの注意点

2015/ 5/27 0:00:00


RSSRSS配信中

https://www.inasoft.org/








最近、Windowsの終了時やログオフの際に、各アプリケーション向けに送付されるメッセージ「WM_QUERYENDSESSION」に関連した修正を、自作ソフトに施すことが多くなっています。今日はその背景と、分かった注意点について書こうかと思っています。

タスクバーの通知領域(タスクトレイ)に常駐するタイプの自作ソフトを見直したところ、設定をレジストリに保存するタイミングについて、設定ダイアログを閉じたときとしているものと、アプリケーションが終了したときにしているものの2つが存在していることに気付きました。

我ながら統一性がないですね。まぁ、設定ダイアログ以外の、タスクトレイアイコンの右クリックメニュー自体にラジオボタンやチェックボックスが付いているタイプのソフトもあるので、設定ダイアログだけを気にすればよいわけでもないのですが。

そんなソフトの場合に、タスクトレイに常駐させたままWindowsを終了したらどうなるのかを試してみたら、どうやらちゃんと保存されていたらしいことがわかりました。

プログラムを調べてみたら、WM_QUERYENDSESSIONを受け取ったら即座に自ウインドウに対してDestroyWindow() APIを発行するようになっており、これが設定を保存するために一役買っていたようです。

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

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

というわけで、特に悪影響はなかった(ちょっとはあったけど、微々たるもの)ものの、本来のWM_QUERYENDSESSION, WM_ENDSESSION のやり方に沿うべく、修正を行っていくことにしました。
具体的には、WM_QUERYENDSESSIONに対しては return TRUE; (終了許可) を返答するにとどめ、WM_ENDSESSIONのwParamがTRUEならば、自アプリケーションを終了するように処理を変えました。
なお、WM_QUERYENDSESSIONに対しては return TRUE; (終了許可) を返答するだけであれば、DefWindowProc() がやってくれますので、WM_QUERYENDSESSIONに対する処理自体はあえて書く必要はありません。



次に、編集系アプリケーションに関する、WM_QUERYENDSESSION, WM_ENDSESSION の挙動です。
よくメモ帳などで編集中かつ未保存の状態でWindowsを終了しようとすると、保存確認のダイアログが出てきたり、「メモ帳が終了をブロックしている」旨のメッセージがWindowsから通知されるのを見たことがあるかと思います。それを実現したいと思いました。

「いじくるつくーる」において、設定を編集中かつ未保存の状態の場合に、[×]ボタンが押された時と同じ挙動を起こさせることを目標に、調査を開始しました。

(設定にも寄りますが)いじくるつくーるで編集中かつ未保存状態で[×]ボタンが押されると、設定を保存するかどうか確認されるか、あるいは、設定を保存しないまま終了してもよいか確認されます。

このダイアログが出ている間はWindowsの終了をブロックし、かつ、ダイアログに応答した結果として編集を継続する意思をユーザーが示したら、Windowsの終了をブロックしつづけるような動きが理想的です。

というわけで、各所に書かれているサンプルをもとに、ユーザー応答の結果編集を継続する場合には、WM_QUERYENDSESSION の戻り値として return FALSE; を返すように修正しました。


で、動作テスト。
失敗。
なんでだ!?


いろいろ悩みましたら、MSDNライブラリをしっかり見れば答えが書いてありました。
Windows Vista以降、このWM_QUERYENDSESSIONの動作仕様が変えられており、単に return FALSE; を返すだけではWindowsの終了をブロックしてくれません。

ShutdownBlockReasonCreate() API を使って、Windowsの終了をブロックする理由を文字列で登録してやらないといけないのです。そのうえで、return FALSE; を返します。


そして、理由が消失したら、ShutdownBlockReasonDestroy() で理由の消失を伝えます。

詳しくはMSDNのこちらのページを参照。

ここまでやって、ようやく、Windowsの終了をブロックすることができます。

(正確には、ダイアログを表示してユーザーの意思を確認している間は、これまで通りブロックされますが、ユーザーが何らかのボタンを押してダイアログを閉じた後に、ブロックをし続けるならば、上記のような動きをしなければなりません)



目次 | ←前へ / 2015-05-27 00:00 / 次へ→ / 最新へ⇒


目次の表示:


ブログではないので、コメント機能とトラックバック機能は提供していません。ご質問・ご意見等はメールフィードバックまたはTwitter等からお願いします。いただいたご質問・ご意見などは、この「管理人のひとこと」の記事に追加、あるいは新規の記事にする形で一部または全文をそのまま、あるいは加工させていただいた上で、ご紹介させていただく場合があります。
当サイトでは掲載内容による不具合等に関する責任を持ちません。また、内容の正確性についての保証もありませんので、情報をご利用の際は、利用者の自己責任で確認をお願いします。本ページは公開から1年半後の任意のタイミングで削除される予定です。




2554548 (+0248)[+0573]

Copyright© 2010-2021 INASOFT