È possibile iniziare a creare un progetto con SharpShell per registrare un nuovo menu contestuale shell come in questo tutorial.
Qui, dobbiamo definire una classe che implementa SharpContextMenu
. Per semplicità creeremo il menu per qualsiasi tipo di file e mostra sempre:
[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()
{
...
}
}
Ma sono sicuro che hai fatto tutto questo, il problema è quello di implementare il metodo CopyFiles()
.
Un modo per fare questo sta mostrando una finestra di dialogo che chiede per il nome della cartella, qualcosa di simile:
Poi, implementare CopyFiles()
in questo modo:
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);
}
}
}
}
In precedenza codice, abbiamo chiesto il nome della cartella, quindi creare la cartella e infine spostare i file selezionati in quella cartella.
Tuttavia, se si vuole farlo utilizzando Rinomina comando nel Esplora risorse possiamo cominciare importando alcuni necessari Win32 funzioni:
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
ci permette di ottenere il PIDL da un nome file.
SHOpenFolderAndSelectItems
consentici di selezionare il file e inviare il comando di rinomina.
ILFree
libero non gestito PIDL
creato.
Con queste Win32 funzioni possiamo definisce CopyFiles()
come segue:
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);
}
}
Non possiamo usare SharpShell.Interop.Shell32
poiché l'unico metodo disponibile in questa classe è ShellExecuteEx()
che viene utilizzato per lanciare nuovi processi.
Quando si crea una nuova cartella utilizzando Explorer, esso denomina la cartella "Nuova cartella", quindi entra nella modalità di rinomina. Quando stai digitando il nome della cartella e poi premi invio, stai effettivamente rinominando la cartella. Cosa succede se l'utente rinomina la cartella, quindi preme Invio prima che i file finiscano di copiare? Probabilmente il rinominare fallirà perché i file vengono ancora copiati nella cartella. Penso che questo approccio non sia buono e che tu stia meglio mostrando un modulo con una casella di testo all'utente. – Ove