例えば、C#でボタン一個だけの簡単なFormアプリを作ったとしよう。
こんな感じ(下図)。
これを実行すると、Form1が開く(下図)。
さて、この時幾つか気になる点がある。
- 実行する度にウインドウ位置が変化する。
- 前回終了時のウインドウ位置やサイズが記憶されない。
などの点だ。
一番目の「実行する度にウインドウ位置が変化する。」に関しては、Form1のプロパティ設定を出すと、デフォルトだと以下の様にWindowsDefaultLocationに設定されている。
StartPositionと言う項目だ。
StartPositionの選択可能な値は以下の通り。
- Manual
- CenterScreen
- WindowsDefaultLocation(デフォルト値)
- WindowsDefaultBounds
- CenterParent
の五つから選べる。
デフォルトのWindowsDefaultLocationでは、Windowsが勝手に初期位置を決めると言う意味になる。
さて、どれを選んでも直前の位置やサイズを記憶しておくなどと言う機能は無いようだ。
でも、実用性を考えると位置・サイズの記憶機能があると利用者にも便利。
今回は、C#のWindows Formアプリケーションにおいて、前回終了時のウインドウ位置とウインドウサイズを記憶しておいて、次回起動時にその位置とサイズを復元する手法を紹介したい。
この手の手法には各種のやり方がある。レジストリを使う、iniファイルに保存するなど。
この記事では、そう言う従来の手法を使わなくてもC#のWindows Formプロジェクトにほんの少しの設定を行うだけで、ウインドウ位置・サイズのデータを保存してくれる機能があるので、それを利用する手法を説明したい。最新のC#を使っている人にはお勧めの方法だ。
テスト環境は以下の通り。
Visual Studio 2017 Community
.Net Frameworkバージョン 4.6.2
C# Windows Formプロジェクト
では、本題に入ろう。
C# Formアプリで前回終了時ウインドウ位置・サイズを記憶する手法
下図のようにプロジェクト名の上で右クリックしてプロパティウインドウを表示する。
その中の[設定]を選択する(下図)。
この[設定]機能を使うと、アプリケーションが何らかの値を記憶しておいたり、あるいはその値を読み取って利用するなどが可能だ。
今回は、ウインドウの位置、大きさ、ステート(Normal、最小化、最大化)の3つの状態を記憶する設定を行う。
アプリの終了時に現在のウインドウ状態をそれらに記憶しておき、次回起動時にその値を読み出して復元するのだ。
設定画面で3つの値を定義する
まず、下図のようにForm1ウインドウの状態(Normal、Minimize、Maximize)を保持する変数をF1Stateと名付けてセットする。
もしForm2も有る場合には F2Stateなどとすると良いだろう。
この変数名は好き好きなので自由に変更しても構わない。
次に、下図のようにその変数の種類を
System.Windows.Forms.FormWindowState
にする。
実際の手順としては、参照の部分をクリックすると下図のように沢山の候補が出るので、その中から選ぶ。
OKボタンをクリックすると、値の部分にデフォルト値(Normal)が入る。
同様にして、残りの2つの変数も以下のように設定する。
以下の表のようになっていれば成功だ。
名前 | 種類 | スコープ | 値 |
F1State | System.Windows.Forms.FormWindowState | ユーザー | Normal |
F1Location | System.Drawing.Point | ユーザー | 0, 0 |
F1Size | System.Drawing.Size | ユーザー | 0, 0 |
FormのLoadとClosingのイベントハンドラ関数を設定する
下図に示すようにForm1のデザイン画面で右クリックしてプロパティを表示する。
そのプロパティ画面で稲妻アイコンを選択すると下図が開く。
その中に[動作]の項目があるので、FormClosingの文字の上でダブルクリックする。
そうすると、下図に示すように Form1_FormClosing() の関数が自動で追加される。
同様に、Form1_Load() も追加する。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SaveRestoreFormPosSize { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { this.Close(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { } private void Form1_Load(object sender, EventArgs e) { } } }
なお、これらのイベントハンドラ関数はキーボードから手入力で関数を書いてはいけない。
あくまで今やったようにダブルクリックで追加する。
もしキーボードから手作業で追加した場合には、先ほどのプロパティ画面でダブルクリックではなく、プルダウンメニューの中から関数を選択する事が可能なので自分が追加した関数を選択すると良い。
ただし、関数の引数が正しくない場合にはプルダウンメニューにその関数が出て来ないので注意が必要だ。
設定値を保存・復元する処理を追加する
以下の様にコードを追加する。
それぞれの意味はコメントで説明しているので、確認して頂きたい。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SaveRestoreFormPosSize { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { this.Close(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Properties.Settings.Default.F1State = this.WindowState; if (this.WindowState == FormWindowState.Normal) { // ウインドウステートがNormalな場合には位置(location)とサイズ(size)を記憶する。 Properties.Settings.Default.F1Location = this.Location; Properties.Settings.Default.F1Size = this.Size; } else { // もし最小化(minimized)や最大化(maximized)の場合には、RestoreBoundsを記憶する。 Properties.Settings.Default.F1Location = this.RestoreBounds.Location; Properties.Settings.Default.F1Size = this.RestoreBounds.Size; } // ここで設定を保存する Properties.Settings.Default.Save(); } private void Form1_Load(object sender, EventArgs e) { // この設定は無くても良い if (Properties.Settings.Default.F1Size.Width == 0) Properties.Settings.Default.Upgrade(); // もしC#デスクトップアプリをバージョンアップすると、記憶している情報が消え去るが、この↑を // 入れておくと引き継がれる(らしい)。 if (Properties.Settings.Default.F1Size.Width == 0 || Properties.Settings.Default.F1Size.Height == 0) { // 初回起動時にはここに来るので必要なら初期値を与えても良い。 // 何も与えない場合には、デザイナーウインドウで指定されている大きさになる。 } else { this.WindowState = Properties.Settings.Default.F1State; // もし前回終了時に最小化されていても、今回起動時にはNormal状態にしておく if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal; this.Location = Properties.Settings.Default.F1Location; this.Size = Properties.Settings.Default.F1Size; } } } }
これで全部の設定が完了だ。
Formアプリを実行してみる
デバッグ無し実行(CTRL+F5)でもデバッグ有り実行(F5)でもどちらでも良いので実行してみる。
そうするとForm1が表示される。
ここで、Form1の大きさや位置をマウスで変更してみる。
button1をクリックするとForm1が閉じる。
その直前にClosingイベントが発生するので、現在のForm1ウインドウの状態、位置、大きさが保管される。
さて、もう一回実行してみる。
これで前回終了時の状態の復元機能が動けば成功だ。
結果はどうでしょうか?
特に難しい部分は無いと思うので、ここまでの手順を間違いなくやれば正しく復元できたはずです。
設定はどこに保管されているのか?
確かに、設定はどこに保管されているのか気になる。
ワテが今回作ったサンプルプロジェクトの場合には、以下の通り。
C:\Users\wate\AppData\Local\SaveRestoreFormPosSize\SaveRestoreFormPosSize.ex_Url_jfnqfasd54hfdsmzfdaketeakl435c\1.0.0.0
このフォルダの中に、user.config と言う名前のファイルがあり、その中味は、
<?xml version="1.0" encoding="utf-8"?> <configuration> <userSettings> <SaveRestoreFormPosSize.Properties.Settings> <setting name="F1State" serializeAs="String"> <value>Normal</value> </setting> <setting name="F1Location" serializeAs="String"> <value>836, 255</value> </setting> <setting name="F1Size" serializeAs="String"> <value>696, 568</value> </setting> </SaveRestoreFormPosSize.Properties.Settings> </userSettings> </configuration>
こんなふうになっている。
まとめ
C#のWindows Formアプリにおいて、終了時のウインドウ状態、位置、サイズを記憶しておいて、次回の起動時に復元する手法を紹介した。
今回紹介した方法は、C#だけでなくVB.NETでも利用出来るのでお手軽である。
他の言語例えばC、C++などではこの手法が無いので自前で実装する必要がある。
一般的には、レジストリを使う方法や拡張子 .ini のファイルに保存しておく方法などがある。
興味ある人は各自で調査して頂きたい。
Windowsのレジストリの仕組みを勉強するなら、たぶんこういう本に詳しく書いてあると思うのだが、ワテは読んでいないので分からない。
買ってみるかな。キンドル版もあるし。
コメント
[…] と思ったのは、ウインドウ位置とサイズの記憶と復元。 【ワレコのC#】Formアプリ 前回終了時 ウインドウ位置・サイズを記憶復元 DestroyWindowでWindowレクトを保存してInitInstanceでMoveWindowす […]