mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-09-30 17:16:52 +13:00
328 lines
13 KiB
C#
328 lines
13 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
|
|
namespace SystemTrayMenu.UserInterface.FolderDialog
|
|
{
|
|
public class FolderDialog : IFolderDialog, IDisposable
|
|
{
|
|
private bool isDisposed;
|
|
|
|
/// <summary>
|
|
/// Gets/sets folder in which dialog will be open.
|
|
/// </summary>
|
|
public string InitialFolder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets/sets directory in which dialog will be open
|
|
/// if there is no recent directory available.
|
|
/// </summary>
|
|
public string DefaultFolder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets selected folder.
|
|
/// </summary>
|
|
public string Folder { get; set; }
|
|
public DialogResult ShowDialog()
|
|
{
|
|
return ShowDialog(owner: new WindowWrapper(IntPtr.Zero));
|
|
}
|
|
public DialogResult ShowDialog(IWin32Window owner)
|
|
{
|
|
if (Environment.OSVersion.Version.Major >= 6)
|
|
{
|
|
return ShowVistaDialog(owner);
|
|
}
|
|
else
|
|
{
|
|
return ShowLegacyDialog(owner);
|
|
}
|
|
}
|
|
public DialogResult ShowVistaDialog(IWin32Window owner)
|
|
{
|
|
var frm = (NativeMethods.IFileDialog)(new NativeMethods.FileOpenDialogRCW());
|
|
uint options;
|
|
frm.GetOptions(out options);
|
|
options |= NativeMethods.FOS_PICKFOLDERS |
|
|
NativeMethods.FOS_FORCEFILESYSTEM |
|
|
NativeMethods.FOS_NOVALIDATE |
|
|
NativeMethods.FOS_NOTESTFILECREATE |
|
|
NativeMethods.FOS_DONTADDTORECENT;
|
|
frm.SetOptions(options);
|
|
if (this.InitialFolder != null)
|
|
{
|
|
NativeMethods.IShellItem directoryShellItem;
|
|
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
|
if (NativeMethods.SHCreateItemFromParsingName
|
|
(this.InitialFolder, IntPtr.Zero, ref riid,
|
|
out directoryShellItem) == NativeMethods.S_OK)
|
|
{
|
|
frm.SetFolder(directoryShellItem);
|
|
}
|
|
}
|
|
if (this.DefaultFolder != null)
|
|
{
|
|
NativeMethods.IShellItem directoryShellItem;
|
|
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
|
if (NativeMethods.SHCreateItemFromParsingName
|
|
(this.DefaultFolder, IntPtr.Zero, ref riid,
|
|
out directoryShellItem) == NativeMethods.S_OK)
|
|
{
|
|
frm.SetDefaultFolder(directoryShellItem);
|
|
}
|
|
}
|
|
|
|
if (frm.Show(owner.Handle) == NativeMethods.S_OK)
|
|
{
|
|
NativeMethods.IShellItem shellItem;
|
|
if (frm.GetResult(out shellItem) == NativeMethods.S_OK)
|
|
{
|
|
IntPtr pszString;
|
|
if (shellItem.GetDisplayName(NativeMethods.SIGDN_FILESYSPATH,
|
|
out pszString) == NativeMethods.S_OK)
|
|
{
|
|
if (pszString != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
this.Folder = Marshal.PtrToStringAuto(pszString);
|
|
return DialogResult.OK;
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeCoTaskMem(pszString);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return DialogResult.Cancel;
|
|
}
|
|
public DialogResult ShowLegacyDialog(IWin32Window owner)
|
|
{
|
|
using (var frm = new SaveFileDialog())
|
|
{
|
|
frm.CheckFileExists = false;
|
|
frm.CheckPathExists = true;
|
|
frm.CreatePrompt = false;
|
|
frm.Filter = "|" + Guid.Empty.ToString();
|
|
frm.FileName = "any";
|
|
if (this.InitialFolder != null) { frm.InitialDirectory = this.InitialFolder; }
|
|
frm.OverwritePrompt = false;
|
|
frm.Title = "Select Folder";
|
|
frm.ValidateNames = false;
|
|
if (frm.ShowDialog(owner) == DialogResult.OK)
|
|
{
|
|
this.Folder = Path.GetDirectoryName(frm.FileName);
|
|
return DialogResult.OK;
|
|
}
|
|
else
|
|
{
|
|
return DialogResult.Cancel;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!isDisposed)
|
|
{
|
|
//just to have possibility of Using statement.
|
|
}
|
|
isDisposed = true;
|
|
}
|
|
}
|
|
public class WindowWrapper : System.Windows.Forms.IWin32Window
|
|
{
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="handle">Handle to wrap</param>
|
|
public WindowWrapper(IntPtr handle)
|
|
{
|
|
_hwnd = handle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Original ptr
|
|
/// </summary>
|
|
public IntPtr Handle
|
|
{
|
|
get { return _hwnd; }
|
|
}
|
|
|
|
private IntPtr _hwnd;
|
|
}
|
|
internal static class NativeMethods
|
|
{
|
|
#region Constants
|
|
|
|
public const uint FOS_PICKFOLDERS = 0x00000020;
|
|
public const uint FOS_FORCEFILESYSTEM = 0x00000040;
|
|
public const uint FOS_NOVALIDATE = 0x00000100;
|
|
public const uint FOS_NOTESTFILECREATE = 0x00010000;
|
|
public const uint FOS_DONTADDTORECENT = 0x02000000;
|
|
|
|
public const uint S_OK = 0x0000;
|
|
|
|
public const uint SIGDN_FILESYSPATH = 0x80058000;
|
|
|
|
#endregion
|
|
|
|
#region COM
|
|
|
|
[ComImport, ClassInterface(ClassInterfaceType.None),
|
|
TypeLibType(TypeLibTypeFlags.FCanCreate),
|
|
Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")]
|
|
internal class FileOpenDialogRCW { }
|
|
|
|
[ComImport(), Guid("42F85136-DB7E-439C-85F1-E4075D135FC8"),
|
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IFileDialog
|
|
{
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
[PreserveSig()]
|
|
uint Show([In, Optional] IntPtr hwndOwner); //IModalWindow
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFileTypes([In] uint cFileTypes,
|
|
[In, MarshalAs(UnmanagedType.LPArray)] IntPtr rgFilterSpec);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFileTypeIndex([In] uint iFileType);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetFileTypeIndex(out uint piFileType);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint Advise([In, MarshalAs(UnmanagedType.Interface)] IntPtr pfde,
|
|
out uint pdwCookie);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint Unadvise([In] uint dwCookie);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetOptions([In] uint fos);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetOptions(out uint fos);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
void SetDefaultFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetFolder([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetCurrentSelection
|
|
([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetResult([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint AddPlace
|
|
([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, uint fdap);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)]
|
|
string pszDefaultExtension);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint Close([MarshalAs(UnmanagedType.Error)] uint hr);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetClientGuid([In] ref Guid guid);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint ClearClientData();
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
|
|
}
|
|
|
|
[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"),
|
|
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IShellItem
|
|
{
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint BindToHandler([In] IntPtr pbc, [In] ref Guid rbhid,
|
|
[In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IntPtr ppvOut);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetDisplayName([In] uint sigdnName, out IntPtr ppszName);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs);
|
|
|
|
[MethodImpl(MethodImplOptions.InternalCall,
|
|
MethodCodeType = MethodCodeType.Runtime)]
|
|
uint Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi,
|
|
[In] uint hint, out int piOrder);
|
|
}
|
|
|
|
#endregion
|
|
|
|
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
internal static extern int SHCreateItemFromParsingName
|
|
([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc,
|
|
ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);
|
|
}
|
|
}
|