您可以开始使用SharpShell创建一个项目来注册一个新的 shell 上下文菜单,就像在本教程中一样。
在这里,我们必须定义一个实现SharpContextMenu
. 为简单起见,我们将为任何文件类型创建菜单并始终显示它:
[ComVisible(true)]
[COMServerAssociation(AssociationType.AllFiles)]
public class CopyFilesExtension : SharpContextMenu
{
protected override bool CanShowMenu()
{
return true;
}
protected override ContextMenuStrip CreateMenu()
{
var menu = new ContextMenuStrip();
var copyFiles = new ToolStripMenuItem { Text = "Copy Files To Folder..." };
copyFiles.Click += (sender, args) => CopyFiles();
menu.Items.Add(copyFiles);
return menu;
}
private void CopyFiles()
{
...
}
}
但我相信你已经完成了这一切,这里的问题是实现CopyFiles()
方法。
一种方法是显示一个询问文件夹名称的对话框,如下所示:
然后,CopyFiles()
像这样实现:
private void CopyFiles()
{
using (var dialog = new CopyFileDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
var folder = Path.GetDirectoryName(SelectedItemPaths.First());
var newFolder = Path.Combine(folder, dialog.FolderName);
Directory.CreateDirectory(newFolder);
foreach (var path in SelectedItemPaths)
{
var newPath = Path.Combine(newFolder, Path.GetFileName(path));
File.Move(path, newPath);
}
}
}
}
在上面的代码中,我们询问了文件夹的名称,然后创建文件夹,最后将选定的文件移动到该文件夹。
但是,如果您想在Windows 资源管理器中使用重命名命令来执行此操作,我们可以从导入一些必需的Win32函数开始:
class Win32
{
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr ILCreateFromPath([In, MarshalAs(UnmanagedType.LPWStr)] string pszPath);
[DllImport("shell32.dll")]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, int dwFlags);
[DllImport("shell32.dll")]
public static extern void ILFree(IntPtr pidl);
}
ILCreateFromPath
允许我们从文件名中获取PIDL。
SHOpenFolderAndSelectItems
允许我们选择文件并发送重命名命令。
ILFree
释放非托管PIDL
创建。
使用这些Win32函数,我们可以定义CopyFiles()
如下:
private void CopyFiles()
{
var folder = Path.GetDirectoryName(SelectedItemPaths.First());
var newFolder = Path.Combine(folder, "New Folder");
Directory.CreateDirectory(newFolder);
foreach (var path in SelectedItemPaths)
{
var newPath = Path.Combine(newFolder, Path.GetFileName(path));
File.Move(path, newPath);
}
RenameInExplorer(newFolder);
}
private static void RenameInExplorer(string itemPath)
{
IntPtr folder = Win32.ILCreateFromPath(Path.GetDirectoryName(itemPath));
IntPtr file = Win32.ILCreateFromPath(itemPath);
try
{
Win32.SHOpenFolderAndSelectItems(folder, 1, new[] { file }, 1);
}
finally
{
Win32.ILFree(folder);
Win32.ILFree(file);
}
}
我们不能使用SharpShell.Interop.Shell32
,因为此类中唯一可用的方法ShellExecuteEx()
是用于启动新进程。