ゲームエフェクトデザイナーのブログ | A Real-Time VFX Artist's Blog

About Making Materials on UE, Making Tools with C#, etc

C#でサブフォルダをリストアップ

前回に続いて、任意のフォルダの直下にあるサブフォルダ名をリストアップするツールについて、備忘録としてメモしておきたいと思います。

恐らくプログラム初心者ならではの全くスマートではない見苦しいコードになってるのではと思うので、そのあたりご注意ください。。

ツールの外観は下図のような感じで、上段のテキストボックスにフォルダのパスを入力してEnterを押すか、またはフォルダやファイルをツール上へドラッグ&ドロップすることで下段の「サブフォルダリスト」内にサブフォルダ名をずらずらっとリストアップします。

f:id:moko_03_25:20170807235416j:plain

 

実装したもの


ここで実装した内容は以下になります。

・あるパスがファイルかフォルダかを判定してフォルダパスを取得するメソッド
  - ファイルの場合は親フォルダのパスを取得
  - フォルダの場合は自身のフォルダパスを取得
・フォルダパスから直下のサブフォルダ名を取得してリストアップするメソッド

・パスを入力してEnterキー入力でリストアップを実行する
・ファイルかフォルダをドラッグ&ドロップするとリストアップを実行する


1つずつ見ていきます。

usingと変数の宣言

 

using System.IO;

~~~~省略~~~~

//変数の宣言
string filePath; //ファイルのフルパス
string folderPath; //親フォルダのフルパス


既存のファイル情報を得るクラスを使用するので「System.IO」を using に追記します。

また、パスのややこしい部分ですが、ファイルパスとフォルダパスの扱いを明示的に分けたかったので変数を2つ用意しました。

ファイルかフォルダか判定してフォルダパスを取得するメソッド


次に、あるパスがファイルかフォルダかを判定して、どちらの場合でもフォルダのパスを取得するよう記述したメソッドが下記です。
青文字はクラス名・メソッド名・変数名です)

//ファイルかフォルダか判定してフォルダパスを取得するメソッド
private void determine()
{
  if (File.Exists(filePath)) //ファイルの場合
  {
    folderPath = Path.GetDirectoryName(filePath);
  }
  else if (Directory.Exists(filePath)) //フォルダの場合
  {
    folderPath = filePath;
  }
}


File.Exists」「Directory.Exists」を使うことで、パス先がファイルなのかフォルダなのか簡単に判定できるようです。便利!

それから、パスの取得周りはルールがちょっとややこしいです。
こちらの記事を参考にしました。

パスからファイル名、拡張子、ディレクトリ名、ルートディレクトリ名等の情報を取得する: .NET Tips: C#, VB.NET

こちらの一覧表を見ると分かりますが、現在のフォルダ名(上記サイトの例だと"sub"がそれにあたる)を取得するには、フォルダパスに対して「Path.GetFileName」で行うことになるかと思います。

しかしドラッグ&ドロップで入力したものがファイルだった場合に、ファイルパスに対して「Path.GetDirectoryName」でフォルダパスを得ています。

フォルダパスからサブフォルダ名を取得してリストアップするメソッド


今回の要となる、サブフォルダをリストアップするメソッドがこちら。

//フォルダパスからサブフォルダをリストアップするメソッド
private void listUp()
{
  //テキストの内容をTextBoxに表示
  textBoxPath.Text = folderPath;

  //指定フォルダ以下のサブフォルダをすべて取得する
  string subFolders = Directory.GetDirectories(
    folderPath, "*",
    SearchOption.TopDirectoryOnly); //サブフォルダTOP階層のみ取得

  //一旦内容をクリア
  textBoxList.ResetText();

  //取得したサブフォルダ群を1つずつテキストボックスに追加していく
  for (int i = 0; i < subFolders.Length; i++)
  {
    //サブフォルダのパスからフォルダ名を取得
    string stFileName = Path.GetFileName(subFolders[i]);
    //フォルダ名を改行しながら追加
    textBoxList.AppendText(stFileName + "\r\n");
  }
}


先ほどの判定メソッドで得たフォルダパスを利用して、そのフォルダ直下のサブフォルダ名を「Directory.GetDirectories」で取得して配列に代入しています。

こちらの記事を参考にさせて頂きました。

あるフォルダ以下にあるサブフォルダをすべて取得する: .NET Tips: C#, VB.NET

その後にfor分で1つずつテキストボックスに改行しながら追記していきます。

パスを入力してEnterキー入力でリストアップを実行する


まず探すきっかけとなるパスをどう取得するかですが、今回は手動での入力とドラッグ&ドロップに両対応することにしました。

専用のテキストボックスにパスを手動で入力してEnterキーを押した時の挙動がこちら。

//TextBoxPathのキー入力による挙動
private void textBoxPath_KeyDown(object sender, KeyEventArgs e)
{
  //Ctrl + A で全選択可能にする
  if (e.Control && e.KeyCode == Keys.A)
    textBoxPath.SelectAll();

  //Enterでパスを取得
  if (e.KeyCode == Keys.Enter)
  {
    //フォルダが存在しているかどうか判定
    if (Directory.Exists(textBoxPath.Text))
    {
      //TextBoxの内容からパスを取得
      filePath = textBoxPath.Text;
      //ファイルかフォルダかを判定してフォルダパスを取得
      determine();
      //フォルダパスからサブフォルダをリストアップする
      listUp();
    }
    else
    {
      MessageBox.Show("存在しないフォルダです");
    }
  }
}


テキストボックスは1行だけのボックスであっても全選択したいものだと思うので、前回の記事同様にKeyDownイベントに Ctrl + A による全選択を記述しています。

また、Enterキーによる実行もKeyDownイベントなので、こちらも平行して記述します。
まずテキストボックスに入力したパス先にフォルダがあるか判定してから、最初に解説したメソッド2つを実行します。ここはとてもシンプルです。

フォルダと判定できなかった場合はメッセージボックスを表示します。

f:id:moko_03_25:20170809021356j:plain

ファイルかフォルダをドラッグ&ドロップするとリストアップを実行


最後にドラッグ&ドロップされたフォルダ(またはファイル)からパスを取得した時の挙動がこちらになります。

//Formへのドラッグ&ドロップの挙動1
private void Form1_DragEnter(object sender, DragEventArgs e)
{
  //ドロップされたものがファイルかどうかチェックする定番の書き方
  if (e.Data.GetDataPresent(DataFormats.FileDrop))
  {
    //ファイルのときは受け付ける
    e.Effect = DragDropEffects.All;
  }
  else
  {
    //ファイル以外は受け付けない
    e.Effect = DragDropEffects.None;
  }
}
//Formへのドラッグ&ドロップの挙動2
private void Form1_DragDrop(object sender, DragEventArgs e)
{
  //ファイルが複数ドロップされた時のためにフルパスを配列に代入
  string multiPass = (string[])e.Data.GetData(DataFormats.FileDrop, false);
  //0番目のファイルだけフルパスを取得
  filePath = multiPass[0];
  //ファイルかフォルダかを判定してフォルダパスを取得
  determine();
  //フォルダパスからサブフォルダをリストアップする
  listUp();
}


ドラッグ&ドロップの対応はこちらの記事を参考にさせて頂きました。

Drag&Dropされたファイルのファイル名を取得する: .NET Tips: C#, VB.NET

他にもいくつかのサイトを参考にしましたが、この形がお約束のようで、ドラッグ時のウインドウ上部への侵入時の挙動と、ドロップ時のふたつの挙動がセットになるようです。

複数のファイルがドロップされた時のために、配列に代入するのもお約束のようです。
そうして得たパスに対して、最初に解説したメソッド2つを実行します。

プロジェクトデータと実行ファイル


Googleドライブにアップしました。ライセンスはMITです。

MyTool_FolderList.zip - Google ドライブ

binフォルダの中にexeが入っています。