ファイルやフォルダにタグやコメントをつけて、検索して必要なものを見つけやすくするアプリを作成します。ファイルそのものに情報を書き込むのではなく、別のアプリのデータで管理します。
またデジタルカメラで撮影された写真には、撮影時のさまざまな情報(メタデータ)を埋め込んで保存するための画像ファイルのフォーマットとしてEXIF(イグジフ)があります。これを知らずにアップロードしてしまうと個人情報が漏れる原因になります。そのためExif情報のすべての項目を削除できるソフトも需要があるそうです。
これから作成するアプリはファイルそのものには変化を加えません。ただファイルを移動してしまうとファイルやフォルダに関連づけたデータは意味を失ってしまいます。長短ありますが、そのようなアプリをつくります。
やることは極めてシンプルでファイルパスとデータをセットにしてデータとして保存するだけです。
では簡単なものとして以下を作成します。劣化版のエクスプローラーです。
最初にリストボックスの設定ですが、同時に複数の選択はできないものとします。選択できるファイルとフォルダはひとつだけです。コントロールにフォーカスがないときも選択されているアイテムを強調表示されたままにします。
1 2 3 4 |
listView1.View = View.Details; listView1.FullRowSelect = true; listView1.HideSelection = false; listView1.MultiSelect = false; |
コンボボックスはドロップダウンメニューに現在使用できるドライブの一覧を表示させます。そして選択するとそのドライブの中身を表示させます。
アプリケーションが起動したら自作メソッド MoveRootFolderを呼び出し、Cドライブのなかのファイルとフォルダを表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); listView1.FullRowSelect = true; listView1.HideSelection = false; listView1.MultiSelect = false; InitComboBox(); } void InitComboBox() { comboBox1.DropDownClosed += ComboBox1_DropDownClosed; comboBox1.DropDown += ComboBox1_DropDown; } private void ComboBox1_DropDown(object sender, EventArgs e) { comboBox1.Items.Clear(); DriveInfo[] infos = DriveInfo.GetDrives(); infos = infos.Where(x => x.IsReady == true).ToArray(); foreach(var d in infos) { comboBox1.Items.Add(d.Name); } } private void ComboBox1_DropDownClosed(object sender, EventArgs e) { int index = comboBox1.SelectedIndex; if(index == -1) return; string driveName = (string)comboBox1.Items[index]; MoveRootFolder(driveName); } private void Form1_Load(object sender, EventArgs e) { comboBox1.Text = "C:\\"; MoveRootFolder("C:\\"); } } |
MoveRootFolderメソッドはルートフォルダにあるフォルダとファイルを調べて、その名前をリストビューに表示させます。それと同時にCurFolderPathプロパティに現在どのフォルダにいるのかがわかるように、パスをセットします。CurFolderPathプロパティにパスがセットされると現在参照しているフォルダのパスがテキストボックスに表示されます。
system volume informationと$recycle.binは表示させません(アプリの目的上、表示させても意味が無いので)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
using System.IO; public partial class Form1 : Form { void MoveRootFolder(string driveName) { DriveInfo driveInfo = new DriveInfo(driveName); CurFolderPath = driveInfo.RootDirectory.FullName; SelectedPath = ""; listView1.Items.Clear(); DirectoryInfo[] ds = driveInfo.RootDirectory.GetDirectories(); foreach(DirectoryInfo info in ds) { string fullName = info.FullName; if( fullName.ToLower().EndsWith(":\\system volume information") || fullName.ToLower().EndsWith(":\\$recycle.bin") ) continue; ListViewItem item = new ListViewItem(new string[] { info.Name, "フォルダ", info.CreationTime.ToString(), info.LastWriteTime.ToString(), "", "" }); listView1.Items.Add(item); } FileInfo[] fs = driveInfo.RootDirectory.GetFiles(); foreach(FileInfo info in fs) { ListViewItem item = new ListViewItem(new string[] { info.Name, "ファイル", info.CreationTime.ToString(), info.LastWriteTime.ToString(), (info.Length / 1024 + 1).ToString(), "" }); listView1.Items.Add(item); } } string _curFolderPath = ""; string CurFolderPath { get { return _curFolderPath; } set { if(Directory.Exists(value)) { _curFolderPath = value; textBoxCurFolder.Text = value; } } } } |
リストビューに表示されているアイテムが選択されたら、そのファイル、フォルダをプロパティにセットして名前とパスを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public partial class Form1 : Form { private void listView1_SelectedIndexChanged(object sender, EventArgs e) { var selItems = listView1.SelectedItems; if(selItems.Count == 0) return; string newPath; if(CurFolderPath.EndsWith("\\")) newPath = CurFolderPath + selItems[0].Text; else newPath = CurFolderPath + "\\" + selItems[0].Text; SelectedPath = newPath; textBoxSelectedPath.Text = newPath; } string _selectedPath = ""; string SelectedPath { get { return _selectedPath; } set { if(Directory.Exists(value) || File.Exists(value)) { _selectedPath = value; textBoxSelectedPath.Text = value; // ファイル名取得もこれでOK DirectoryInfo info1 = new DirectoryInfo(value); textBoxSelectedName.Text = info1.Name; } else { _selectedPath = ""; textBoxSelectedPath.Text = ""; textBoxSelectedName.Text = ""; } } } } |
アイテムがダブルクリックされたらそれがフォルダであればそのフォルダの中身を表示させます。このときに呼び出されるのが自作メソッド MoveToFolder(string path)です。アクセスできないフォルダの場合はアクセスできないというメッセージボックスを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public partial class Form1 : Form { private void listView1_DoubleClick(object sender, EventArgs e) { var sels = listView1.SelectedItems; Text = sels[0].Text; string newPath = CurFolderPath + "\\" + sels[0].Text; if(Directory.Exists(newPath)) MoveToFolder(newPath); } void MoveToFolder(string path) { DirectoryInfo info = new DirectoryInfo(path); DirectoryInfo[] ds = null; try { ds = info.GetDirectories(); } catch { MessageBox.Show("アクセスを拒否されました!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } CurFolderPath = info.FullName; SelectedPath = ""; listView1.Items.Clear(); foreach(DirectoryInfo dirInfo in ds) { string fullName = dirInfo.FullName; if( fullName.ToLower().EndsWith(":\\system volume information") || fullName.ToLower().EndsWith(":\\$recycle.bin") ) continue; ListViewItem item = new ListViewItem(new string[] { dirInfo.Name, "フォルダ", dirInfo.CreationTime.ToString(), dirInfo.LastWriteTime.ToString(), "", // フォルダなのでサイズはない "" }); listView1.Items.Add(item); } FileInfo[] fs = info.GetFiles(); foreach(var fileInfo in fs) { ListViewItem item = new ListViewItem(new string[] { fileInfo.Name, "ファイル", fileInfo.CreationTime.ToString(), fileInfo.LastWriteTime.ToString(), (fileInfo.Length/1024 +1).ToString(), "" }); listView1.Items.Add(item); } } } |
フォルダのなかへ移動できるのであれば、親フォルダに戻れるようにする必要があります。[上へ]ボタンを押せば親フォルダへ移動できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public partial class Form1 : Form { private void buttonMoveParent_Click(object sender, EventArgs e) { MoveToParentFolder(); } void MoveToParentFolder() { DirectoryInfo info = new DirectoryInfo(CurFolderPath); if(info == null || info.Parent == null) return; MoveToFolder(info.Parent.FullName); } } |