C#用IShellFolderのファイル名(表示名)変更に必要な関数のラッパーを提供するクラスと拡張メソッドファイル
概要とコード
動作確認環境:Windows 10 64ビット、Microsoft Visual Studio 2019、C# 7.3
Win32 API IShellFolderインターフェイスのファイル名(表示名)変更に必要な関数のラッパーを提供するクラスと拡張メソッドファイルの組み合わせです。サイズよりも独立性を優先しており、拡張メソッドはそれぞれ別ファイルに定義して、各ファイルにIShellFolderインターフェイスを最小限定義しています。
IShellFolderインターフェイスのラッパークラス。このクラスはCOMオブジェクトラッパー以外の機能を持たず、別のファイルで拡張メソッドを定義します。
ShellFolderWrapper.cs - GitHub
上記ラッパークラスの拡張メソッド定義ファイル。それぞれのファイルが拡張メソッドとそれに必要なIShellFolderインターフェイスの定義、列挙型などを持ちます。
ShellFolderSetNameOfExtensions.cs - GitHub
ShellFolderGetDisplayNameOfExtensions.cs - GitHub
ShellFolderBindToObjectAsIShellFolderExtensions.cs - GitHub
サンプルコード
C#の標準機能(Data.GetData(DataFormats.FileDrop)
)では取得できないコントロールパネル項目の名前なども取得できます。なお、このサンプルでは以前に公開したSTRRETとCIDAのラッパーを使用しています。
- Windows フォーム アプリケーション (.NET Framework) [C# Windows デスクトップ]を作成する。
- Form1.csのコードを以下の通り書き換える。名前空間WindowsFormsApp1は必要に応じて変更する。
- プロジェクトを実行して適当なファイルやコントロールパネルの項目をドラッグする。
- IDEの出力ウィンドウを確認する。
using System; using System.IO; using System.Windows.Forms; using Oxalis.Windows.Shell; using Oxalis.Windows.Shell.ShellFolder; namespace WindowsFormsApp1 { public partial class MainForm : Form { public MainForm() { InitializeComponent(); this.AllowDrop = true; this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop); this.DragOver += new System.Windows.Forms.DragEventHandler(this.MainForm_DragOver); } private void MainForm_DragOver(object sender, DragEventArgs e) { e.Effect = e.AllowedEffect; } private void MainForm_DragDrop(object sender, DragEventArgs e) { var desktop = default(ShellFolderWrapper); var folder = default(ShellFolderWrapper); try { desktop = ShellFolderWrapper.GetDesktopFolder(); using (var stream = (MemoryStream)e.Data.GetData("Shell IDList Array")) { using (var shellItemIDList = new ShellIDListArray(stream)) { if (!shellItemIDList.IsFolderDesktop) { folder = desktop.BindToShellFolder( shellItemIDList.FolderItemIDListAddress); } else { // デスクトップからデスクトップを取得しようとするエラーを防ぐ。 folder = desktop; } foreach (var pidl in shellItemIDList.FileItemIDListAddresses) { var oldName = folder.GetDisplayNameOf( pidl, ShellFolderGetDisplayNameOfExtensions.SHGDN.SHGDN_NORMAL); Console.WriteLine(oldName); //TODO:名前を変更する場合は以下をコメントアウトします。 // ここでは前後の空白と途中の改行(CR、LF)を削除します。 var newName = oldName.Trim() .Replace('\r', ' ') .Replace('\n', ' '); if (oldName != newName) { folder.SetNameOf( pidl, newName, ShellFolderSetNameOfExtensions.SHCONTF.SHCONTF_FOLDERS, Handle); } } } } } finally { desktop?.Dispose(); folder?.Dispose(); } } } }
memos-by-oxalis.hatenablog.com memos-by-oxalis.hatenablog.com