Skip to content

Common file dialogs new properties #7916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ internal static class IID
public const string EnumObjects = "2c1c7e2e-2d0e-4059-831e-1e6f82335c2e";
/// <summary>IID_IFileDialog</summary>
public const string FileDialog = "42f85136-db7e-439c-85f1-e4075d135fc8";
/// <summary>IID_IFileDialog2</summary>
public const string FileDialog2 = "61744fc7-85b5-4791-a9b0-272276309b13";
/// <summary>IID_IFileDialogEvents</summary>
public const string FileDialogEvents = "973510DB-7D7F-452B-8975-74A85828D354";
/// <summary>IID_IFileOpenDialog</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,72 @@ internal interface IFileDialog : IModalWindow
void SetFilter([MarshalAs(UnmanagedType.Interface)] object pFilter);
}

[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid(IID.FileDialog2),
]
internal interface IFileDialog2 : IFileDialog
{
#region IFileDialog redeclarations
#region IModalWindow redeclarations
[PreserveSig]
new HRESULT Show(IntPtr parent);
#endregion

new void SetFileTypes(uint cFileTypes, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] COMDLG_FILTERSPEC[] rgFilterSpec);

new void SetFileTypeIndex(uint iFileType);

new uint GetFileTypeIndex();

new uint Advise(IFileDialogEvents pfde);

new void Unadvise(uint dwCookie);

new void SetOptions(FOS fos);

new FOS GetOptions();

new void SetDefaultFolder(IShellItem psi);

new void SetFolder(IShellItem psi);

new IShellItem GetFolder();

new IShellItem GetCurrentSelection();

new void SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);

[return: MarshalAs(UnmanagedType.LPWStr)]
new string GetFileName();

new void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);

new void SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);

new void SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);

new IShellItem GetResult();

new void AddPlace(IShellItem psi, FDAP alignment);

new void SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);

new void Close([MarshalAs(UnmanagedType.Error)] int hr);

new void SetClientGuid([In] ref Guid guid);

new void ClearClientData();

new void SetFilter([MarshalAs(UnmanagedType.Interface)] object pFilter);
#endregion

void SetCancelButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);

void SetNavigationRoot(IShellItem psi);
}

[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,49 @@ public override string ToString()
//---------------------------------------------------
#region Public Properties

// FOS_DONTADDTORECENT
// Do not add the item being opened or saved to the recent documents list (SHAddToRecentDocs).
//
/// <summary>
/// Gets or sets a value indicating whether the dialog box will add the item
/// being opened or saved to the recent documents list.
/// </summary>
public bool AddToRecent
{
get
{
return !GetOption(FOS.DONTADDTORECENT);
}
set
{

SetOption(FOS.DONTADDTORECENT, !value);
}
}

/// <summary>
/// Gets or sets a Guid to associate with the dialog's persisted state.
/// </summary>
public Guid? ClientGuid { get; set; }

/// <summary>
/// Gets or sets the initial directory displayed by the file dialog box
/// if there is not a recently used directory value available.
/// </summary>
public string DefaultDirectory
{
get
{
// Avoid returning a null string - return String.Empty instead.
return _defaultDirectory.Value == null ? String.Empty : _defaultDirectory.Value;
}
set
{

_defaultDirectory.Value = value;
}
}

// The actual flag is FOS_NODEREFERENCELINKS (set = do not dereference, unset = deref) -
// while we have true = dereference and false=do not dereference. Because we expose
// the opposite of the Windows flag as a property to be clearer, we need to negate
Expand Down Expand Up @@ -137,6 +180,43 @@ public string InitialDirectory
}
}

/// <summary>
/// Gets or sets the initial directory displayed by the file dialog box.
/// </summary>
public string RootDirectory
{
get
{
// Avoid returning a null string - return String.Empty instead.
return _rootDirectory.Value == null ? String.Empty : _rootDirectory.Value;
}
set
{

_rootDirectory.Value = value;
}
}

// FOS_FORCESHOWHIDDEN
// Include hidden and system items.
//
/// <summary>
/// Gets or sets a value indicating whether the dialog box will show
/// Include hidden items regardless of user preferences.
/// </summary>
public bool ShowHiddenItems
{
get
{
return GetOption(FOS.FORCESHOWHIDDEN);
}
set
{

SetOption(FOS.FORCESHOWHIDDEN, value);
}
}

/// <summary>
/// Gets or sets a string shown in the title bar of the file dialog.
/// If this property is null, a localized default from the operating
Expand Down Expand Up @@ -299,17 +379,43 @@ internal bool MessageBoxWithFocusRestore(string message,

private protected virtual void PrepareDialog(IFileDialog dialog)
{
if (ClientGuid is Guid guid)
{
dialog.SetClientGuid(ref guid);
}

if (!string.IsNullOrEmpty(DefaultDirectory))
{
IShellItem defaultDirectory = ShellUtil.GetShellItemForPath(DefaultDirectory);
if (defaultDirectory != null)
{
dialog.SetDefaultFolder(defaultDirectory);
}
}

if (!string.IsNullOrEmpty(InitialDirectory))
{
IShellItem initialDirectory = ShellUtil.GetShellItemForPath(InitialDirectory);
if (initialDirectory != null)
{
// Setting both of these so the dialog doesn't display errors when a remembered folder is missing.
dialog.SetDefaultFolder(initialDirectory);
if (string.IsNullOrEmpty(DefaultDirectory))
{
dialog.SetDefaultFolder(initialDirectory);
}
dialog.SetFolder(initialDirectory);
}
}

if (!string.IsNullOrEmpty(RootDirectory))
{
IShellItem rootDirectory = ShellUtil.GetShellItemForPath(RootDirectory);
if (rootDirectory != null && dialog is IFileDialog2 dialog2)
{
dialog2.SetNavigationRoot(rootDirectory);
}
}

dialog.SetTitle(Title);
dialog.SetFileName(CriticalItemName);

Expand Down Expand Up @@ -456,9 +562,13 @@ private void Initialize()
_itemNames = null;
_title.Value = null;
_initialDirectory.Value = null;
_defaultDirectory.Value = null;
_rootDirectory.Value = null;

// Set this to an empty list so callers can simply add to it. They can also replace it wholesale.
CustomPlaces = new List<FileDialogCustomPlace>();
ClientGuid = null;

}

private bool HandleItemOk(IFileDialog dialog)
Expand Down Expand Up @@ -667,6 +777,8 @@ void IDisposable.Dispose()
// that control the appearance of the file dialog box.
private SecurityCriticalDataForSet<string> _title; // Title bar of the message box
private SecurityCriticalDataForSet<string> _initialDirectory; // Starting directory
private SecurityCriticalDataForSet<string> _defaultDirectory; // Starting directory if no recent
private SecurityCriticalDataForSet<string> _rootDirectory; // Topmost directory

// We store the handle of the file dialog inside our class
// for a variety of purposes (like getting the title of the dialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,25 @@ public override void Reset()
//---------------------------------------------------
#region Public Properties

// FOS_FORCEPREVIEWPANEON
// Indicates to the Open dialog box that the preview pane should always be displayed.
//
/// <summary>
/// Gets or sets an option flag indicating whether the
/// dialog box forces the preview pane on.
/// </summary>
public bool ForcePreviewPane
{
get
{
return GetOption(FOS.FORCEPREVIEWPANEON);
}
set
{
SetOption(FOS.FORCEPREVIEWPANEON, value);
}
}

// FOS_ALLOWMULTISELECT
// Enables the user to select multiple items in the open dialog.
//
Expand Down Expand Up @@ -186,17 +205,7 @@ public bool Multiselect
/// Gets or sets a value indicating whether the dialog
/// contains a read-only check box.
/// </summary>
public bool ShowReadOnly
{
get
{
return _showReadOnly;
}
set
{
_showReadOnly = false;
}
}
public bool ShowReadOnly { get; set; }

#endregion Public Properties

Expand Down Expand Up @@ -288,9 +297,6 @@ private void Initialize()
//
//---------------------------------------------------
//#region Private Fields

private bool _showReadOnly = false;

//#endregion Private Fields
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,24 @@ public override void Reset()
/// </Remarks>
public bool CreatePrompt { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the dialog box will attempt to create
/// a test file at the selected path (default is true). If this flag is not set,
/// the calling application must handle errors, such as denial of access,
/// discovered when the item is created.
/// </summary>
public bool CreateTestFile
{
get
{
return !GetOption(FOS.NOTESTFILECREATE);
}
set
{
SetOption(FOS.NOTESTFILECREATE, !value);
}
}

// Causes our code to generate a message box if the selected file already
// exists. The user must confirm whether to overwrite the file.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ protected virtual void CheckPermissionsToShowDialog() { }
public abstract partial class CommonItemDialog : Microsoft.Win32.CommonDialog
{
private protected CommonItemDialog() { }
public bool AddToRecent { get { throw null; } set { } }
public System.Guid? ClientGuid { get; set; }
public System.Collections.Generic.IList<Microsoft.Win32.FileDialogCustomPlace> CustomPlaces { get { throw null; } set { } }
public string DefaultDirectory { get { throw null; } set { } }
public bool DereferenceLinks { get { throw null; } set { } }
public string InitialDirectory { get { throw null; } set { } }
public string RootDirectory { get { throw null; } set { } }
public bool ShowHiddenItems { get; set; }
public string Title { get { throw null; } set { } }
public bool ValidateNames { get { throw null; } set { } }
protected virtual void OnItemOk(System.ComponentModel.CancelEventArgs e) { }
Expand Down Expand Up @@ -73,6 +78,7 @@ public static partial class FileDialogCustomPlaces
public sealed partial class OpenFileDialog : Microsoft.Win32.FileDialog
{
public OpenFileDialog() { }
public bool ForcePreviewPane { get; set; }
public bool Multiselect { get { throw null; } set { } }
public System.IO.Stream OpenFile() { throw null; }
public System.IO.Stream[] OpenFiles() { throw null; }
Expand All @@ -97,6 +103,7 @@ public sealed partial class SaveFileDialog : Microsoft.Win32.FileDialog
{
public SaveFileDialog() { }
public bool CreatePrompt { get { throw null; } set { } }
public bool CreateTestFile { get { throw null; } set { } }
public bool OverwritePrompt { get { throw null; } set { } }
public System.IO.Stream OpenFile() { throw null; }
public override void Reset() { }
Expand Down