宇宙仮面の
C# Programming

 
Image

ウィンドウの位置、サイズを保存する。

開発環境: Visual Studio 2003 

1.目次

1.目次
2.目的
3.参考書
4.ユーザレジストリにウィンドウの位置、サイズを記録する方法
5.レジストリ記録したウィンドウの位置、サイズから、ウィンドウの位置を復元する方法
6.ウィンドウの位置、サイズを保存するクラス。

2.目的

前回起動したときのウィンドウの位置やサイズで、再起動したいという要求はかなりあると思います。
その方法について、2つ紹介します。

1つは、従来と同じレジストリに各エントリを記述する方法。
もう1つは、レジストリに書くのは一緒ですが、シリアライズデータを書いてしまう方法です。

Microsoft TechEd 2002 では、シリアライズする方法が紹介されていました。
でも、データサイズが大きくなることと、XML スキーマに依存してしまう点から、自分としてはあまりお勧めできないと思います。

レジストリは、HKEY_CURRENT_USERで、ユーザごとの設定を保存することができます。
レジストリを使わないで、ini ファイルや、AppConfig ファイルにウィンドウの位置などを書くこともできますが、ユーザごとに設定できません。ウィンドウの位置のようなユーザに依存する設定をini ファイルや、AppConfig ファイルに書くべきではありません。

でも、一番のお勧めは、ウィンドウの位置、サイズなどを保存しようなどという、つまらぬ要求は突っぱねることです。^ ^)/
そうすれば、レジストリに依存するコード書かなくてすむもんね!

3.参考書

(1) MSDN .NET Framework におけるアプリケーション設定の永続化

4.ユーザレジストリに ウィンドウの位置、サイズを記録する方法

ウィンドウの位置、サイズを保存するには、データをユーザごとにレジストリに保存するには、Application クラスの UserAppDataRegistry プロパティを使用します。Application.UserAppDataRegistry のレジストリ キーは、自動的にHKEY_CURRENT_USER\Software\[Control.CompanyName]\[Control.ProductName]\[Control.ProductVersion] になりますので、直接Registry クラスを使って、次のようなことをするより、ずっと安全です。

注意: 全ユーザに対して、共通の値として格納する場合は、UserAppDataRegistry ではなく、CommonAppDataRegistryを使用します。

注意: 最小化時のウィンドウの位置情報を保存し、元に戻すと正しく表示されなくなります。最小化時の時だけ、位置情報を保存するようにします。

 
ウィンドウの状態、位置、大きさを保存する方法
using Microsoft.Win32;

....

private RegistryKey userReg =null;

....
userReg = Application.UserAppDataRegistry;

userReg.SetValue("WindowState", (int)(form.WindowState));
// 最小化時の場所を保存するとおかしくなる。
if(form.WindowState == FormWindowState.Normal)
{
    userReg.SetValue("X", form.Location.X);
    userReg.SetValue("Y", form.Location.Y);
    userReg.SetValue("Height", form.Height);
    userReg.SetValue("Width", form.Width);
}

 

これにより、次のようにレジストリに情報が格納されます。

注意: バージョンごとにレジストリができてしまいます。アンインストーラで、きれいにすることを忘れずに!


Image

 

5.レジストリ記録したウィンドウの位置、サイズから、ウィンドウの位置を復元する方法

同様に、Application.UserAppDataRegistry.GetValue(...)で、ユーザ固有のアプリケーションのレジストリー値を取得することができます。これを利用して、フォームがロードされるときに発生する、Load イベントに対して、レジストリに該当するキーがあれば、そこから X, Y, Width, Height を読み込みます。一番最初は、これらのキーがないので、NullRefenceException 例外 があがりますから、例外を拾って無視する必要があります。

1点だけわかりにくい部分を説明しておきます。
Location に new Point() で代入していますが、これは Location.X, Location.Y に直接値をセットできないためです。
これは、Location.X がLocation プロパティの中間式であるためです。
 
ウィンドウの状態、位置、大きさを復元する方法
using Microsoft.Win32;

....

private RegistryKey userReg =null;
userReg = Application.UserAppDataRegistry;

try
{
  // Locationを設定する。
  int x = (int)(userReg.GetValue("X"));
  int y = (int)(userReg.GetValue("Y"));
  form.Location = new Point( x, y );

  // Sizeを設定する。
  int height = (int)userReg.GetValue("Height");
  int width = (int)userReg.GetValue("Width");
  form.Size = new Size(width, height);

  // WindowStateを設定する。
  form.WindowState = (FormWindowState)userReg.GetValue("WindowState");
}
catch
{
  // 一番最初はレジストリに登録されていないので、
  // NullReferenceExceptionになるが、これは無視する。
}

6.ウィンドウの位置、サイズを保存するクラス。

毎回、このようなコードを書くのはめんどくさいので、次のようなウィンドウの状態、位置、大きさをセーブ、ロードするクラスを作っておくと便利です。
 
ウィンドウの状態、位置、大きさを復元するためのクラス
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;

namespace Uchukamen.SavePosition
{
	/// 
	/// WindowState の概要の説明です。
	/// 
	public class SaveWindowPosition
	{
		public SaveWindowPosition( Form form )
		{
			this.form = form;
			userReg = Application.UserAppDataRegistry;
		}

		private Form form = null;
		private RegistryKey userReg =null;

		public void Save()
		{
			userReg.SetValue("WindowState", (int)(form.WindowState));
			// 最小化時の場所を保存するとおかしくなる。
			if(form.WindowState == FormWindowState.Normal)
			{
				userReg.SetValue("X", form.Location.X);
				userReg.SetValue("Y", form.Location.Y);
				userReg.SetValue("Height", form.Height);
				userReg.SetValue("Width", form.Width);
			}
		}

		public void Load()
		{
			try
			{
				// Locationを設定する。
				int x = (int)(userReg.GetValue("X"));
				int y = (int)(userReg.GetValue("Y"));
				form.Location = new Point( x, y );

				// Sizeを設定する。
				int height = (int)userReg.GetValue("Height");
				int width = (int)userReg.GetValue("Width");
				form.Size = new Size(width, height);

				// WindowStateを設定する。
				form.WindowState = (FormWindowState)userReg.GetValue("WindowState");
			}
			catch
			{
				// 一番最初はレジストリに登録されていないので、
				// NullReferenceExceptionになるが、これは無視する。
			}
		}
	}
}

利用方法は、Windows.Forms のLoad イベント、OnClosing イベントで、それぞれLoad(), Save()と呼び出してあげます。

ウィンドウの状態、位置、大きさを復元するクラスの呼び出し方法
private SaveWindowPosition swp = null;

private void Form1_Load(object sender, System.EventArgs e)
{
    swp = new SaveWindowPosition( this );
    swp.Load();
}

private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
    swp.Save();
}