fixed #7988: Fixed BrowseFolder

This commit is contained in:
Jaex 2025-06-22 11:38:23 +03:00
parent 3fdd1ab5af
commit 5436eedd5b
6 changed files with 91 additions and 466 deletions

View File

@ -462,33 +462,50 @@ namespace ShareX.HelpersLib
return false;
}
public static bool BrowseFolder(TextBox tb, string initialDirectory = "", bool detectSpecialFolders = false)
public static string BrowseFolder(string title = null, string initialDirectory = null)
{
using (FolderBrowserDialog fbd = new FolderBrowserDialog())
{
if (!string.IsNullOrEmpty(title))
{
fbd.Description = title;
fbd.UseDescriptionForTitle = true;
}
if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory))
{
fbd.InitialDirectory = initialDirectory;
}
if (fbd.ShowDialog() == DialogResult.OK)
{
return fbd.SelectedPath;
}
}
return null;
}
public static bool BrowseFolder(TextBox tb, string initialDirectory = null, bool detectSpecialFolders = false)
{
return BrowseFolder("ShareX - " + Resources.Helpers_BrowseFolder_Choose_folder, tb, initialDirectory, detectSpecialFolders);
}
public static bool BrowseFolder(string title, TextBox tb, string initialDirectory = "", bool detectSpecialFolders = false)
public static bool BrowseFolder(string title, TextBox tb, string initialDirectory = null, bool detectSpecialFolders = false)
{
using (FolderSelectDialog fsd = new FolderSelectDialog())
string path = tb.Text;
if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
{
fsd.Title = title;
initialDirectory = path;
}
string path = tb.Text;
string selectedPath = BrowseFolder(title, initialDirectory);
if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
{
fsd.InitialDirectory = path;
}
else if (!string.IsNullOrEmpty(initialDirectory))
{
fsd.InitialDirectory = initialDirectory;
}
if (fsd.ShowDialog())
{
tb.Text = detectSpecialFolders ? GetVariableFolderPath(fsd.FileName) : fsd.FileName;
return true;
}
if (!string.IsNullOrEmpty(selectedPath))
{
tb.Text = detectSpecialFolders ? GetVariableFolderPath(selectedPath) : selectedPath;
return true;
}
return false;

View File

@ -1,382 +0,0 @@
#region License Information (GPL v3)
/*
ShareX - A program that allows you to take screenshots and share any file type
Copyright (c) 2007-2025 ShareX Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion License Information (GPL v3)
// http://www.lyquidity.com/devblog/?p=136
using ShareX.HelpersLib.Properties;
using System;
using System.Reflection;
using System.Windows.Forms;
namespace ShareX.HelpersLib
{
/// <summary>
/// Wraps System.Windows.Forms.OpenFileDialog to make it present
/// a vista-style dialog.
/// </summary>
public class FolderSelectDialog : IDisposable
{
// Wrapped dialog
private OpenFileDialog ofd;
/// <summary>
/// Default constructor
/// </summary>
public FolderSelectDialog()
{
ofd = new OpenFileDialog();
ofd.Filter = "Folders|\n";
ofd.AddExtension = false;
ofd.CheckFileExists = false;
ofd.DereferenceLinks = true;
ofd.Multiselect = false;
}
/// <summary>
/// Gets/Sets the initial folder to be selected. A null value selects the current directory.
/// </summary>
public string InitialDirectory
{
get
{
return ofd.InitialDirectory;
}
set
{
ofd.InitialDirectory = string.IsNullOrEmpty(value) ? Environment.CurrentDirectory : value;
}
}
/// <summary>
/// Gets/Sets the title to show in the dialog
/// </summary>
public string Title
{
get
{
return ofd.Title;
}
set
{
ofd.Title = string.IsNullOrEmpty(value) ? Resources.FolderSelectDialog_Title_Select_a_folder : value;
}
}
/// <summary>
/// Gets the selected folder
/// </summary>
public string FileName
{
get
{
return ofd.FileName;
}
}
/// <summary>
/// Shows the dialog
/// </summary>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog()
{
return ShowDialog(NativeMethods.GetActiveWindow());
}
/// <summary>
/// Shows the dialog
/// </summary>
/// <param name="hWndOwner">Handle of the control to be parent</param>
/// <returns>True if the user presses OK else false</returns>
public bool ShowDialog(IntPtr hWndOwner)
{
bool flag;
if (Helpers.IsWindowsVistaOrGreater())
{
Reflector r = new Reflector("System.Windows.Forms");
uint num = 0;
Type typeIFileDialog = r.GetType("FileDialogNative.IFileDialog");
object dialog = r.Call(ofd, "CreateVistaDialog");
r.Call(ofd, "OnBeforeVistaDialog", dialog);
uint options = (uint)r.CallAs(typeof(FileDialog), ofd, "GetOptions");
options |= (uint)r.GetEnum("FileDialogNative.FOS", "FOS_PICKFOLDERS");
r.CallAs(typeIFileDialog, dialog, "SetOptions", options);
object pfde = r.New("FileDialog.VistaDialogEvents", ofd);
object[] parameters = new object[] { pfde, num };
r.CallAs2(typeIFileDialog, dialog, "Advise", parameters);
num = (uint)parameters[1];
try
{
int num2 = (int)r.CallAs(typeIFileDialog, dialog, "Show", hWndOwner);
flag = num2 == 0;
}
finally
{
r.CallAs(typeIFileDialog, dialog, "Unadvise", num);
GC.KeepAlive(pfde);
}
}
else
{
using (FolderBrowserDialog fbd = new FolderBrowserDialog())
{
fbd.Description = Title;
fbd.SelectedPath = InitialDirectory;
if (fbd.ShowDialog(new WindowWrapper(hWndOwner)) != DialogResult.OK) return false;
ofd.FileName = fbd.SelectedPath;
flag = true;
}
}
return flag;
}
public void Dispose()
{
if (ofd != null)
{
ofd.Dispose();
}
}
}
/// <summary>
/// Creates IWin32Window around an IntPtr
/// </summary>
internal class WindowWrapper : IWin32Window
{
/// <summary>
/// Original ptr
/// </summary>
public IntPtr Handle
{
get
{
return hwnd;
}
}
private IntPtr hwnd;
/// <summary>
/// Constructor
/// </summary>
/// <param name="handle">Handle to wrap</param>
public WindowWrapper(IntPtr handle)
{
hwnd = handle;
}
}
/// <summary>
/// This class is from the Front-End for Dosbox and is used to present a 'vista' dialog box to select folders.
/// Being able to use a vista style dialog box to select folders is much better then using the shell folder browser.
/// http://code.google.com/p/fed/
///
/// Example:
/// var r = new Reflector("System.Windows.Forms");
/// </summary>
internal class Reflector
{
#region variables
private string m_ns;
private Assembly m_asmb;
#endregion variables
#region Constructors
/// <summary>
/// Constructor
/// </summary>
/// <param name="ns">The namespace containing types to be used</param>
public Reflector(string ns) : this(ns, ns)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="an">A specific assembly name (used if the assembly name does not tie exactly with the namespace)</param>
/// <param name="ns">The namespace containing types to be used</param>
public Reflector(string an, string ns)
{
m_ns = ns;
m_asmb = null;
foreach (AssemblyName aN in Assembly.GetExecutingAssembly().GetReferencedAssemblies())
{
if (aN.FullName.StartsWith(an))
{
m_asmb = Assembly.Load(aN);
break;
}
}
}
#endregion Constructors
#region Methods
/// <summary>
/// Return a Type instance for a type 'typeName'
/// </summary>
/// <param name="typeName">The name of the type</param>
/// <returns>A type instance</returns>
public Type GetType(string typeName)
{
Type type = null;
string[] names = typeName.Split('.');
if (names.Length > 0)
type = m_asmb.GetType(m_ns + "." + names[0]);
for (int i = 1; i < names.Length; ++i)
{
type = type.GetNestedType(names[i], BindingFlags.NonPublic);
}
return type;
}
/// <summary>
/// Create a new object of a named type passing along any params
/// </summary>
/// <param name="name">The name of the type to create</param>
/// <param name="parameters"></param>
/// <returns>An instantiated type</returns>
public object New(string name, params object[] parameters)
{
Type type = GetType(name);
ConstructorInfo[] ctorInfos = type.GetConstructors();
foreach (ConstructorInfo ci in ctorInfos)
{
try
{
return ci.Invoke(parameters);
}
catch
{
}
}
return null;
}
/// <summary>
/// Calls method 'func' on object 'obj' passing parameters 'parameters'
/// </summary>
/// <param name="obj">The object on which to excute function 'func'</param>
/// <param name="func">The function to execute</param>
/// <param name="parameters">The parameters to pass to function 'func'</param>
/// <returns>The result of the function invocation</returns>
public object Call(object obj, string func, params object[] parameters)
{
return Call2(obj, func, parameters);
}
/// <summary>
/// Calls method 'func' on object 'obj' passing parameters 'parameters'
/// </summary>
/// <param name="obj">The object on which to excute function 'func'</param>
/// <param name="func">The function to execute</param>
/// <param name="parameters">The parameters to pass to function 'func'</param>
/// <returns>The result of the function invocation</returns>
public object Call2(object obj, string func, object[] parameters)
{
return CallAs2(obj.GetType(), obj, func, parameters);
}
/// <summary>
/// Calls method 'func' on object 'obj' which is of type 'type' passing parameters 'parameters'
/// </summary>
/// <param name="type">The type of 'obj'</param>
/// <param name="obj">The object on which to excute function 'func'</param>
/// <param name="func">The function to execute</param>
/// <param name="parameters">The parameters to pass to function 'func'</param>
/// <returns>The result of the function invocation</returns>
public object CallAs(Type type, object obj, string func, params object[] parameters)
{
return CallAs2(type, obj, func, parameters);
}
/// <summary>
/// Calls method 'func' on object 'obj' which is of type 'type' passing parameters 'parameters'
/// </summary>
/// <param name="type">The type of 'obj'</param>
/// <param name="obj">The object on which to excute function 'func'</param>
/// <param name="func">The function to execute</param>
/// <param name="parameters">The parameters to pass to function 'func'</param>
/// <returns>The result of the function invocation</returns>
public object CallAs2(Type type, object obj, string func, object[] parameters)
{
MethodInfo methInfo = type.GetMethod(func, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return methInfo.Invoke(obj, parameters);
}
/// <summary>
/// Returns the value of property 'prop' of object 'obj'
/// </summary>
/// <param name="obj">The object containing 'prop'</param>
/// <param name="prop">The property name</param>
/// <returns>The property value</returns>
public object Get(object obj, string prop)
{
return GetAs(obj.GetType(), obj, prop);
}
/// <summary>
/// Returns the value of property 'prop' of object 'obj' which has type 'type'
/// </summary>
/// <param name="type">The type of 'obj'</param>
/// <param name="obj">The object containing 'prop'</param>
/// <param name="prop">The property name</param>
/// <returns>The property value</returns>
public object GetAs(Type type, object obj, string prop)
{
PropertyInfo propInfo = type.GetProperty(prop, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return propInfo.GetValue(obj, null);
}
/// <summary>
/// Returns an enum value
/// </summary>
/// <param name="typeName">The name of enum type</param>
/// <param name="name">The name of the value</param>
/// <returns>The enum value</returns>
public object GetEnum(string typeName, string name)
{
Type type = GetType(typeName);
FieldInfo fieldInfo = type.GetField(name);
return fieldInfo.GetValue(null);
}
#endregion Methods
}
}

View File

@ -39,14 +39,11 @@ namespace ShareX.HelpersLib
return base.EditValue(context, provider, value);
}
using (FolderSelectDialog dlg = new FolderSelectDialog())
{
dlg.Title = Resources.DirectoryNameEditor_EditValue_Browse_for_a_folder___;
string selectedPath = FileHelpers.BrowseFolder(Resources.DirectoryNameEditor_EditValue_Browse_for_a_folder___);
if (dlg.ShowDialog())
{
value = FileHelpers.GetVariableFolderPath(dlg.FileName, true);
}
if (!string.IsNullOrEmpty(selectedPath))
{
value = FileHelpers.GetVariableFolderPath(selectedPath, true);
}
return value;

View File

@ -84,15 +84,14 @@ namespace ShareX.ScreenCaptureLib
private void btnAdd_Click(object sender, EventArgs e)
{
using (FolderSelectDialog fsd = new FolderSelectDialog())
string selectedPath = FileHelpers.BrowseFolder();
if (!string.IsNullOrEmpty(selectedPath))
{
if (fsd.ShowDialog())
{
StickerPackInfo stickerPackInfo = new StickerPackInfo(fsd.FileName);
Stickers.Add(stickerPackInfo);
cbStickers.Items.Add(stickerPackInfo);
cbStickers.SelectedIndex = cbStickers.Items.Count - 1;
}
StickerPackInfo stickerPackInfo = new StickerPackInfo(selectedPath);
Stickers.Add(stickerPackInfo);
cbStickers.Items.Add(stickerPackInfo);
cbStickers.SelectedIndex = cbStickers.Items.Count - 1;
}
}

View File

@ -294,14 +294,13 @@ namespace ShareX.UploadersLib
{
if (Config.CustomUploadersList != null && Config.CustomUploadersList.Count > 0)
{
using (FolderSelectDialog fsd = new FolderSelectDialog())
string selectedPath = FileHelpers.BrowseFolder();
if (!string.IsNullOrEmpty(selectedPath))
{
if (fsd.ShowDialog())
foreach (CustomUploaderItem cui in Config.CustomUploadersList)
{
foreach (CustomUploaderItem cui in Config.CustomUploadersList)
{
CustomUploaderSerialize(cui, fsd.FileName);
}
CustomUploaderSerialize(cui, selectedPath);
}
}
}
@ -309,38 +308,37 @@ namespace ShareX.UploadersLib
private void CustomUploaderUpdateFolder()
{
using (FolderSelectDialog fsd = new FolderSelectDialog())
string selectedPath = FileHelpers.BrowseFolder();
if (!string.IsNullOrEmpty(selectedPath))
{
if (fsd.ShowDialog())
string folderPath = selectedPath;
string[] files = Directory.GetFiles(folderPath, "*.sxcu", SearchOption.TopDirectoryOnly);
int updated = 0;
if (files != null)
{
string folderPath = fsd.FileName;
string[] files = Directory.GetFiles(folderPath, "*.sxcu", SearchOption.TopDirectoryOnly);
int updated = 0;
if (files != null)
foreach (string filePath in files)
{
foreach (string filePath in files)
{
CustomUploaderItem cui = JsonHelpers.DeserializeFromFile<CustomUploaderItem>(filePath);
CustomUploaderItem cui = JsonHelpers.DeserializeFromFile<CustomUploaderItem>(filePath);
if (cui != null)
if (cui != null)
{
try
{
cui.CheckBackwardCompatibility();
CustomUploaderSerialize(cui, folderPath);
updated++;
}
catch
{
try
{
cui.CheckBackwardCompatibility();
CustomUploaderSerialize(cui, folderPath);
updated++;
}
catch
{
}
}
}
}
MessageBox.Show($"{updated} custom uploader files updated.", "ShareX", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
MessageBox.Show($"{updated} custom uploader files updated.", "ShareX", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}

View File

@ -123,24 +123,21 @@ namespace ShareX
public static void UploadFolder(TaskSettings taskSettings = null)
{
using (FolderSelectDialog folderDialog = new FolderSelectDialog())
string initialDirectory;
if (!string.IsNullOrEmpty(Program.Settings.FileUploadDefaultDirectory) && Directory.Exists(Program.Settings.FileUploadDefaultDirectory))
{
folderDialog.Title = "ShareX - " + Resources.UploadManager_UploadFolder_Folder_upload;
initialDirectory = Program.Settings.FileUploadDefaultDirectory;
}
else
{
initialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}
string selectedPath = FileHelpers.BrowseFolder("ShareX - " + Resources.UploadManager_UploadFolder_Folder_upload, initialDirectory);
if (!string.IsNullOrEmpty(Program.Settings.FileUploadDefaultDirectory) && Directory.Exists(Program.Settings.FileUploadDefaultDirectory))
{
folderDialog.InitialDirectory = Program.Settings.FileUploadDefaultDirectory;
}
else
{
folderDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}
if (folderDialog.ShowDialog() && !string.IsNullOrEmpty(folderDialog.FileName))
{
Program.Settings.FileUploadDefaultDirectory = folderDialog.FileName;
UploadFile(folderDialog.FileName, taskSettings);
}
if (!string.IsNullOrEmpty(selectedPath))
{
Program.Settings.FileUploadDefaultDirectory = selectedPath;
UploadFile(selectedPath, taskSettings);
}
}
@ -560,12 +557,11 @@ namespace ShareX
public static void IndexFolder(TaskSettings taskSettings = null)
{
using (FolderSelectDialog dlg = new FolderSelectDialog())
string selectedPath = FileHelpers.BrowseFolder();
if (!string.IsNullOrEmpty(selectedPath))
{
if (dlg.ShowDialog())
{
IndexFolder(dlg.FileName, taskSettings);
}
IndexFolder(selectedPath, taskSettings);
}
}