最大化/最小化問題にも耐える、Windowsアプリケーションの位置やサイズを保存するには?
.NETのApplicationSettings機能って便利でして、前回のアプリケーション終了時の位置とフォームサイズを、ちょこちょこ設定するだけで行ってくれるようになります。
- Windowsアプリケーションの位置やサイズを保存するには?[2.0のみ、C#、VB] − @IT
http://www.atmarkit.co.jp/fdotnet/dotnettips/438winsettings/winsettings.html
この機能、非常に便利でして、ちょっとしたツールを.NETで作る際、いつもこの機能を利用しています。
例えば、起動直後、以下の位置&サイズでアプリが起動したとしますね。

2 posted by (C)wacky
この位置に移動&拡大して終了したとします。

3 posted by (C)wacky
次に起動すると、同じ位置&サイズでアプリを起動してくれる訳です。
この機能を行う為に必要なのは、プロパティ設定画面で ちょこちょこ弄る程度で済む訳ですから、使わない手はありません。
(正確には、プロパティ弄るだけでOKなのは、VB.NETで、C#の場合、FormClosedイベントに'Properties.Settings.Default.Save();'の1行を記述する必要があります)

1 posted by (C)wacky
ところが
ところが、この機能、一点欠点がありまして、これを使って最大化/最小化を行うと、次の回復時に変な動きになります。
例えば、「最大化」した後、「普通」に戻します。すると、以下のようになってしまいます。

4 posted by (C)wacky
他にも、
- 「最大化」した状態で閉じると、次に起動した時「普通」が「最大化」状態
- 「最小化」した常態で閉じると、次に起動した時「普通」が「最小化」状態
になったりと、「ちょっと待て」と言いたくなる挙動を起こしてくれます。
気になる人も結構いらっしゃるようで、幾つか対策案が提示されています。
- 設定(My.Settings)の動作 - MSDN フォーラム
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=893729&SiteID=7&pageid=0#913613 - Coding4Fun: パネル ゲーム
http://msdn2.microsoft.com/ja-jp/library/bb932356.aspx - Cool Client Stuff : Saving out a Form's Size and Location using the Application Settings feature
http://blogs.msdn.com/rprabhu/archive/2005/11/28/497792.aspx
やっている事は、前の値を独自変数で保持&意図しない状態の際復旧。というパターンです。
ApplicationSettingsBase.SettingChangingイベントを使ってみる対策
他に何か良い方法は無いかな〜と、MSDN Libraryを眺め回していたら、私的解決方法を思いつきました。
ApplicationSettingsBase.SettingChangingイベントを使う方法です。
早速ですが、以下にコードサンプルを示します。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using DBG = System.Diagnostics.Trace; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { Properties.Settings.Default.Save(); } private void Form1_Load(object sender, EventArgs e) { Properties.Settings.Default.SettingChanging += new System.Configuration.SettingChangingEventHandler(Default_SettingChanging); } void Default_SettingChanging(object sender, System.Configuration.SettingChangingEventArgs e) { DBG.WriteLine(string.Format("SettingChanging {0}, {1}", e.SettingName, e.NewValue)); if (this.WindowState != FormWindowState.Normal) { if ((e.SettingName == "MyClientSize") || (e.SettingName == "MyLocation")) { DBG.WriteLine("MyClientSize cancel"); e.Cancel = true; } } } } }
上のコードの肝は、Default_SettingChangingで、以下のように処理している箇所です。
- 現在のWindowStateがFormWindowState.Normalでない(即ちMaximizedかMinimized)
- 変更しようとしているプロパティ値は、MyLocation(LocationのApplicaitonSettings値)かMyClientSize(ClientSizeのApplicationSettings値)である
- 1.と2.を満たす場合、ApplicationSettingsの反映を阻害(Cancel = true)する
上記のコードを追加する事で、前項の「楽しくない挙動」から解放されます。(VS2005とVS2008で確認)
つまり、以下のケースに対応できます。
(Powered by.フォト蔵(見やすくする為に、ちょっとタグを弄らせてもらっています))
| ケース | 事例 |
|---|---|
| 「普通」→「最大化」→「普通」 | 「普通」 →「最大化」 →「普通」![]() |
| 「最大化」→「閉じる」→「起動」 | 「最大化」 →「閉じる」→「起動」![]() |
| 「最小化」→「閉じる」→「起動」 | 「最小化」![]() |
まとめ
ApplicationSetttingsを使って「Windowsアプリケーションの位置やサイズを保存する」場合、ApplicationSettingsBase.SettingChangingイベントを使ってみては、どうでしょう?
