C#のWinFormsでファイルマネージャーのような物をつくる。

コンピュータ

ファイルマネージャーをUserControlで作成すると再利用できるのではないかと思い試作してみました。
ファイル名:Form1.cs

namespace FileManagerControl;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        var fm = new FileManager
        {
            CurrentDirectory = @"c:\",
            Dock = DockStyle.Fill,
        };
        fm.FileSelected += (s, e) =>
        {
            var ee = (FileManagerEventArgs)e;
            MessageBox.Show(ee.FullPath,"ファイルが選択されたよ。");
        };
        var cms = new ContextMenuStrip();
        var viewLabel = new ToolStripMenuItem{ Text = "パスを表示" };
        var deleteLabel = new ToolStripMenuItem{ Text = "削除" };
        cms.Items.AddRange(new ToolStripMenuItem[]{viewLabel, deleteLabel});
        fm.ContextMenuStrip = cms;

        viewLabel.Click += (s, e) =>
        {
            string text = "";

            foreach(var t in fm.GetSlectedPath())
            {
                text = text + t + "\n";
            }

            MessageBox.Show(text, "パスの表示");
        };
        deleteLabel.Click += (s, e) =>
        {
            string text = "";

            foreach(var t in fm.GetSlectedPath())
            {
                text = text + t + "\n";
            }
            var result = MessageBox.Show(text, "削除しますか?", MessageBoxButtons.YesNo, MessageBoxIcon.Hand);

            if (result != DialogResult.Yes) return;
            foreach(var path in fm.GetSlectedPath())
            {
                if (File.Exists(path)) File.Delete(path);
            }
            fm.Reload();
        };

        Controls.Add(fm);
    }
}

ファイル名:FileManager.cs

using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace FileManagerControl;

public class FileManagerEventArgs : EventArgs
{
    public String FullPath {get; set;} = "";
}
public class FileManager : UserControl
{
    public static Bitmap DataToBitmap(int[] data, Color[] pallet)
    {
        int width = (int)Math.Sqrt(data.Length);
        int height = width;

        int ch = 32 / 8;
        byte[] bytes = new byte[width * height * ch];
        for(int i = 0; i < data.Length; i++)
        {
            Color c = pallet[data[i]];
            bytes[i*ch+0] = c.B;
            bytes[i*ch+1] = c.G;
            bytes[i*ch+2] = c.R;
            bytes[i*ch+3] = c.A;
        };

        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
        BitmapData bitmapData = bitmap.LockBits(
            new Rectangle(Point.Empty, bitmap.Size),
            ImageLockMode.WriteOnly,
            bitmap.PixelFormat);

        Marshal.Copy(bytes, 0, bitmapData.Scan0, bytes.Length);
        bitmap.UnlockBits(bitmapData);

        return bitmap;
    }
    
    public event EventHandler FileSelected;
    Button parentDirectoyButton = new Button
    {
        Dock = DockStyle.Fill,        
        Height = 32,
        Width = 32,
        //Text = "↑",
    };
    ComboBox pathEntoryBox = new ComboBox
    {
        Dock = DockStyle.Fill,
        //Height = 32,
        //Width = 600,
    };
    Panel topPanel = new Panel
    {
        Padding = new Padding(4),
        Height = 48,
        Dock = DockStyle.Top,
    };
    Panel topLeftPanel = new Panel
    {
        Width = 40,
        Padding = new Padding(4),
        Dock = DockStyle.Left,
    };
    Panel topFillPanel = new Panel
    {
        Padding = new Padding(4),
        Dock = DockStyle.Fill,
    };
    Panel middlePanel = new Panel
    {
        Padding = new Padding(8),
        Dock = DockStyle.Fill,
    };
    ListView FileListView = new ListView
    {
        Dock = DockStyle.Fill,
        View = View.Details,
        FullRowSelect = true,
    };
    private string _currentDirectory = "";
    public string CurrentDirectory
    {
        get
        {
            return _currentDirectory;
        }
        set
        {
            if (_currentDirectory == value) return;
            if (!Directory.Exists(value)) return;

            _currentDirectory = value;
            changeDirectory();
        }
    }
    public string[] GetSlectedPath()
    {
        var files = new List<string>();

        var si = FileListView.SelectedItems;
        for(int i = 0; i < si.Count; i++)
        {
            files.Add(Path.Join(_currentDirectory, si[i].Text));
        }

        return files.ToArray();
    }
    public void Reload() => changeDirectory();
    public FileManager()
    {
        _currentDirectory = Directory.GetCurrentDirectory();
        var data = new int[]
        {
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
            0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
            0,0,0,0,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,
            0,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,0,0,0,0,
            0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,
            0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,
            0,0,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,0,0,
            0,0,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        };
        var pallet = new Color[]
        {
            Color.FromArgb(0,255,255,255),
            Color.FromArgb(255, 0, 0, 0),
        };
        Bitmap Allow = DataToBitmap(data, pallet);
        data = new int[]
        {
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,
            0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
            0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        };
        Bitmap FolderIcon = DataToBitmap(data, pallet);
        data = new int[]
        {
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
            0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
            0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,
            0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
            0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        };
        Bitmap FileIcon = DataToBitmap(data, pallet);

        parentDirectoyButton.Image = Allow;
        parentDirectoyButton.FlatStyle = FlatStyle.Popup;
        parentDirectoyButton.BackColor = Color.Empty;

        var imgList = new ImageList();
        imgList.ImageSize = FolderIcon.Size;
        imgList.Images.Add(FolderIcon);
        imgList.Images.Add(FileIcon);
                
        this.FileSelected += (s, e) => {};
        this.ContextMenuStripChanged += (s, e) => {};

        string[] drives = Directory.GetLogicalDrives();
        foreach (var drive in drives)
        {
            pathEntoryBox.Items.Add(drive);
        }

        FileListView.Columns.Add("名前", 400, HorizontalAlignment.Left);
        FileListView.Columns.Add("更新日時", 180, HorizontalAlignment.Left);
        FileListView.Columns.Add("種類", 100, HorizontalAlignment.Left);
        FileListView.Columns.Add("サイズ", 100, HorizontalAlignment.Right);
        FileListView.SmallImageList = imgList;

        pathEntoryBox.TextChanged += (s, e) =>
        {
            var path = pathEntoryBox.Text;
            if (!Directory.Exists(path)) return;
            CurrentDirectory = path;
        };
        topFillPanel.Controls.Add(pathEntoryBox);
        topLeftPanel.Controls.Add(parentDirectoyButton);
        middlePanel.Controls.Add(FileListView);
        topPanel.Controls.AddRange(new Control[]{topFillPanel, topLeftPanel});
        Controls.AddRange(new Control[]{middlePanel, topPanel});

        Load += (s, e) =>
        {
            pathEntoryBox.Text = _currentDirectory;
            Reload();
        };

        parentDirectoyButton.Click += (s, e) =>
        {
            pathEntoryBox.Text = Path.GetFullPath(Path.Join(_currentDirectory, ".."));
        };
        FileListView.ItemActivate += (s, e) =>
        {
            var si = FileListView.SelectedItems;
            if (si == null || si.Count == 0) return;
            var path = Path.Join(_currentDirectory, si[0].Text);
            if (Directory.Exists(path))
            {
                pathEntoryBox.Text = path;
                return;
            }
            if (File.Exists(path))
            {
                FileSelected?.Invoke(this, new FileManagerEventArgs{ FullPath = path });
            }
        };
    }
    void changeDirectory()
    {
        FileListView.Items.Clear();
        FileListView.BeginUpdate();

        var di = new DirectoryInfo(_currentDirectory);
        foreach(var d in di.GetDirectories())
        {
            var items = new string []
            {
                d.Name, d.LastWriteTime.ToString(), "フォルダー", "" 
            };
            var lvi = new ListViewItem(items);
            lvi.ImageIndex = 0;
            FileListView.Items.Add(lvi);
        }

        foreach(var f in di.GetFiles())
        {
            var items = new string []
            {
                f.Name, f.LastWriteTime.ToString(), f.Extension, f.Length.ToString() 
            };
            var lvi = new ListViewItem(items);
            lvi.ImageIndex = 1;
            FileListView.Items.Add(lvi);
        }
        FileListView.EndUpdate();
        parentDirectoyButton.Enabled = Path.GetPathRoot(_currentDirectory) != _currentDirectory;
    }
}//class

コメント