From 8cfaa5f2ffe8f76067f3b1d7585a379b21058279 Mon Sep 17 00:00:00 2001 From: Cam Sinclair Date: Fri, 31 Jan 2025 10:32:29 +1000 Subject: [PATCH] Add Windows directory picker, add XML comments and general tidying --- src/SharpFileDialog.Sample/Program.cs | 24 ++- .../SharpFileDialog.Sample.csproj | 10 +- src/SharpFileDialog/DialogResult.cs | 10 + src/SharpFileDialog/DirectoryDialog.cs | 19 +- src/SharpFileDialog/Gtk/GtkDirectoryDialog.cs | 5 +- src/SharpFileDialog/Gtk/GtkOpenFileDialog.cs | 5 +- src/SharpFileDialog/Gtk/GtkSaveFileDialog.cs | 10 +- src/SharpFileDialog/Gtk/GtkUtil.cs | 2 +- src/SharpFileDialog/ISaveFileDialogBackend.cs | 2 +- src/SharpFileDialog/OpenFileDialog.cs | 20 +- src/SharpFileDialog/SaveFileDialog.cs | 28 ++- src/SharpFileDialog/SharpFileDialog.csproj | 4 +- src/SharpFileDialog/Win/WinDirectoryDialog.cs | 133 ++++++++++-- src/SharpFileDialog/Win/WinInterop.cs | 201 +++++++++++++++++- src/SharpFileDialog/Win/WinOpenFileDialog.cs | 5 +- src/SharpFileDialog/Win/WinSaveFileDialog.cs | 9 +- .../Zenity/ZenityDirectoryDialog.cs | 4 +- .../Zenity/ZenityOpenFileDialog.cs | 4 +- .../Zenity/ZenitySaveFileDialog.cs | 9 +- 19 files changed, 427 insertions(+), 77 deletions(-) diff --git a/src/SharpFileDialog.Sample/Program.cs b/src/SharpFileDialog.Sample/Program.cs index 1dbba48..0455fbc 100644 --- a/src/SharpFileDialog.Sample/Program.cs +++ b/src/SharpFileDialog.Sample/Program.cs @@ -4,23 +4,28 @@ namespace SharpFileDialog.Sample { class Program { + [STAThread] static void Main(string[] args) { - var dirDialog = new DirectoryDialog("Select a directory"); - dirDialog.Open(result => OpenDirectory(result.FileName)); + using (var dirDialog = new DirectoryDialog("Select a directory")) + dirDialog.Open(result => OpenDirectory(result.FileName)); Console.ReadKey(); - var openDialog = new OpenFileDialog("This is a test dialog"); - var filter = "Text files(*.txt) | *.txt | Png files(*.png) | *.png | All files(*.*) | *.*"; - openDialog.Open(result => OpenFile(result.FileName), filter); + using (var openDialog = new OpenFileDialog("This is a test dialog")) + { + var filter = "Text files(*.txt) | *.txt | Png files(*.png) | *.png | All files(*.*) | *.*"; + openDialog.Open(result => OpenFile(result.FileName), filter); + } Console.ReadKey(); - var saveDialog = new SaveFileDialog("Another test for saving"); - filter = "Text files(*.txt) | *.txt | Png files(*.png) | *.png | All files(*.*) | *.*"; - saveDialog.DefaultFileName = "filename.txt"; - saveDialog.Save(result => SaveFile(result.FileName), filter); + using (var saveDialog = new SaveFileDialog("Another test for saving")) + { + var filter = "Text files(*.txt) | *.txt | Png files(*.png) | *.png | All files(*.*) | *.*"; + saveDialog.DefaultFileName = "filename.txt"; + saveDialog.Save(result => SaveFile(result.FileName), filter); + } Console.ReadKey(); } @@ -39,6 +44,5 @@ private static void SaveFile(string filename) { Console.WriteLine("Saving file: {0}", filename); } - } } diff --git a/src/SharpFileDialog.Sample/SharpFileDialog.Sample.csproj b/src/SharpFileDialog.Sample/SharpFileDialog.Sample.csproj index 540fe00..1e267fb 100644 --- a/src/SharpFileDialog.Sample/SharpFileDialog.Sample.csproj +++ b/src/SharpFileDialog.Sample/SharpFileDialog.Sample.csproj @@ -1,12 +1,10 @@ - - - - - Exe - netcoreapp2.2 + net8.0 + + + diff --git a/src/SharpFileDialog/DialogResult.cs b/src/SharpFileDialog/DialogResult.cs index 39c9b0c..62cee33 100644 --- a/src/SharpFileDialog/DialogResult.cs +++ b/src/SharpFileDialog/DialogResult.cs @@ -1,8 +1,18 @@ namespace SharpFileDialog { + /// + /// The result of a file/directory selection dialog + /// public struct DialogResult { + /// + /// The path to the file or directory chosen + /// public string FileName { get; set; } + + /// + /// True if a file or directory was chosen, false if the dialog was cancelled or an error was encountered. + /// public bool Success { get; set; } } } diff --git a/src/SharpFileDialog/DirectoryDialog.cs b/src/SharpFileDialog/DirectoryDialog.cs index 0e0cedf..a1da4de 100644 --- a/src/SharpFileDialog/DirectoryDialog.cs +++ b/src/SharpFileDialog/DirectoryDialog.cs @@ -3,11 +3,19 @@ namespace SharpFileDialog { - + /// + /// Represents a dialog for selecting directories. + /// public class DirectoryDialog : IDirectoryDialogBackend { - private IDirectoryDialogBackend _backend; + private readonly IDirectoryDialogBackend _backend; + /// + /// Initializes a new instance of the class. + /// On Windows, the native dialog is used (if a hang is experienced, ensure your Main method has an [STAThread] attribute). + /// On Linux, Zenity is used if available, otherwise Gtk is used. + /// + /// The title of the dialog. public DirectoryDialog(string title = null) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -27,11 +35,18 @@ public DirectoryDialog(string title = null) } } + /// + /// Releases all resources used by the . + /// public void Dispose() { _backend.Dispose(); } + /// + /// Opens the directory dialog. + /// + /// The callback to be invoked when the dialog is closed. public void Open(Action callback) { _backend.Open(callback); diff --git a/src/SharpFileDialog/Gtk/GtkDirectoryDialog.cs b/src/SharpFileDialog/Gtk/GtkDirectoryDialog.cs index ab89d2c..9c8b186 100644 --- a/src/SharpFileDialog/Gtk/GtkDirectoryDialog.cs +++ b/src/SharpFileDialog/Gtk/GtkDirectoryDialog.cs @@ -3,10 +3,9 @@ namespace SharpFileDialog.Gtk { - internal class GtkDirectoryDialog : IDirectoryDialogBackend { - private FileChooserDialog _dialog; + private readonly FileChooserDialog _dialog; public GtkDirectoryDialog(string title) { @@ -33,7 +32,7 @@ public void Open(Action callback) { if (_dialog.Run() == (int)ResponseType.Ok) { - callback(new DialogResult() + callback(new DialogResult { FileName = _dialog.Filename, Success = true diff --git a/src/SharpFileDialog/Gtk/GtkOpenFileDialog.cs b/src/SharpFileDialog/Gtk/GtkOpenFileDialog.cs index 75988af..d29a96b 100644 --- a/src/SharpFileDialog/Gtk/GtkOpenFileDialog.cs +++ b/src/SharpFileDialog/Gtk/GtkOpenFileDialog.cs @@ -3,10 +3,9 @@ namespace SharpFileDialog.Gtk { - internal class GtkOpenFileDialog : IOpenFileDialogBackend { - private FileChooserDialog _dialog; + private readonly FileChooserDialog _dialog; public GtkOpenFileDialog(string title) { @@ -42,7 +41,7 @@ public void Open(Action callback, string filterString) if (_dialog.Run() == (int)ResponseType.Ok) { - callback(new DialogResult() + callback(new DialogResult { FileName = _dialog.Filename, Success = true diff --git a/src/SharpFileDialog/Gtk/GtkSaveFileDialog.cs b/src/SharpFileDialog/Gtk/GtkSaveFileDialog.cs index 00da7af..ef0fa42 100644 --- a/src/SharpFileDialog/Gtk/GtkSaveFileDialog.cs +++ b/src/SharpFileDialog/Gtk/GtkSaveFileDialog.cs @@ -1,19 +1,15 @@ using System; -using System.Threading.Tasks; using Gtk; namespace SharpFileDialog.Gtk { internal class GtkSaveFileDialog : ISaveFileDialogBackend { - private FileChooserDialog _dialog; + private readonly FileChooserDialog _dialog; public string DefaultFileName { - set - { - _dialog.CurrentName = value; - } + set => _dialog.CurrentName = value; } public GtkSaveFileDialog(string title) @@ -50,7 +46,7 @@ public void Save(Action callback, string filterString) if (_dialog.Run() == (int)ResponseType.Ok) { - callback(new DialogResult() + callback(new DialogResult { FileName = _dialog.Filename, Success = true diff --git a/src/SharpFileDialog/Gtk/GtkUtil.cs b/src/SharpFileDialog/Gtk/GtkUtil.cs index ad25543..b32fff4 100644 --- a/src/SharpFileDialog/Gtk/GtkUtil.cs +++ b/src/SharpFileDialog/Gtk/GtkUtil.cs @@ -9,7 +9,7 @@ struct Filter public string Pattern; } - static internal class GtkUtil + internal static class GtkUtil { static bool _initialized = false; diff --git a/src/SharpFileDialog/ISaveFileDialogBackend.cs b/src/SharpFileDialog/ISaveFileDialogBackend.cs index 4280fcf..c95b94f 100644 --- a/src/SharpFileDialog/ISaveFileDialogBackend.cs +++ b/src/SharpFileDialog/ISaveFileDialogBackend.cs @@ -2,7 +2,7 @@ namespace SharpFileDialog { - interface ISaveFileDialogBackend : IDisposable + internal interface ISaveFileDialogBackend : IDisposable { string DefaultFileName { set; } void Save(Action callback, string filter); diff --git a/src/SharpFileDialog/OpenFileDialog.cs b/src/SharpFileDialog/OpenFileDialog.cs index fd19a46..8cadf10 100644 --- a/src/SharpFileDialog/OpenFileDialog.cs +++ b/src/SharpFileDialog/OpenFileDialog.cs @@ -3,11 +3,19 @@ namespace SharpFileDialog { - + /// + /// Represents a dialog for opening files. + /// public class OpenFileDialog : IOpenFileDialogBackend { - private IOpenFileDialogBackend _backend; + private readonly IOpenFileDialogBackend _backend; + /// + /// Initializes a new instance of the class. + /// On Windows, the native dialog is used. + /// On Linux, Zenity is used if available, otherwise Gtk is used. + /// + /// The title of the dialog. public OpenFileDialog(string title = null) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -27,11 +35,19 @@ public OpenFileDialog(string title = null) } } + /// + /// Releases all resources used by the . + /// public void Dispose() { _backend.Dispose(); } + /// + /// Opens the file dialog. + /// + /// The callback to be invoked when the dialog is closed. + /// The filter for the types of files to be displayed. public void Open(Action callback, string filter = "All files(*.*) | *.*") { _backend.Open(callback, filter); diff --git a/src/SharpFileDialog/SaveFileDialog.cs b/src/SharpFileDialog/SaveFileDialog.cs index 7ba1391..93a5457 100644 --- a/src/SharpFileDialog/SaveFileDialog.cs +++ b/src/SharpFileDialog/SaveFileDialog.cs @@ -3,17 +3,27 @@ namespace SharpFileDialog { + /// + /// Represents a dialog for saving files. + /// public class SaveFileDialog : ISaveFileDialogBackend { - private ISaveFileDialogBackend _backend; + private readonly ISaveFileDialogBackend _backend; + + /// + /// Gets or sets the default file name. + /// public string DefaultFileName { - set - { - _backend.DefaultFileName = value; - } + set => _backend.DefaultFileName = value; } + /// + /// Initializes a new instance of the class. + /// On Windows, the native dialog is used. + /// On Linux, Zenity is used if available, otherwise Gtk is used. + /// + /// The title of the dialog. public SaveFileDialog(string title = null) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -33,11 +43,19 @@ public SaveFileDialog(string title = null) } } + /// + /// Releases all resources used by the . + /// public void Dispose() { _backend.Dispose(); } + /// + /// Opens the save file dialog. + /// + /// The callback to be invoked when the dialog is closed. + /// The filter for the types of files to be displayed. public void Save(Action callback, string filter = "All files(*.*) | *.*") { _backend.Save(callback, filter); diff --git a/src/SharpFileDialog/SharpFileDialog.csproj b/src/SharpFileDialog/SharpFileDialog.csproj index c936dfb..6ad2b6b 100644 --- a/src/SharpFileDialog/SharpFileDialog.csproj +++ b/src/SharpFileDialog/SharpFileDialog.csproj @@ -1,10 +1,10 @@ - + netstandard2.0 true true - bin/SharpAudio.xml + bin/$(AssemblyName).xml diff --git a/src/SharpFileDialog/Win/WinDirectoryDialog.cs b/src/SharpFileDialog/Win/WinDirectoryDialog.cs index da715f5..a30313f 100644 --- a/src/SharpFileDialog/Win/WinDirectoryDialog.cs +++ b/src/SharpFileDialog/Win/WinDirectoryDialog.cs @@ -1,35 +1,138 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; +using static SharpFileDialog.Win.WinInterop; namespace SharpFileDialog.Win { + // Based on https://stackoverflow.com/a/66187224 internal class WinDirectoryDialog : IDirectoryDialogBackend { - OpenFileName _openFileName; + readonly List _resultPaths = new List(); + readonly List _resultNames = new List(); public WinDirectoryDialog(string title) { - _openFileName = new OpenFileName(); - _openFileName.structSize = Marshal.SizeOf(_openFileName); - _openFileName.file = new string(new char[256]); - _openFileName.maxFile = _openFileName.file.Length; - _openFileName.title = title; + Title = title; } - public void Dispose() + public void Dispose() { } + + public void Open(Action callback) { + bool success = ShowDialog(IntPtr.Zero); + callback( + new DialogResult { FileName = _resultPaths.FirstOrDefault(), Success = success } + ); } - public void Open(Action callback) + public string InputPath { get; set; } + public bool ForceFileSystem { get; set; } + public bool Multiselect { get; set; } + public string Title { get; set; } + public string OkButtonLabel { get; set; } + public string FileNameLabel { get; set; } + + int SetOptions(int options) + { + if (ForceFileSystem) + options |= (int)FOS.FOS_FORCEFILESYSTEM; + + if (Multiselect) + options |= (int)FOS.FOS_ALLOWMULTISELECT; + + return options; + } + + bool ShowDialog(IntPtr owner, bool throwOnError = false) { - // TODO: Implement the choosing a directory - bool success = WinInterop.GetOpenFileName(_openFileName); - callback(new DialogResult() + // ReSharper disable once SuspiciousTypeConversion.Global + var dialog = new FileOpenDialog() as IFileOpenDialog; + if (dialog == null) + return false; + + if (!string.IsNullOrEmpty(InputPath)) + { + if ( + CheckHr( + SHCreateItemFromParsingName( + InputPath, + null, + typeof(IShellItem).GUID, + out var item + ), + throwOnError + ) != 0 + ) + { + return false; + } + + dialog.SetFolder(item); + } + + var options = FOS.FOS_PICKFOLDERS; + options = (FOS)SetOptions((int)options); + dialog.SetOptions(options); + + if (Title != null) + dialog.SetTitle(Title); + + if (OkButtonLabel != null) + dialog.SetOkButtonLabel(OkButtonLabel); + + if (FileNameLabel != null) + dialog.SetFileName(FileNameLabel); + + if (owner == IntPtr.Zero) + { + owner = Process.GetCurrentProcess().MainWindowHandle; + if (owner == IntPtr.Zero) + owner = GetDesktopWindow(); + } + + var hr = dialog.Show(owner); + if (hr == ERROR_CANCELLED) + return false; + + if (CheckHr(hr, throwOnError) != 0) + return false; + + if (CheckHr(dialog.GetResults(out var items), throwOnError) != 0) + return false; + + items.GetCount(out var count); + + for (var i = 0; i < count; i++) { - FileName = _openFileName.file, - Success = success - }); + items.GetItemAt(i, out var item); + CheckHr( + item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out var path), + throwOnError + ); + + CheckHr( + item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING, out var name), + throwOnError + ); + + if (path != null || name != null) + { + _resultPaths.Add(path); + _resultNames.Add(name); + } + } + return true; + } + + static int CheckHr(int hr, bool throwOnError) + { + if (hr != 0 && throwOnError) + Marshal.ThrowExceptionForHR(hr); + return hr; } } -} \ No newline at end of file +} diff --git a/src/SharpFileDialog/Win/WinInterop.cs b/src/SharpFileDialog/Win/WinInterop.cs index 4b50136..1cfa5f6 100644 --- a/src/SharpFileDialog/Win/WinInterop.cs +++ b/src/SharpFileDialog/Win/WinInterop.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; namespace SharpFileDialog.Win { @@ -41,13 +42,211 @@ internal class OpenFileName public int flagsEx = 0; } + [ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] // CLSID_FileOpenDialog + internal class FileOpenDialog { } + + [ + ComImport, + Guid("d57c7288-d4ad-4768-be02-9d969532d960"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown) + ] + internal interface IFileOpenDialog + { + [PreserveSig] + int Show(IntPtr parent); // IModalWindow + + [PreserveSig] + int SetFileTypes(); // not fully defined + + [PreserveSig] + int SetFileTypeIndex(int iFileType); + + [PreserveSig] + int GetFileTypeIndex(out int piFileType); + + [PreserveSig] + int Advise(); // not fully defined + + [PreserveSig] + int Unadvise(); + + [PreserveSig] + int SetOptions(FOS fos); + + [PreserveSig] + int GetOptions(out FOS pfos); + + [PreserveSig] + int SetDefaultFolder(IShellItem psi); + + [PreserveSig] + int SetFolder(IShellItem psi); + + [PreserveSig] + int GetFolder(out IShellItem ppsi); + + [PreserveSig] + int GetCurrentSelection(out IShellItem ppsi); + + [PreserveSig] + int SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName); + + [PreserveSig] + int GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName); + + [PreserveSig] + int SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle); + + [PreserveSig] + int SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText); + + [PreserveSig] + int SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel); + + [PreserveSig] + int GetResult(out IShellItem ppsi); + + [PreserveSig] + int AddPlace(IShellItem psi, int alignment); + + [PreserveSig] + int SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension); + + [PreserveSig] + int Close(int hr); + + [PreserveSig] + int SetClientGuid(); // not fully defined + + [PreserveSig] + int ClearClientData(); + + [PreserveSig] + int SetFilter([MarshalAs(UnmanagedType.IUnknown)] object pFilter); + + [PreserveSig] + int GetResults(out IShellItemArray ppenum); + + [PreserveSig] + int GetSelectedItems([MarshalAs(UnmanagedType.IUnknown)] out object ppsai); + } + + [ + ComImport, + Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown) + ] + internal interface IShellItem + { + [PreserveSig] + int BindToHandler(); // not fully defined + + [PreserveSig] + int GetParent(); // not fully defined + + [PreserveSig] + int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); + + [PreserveSig] + int GetAttributes(); // not fully defined + + [PreserveSig] + int Compare(); // not fully defined + } + + [ + ComImport, + Guid("b63ea76d-1f85-456f-a19c-48159efa858b"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown) + ] + internal interface IShellItemArray + { + [PreserveSig] + int BindToHandler(); // not fully defined + + [PreserveSig] + int GetPropertyStore(); // not fully defined + + [PreserveSig] + int GetPropertyDescriptionList(); // not fully defined + + [PreserveSig] + int GetAttributes(); // not fully defined + + [PreserveSig] + int GetCount(out int pdwNumItems); + + [PreserveSig] + int GetItemAt(int dwIndex, out IShellItem ppsi); + + [PreserveSig] + int EnumItems(); // not fully defined + } + +#pragma warning disable CA1712 // Do not prefix enum values with type name + 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 + } + + [Flags] + internal enum FOS + { + FOS_OVERWRITEPROMPT = 0x2, + FOS_STRICTFILETYPES = 0x4, + FOS_NOCHANGEDIR = 0x8, + FOS_PICKFOLDERS = 0x20, + FOS_FORCEFILESYSTEM = 0x40, + FOS_ALLNONSTORAGEITEMS = 0x80, + FOS_NOVALIDATE = 0x100, + FOS_ALLOWMULTISELECT = 0x200, + FOS_PATHMUSTEXIST = 0x800, + FOS_FILEMUSTEXIST = 0x1000, + FOS_CREATEPROMPT = 0x2000, + FOS_SHAREAWARE = 0x4000, + FOS_NOREADONLYRETURN = 0x8000, + FOS_NOTESTFILECREATE = 0x10000, + FOS_HIDEMRUPLACES = 0x20000, + FOS_HIDEPINNEDPLACES = 0x40000, + FOS_NODEREFERENCELINKS = 0x100000, + FOS_OKBUTTONNEEDSINTERACTION = 0x200000, + FOS_DONTADDTORECENT = 0x2000000, + FOS_FORCESHOWHIDDEN = 0x10000000, + FOS_DEFAULTNOMINIMODE = 0x20000000, + FOS_FORCEPREVIEWPANEON = 0x40000000, + FOS_SUPPORTSTREAMABLEITEMS = unchecked((int)0x80000000) + } +#pragma warning restore CA1712 // Do not prefix enum values with type name + internal class WinInterop { +#pragma warning disable IDE1006 // Naming Styles + public const int ERROR_CANCELLED = unchecked((int)0x800704C7); +#pragma warning restore IDE1006 // Naming Styles + [DllImport("Comdlg32.dll", CharSet = CharSet.Auto)] public static extern bool GetOpenFileName([In, Out] OpenFileName ofn); - [DllImport("Comdlg32.dll", CharSet = CharSet.Auto)] public static extern bool GetSaveFileName([In, Out] OpenFileName ofn); + + [DllImport("shell32")] + public static extern int SHCreateItemFromParsingName( + [MarshalAs(UnmanagedType.LPWStr)] string pszPath, + IBindCtx pbc, + [MarshalAs(UnmanagedType.LPStruct)] Guid riid, + out IShellItem ppv + ); + + [DllImport("user32")] + public static extern IntPtr GetDesktopWindow(); } } diff --git a/src/SharpFileDialog/Win/WinOpenFileDialog.cs b/src/SharpFileDialog/Win/WinOpenFileDialog.cs index 98bd3ce..04208b6 100644 --- a/src/SharpFileDialog/Win/WinOpenFileDialog.cs +++ b/src/SharpFileDialog/Win/WinOpenFileDialog.cs @@ -5,7 +5,7 @@ namespace SharpFileDialog.Win { internal class WinOpenFileDialog : IOpenFileDialogBackend { - OpenFileName _openFileName; + readonly OpenFileName _openFileName; public WinOpenFileDialog(string title) { @@ -24,12 +24,11 @@ public void Open(Action callback, string filter) { _openFileName.filter = WinUtil.ConvertFilter(filter); bool success = WinInterop.GetOpenFileName(_openFileName); - callback(new DialogResult() + callback(new DialogResult { FileName = _openFileName.file, Success = success }); - } } } \ No newline at end of file diff --git a/src/SharpFileDialog/Win/WinSaveFileDialog.cs b/src/SharpFileDialog/Win/WinSaveFileDialog.cs index 660a138..d0f28bf 100644 --- a/src/SharpFileDialog/Win/WinSaveFileDialog.cs +++ b/src/SharpFileDialog/Win/WinSaveFileDialog.cs @@ -5,13 +5,10 @@ namespace SharpFileDialog.Win { class WinSaveFileDialog : ISaveFileDialogBackend { - OpenFileName _openFileName; + readonly OpenFileName _openFileName; public string DefaultFileName { - set - { - _openFileName.file = value; - } + set => _openFileName.file = value; } public WinSaveFileDialog(string title) @@ -31,7 +28,7 @@ public void Save(Action callback, string filter) { _openFileName.filter = WinUtil.ConvertFilter(filter); bool success = WinInterop.GetSaveFileName(_openFileName); - callback(new DialogResult() + callback(new DialogResult { FileName = _openFileName.file, Success = success diff --git a/src/SharpFileDialog/Zenity/ZenityDirectoryDialog.cs b/src/SharpFileDialog/Zenity/ZenityDirectoryDialog.cs index 11abf51..59d036d 100644 --- a/src/SharpFileDialog/Zenity/ZenityDirectoryDialog.cs +++ b/src/SharpFileDialog/Zenity/ZenityDirectoryDialog.cs @@ -6,7 +6,7 @@ namespace SharpFileDialog.Zenity class ZenityDirectoryDialog : IDirectoryDialogBackend { string _title; - Process _process; + readonly Process _process; public ZenityDirectoryDialog(string title) { @@ -36,7 +36,7 @@ public void Open(Action callback) return; } - callback(new DialogResult() + callback(new DialogResult { FileName = data.Data, Success = true diff --git a/src/SharpFileDialog/Zenity/ZenityOpenFileDialog.cs b/src/SharpFileDialog/Zenity/ZenityOpenFileDialog.cs index 3271c3e..44c528e 100644 --- a/src/SharpFileDialog/Zenity/ZenityOpenFileDialog.cs +++ b/src/SharpFileDialog/Zenity/ZenityOpenFileDialog.cs @@ -6,7 +6,7 @@ namespace SharpFileDialog.Zenity class ZenityOpenFileDialog : IOpenFileDialogBackend { string _title; - Process _process; + readonly Process _process; public ZenityOpenFileDialog(string title) { @@ -43,7 +43,7 @@ public void Open(Action callback, string filter) return; } - callback(new DialogResult() + callback(new DialogResult { FileName = data.Data, Success = true diff --git a/src/SharpFileDialog/Zenity/ZenitySaveFileDialog.cs b/src/SharpFileDialog/Zenity/ZenitySaveFileDialog.cs index f21f1a3..4cca937 100644 --- a/src/SharpFileDialog/Zenity/ZenitySaveFileDialog.cs +++ b/src/SharpFileDialog/Zenity/ZenitySaveFileDialog.cs @@ -6,13 +6,10 @@ namespace SharpFileDialog.Zenity class ZenitySaveFileDialog : ISaveFileDialogBackend { string _title; - Process _process; + readonly Process _process; public string DefaultFileName { - set - { - _process.StartInfo.Arguments += $" --filename=\"{value}\""; - } + set => _process.StartInfo.Arguments += $" --filename=\"{value}\""; } public ZenitySaveFileDialog(string title) @@ -48,7 +45,7 @@ public void Save(Action callback, string filter) return; } - callback(new DialogResult() + callback(new DialogResult { FileName = data.Data, Success = true