mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-30 10:19:51 +08:00
934 lines
26 KiB
C#
934 lines
26 KiB
C#
using MicaSetup.Helper;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Markup;
|
|
|
|
namespace MicaSetup.Shell.Dialogs;
|
|
|
|
#pragma warning disable CS8618
|
|
|
|
[ContentProperty("Controls")]
|
|
public abstract class CommonFileDialog : IDialogControlHost, IDisposable
|
|
{
|
|
internal readonly Collection<IShellItem> items;
|
|
|
|
internal DialogShowState showState = DialogShowState.PreShow;
|
|
|
|
private readonly CommonFileDialogControlCollection<CommonFileDialogControl> controls;
|
|
|
|
private readonly Collection<string> filenames;
|
|
|
|
private readonly CommonFileDialogFilterCollection filters;
|
|
|
|
private bool addToMruList = true;
|
|
|
|
private bool allowPropertyEditing;
|
|
|
|
private bool? canceled;
|
|
|
|
private Guid cookieIdentifier;
|
|
|
|
private IFileDialogCustomize customize;
|
|
|
|
private string defaultDirectory;
|
|
|
|
private ShellContainer defaultDirectoryShellContainer;
|
|
|
|
private bool ensureFileExists;
|
|
|
|
private bool ensurePathExists;
|
|
|
|
private bool ensureReadOnly;
|
|
|
|
private bool ensureValidNames;
|
|
|
|
private bool filterSet;
|
|
|
|
private string initialDirectory;
|
|
|
|
private ShellContainer initialDirectoryShellContainer;
|
|
|
|
private IFileDialog nativeDialog;
|
|
|
|
private NativeDialogEventSink nativeEventSink;
|
|
|
|
private bool navigateToShortcut = true;
|
|
|
|
private nint parentWindow = 0;
|
|
|
|
private bool resetSelections;
|
|
|
|
private bool restoreDirectory;
|
|
|
|
private bool showHiddenItems;
|
|
|
|
private bool showPlacesList = true;
|
|
|
|
private string title;
|
|
|
|
protected CommonFileDialog()
|
|
{
|
|
if (!OsVersionHelper.IsWindowsVista_OrGreater)
|
|
{
|
|
throw new PlatformNotSupportedException(LocalizedMessages.CommonFileDialogRequiresVista);
|
|
}
|
|
|
|
filenames = new Collection<string>();
|
|
filters = new CommonFileDialogFilterCollection();
|
|
items = new Collection<IShellItem>();
|
|
controls = new CommonFileDialogControlCollection<CommonFileDialogControl>(this);
|
|
}
|
|
|
|
protected CommonFileDialog(string title)
|
|
: this() => this.title = title;
|
|
|
|
public event EventHandler DialogOpening;
|
|
|
|
public event CancelEventHandler FileOk;
|
|
|
|
public event EventHandler FileTypeChanged;
|
|
|
|
public event EventHandler FolderChanged;
|
|
|
|
public event EventHandler<CommonFileDialogFolderChangeEventArgs> FolderChanging;
|
|
|
|
public event EventHandler SelectionChanged;
|
|
|
|
public static bool IsPlatformSupported =>
|
|
OsVersionHelper.IsWindowsVista_OrGreater;
|
|
|
|
public bool AddToMostRecentlyUsedList
|
|
{
|
|
get => addToMruList;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.AddToMostRecentlyUsedListCannotBeChanged);
|
|
addToMruList = value;
|
|
}
|
|
}
|
|
|
|
public bool AllowPropertyEditing
|
|
{
|
|
get => allowPropertyEditing;
|
|
set => allowPropertyEditing = value;
|
|
}
|
|
|
|
public CommonFileDialogControlCollection<CommonFileDialogControl> Controls => controls;
|
|
|
|
public Guid CookieIdentifier
|
|
{
|
|
get => cookieIdentifier;
|
|
set => cookieIdentifier = value;
|
|
}
|
|
|
|
public string DefaultDirectory
|
|
{
|
|
get => defaultDirectory;
|
|
set => defaultDirectory = value;
|
|
}
|
|
|
|
public ShellContainer DefaultDirectoryShellContainer
|
|
{
|
|
get => defaultDirectoryShellContainer;
|
|
set => defaultDirectoryShellContainer = value;
|
|
}
|
|
|
|
public string DefaultExtension { get; set; }
|
|
|
|
public string DefaultFileName { get; set; } = string.Empty;
|
|
|
|
public bool EnsureFileExists
|
|
{
|
|
get => ensureFileExists;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.EnsureFileExistsCannotBeChanged);
|
|
ensureFileExists = value;
|
|
}
|
|
}
|
|
|
|
public bool EnsurePathExists
|
|
{
|
|
get => ensurePathExists;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.EnsurePathExistsCannotBeChanged);
|
|
ensurePathExists = value;
|
|
}
|
|
}
|
|
|
|
public bool EnsureReadOnly
|
|
{
|
|
get => ensureReadOnly;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.EnsureReadonlyCannotBeChanged);
|
|
ensureReadOnly = value;
|
|
}
|
|
}
|
|
|
|
public bool EnsureValidNames
|
|
{
|
|
get => ensureValidNames;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.EnsureValidNamesCannotBeChanged);
|
|
ensureValidNames = value;
|
|
}
|
|
}
|
|
|
|
public ShellObject FileAsShellObject
|
|
{
|
|
get
|
|
{
|
|
CheckFileItemsAvailable();
|
|
|
|
if (items.Count > 1)
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogMultipleItems);
|
|
}
|
|
|
|
if (items.Count == 0) { return null!; }
|
|
|
|
return ShellObjectFactory.Create(items[0]);
|
|
}
|
|
}
|
|
|
|
public string FileName
|
|
{
|
|
get
|
|
{
|
|
CheckFileNamesAvailable();
|
|
|
|
if (filenames.Count > 1)
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogMultipleFiles);
|
|
}
|
|
|
|
var returnFilename = filenames[0];
|
|
|
|
if (this is CommonSaveFileDialog)
|
|
{
|
|
returnFilename = System.IO.Path.ChangeExtension(returnFilename, this.filters[this.SelectedFileTypeIndex - 1].Extensions[0]);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(DefaultExtension))
|
|
{
|
|
returnFilename = System.IO.Path.ChangeExtension(returnFilename, DefaultExtension);
|
|
}
|
|
|
|
return returnFilename;
|
|
}
|
|
}
|
|
|
|
public CommonFileDialogFilterCollection Filters => filters;
|
|
|
|
public string InitialDirectory
|
|
{
|
|
get => initialDirectory;
|
|
set => initialDirectory = value;
|
|
}
|
|
|
|
public ShellContainer InitialDirectoryShellContainer
|
|
{
|
|
get => initialDirectoryShellContainer;
|
|
set => initialDirectoryShellContainer = value;
|
|
}
|
|
|
|
public bool NavigateToShortcut
|
|
{
|
|
get => navigateToShortcut;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.NavigateToShortcutCannotBeChanged);
|
|
navigateToShortcut = value;
|
|
}
|
|
}
|
|
|
|
public bool RestoreDirectory
|
|
{
|
|
get => restoreDirectory;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.RestoreDirectoryCannotBeChanged);
|
|
restoreDirectory = value;
|
|
}
|
|
}
|
|
|
|
public int SelectedFileTypeIndex
|
|
{
|
|
get
|
|
{
|
|
if (nativeDialog != null)
|
|
{
|
|
nativeDialog.GetFileTypeIndex(out var fileType);
|
|
return (int)fileType;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public bool ShowHiddenItems
|
|
{
|
|
get => showHiddenItems;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.ShowHiddenItemsCannotBeChanged);
|
|
showHiddenItems = value;
|
|
}
|
|
}
|
|
|
|
public bool ShowPlacesList
|
|
{
|
|
get => showPlacesList;
|
|
set
|
|
{
|
|
ThrowIfDialogShowing(LocalizedMessages.ShowPlacesListCannotBeChanged);
|
|
showPlacesList = value;
|
|
}
|
|
}
|
|
|
|
public string Title
|
|
{
|
|
get => title;
|
|
set
|
|
{
|
|
title = value;
|
|
if (NativeDialogShowing) { nativeDialog.SetTitle(value); }
|
|
}
|
|
}
|
|
|
|
protected IEnumerable<string> FileNameCollection
|
|
{
|
|
get
|
|
{
|
|
foreach (var name in filenames)
|
|
{
|
|
yield return name;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool NativeDialogShowing => (nativeDialog != null)
|
|
&& (showState == DialogShowState.Showing || showState == DialogShowState.Closing);
|
|
|
|
public void AddPlace(ShellContainer place, FileDialogAddPlaceLocation location)
|
|
{
|
|
if (place == null!)
|
|
{
|
|
throw new ArgumentNullException("place");
|
|
}
|
|
|
|
if (nativeDialog == null)
|
|
{
|
|
InitializeNativeFileDialog();
|
|
nativeDialog = GetNativeFileDialog();
|
|
}
|
|
nativeDialog?.AddPlace(place.NativeShellItem, (FileDialogAddPlacement)location);
|
|
}
|
|
|
|
public void AddPlace(string path, FileDialogAddPlaceLocation location)
|
|
{
|
|
if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); }
|
|
|
|
if (nativeDialog == null)
|
|
{
|
|
InitializeNativeFileDialog();
|
|
nativeDialog = GetNativeFileDialog();
|
|
}
|
|
|
|
var guid = new Guid(ShellIIDGuid.IShellItem2);
|
|
var retCode = Shell32.SHCreateItemFromParsingName(path, 0, ref guid, out
|
|
IShellItem2 nativeShellItem);
|
|
|
|
if (!CoreErrorHelper.Succeeded(retCode))
|
|
{
|
|
throw new CommonControlException(LocalizedMessages.CommonFileDialogCannotCreateShellItem, Marshal.GetExceptionForHR(retCode));
|
|
}
|
|
|
|
nativeDialog?.AddPlace(nativeShellItem, (FileDialogAddPlacement)location);
|
|
}
|
|
|
|
public virtual void ApplyCollectionChanged()
|
|
{
|
|
GetCustomizedFileDialog();
|
|
foreach (var control in controls)
|
|
{
|
|
if (!control.IsAdded)
|
|
{
|
|
control.HostingDialog = this;
|
|
control.Attach(customize);
|
|
control.IsAdded = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void ApplyControlPropertyChange(string propertyName, DialogControl control)
|
|
{
|
|
if (control == null)
|
|
{
|
|
throw new ArgumentNullException("control");
|
|
}
|
|
|
|
CommonFileDialogControl dialogControl;
|
|
if (propertyName == "Text")
|
|
{
|
|
if (control is CommonFileDialogTextBox textBox)
|
|
{
|
|
customize.SetEditBoxText(control.Id, textBox.Text);
|
|
}
|
|
else if (control is CommonFileDialogLabel label)
|
|
{
|
|
customize.SetControlLabel(control.Id, label.Text);
|
|
}
|
|
}
|
|
else if (propertyName == "Visible" && (dialogControl = (control as CommonFileDialogControl)!) != null)
|
|
{
|
|
customize.GetControlState(control.Id, out var state);
|
|
|
|
if (dialogControl.Visible == true)
|
|
{
|
|
state |= ControlState.Visible;
|
|
}
|
|
else if (dialogControl.Visible == false)
|
|
{
|
|
state &= ~ControlState.Visible;
|
|
}
|
|
|
|
customize.SetControlState(control.Id, state);
|
|
}
|
|
else if (propertyName == "Enabled" && (dialogControl = (control as CommonFileDialogControl)!) != null)
|
|
{
|
|
customize.GetControlState(control.Id, out var state);
|
|
|
|
if (dialogControl.Enabled == true)
|
|
{
|
|
state |= ControlState.Enable;
|
|
}
|
|
else if (dialogControl.Enabled == false)
|
|
{
|
|
state &= ~ControlState.Enable;
|
|
}
|
|
|
|
customize.SetControlState(control.Id, state);
|
|
}
|
|
else if (propertyName == "SelectedIndex")
|
|
{
|
|
CommonFileDialogRadioButtonList list;
|
|
CommonFileDialogComboBox box;
|
|
|
|
if ((list = (control as CommonFileDialogRadioButtonList)!) != null)
|
|
{
|
|
customize.SetSelectedControlItem(list.Id, list.SelectedIndex);
|
|
}
|
|
else if ((box = (control as CommonFileDialogComboBox)!) != null)
|
|
{
|
|
customize.SetSelectedControlItem(box.Id, box.SelectedIndex);
|
|
}
|
|
}
|
|
else if (propertyName == "IsChecked")
|
|
{
|
|
if (control is CommonFileDialogCheckBox checkBox)
|
|
{
|
|
customize.SetCheckButtonState(checkBox.Id, checkBox.IsChecked);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public virtual bool IsCollectionChangeAllowed() => true;
|
|
|
|
public virtual bool IsControlPropertyChangeAllowed(string propertyName, DialogControl control)
|
|
{
|
|
CommonFileDialog.GenerateNotImplementedException();
|
|
return false;
|
|
}
|
|
|
|
public void ResetUserSelections() => resetSelections = true;
|
|
|
|
public CommonFileDialogResult ShowDialog(nint ownerWindowHandle)
|
|
{
|
|
if (ownerWindowHandle == 0)
|
|
{
|
|
throw new ArgumentException(LocalizedMessages.CommonFileDialogInvalidHandle, "ownerWindowHandle");
|
|
}
|
|
|
|
parentWindow = ownerWindowHandle;
|
|
|
|
return ShowDialog();
|
|
}
|
|
|
|
public CommonFileDialogResult ShowDialog(Window window)
|
|
{
|
|
if (window == null)
|
|
{
|
|
throw new ArgumentNullException("window");
|
|
}
|
|
|
|
parentWindow = (new WindowInteropHelper(window)).Handle;
|
|
|
|
return ShowDialog();
|
|
}
|
|
|
|
public CommonFileDialogResult ShowDialog()
|
|
{
|
|
CommonFileDialogResult result;
|
|
|
|
InitializeNativeFileDialog();
|
|
nativeDialog = GetNativeFileDialog();
|
|
|
|
ApplyNativeSettings(nativeDialog);
|
|
InitializeEventSink(nativeDialog);
|
|
|
|
if (resetSelections)
|
|
{
|
|
resetSelections = false;
|
|
}
|
|
|
|
showState = DialogShowState.Showing;
|
|
var hresult = nativeDialog.Show(parentWindow);
|
|
showState = DialogShowState.Closed;
|
|
|
|
if (CoreErrorHelper.Matches(hresult, (int)HResult.Win32ErrorCanceled))
|
|
{
|
|
canceled = true;
|
|
result = CommonFileDialogResult.Cancel;
|
|
filenames.Clear();
|
|
}
|
|
else
|
|
{
|
|
canceled = false;
|
|
result = CommonFileDialogResult.Ok;
|
|
|
|
PopulateWithFileNames(filenames);
|
|
|
|
PopulateWithIShellItems(items);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
internal static string GetFileNameFromShellItem(IShellItem item)
|
|
{
|
|
string filename = null!;
|
|
var hr = item.GetDisplayName(ShellItemDesignNameOptions.DesktopAbsoluteParsing, out var pszString);
|
|
if (hr == HResult.Ok && pszString != 0)
|
|
{
|
|
filename = Marshal.PtrToStringAuto(pszString);
|
|
Marshal.FreeCoTaskMem(pszString);
|
|
}
|
|
return filename;
|
|
}
|
|
|
|
internal static IShellItem GetShellItemAt(IShellItemArray array, int i)
|
|
{
|
|
var index = (uint)i;
|
|
array.GetItemAt(index, out var result);
|
|
return result;
|
|
}
|
|
|
|
internal abstract void CleanUpNativeFileDialog();
|
|
|
|
internal abstract FileOpenOptions GetDerivedOptionFlags(FileOpenOptions flags);
|
|
|
|
internal abstract IFileDialog GetNativeFileDialog();
|
|
|
|
internal abstract void InitializeNativeFileDialog();
|
|
|
|
internal abstract void PopulateWithFileNames(Collection<string> names);
|
|
|
|
internal abstract void PopulateWithIShellItems(Collection<IShellItem> shellItems);
|
|
|
|
protected void CheckFileItemsAvailable()
|
|
{
|
|
if (showState != DialogShowState.Closed)
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogNotClosed);
|
|
}
|
|
|
|
if (canceled.GetValueOrDefault())
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogCanceled);
|
|
}
|
|
|
|
Debug.Assert(items.Count != 0,
|
|
"Items list empty - shouldn't happen unless dialog canceled or not yet shown.");
|
|
}
|
|
|
|
protected void CheckFileNamesAvailable()
|
|
{
|
|
if (showState != DialogShowState.Closed)
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogNotClosed);
|
|
}
|
|
|
|
if (canceled.GetValueOrDefault())
|
|
{
|
|
throw new InvalidOperationException(LocalizedMessages.CommonFileDialogCanceled);
|
|
}
|
|
|
|
Debug.Assert(filenames.Count != 0,
|
|
"FileNames empty - shouldn't happen unless dialog canceled or not yet shown.");
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
CleanUpNativeFileDialog();
|
|
}
|
|
}
|
|
|
|
protected virtual void OnFileOk(CancelEventArgs e)
|
|
{
|
|
FileOk?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnFileTypeChanged(EventArgs e)
|
|
{
|
|
FileTypeChanged?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnFolderChanged(EventArgs e)
|
|
{
|
|
FolderChanged?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnFolderChanging(CommonFileDialogFolderChangeEventArgs e)
|
|
{
|
|
FolderChanging?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnOpening(EventArgs e)
|
|
{
|
|
DialogOpening?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnSelectionChanged(EventArgs e)
|
|
{
|
|
SelectionChanged?.Invoke(this, e);
|
|
}
|
|
|
|
protected void ThrowIfDialogShowing(string message)
|
|
{
|
|
if (NativeDialogShowing)
|
|
{
|
|
throw new InvalidOperationException(message);
|
|
}
|
|
}
|
|
|
|
private static void GenerateNotImplementedException() => throw new NotImplementedException(LocalizedMessages.NotImplementedException);
|
|
|
|
private void ApplyNativeSettings(IFileDialog dialog)
|
|
{
|
|
Debug.Assert(dialog != null, "No dialog instance to configure");
|
|
|
|
if (parentWindow == 0)
|
|
{
|
|
if (Application.Current != null && Application.Current.MainWindow != null)
|
|
{
|
|
parentWindow = (new WindowInteropHelper(Application.Current.MainWindow)).Handle;
|
|
}
|
|
else if (System.Windows.Forms.Application.OpenForms.Count > 0)
|
|
{
|
|
parentWindow = System.Windows.Forms.Application.OpenForms[0].Handle;
|
|
}
|
|
}
|
|
|
|
var guid = new Guid(ShellIIDGuid.IShellItem2);
|
|
|
|
dialog!.SetOptions(CalculateNativeDialogOptionFlags());
|
|
|
|
if (title != null) { dialog.SetTitle(title); }
|
|
|
|
if (initialDirectoryShellContainer != null!)
|
|
{
|
|
dialog.SetFolder(initialDirectoryShellContainer.NativeShellItem);
|
|
}
|
|
|
|
if (defaultDirectoryShellContainer != null!)
|
|
{
|
|
dialog.SetDefaultFolder(defaultDirectoryShellContainer.NativeShellItem);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(initialDirectory))
|
|
{
|
|
Shell32.SHCreateItemFromParsingName(initialDirectory, 0, ref guid, out
|
|
IShellItem2 initialDirectoryShellItem);
|
|
|
|
if (initialDirectoryShellItem != null)
|
|
dialog.SetFolder(initialDirectoryShellItem);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(defaultDirectory))
|
|
{
|
|
Shell32.SHCreateItemFromParsingName(defaultDirectory, 0, ref guid, out
|
|
IShellItem2 defaultDirectoryShellItem);
|
|
|
|
if (defaultDirectoryShellItem != null)
|
|
{
|
|
dialog.SetDefaultFolder(defaultDirectoryShellItem);
|
|
}
|
|
}
|
|
|
|
if (filters.Count > 0 && !filterSet)
|
|
{
|
|
dialog.SetFileTypes(
|
|
(uint)filters.Count,
|
|
filters.GetAllFilterSpecs());
|
|
|
|
filterSet = true;
|
|
|
|
SyncFileTypeComboToDefaultExtension(dialog);
|
|
}
|
|
|
|
if (cookieIdentifier != Guid.Empty)
|
|
{
|
|
dialog.SetClientGuid(ref cookieIdentifier);
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(DefaultExtension))
|
|
{
|
|
dialog.SetDefaultExtension(DefaultExtension);
|
|
}
|
|
|
|
dialog.SetFileName(DefaultFileName);
|
|
}
|
|
|
|
private FileOpenOptions CalculateNativeDialogOptionFlags()
|
|
{
|
|
var flags = FileOpenOptions.NoTestFileCreate;
|
|
|
|
flags = GetDerivedOptionFlags(flags);
|
|
|
|
if (ensureFileExists)
|
|
{
|
|
flags |= FileOpenOptions.FileMustExist;
|
|
}
|
|
if (ensurePathExists)
|
|
{
|
|
flags |= FileOpenOptions.PathMustExist;
|
|
}
|
|
if (!ensureValidNames)
|
|
{
|
|
flags |= FileOpenOptions.NoValidate;
|
|
}
|
|
if (!EnsureReadOnly)
|
|
{
|
|
flags |= FileOpenOptions.NoReadOnlyReturn;
|
|
}
|
|
if (restoreDirectory)
|
|
{
|
|
flags |= FileOpenOptions.NoChangeDirectory;
|
|
}
|
|
if (!showPlacesList)
|
|
{
|
|
flags |= FileOpenOptions.HidePinnedPlaces;
|
|
}
|
|
if (!addToMruList)
|
|
{
|
|
flags |= FileOpenOptions.DontAddToRecent;
|
|
}
|
|
if (showHiddenItems)
|
|
{
|
|
flags |= FileOpenOptions.ForceShowHidden;
|
|
}
|
|
if (!navigateToShortcut)
|
|
{
|
|
flags |= FileOpenOptions.NoDereferenceLinks;
|
|
}
|
|
return flags;
|
|
}
|
|
|
|
private void GetCustomizedFileDialog()
|
|
{
|
|
if (customize == null)
|
|
{
|
|
if (nativeDialog == null)
|
|
{
|
|
InitializeNativeFileDialog();
|
|
nativeDialog = GetNativeFileDialog();
|
|
}
|
|
customize = (IFileDialogCustomize)nativeDialog;
|
|
}
|
|
}
|
|
|
|
private void InitializeEventSink(IFileDialog nativeDlg)
|
|
{
|
|
if (FileOk != null
|
|
|| FolderChanging != null
|
|
|| FolderChanged != null
|
|
|| SelectionChanged != null
|
|
|| FileTypeChanged != null
|
|
|| DialogOpening != null
|
|
|| (controls != null && controls.Count > 0))
|
|
{
|
|
nativeEventSink = new NativeDialogEventSink(this);
|
|
nativeDlg.Advise(nativeEventSink, out var cookie);
|
|
nativeEventSink.Cookie = cookie;
|
|
}
|
|
}
|
|
|
|
private void SyncFileTypeComboToDefaultExtension(IFileDialog dialog)
|
|
{
|
|
if (this is not CommonSaveFileDialog || DefaultExtension == null ||
|
|
filters.Count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CommonFileDialogFilter filter;
|
|
|
|
for (uint filtersCounter = 0; filtersCounter < filters.Count; filtersCounter++)
|
|
{
|
|
filter = filters[(int)filtersCounter];
|
|
|
|
if (filter.Extensions.Contains(DefaultExtension))
|
|
{
|
|
dialog.SetFileTypeIndex(filtersCounter + 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class NativeDialogEventSink : IFileDialogEvents, IFileDialogControlEvents
|
|
{
|
|
private readonly CommonFileDialog parent;
|
|
private bool firstFolderChanged = true;
|
|
|
|
public NativeDialogEventSink(CommonFileDialog commonDialog) => parent = commonDialog;
|
|
|
|
public uint Cookie { get; set; }
|
|
|
|
public void OnButtonClicked(IFileDialogCustomize pfdc, int dwIDCtl)
|
|
{
|
|
var control = parent.controls.GetControlbyId(dwIDCtl);
|
|
var button = control as CommonFileDialogButton;
|
|
button?.RaiseClickEvent();
|
|
}
|
|
|
|
public void OnCheckButtonToggled(IFileDialogCustomize pfdc, int dwIDCtl, bool bChecked)
|
|
{
|
|
var control = parent.controls.GetControlbyId(dwIDCtl);
|
|
|
|
if (control is CommonFileDialogCheckBox box)
|
|
{
|
|
box.IsChecked = bChecked;
|
|
box.RaiseCheckedChangedEvent();
|
|
}
|
|
}
|
|
|
|
public void OnControlActivating(IFileDialogCustomize pfdc, int dwIDCtl)
|
|
{
|
|
}
|
|
|
|
public HResult OnFileOk(IFileDialog pfd)
|
|
{
|
|
var args = new CancelEventArgs();
|
|
parent.OnFileOk(args);
|
|
|
|
if (!args.Cancel)
|
|
{
|
|
if (parent.Controls != null)
|
|
{
|
|
foreach (var control in parent.Controls)
|
|
{
|
|
CommonFileDialogTextBox textBox;
|
|
CommonFileDialogGroupBox groupBox; ;
|
|
|
|
if ((textBox = (control as CommonFileDialogTextBox)!) != null)
|
|
{
|
|
textBox.SyncValue();
|
|
textBox.Closed = true;
|
|
}
|
|
else if ((groupBox = (control as CommonFileDialogGroupBox)!) != null)
|
|
{
|
|
foreach (CommonFileDialogControl subcontrol in groupBox.Items.Cast<CommonFileDialogControl>())
|
|
{
|
|
if (subcontrol is CommonFileDialogTextBox textbox)
|
|
{
|
|
textbox.SyncValue();
|
|
textbox.Closed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (args.Cancel ? HResult.False : HResult.Ok);
|
|
}
|
|
|
|
public void OnFolderChange(IFileDialog pfd)
|
|
{
|
|
if (firstFolderChanged)
|
|
{
|
|
firstFolderChanged = false;
|
|
parent.OnOpening(EventArgs.Empty);
|
|
}
|
|
else
|
|
{
|
|
parent.OnFolderChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
public HResult OnFolderChanging(IFileDialog pfd, IShellItem psiFolder)
|
|
{
|
|
var args = new CommonFileDialogFolderChangeEventArgs(
|
|
CommonFileDialog.GetFileNameFromShellItem(psiFolder));
|
|
|
|
if (!firstFolderChanged) { parent.OnFolderChanging(args); }
|
|
|
|
return (args.Cancel ? HResult.False : HResult.Ok);
|
|
}
|
|
|
|
public void OnItemSelected(IFileDialogCustomize pfdc, int dwIDCtl, int dwIDItem)
|
|
{
|
|
var control = parent.controls.GetControlbyId(dwIDCtl);
|
|
|
|
if (control is ICommonFileDialogIndexedControls controlInterface)
|
|
{
|
|
controlInterface.SelectedIndex = dwIDItem;
|
|
controlInterface.RaiseSelectedIndexChangedEvent();
|
|
}
|
|
else if (control is CommonFileDialogMenu menu)
|
|
{
|
|
foreach (var item in menu.Items)
|
|
{
|
|
if (item.Id == dwIDItem)
|
|
{
|
|
item.RaiseClickEvent();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnOverwrite(IFileDialog pfd, IShellItem psi, out FileDialogEventOverwriteResponse pResponse) =>
|
|
pResponse = FileDialogEventOverwriteResponse.Default;
|
|
|
|
public void OnSelectionChange(IFileDialog pfd) => parent.OnSelectionChanged(EventArgs.Empty);
|
|
|
|
public void OnShareViolation(
|
|
IFileDialog pfd,
|
|
IShellItem psi,
|
|
out FileDialogEventShareViolationResponse pResponse) =>
|
|
pResponse = FileDialogEventShareViolationResponse.Accept;
|
|
|
|
public void OnTypeChange(IFileDialog pfd) => parent.OnFileTypeChanged(EventArgs.Empty);
|
|
}
|
|
}
|