single.php

C# WinUI 3アプリでXML形式でフォームのサイズと位置を保存する手順

C# WinUI 3アプリを作っていく途中で、躓いた部分を備忘録的に投稿します。今回はアンパッケージ化したプロジェクトでフォームのサイズを位置をXML形式で保存する手順です。

Windows.Storageアセンブリで例外

C#で、WinUI 3プロジェクトをアンパッケージ化した場合、Windows.Storageアセンブリで例外が発生してほとんど使えない状態になります。

手動でXML形式に保存

Windows.Storageアセンブリは使えませんが、System.IOアセンブリのStreamReaderやStreamWriterは使えるのでXML形式で保存する処理を作っていきます。

まずはSystem.Environmentアセンブリで保存する場所としてAppDataを取得します。

string appfolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

サブフォルダー名としてアプリケーションのProductNameを代用します。

System.Diagnostics.FileVersionInfo fvinfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
string productName = fvinfo.ProductName;
string appdatafolder = appfolder + @"\" + fvinfo.ProductName;

ここまでのコードで、AppDataフォルダーに専用のサブフォルダーを作成する準備ができました。

保存と読み出し用のデータクラスを作成

ウィンドウの位置やサイズ、状態などをデータ化するためにクラスを作成します。

public class AppSetting
{
  public int Width = 0;
  public int Height = 0;
  public int Top = 0;
  public int Left = 0;
  public OverlappedPresenterState State = OverlappedPresenterState.Restored;
}

場所的には、アプリケーションクラスの上くらいに追加します。

保存するサイズや位置情報を取得するために、コンストラクターなどに次のコードを追加しておきます。

  Microsoft.UI.Windowing.AppWindow m_AppWindow;

  IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
  Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
  m_AppWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

データ保存用の処理を追加

次にAppSettingクラスを使って、XML形式で保存する処理を追加します。

private void StoreMainWindowRect()
{
  int nWidth = m_AppWindow.Size.Width;
  int nHeight = m_AppWindow.Size.Height;
  int nTop = m_AppWindow.Position.Y;
  int nLeft = m_AppWindow.Position.X;

  OverlappedPresenter olp = (OverlappedPresenter)m_AppWindow.Presenter;
  OverlappedPresenterState State = olp.State;

  string appfolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
  System.Diagnostics.FileVersionInfo fvinfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
  string appdatafolder = appfolder + @"\" + fvinfo.ProductName;
  string appdatafile = appdatafolder + @"\data.xml";
  System.IO.Directory.CreateDirectory(appdatafolder);

  AppSetting aps = new AppSetting();
  aps.Top = nTop;
  aps.Left = nLeft;
  aps.Width = nWidth;
  aps.Height = nHeight;
  aps.State = State;

  System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(AppSetting));
  System.IO.StreamWriter sw = new System.IO.StreamWriter(appdatafile, false, new System.Text.UTF8Encoding(false));
  serializer.Serialize(sw, aps);
  sw.Close();
}

ウィンドウが閉じる際のイベントなどで、追加したプロシージャを呼び出します。

データ読み込み用の処理を追加

保存したXML形式のファイルを読み込んでAppSettingクラスにデータを追加する処理を追加します。

private void LoadMainWindowRect()
{
  string appfolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
  string appdatafolder = appfolder + @"\WinUI3ImageViewer";
  string appdatafile = appdatafolder + @"\data.xml";

  if(System.IO.File.Exists(appdatafile) == true)
  {
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(AppSetting));
    System.IO.StreamReader sr = new System.IO.StreamReader(appdatafile, new System.Text.UTF8Encoding(false));
    AppSetting aps = (AppSetting)serializer.Deserialize(sr);
    sr.Close();

    int nWidth = aps.Width;
    int nHeight = aps.Height;
    int nTop = aps.Top;
    int nLeft = aps.Left;

    OverlappedPresenterState State = aps.State;

    Windows.Graphics.RectInt32 rect = new Windows.Graphics.RectInt32(nLeft, nTop, nWidth, nHeight);
    m_AppWindow.MoveAndResize(rect);

    if (State == OverlappedPresenterState.Maximized)
    {
      OverlappedPresenter olp = (OverlappedPresenter)m_AppWindow.Presenter;
      olp.Maximize();
    }

    if (State == OverlappedPresenterState.Minimized)
    {
      OverlappedPresenter olp = (OverlappedPresenter)m_AppWindow.Presenter;
      olp.Minimize();
    }

  }

}

SettingsクラスやWindows.Storageクラスを使うと簡単に保存や読み込みができますが、System.IOアセンブリなどを使って独自でファイルに保存することができます。

まとめ

今回は、WinUI 3 アプリのウィンドウのサイズと位置をテキストファイルに保存する方法を書きました。

WinUI3プロジェクトを作成した場合、アンパッケージ化を行うとWindows.Storageアセンブリを利用しようとすると例外が発生するために、ローカル設定を保存したり読み込むことができなくなります。

そのために、利用できるSystem.IOアセンブリを使って手動でXML形式で保存することで終了時のウィンドウのサイズや位置を復帰させる処理を追加ができます。

C#のWinUI 3アプリでWindows.Storageアセンブリを使わずに画面サイズや位置を保存したい場合の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です