c#

【.net】ファイル操作系ダイアログで選択したパスを保持する方法

ファイル操作系ダイアログで、
初回に開くフォルダーや、開いたファイル/フォルダーを保持したい場合ってありますよね。
今日はその保持方法について。


標準クラスの挙動

標準のOpenFileDialog、SaveFileDialogはデフォルトで、
前回選択したファイルのパスが次回表示されます。
アプリケーション単位に保持しており、
アプリケーションを再度起動しても保持しているので、レジストリに持っているのでしょう。

なぜかFolderBrowserDialogに関しては保持されていませんが。(2018/10月執筆時点)

ググった感じだと、
レジストリの↓の階層に保存されているらしい。

HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/LastVisitedPidMRU

格納フォルダーの名前は、確かにそれっぽいのですが、
バイナリが格納してあるだけで、実際の格納値の規則などはわかりませんorz

レジストリの値を見るのは現実的ではないので、
自作してみようと思います。


実装の要件

標準と同じ挙動では意味がないので、
下記の要件で実装したいと思います。

  • アプリケーションの初回起動時のみ「デスクトップ」を表示
  • 2回目以降は、選択したファイル/フォルダーを保持
  • FolderBrowserDialogも保持対象

実装のイメージ↓

  1. ファイル操作ダイアログ用に、拡張メソッド定義クラスを作成
  2. 拡張メソッド定義クラスで環境変数を用意
  3. 各ダイアログ表示前にInitialDirectory/SelectedPathに環境変数指定

サンプルソース

以下サンプルソースです。
Form1と拡張メソッドクラスの2つ用意します。

Form1.cs


using System;
using System.Windows.Forms;

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

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.ShowDialogEx(this);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.ShowDialogEx(this);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.ShowDialogEx(this);
        }
    }
}

デザインはこんな感じ↓

確認用フォーム

拡張メソッドクラス


using System;
using System.IO;
using System.Windows.Forms;

namespace FileOperatorSample
{
    /// <summary>
    /// ファイル操作系のダイアログの拡張メソッド定義クラス
    /// </summary>
    public static class FileDialogExtentions
    {
        /// <summary>環境変数名</summary>
        private static string environmentVariableName = $"{Application.ProductName}_CURRENT_DIR_PATH";
        /// <summary>環境変数アクセサ</summary>
        private static string EnvironmentValue
        {
            get
            {
                // 環境変数の値取得
                string variable = Environment.GetEnvironmentVariable(environmentVariableName, EnvironmentVariableTarget.User);
                if (string.IsNullOrEmpty(variable))
                {   // Nullの場合(初回)のみデスクトップとする
                    return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                }
                return variable;
            }
            set
            {
                // 環境変数の値設定
                Environment.SetEnvironmentVariable(environmentVariableName, value, EnvironmentVariableTarget.User);
            }
        }

        /// <summary>
        /// <para>OpenFileDialog.ShowDialogの拡張メソッド</para>
        /// <para>初期フォルダーを設定し、OK選択時に作業ディレクトリを保存します</para>
        /// </summary>
        /// <param name="self"></param>
        /// <param name="window"></param>
        /// <returns></returns>
        public static DialogResult ShowDialogEx(this OpenFileDialog self, IWin32Window window)
        {
            self.InitialDirectory = EnvironmentValue;

            DialogResult ret = self.ShowDialog(window);
            if (ret.Equals(DialogResult.OK))
            {   // OK選択時は選択したファイルのディレクトリを保存する
                EnvironmentValue = Path.GetDirectoryName(self.FileName);
            }
            return ret;
        }

        /// <summary>
        /// <para>FolderBrowserDialog.ShowDialogの拡張メソッド</para>
        /// <para>初期フォルダーを設定し、OK選択時に作業ディレクトリを保存します</para>
        /// </summary>
        /// <param name="self"></param>
        /// <param name="window"></param>
        /// <returns></returns>
        public static DialogResult ShowDialogEx(this FolderBrowserDialog self, IWin32Window window)
        {
            self.SelectedPath = EnvironmentValue;

            DialogResult ret = self.ShowDialog(window);
            if (ret.Equals(DialogResult.OK))
            {   // OK選択時は選択したディレクトリを保存する
                EnvironmentValue = self.SelectedPath;
            }
            return ret;
        }

        /// <summary>
        /// <para>SaveFileDialog.ShowDialogの拡張メソッド</para>
        /// <para>初期フォルダーを設定し、保存選択時に作業ディレクトリを保存します</para>
        /// </summary>
        /// <param name="self"></param>
        /// <param name="window"></param>
        /// <returns></returns>
        public static DialogResult ShowDialogEx(this SaveFileDialog self, IWin32Window window)
        {
            self.InitialDirectory = EnvironmentValue;

            DialogResult ret = self.ShowDialog(window);
            if (ret.Equals(DialogResult.OK))
            {   // OK選択時は選択したファイルのディレクトリを保存する
                EnvironmentValue = Path.GetDirectoryName(self.FileName);
            }
            return ret;
        }

    }
}

結果

順に実行していきます。
初回起動時

初回起動(OpenFileDialog)

初回起動(FolderBrowseDialog)

初回起動(SaveFileDialog)

デスクトップになっていますね。
ここで任意のファイルを選択してみます。
そうすると↓の通り環境変数に表示されます。

環境変数追加を確認

それでは2回目

2回目起動(OpenFileDialog)

2回目起動(FolderBrowseDialog)

2回目起動(SaveFileDialog)

無事選択したファイルのフォルダーが、初期表示されました。
参考までに、アプリケーションを起動するたびに、
保持しているパスをリセットしたい場合は、
環境変数アクセサの箇所を

EnvironmentVariableTarget.User

EnvironmentVariableTarget.Process

のように変更すればいけます。
上の変更は、環境変数の持ち方を現在のユーザ ⇒ プロセスに限定しています。

おしまい。


 

コメントを残す

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