648 lines
26 KiB
C#
648 lines
26 KiB
C#
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
|
using UnityEngine;
|
|
using System;
|
|
|
|
namespace Crosstales.FB.Wrapper
|
|
{
|
|
/// <summary>File browser implementation for Windows.</summary>
|
|
public class FileBrowserWindows : BaseFileBrowserStandalone
|
|
{
|
|
#region Variables
|
|
|
|
private static FileBrowserWindows instance;
|
|
|
|
private static string _initialPath = string.Empty;
|
|
|
|
private const int OFN_EXPLORER = 0x80000;
|
|
|
|
//private const int MAX_FILE_LENGTH = 4096;
|
|
private const int MAX_FILE_LENGTH = 260;
|
|
|
|
//private const int MAX_PATH_LENGTH = 4096;
|
|
private const int MAX_PATH_LENGTH = 260;
|
|
|
|
private const int WM_USER = 0x400;
|
|
private const int BFFM_INITIALIZED = 1;
|
|
private const int BFFM_SELCHANGED = 2;
|
|
private const int BFFM_SETSELECTIONW = WM_USER + 103;
|
|
private const int BFFM_SETSTATUSTEXTW = WM_USER + 104;
|
|
|
|
private const uint BIF_NEWDIALOGSTYLE = 0x0040; // Use the new dialog layout with the ability to resize
|
|
private const uint BIF_SHAREABLE = 0x8000; // sharable resources displayed (remote shares, requires BIF_USENEWUI)
|
|
|
|
private static readonly IntPtr currentWindow = NativeMethods.GetActiveWindow();
|
|
private static readonly char[] nullChar = { (char)0 };
|
|
|
|
private string allFilesText;
|
|
|
|
private static bool isDialogShown = false;
|
|
|
|
#endregion
|
|
|
|
|
|
#region Properties
|
|
|
|
//private static int MAX_OPEN_FILE_LENGTH => 65536;
|
|
private static int MAX_OPEN_FILE_LENGTH => MAX_FILE_LENGTH * Crosstales.FB.Util.Constants.WINDOWS_MIN_OPEN_NUMBER_OF_FILES;
|
|
|
|
#endregion
|
|
|
|
|
|
#region Constructor
|
|
|
|
public FileBrowserWindows()
|
|
{
|
|
instance = this;
|
|
allFilesText = FileBrowser.Instance.TextAllFiles;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Implemented methods
|
|
|
|
public override bool canOpenMultipleFolders => false;
|
|
|
|
public override bool isPlatformSupported => Crosstales.FB.Util.Helper.isWindowsPlatform; // || Util.Helper.isWindowsEditor;
|
|
|
|
public override bool isWorkingInEditor => true;
|
|
|
|
public override string[] OpenFiles(string title, string directory, string defaultName, bool multiselect, params ExtensionFilter[] extensions)
|
|
{
|
|
//resetOpenFiles();
|
|
|
|
return openFiles(title, directory, defaultName, multiselect, extensions);
|
|
}
|
|
|
|
public override string[] OpenFolders(string title, string directory, bool multiselect)
|
|
{
|
|
if (Crosstales.FB.Util.Config.DEBUG && !string.IsNullOrEmpty(title))
|
|
Debug.LogWarning("'title' is not supported under Windows.");
|
|
|
|
if (multiselect)
|
|
Debug.LogWarning("'multiselect' for folders is not supported under Windows.");
|
|
|
|
if (!Crosstales.FB.Util.Helper.isIL2CPP && !FileBrowser.Instance.LegacyFolderBrowser)
|
|
Debug.LogWarning("The new folder dialog works only with IL2CPP!");
|
|
|
|
//resetOpenFolders();
|
|
|
|
string[] paths = !Crosstales.FB.Util.Helper.isIL2CPP || FileBrowser.Instance.LegacyFolderBrowser ? openFolders(directory, false) : openFoldersNew(directory, false);
|
|
|
|
return paths;
|
|
}
|
|
|
|
public override string SaveFile(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
//resetSaveFile();
|
|
|
|
return saveFile(title, directory, defaultName, extensions);
|
|
}
|
|
|
|
public override void OpenFilesAsync(string title, string directory, string defaultName, bool multiselect, ExtensionFilter[] extensions, Action<string[]> cb)
|
|
{
|
|
//resetOpenFiles();
|
|
|
|
new System.Threading.Thread(() => cb.Invoke(OpenFiles(title, directory, defaultName, multiselect, extensions))).Start();
|
|
}
|
|
|
|
public override void OpenFoldersAsync(string title, string directory, bool multiselect, Action<string[]> cb)
|
|
{
|
|
if (Crosstales.FB.Util.Config.DEBUG && !string.IsNullOrEmpty(title))
|
|
Debug.LogWarning("'title' is not supported under Windows.");
|
|
|
|
if (multiselect)
|
|
Debug.LogWarning("'multiselect' for folders is not supported under Windows.");
|
|
|
|
if (!Crosstales.FB.Util.Helper.isIL2CPP && !FileBrowser.Instance.LegacyFolderBrowser)
|
|
Debug.LogWarning("The new folder dialog works only with IL2CPP!");
|
|
|
|
//resetOpenFolders();
|
|
|
|
if (!Crosstales.FB.Util.Helper.isIL2CPP || FileBrowser.Instance.LegacyFolderBrowser)
|
|
{
|
|
new System.Threading.Thread(() => cb.Invoke(openFolders(directory, true))).Start();
|
|
}
|
|
else
|
|
{
|
|
if (isDialogShown)
|
|
{
|
|
new System.Threading.Thread(() => cb.Invoke(openFoldersNew(directory, true))).Start();
|
|
}
|
|
else
|
|
{
|
|
cb.Invoke(openFoldersNew(directory, true));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void SaveFileAsync(string title, string directory, string defaultName, ExtensionFilter[] extensions, Action<string> cb)
|
|
{
|
|
//resetSaveFile();
|
|
|
|
new System.Threading.Thread(() => cb.Invoke(SaveFile(title, directory, defaultName, extensions))).Start();
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Private methods
|
|
|
|
private static string[] openFiles(string title, string directory, string defaultName, bool multiselect, params ExtensionFilter[] extensions)
|
|
{
|
|
isDialogShown = true;
|
|
|
|
try
|
|
{
|
|
NativeMethods.OpenFileName ofn = new NativeMethods.OpenFileName();
|
|
|
|
string fileName = defaultName ?? "";
|
|
|
|
ofn.dlgOwner = currentWindow;
|
|
ofn.filter = getFilterFromFileExtensionList(extensions);
|
|
ofn.filterIndex = 1;
|
|
|
|
if (!string.IsNullOrEmpty(directory))
|
|
ofn.initialDir = directory;
|
|
|
|
if (multiselect)
|
|
{
|
|
//ofn.file = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(Util.Helper.CreateString(" ", MAX_OPEN_FILE_LENGTH));
|
|
ofn.file = System.Runtime.InteropServices.Marshal.StringToBSTR(fileName + Crosstales.FB.Util.Helper.CreateString(" ", MAX_OPEN_FILE_LENGTH - fileName.Length));
|
|
ofn.maxFile = MAX_OPEN_FILE_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
ofn.file = System.Runtime.InteropServices.Marshal.StringToBSTR(fileName + Crosstales.FB.Util.Helper.CreateString(" ", MAX_FILE_LENGTH - fileName.Length));
|
|
ofn.maxFile = MAX_FILE_LENGTH;
|
|
}
|
|
|
|
ofn.title = title;
|
|
ofn.flags = (int)FOS.FOS_NOCHANGEDIR | (int)FOS.FOS_FILEMUSTEXIST | (int)FOS.FOS_PATHMUSTEXIST | (multiselect ? (int)FOS.FOS_ALLOWMULTISELECT | OFN_EXPLORER : 0x00000000);
|
|
|
|
ofn.structSize = System.Runtime.InteropServices.Marshal.SizeOf(ofn);
|
|
|
|
if (NativeMethods.GetOpenFileName(ref ofn))
|
|
{
|
|
//string file = System.Runtime.InteropServices.Marshal.PtrToStringUni(ofn.file);
|
|
string file = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ofn.file);
|
|
|
|
if (string.IsNullOrEmpty(file))
|
|
{
|
|
Debug.LogWarning("NO FILE SELECTED!");
|
|
instance.CurrentOpenFiles = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFile = string.Empty;
|
|
|
|
return null;
|
|
}
|
|
|
|
if (multiselect)
|
|
{
|
|
string[] files = file.Split(nullChar, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
if (files.Length > 2)
|
|
{
|
|
System.Collections.Generic.List<string> selectedFilesList = new System.Collections.Generic.List<string>();
|
|
|
|
for (int ii = 1; ii < files.Length - 1; ii++)
|
|
{
|
|
string resultFile = Crosstales.Common.Util.FileHelper.ValidateFile(files[0] + '\\' + files[ii]);
|
|
selectedFilesList.Add(resultFile);
|
|
}
|
|
|
|
instance.CurrentOpenFiles = selectedFilesList.ToArray();
|
|
instance.CurrentOpenSingleFile = instance.CurrentOpenFiles[0];
|
|
|
|
return instance.CurrentOpenFiles;
|
|
}
|
|
}
|
|
|
|
instance.CurrentOpenSingleFile = Crosstales.Common.Util.FileHelper.ValidateFile(file);
|
|
instance.CurrentOpenFiles = new[] { instance.CurrentOpenSingleFile };
|
|
|
|
return instance.CurrentOpenFiles;
|
|
}
|
|
|
|
instance.CurrentOpenFiles = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFile = string.Empty;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
instance.CurrentOpenFiles = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFile = string.Empty;
|
|
|
|
Debug.LogError($"Open file dialog threw an error: {ex}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static string[] openFolders(string directory, bool isAsync)
|
|
{
|
|
isDialogShown = true;
|
|
|
|
if (!string.IsNullOrEmpty(directory))
|
|
_initialPath = directory;
|
|
|
|
IntPtr pidl = IntPtr.Zero;
|
|
IntPtr bufferAddress = IntPtr.Zero;
|
|
|
|
string path = null;
|
|
|
|
try
|
|
{
|
|
NativeMethods.BROWSEINFO bi = new NativeMethods.BROWSEINFO();
|
|
|
|
bufferAddress = System.Runtime.InteropServices.Marshal.AllocHGlobal(MAX_PATH_LENGTH);
|
|
|
|
bi.dlgOwner = currentWindow;
|
|
bi.pidlRoot = IntPtr.Zero;
|
|
if (isAsync)
|
|
{
|
|
bi.ulFlags = BIF_SHAREABLE;
|
|
}
|
|
else
|
|
{
|
|
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
|
|
}
|
|
|
|
bi.lpfn = onBrowseEvent;
|
|
bi.lParam = IntPtr.Zero;
|
|
bi.iImage = 0;
|
|
|
|
pidl = NativeMethods.SHBrowseForFolder(ref bi);
|
|
|
|
if (NativeMethods.SHGetPathFromIDList(pidl, bufferAddress))
|
|
{
|
|
path = System.Runtime.InteropServices.Marshal.PtrToStringUni(bufferAddress);
|
|
_initialPath = path;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError($"Folder dialog threw an error: {ex}");
|
|
}
|
|
finally
|
|
{
|
|
if (bufferAddress != IntPtr.Zero)
|
|
System.Runtime.InteropServices.Marshal.FreeHGlobal(bufferAddress);
|
|
|
|
if (pidl != IntPtr.Zero)
|
|
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pidl);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(path))
|
|
{
|
|
instance.CurrentOpenFolders = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFolder = string.Empty;
|
|
|
|
return null;
|
|
}
|
|
|
|
instance.CurrentOpenFolders = new[] { path };
|
|
instance.CurrentOpenSingleFolder = path;
|
|
|
|
return instance.CurrentOpenFolders;
|
|
}
|
|
|
|
private static string[] openFoldersNew(string directory, bool isAsync)
|
|
{
|
|
if (Crosstales.FB.Util.Config.DEBUG && !string.IsNullOrEmpty(directory))
|
|
Debug.LogWarning("'directory' is not supported under Windows.");
|
|
|
|
isDialogShown = true;
|
|
|
|
NativeMethods.IFileOpenDialog folderDialog = null;
|
|
|
|
try
|
|
{
|
|
folderDialog = new NativeMethods.FileOpenDialog() as NativeMethods.IFileOpenDialog;
|
|
folderDialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_FORCEFILESYSTEM);
|
|
//folderDialog.SetOptions(FOS.FOS_PICKFOLDERS);
|
|
|
|
uint hr = folderDialog.Show(currentWindow);
|
|
|
|
if (hr == 0)
|
|
{
|
|
folderDialog.GetResult(out NativeMethods.IShellItem item);
|
|
|
|
item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out string path);
|
|
|
|
if (string.IsNullOrEmpty(path))
|
|
{
|
|
instance.CurrentOpenFolders = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFolder = string.Empty;
|
|
|
|
return null;
|
|
}
|
|
|
|
instance.CurrentOpenFolders = new[] { path };
|
|
instance.CurrentOpenSingleFolder = path;
|
|
|
|
return instance.CurrentOpenFolders;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (Crosstales.FB.Util.Constants.DEV_DEBUG)
|
|
Debug.LogError($"New folder dialog threw an error: {ex} - {ex.HResult}");
|
|
|
|
if (ex.HResult != -2147023673)
|
|
return openFolders(directory, isAsync);
|
|
|
|
instance.CurrentOpenFolders = System.Array.Empty<string>();
|
|
instance.CurrentOpenSingleFolder = string.Empty;
|
|
}
|
|
finally
|
|
{
|
|
if (folderDialog != null)
|
|
System.Runtime.InteropServices.Marshal.ReleaseComObject(folderDialog);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static string saveFile(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
isDialogShown = true;
|
|
|
|
try
|
|
{
|
|
NativeMethods.OpenFileName sfn = new NativeMethods.OpenFileName();
|
|
string defaultExtension = getDefaultExtension(extensions);
|
|
string fileName = defaultExtension.Equals("*") ? defaultExtension : $"{defaultName}.{defaultExtension}";
|
|
sfn.dlgOwner = currentWindow;
|
|
sfn.filter = getFilterFromFileExtensionList(extensions);
|
|
sfn.filterIndex = 1;
|
|
if (!string.IsNullOrEmpty(directory))
|
|
sfn.initialDir = directory;
|
|
|
|
//sfn.file = System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(fileNames + Util.Helper.CreateString(" ", MAX_SAVE_FILE_LENGTH - fileNames.Length));
|
|
sfn.file = System.Runtime.InteropServices.Marshal.StringToBSTR(fileName + Crosstales.FB.Util.Helper.CreateString(" ", MAX_FILE_LENGTH - fileName.Length));
|
|
sfn.maxFile = MAX_FILE_LENGTH;
|
|
sfn.title = title;
|
|
sfn.defExt = defaultExtension;
|
|
sfn.flags = (int)FOS.FOS_NOCHANGEDIR | (int)FOS.FOS_PATHMUSTEXIST | (FileBrowser.Instance.AskOverwriteFile ? (int)FOS.FOS_OVERWRITEPROMPT : 0);
|
|
sfn.structSize = System.Runtime.InteropServices.Marshal.SizeOf(sfn);
|
|
|
|
if (NativeMethods.GetSaveFileName(ref sfn))
|
|
{
|
|
string file = System.Runtime.InteropServices.Marshal.PtrToStringUni(sfn.file);
|
|
//string file = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(sfn.file);
|
|
|
|
if (string.IsNullOrEmpty(file))
|
|
{
|
|
instance.CurrentSaveFile = string.Empty;
|
|
|
|
return null;
|
|
}
|
|
|
|
string newFile = Crosstales.Common.Util.FileHelper.ValidateFile(file);
|
|
//return newFile.Substring(0, newFile.Length - 1);
|
|
|
|
string path = newFile.Substring(0, newFile.Length);
|
|
|
|
instance.CurrentSaveFile = path;
|
|
|
|
return instance.CurrentSaveFile;
|
|
}
|
|
|
|
instance.CurrentSaveFile = string.Empty;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
instance.CurrentSaveFile = string.Empty;
|
|
|
|
Debug.LogError($"Save file dialog threw an error: {ex}");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
[AOT.MonoPInvokeCallback(typeof(NativeMethods.BrowseCallbackProc))]
|
|
private static int onBrowseEvent(IntPtr hWnd, int msg, IntPtr lp, IntPtr lpData)
|
|
{
|
|
switch (msg)
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
NativeMethods.SendMessage(new System.Runtime.InteropServices.HandleRef(null, hWnd), BFFM_SETSELECTIONW, 1, _initialPath);
|
|
break;
|
|
case BFFM_SELCHANGED:
|
|
{
|
|
IntPtr pathPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(260 * System.Runtime.InteropServices.Marshal.SystemDefaultCharSize);
|
|
|
|
if (NativeMethods.SHGetPathFromIDList(lp, pathPtr))
|
|
NativeMethods.SendMessage(new System.Runtime.InteropServices.HandleRef(null, hWnd), BFFM_SETSTATUSTEXTW, 0, pathPtr);
|
|
|
|
System.Runtime.InteropServices.Marshal.FreeHGlobal(pathPtr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static string getDefaultExtension(ExtensionFilter[] extensions)
|
|
{
|
|
if (extensions?.Length > 0 && extensions[0].Extensions.Length > 0)
|
|
return extensions[0].Extensions[0];
|
|
|
|
return "*";
|
|
}
|
|
|
|
private static string getFilterFromFileExtensionList(ExtensionFilter[] extensions)
|
|
{
|
|
if (extensions?.Length > 0)
|
|
{
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
foreach (ExtensionFilter filter in extensions)
|
|
{
|
|
sb.Append(filter.Name);
|
|
sb.Append("\0");
|
|
|
|
for (int ii = 0; ii < filter.Extensions.Length; ii++)
|
|
{
|
|
sb.Append("*.");
|
|
sb.Append(filter.Extensions[ii]);
|
|
|
|
if (ii + 1 < filter.Extensions.Length)
|
|
sb.Append(";");
|
|
}
|
|
|
|
sb.Append("\0");
|
|
}
|
|
|
|
sb.Append("\0");
|
|
|
|
if (Crosstales.FB.Util.Config.DEBUG)
|
|
Debug.Log($"getFilterFromFileExtensionList: {sb}");
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
return $"{instance.allFilesText}\0*.*\0\0";
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
internal static class NativeMethods
|
|
{
|
|
public delegate int BrowseCallbackProc(IntPtr hwnd, int uMsg, IntPtr lParam, IntPtr lpData);
|
|
|
|
[System.Runtime.InteropServices.DllImport("Comdlg32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
public static extern bool GetOpenFileName(ref OpenFileName ofn);
|
|
|
|
[System.Runtime.InteropServices.DllImport("Comdlg32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
public static extern bool GetSaveFileName(ref OpenFileName sfn);
|
|
|
|
[System.Runtime.InteropServices.DllImport("shell32.dll")]
|
|
internal static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);
|
|
|
|
[System.Runtime.InteropServices.DllImport("shell32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
internal static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath);
|
|
|
|
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
|
internal static extern IntPtr GetActiveWindow();
|
|
|
|
[System.Runtime.InteropServices.DllImport("user32.dll", PreserveSig = true)]
|
|
public static extern IntPtr SendMessage(System.Runtime.InteropServices.HandleRef hWnd, uint Msg, int wParam, IntPtr lParam);
|
|
|
|
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
public static extern IntPtr SendMessage(System.Runtime.InteropServices.HandleRef hWnd, int msg, int wParam, string lParam);
|
|
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
internal struct OpenFileName
|
|
{
|
|
public int structSize;
|
|
public IntPtr dlgOwner;
|
|
public IntPtr instance;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string filter;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string customFilter;
|
|
public int maxCustFilter;
|
|
public int filterIndex;
|
|
public IntPtr file;
|
|
public int maxFile;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string fileTitle;
|
|
public int maxFileTitle;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string initialDir;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string title;
|
|
public int flags;
|
|
public ushort fileOffset;
|
|
public ushort fileExtension;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string defExt;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string custData;
|
|
public IntPtr hook;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] public string templateName;
|
|
public IntPtr reservedPtr;
|
|
public int reservedInt;
|
|
public int flagsEx;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
|
|
internal struct BROWSEINFO
|
|
{
|
|
public IntPtr dlgOwner;
|
|
public IntPtr pidlRoot;
|
|
public IntPtr pszDisplayName;
|
|
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string lpszTitle;
|
|
public uint ulFlags;
|
|
public BrowseCallbackProc lpfn;
|
|
public IntPtr lParam;
|
|
public int iImage;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.ComImportAttribute, System.Runtime.InteropServices.GuidAttribute("43826D1E-E718-42EE-BC55-A1E261C37BFE"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
|
|
public interface IShellItem
|
|
{
|
|
void BindToHandler(); // not fully defined
|
|
void GetParent(); // not fully defined
|
|
void GetDisplayName([System.Runtime.InteropServices.InAttribute] SIGDN sigdnName, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] out string ppszName);
|
|
void GetAttributes(); // not fully defined
|
|
void Compare(); // not fully defined
|
|
}
|
|
|
|
[System.Runtime.InteropServices.ComImportAttribute, System.Runtime.InteropServices.GuidAttribute("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")]
|
|
internal class FileOpenDialog
|
|
{
|
|
}
|
|
|
|
//[System.Runtime.InteropServices.ComImportAttribute, System.Runtime.InteropServices.GuidAttribute("42f85136-db7e-439c-85f1-e4075d135fc8"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
|
|
[System.Runtime.InteropServices.ComImportAttribute, System.Runtime.InteropServices.GuidAttribute("d57c7288-d4ad-4768-be02-9d969532d960"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IFileOpenDialog
|
|
{
|
|
[System.Runtime.InteropServices.PreserveSig]
|
|
uint Show([System.Runtime.InteropServices.In] System.IntPtr parent); // IModalWindow
|
|
|
|
void SetFileTypes(); // not fully defined
|
|
void SetFileTypeIndex([System.Runtime.InteropServices.InAttribute] uint iFileType);
|
|
void GetFileTypeIndex(out uint piFileType);
|
|
void Advise(); // not fully defined
|
|
void Unadvise();
|
|
void SetOptions([System.Runtime.InteropServices.InAttribute] FOS fos);
|
|
void GetOptions(out FOS pfos);
|
|
void SetDefaultFolder(IShellItem psi);
|
|
void SetFolder([System.Runtime.InteropServices.InAttribute] IShellItem psi);
|
|
void GetFolder(out IShellItem ppsi);
|
|
void GetCurrentSelection(out IShellItem ppsi);
|
|
void SetFileName([System.Runtime.InteropServices.InAttribute, System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string pszName);
|
|
void GetFileName([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] out string pszName);
|
|
void SetTitle([System.Runtime.InteropServices.InAttribute, System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string pszTitle);
|
|
void SetOkButtonLabel([System.Runtime.InteropServices.InAttribute, System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string pszText);
|
|
void SetFileNameLabel([System.Runtime.InteropServices.InAttribute, System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string pszLabel);
|
|
void GetResult(out IShellItem ppsi);
|
|
void AddPlace(IShellItem psi, int alignment);
|
|
void SetDefaultExtension([System.Runtime.InteropServices.InAttribute, System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string pszDefaultExtension);
|
|
void Close(int hr);
|
|
void SetClientGuid(); // not fully defined
|
|
void ClearClientData();
|
|
void SetFilter([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Interface)] System.IntPtr pFilter);
|
|
void GetResults([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Interface)] out System.IntPtr ppenum); // not fully defined
|
|
void GetSelectedItems([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Interface)] out System.IntPtr ppsai); // not fully defined
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
internal enum FOS
|
|
{
|
|
//FOS_ALLNONSTORAGEITEMS = 0x80,
|
|
FOS_ALLOWMULTISELECT = 0x200,
|
|
|
|
//FOS_CREATEPROMPT = 0x2000,
|
|
//FOS_DEFAULTNOMINIMODE = 0x20000000,
|
|
//FOS_DONTADDTORECENT = 0x2000000,
|
|
FOS_FILEMUSTEXIST = 0x1000,
|
|
FOS_FORCEFILESYSTEM = 0x40,
|
|
|
|
//FOS_FORCESHOWHIDDEN = 0x10000000,
|
|
//FOS_HIDEMRUPLACES = 0x20000,
|
|
//FOS_HIDEPINNEDPLACES = 0x40000,
|
|
FOS_NOCHANGEDIR = 8,
|
|
|
|
//FOS_NODEREFERENCELINKS = 0x100000,
|
|
//FOS_NOREADONLYRETURN = 0x8000,
|
|
//FOS_NOTESTFILECREATE = 0x10000,
|
|
//FOS_NOVALIDATE = 0x100,
|
|
FOS_OVERWRITEPROMPT = 2,
|
|
FOS_PATHMUSTEXIST = 0x800,
|
|
FOS_PICKFOLDERS = 0x20,
|
|
//FOS_SHAREAWARE = 0x4000,
|
|
//FOS_STRICTFILETYPES = 4
|
|
}
|
|
|
|
internal enum SIGDN : uint
|
|
{
|
|
//SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
|
|
//SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
|
|
SIGDN_FILESYSPATH = 0x80058000,
|
|
//SIGDN_NORMALDISPLAY = 0,
|
|
//SIGDN_PARENTRELATIVE = 0x80080001,
|
|
//SIGDN_PARENTRELATIVEEDITING = 0x80031001,
|
|
//SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
|
|
//SIGDN_PARENTRELATIVEPARSING = 0x80018001,
|
|
//SIGDN_URL = 0x80068000
|
|
}
|
|
}
|
|
#endif
|
|
// © 2017-2023 crosstales LLC (https://www.crosstales.com) |