Singularity/Assets/Plugins/crosstales/FileBrowser/Scripts/Wrapper/FileBrowserWindows.cs
2024-05-06 11:45:45 -07:00

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)