Ответ 1
Вы можете начать создание проекта с помощью SharpShell, чтобы зарегистрировать новое контекстное меню оболочки, например, в учебник.
Здесь мы должны определить класс, реализующий 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()
, который используется для запуска новых процессов.