【C#】【Form】アプリ状態を復元する仕組みを考える

■ はじめに

 * Windowsアプリの状態(ウインドウ位置, サイズ etc)を復元する仕組みを調べてみた。

使い道

 例えば、以下の関連記事のアプリ「画像比較スライダー」の状態(境界線の位置)を
保持しておきたい時などに使用。詳細は、以下の関連記事を参照。
Splitter ~ 画像比較スライダーをWindows Formで実装する ~
https://blogs.yahoo.co.jp/dk521123/37846450.html
設定ファイルの保存については、以下の関連記事を参照。
アプリの設定ファイル
https://blogs.yahoo.co.jp/dk521123/38122457.html

■ サンプル

例1:Hello World

手順
[1] ソリューションエクスプローラ内のプロジェクト名を右クリックして、
    [プロパティ]-[設定]を選択する

 名前         種類    スコープ	値
 HelloWorld   string  ユーザー	

 ※ 名前「HelloWorld」は、キーとなる値

 => 「C:\Users\【アカウント名】\AppData\Local\【アプリ名】\【ランダム?文字列】\user.config」にXML形式で保存される
コントロール構成
 * button x 2
 * Textbox x 1
コード
using System;
using System.Windows.Forms;

namespace SampleForm
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    // 保存処理
    private void button1_Click(object sender, EventArgs e)
    {
      Properties.Settings.Default.HelloWorld = this.textBox1.Text;
      Properties.Settings.Default.Save();
    }

    // 復元処理
    private void button2_Click(object sender, EventArgs e)
    {
      this.textBox1.Text = Properties.Settings.Default.HelloWorld;
    }
  }
}

例2:アプリ状態をクローズで保存、ロードで復元

 * 以下のアプリ状態をクローズで保存、ロードで復元

  [1] ウインドウステート(Normal、最小化、最大化)
  [2] ウインドウの位置
  [3] ウインドウの大きさ
手順
[1] ソリューションエクスプローラ内のプロジェクト名を右クリックして、
    [プロパティ]-[設定]を選択する
    ※「種類」(データ型)を選択するには、「参照」から選んでいく

 名前         種類                                  スコープ  値
 FormState    System.Windows.Forms.FormWindowState  ユーザー  Normal
 FormLocation System.Drawing.Point                  ユーザー  0, 0
 FormSize     System.Drawing.Size                   ユーザー  0, 0	
コード
using System.Windows.Forms;

namespace SampleForm
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, System.EventArgs e)
    {
      if (Properties.Settings.Default.FormSize.IsEmpty)
      {
        // 初回起動時は復元処理は行わない
        return;
      }

      // [1] ウインドウステート(Normal、最小化、最大化)
      if (Properties.Settings.Default.FormState == FormWindowState.Minimized)
      {
        this.WindowState = FormWindowState.Normal;
      }
      else
      {
        this.WindowState = Properties.Settings.Default.FormState;
      }

      // [2] ウインドウの位置
      this.Location = Properties.Settings.Default.FormLocation;

      // [3] ウインドウの大きさ
      this.Size = Properties.Settings.Default.FormSize;
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
      // [1] ウインドウステート(Normal、最小化、最大化)
      Properties.Settings.Default.FormState = this.WindowState;

      if (this.WindowState == FormWindowState.Normal)
      {
        // ウインドウステート = Normalの場合

        // [2] ウインドウの位置
        Properties.Settings.Default.FormLocation = this.Location;
        // [3] ウインドウの大きさ
        Properties.Settings.Default.FormSize = this.Size;
      }
      else
      {
        // ウインドウステート = 最小化/最大化の場合、RestoreBoundsを保存

        // [2] ウインドウの位置
        Properties.Settings.Default.FormLocation = this.RestoreBounds.Location;
        // [3] ウインドウの大きさ
        Properties.Settings.Default.FormSize = this.RestoreBounds.Size;
      }

      Properties.Settings.Default.Save();
    }
  }
}

■ 補足:ウインドウの位置を保持する場合

http://blog.ahh.jp/?p=1360
で記載されているが、以下の「考慮しないといけないケース」だと
復元前に、モニター内に含まれているかを判定する

考慮しないといけないケース

イレギュラーなケースかもしれないが...
[1] マルチモニターで、メインではなく、サブモニター内にフォームを保存
[2] [1]のPCからサブモニターを抜き、メイン画面だけにする

サンプル

var targetArea = new Rectangle(
  Properties.Settings.Default.FormLocation.X,
  Properties.Settings.Default.FormLocation.Y,
  Properties.Settings.Default.FormSize.Width,
  Properties.Settings.Default.FormSize.Height);

// モニター外に出ていないか調査 
foreach (var screen in Screen.AllScreens)
{
  // モニター内にフォームが重なるか判定する
  if (screen.WorkingArea.IntersectsWith(targetArea))
  // モニター内にフォームに含まれているか判定する
  //if (screen.WorkingArea.Contains(targetArea))
  {
    this.Location = Properties.Settings.Default.FormLocation;
    this.Size = Properties.Settings.Default.FormSize;
    break;
  }
}

補足:Rectangle.Contains/IntersectsWith について

図形 ~ 矩形 / Rectangle ~
https://blogs.yahoo.co.jp/dk521123/37888274.html


関連記事

Windows Form

Windows Form ~ 目次 ~
https://blogs.yahoo.co.jp/dk521123/8054245.html
アプリの設定ファイル
https://blogs.yahoo.co.jp/dk521123/38122457.html
Splitter ~ 画像比較スライダーをWindows Formで実装する ~
https://blogs.yahoo.co.jp/dk521123/37846450.html

その他

図形 ~ 矩形 / Rectangle ~
https://blogs.yahoo.co.jp/dk521123/37888274.html