From 12511007e3356ff820271181807914391a1f216b Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 18 Aug 2023 13:28:55 +0800 Subject: [PATCH] fix: using System.Windows.Forms.FolderBrowserDialog instead of Controls.FolderDialog to avoid crashes --- src/SourceGit.csproj | 1 + src/Views/Clone.xaml.cs | 5 +- src/Views/Controls/FolderDialog.cs | 124 ------------------------ src/Views/Preference.xaml.cs | 5 +- src/Views/Widgets/Histories.xaml.cs | 5 +- src/Views/Widgets/RevisionFiles.xaml.cs | 5 +- src/Views/Widgets/Welcome.xaml.cs | 5 +- 7 files changed, 16 insertions(+), 134 deletions(-) delete mode 100644 src/Views/Controls/FolderDialog.cs diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index de1addca..3a2db826 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -3,6 +3,7 @@ net48 WinExe true + true App.ico sourcegit OpenSource GIT client for Windows diff --git a/src/Views/Clone.xaml.cs b/src/Views/Clone.xaml.cs index 03146169..abc66330 100644 --- a/src/Views/Clone.xaml.cs +++ b/src/Views/Clone.xaml.cs @@ -95,8 +95,9 @@ namespace SourceGit.Views { } private void OnFolderSelectorClick(object sender, RoutedEventArgs e) { - var dialog = new Controls.FolderDialog(); - if (dialog.ShowDialog() == true) { + var dialog = new System.Windows.Forms.FolderBrowserDialog(); + dialog.ShowNewFolderButton = true; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { Folder = dialog.SelectedPath; txtFolder.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); } diff --git a/src/Views/Controls/FolderDialog.cs b/src/Views/Controls/FolderDialog.cs deleted file mode 100644 index ea5772da..00000000 --- a/src/Views/Controls/FolderDialog.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; - -namespace SourceGit.Views.Controls { - - [SuppressUnmanagedCodeSecurity] - internal delegate Int32 BrowseCallbackProc(IntPtr hwnd, Int32 msg, IntPtr lParam, IntPtr lpData); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - [SuppressUnmanagedCodeSecurity] - internal class BrowseInfo { - public IntPtr hwndOwner; - public IntPtr pidlRoot; - public IntPtr pszDisplayName; - public String lpszTitle; - public Int32 ulFlags; - public BrowseCallbackProc lpfn; - public IntPtr lParam; - public Int32 iImage; - } - - /// - /// Win32 API封装(user32.dll) - /// - [SuppressUnmanagedCodeSecurity] - internal static class User32 { - [DllImport("user32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, String lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SendMessage(HandleRef hWnd, Int32 msg, Int32 wParam, Int32 lParam); - } - - /// - /// Win32 API封装(ole32.dll) - /// - [SuppressUnmanagedCodeSecurity] - internal static class Ole32 { - [DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)] - internal static extern void CoTaskMemFree(IntPtr pv); - } - - /// - /// Win32 API封装(shell32.dll) - /// - [SuppressUnmanagedCodeSecurity] - internal static class Shell32 { - [DllImport("shell32.dll", CharSet = CharSet.Auto)] - public static extern Boolean SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath); - - [DllImport("shell32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr SHBrowseForFolder([In] BrowseInfo lpbi); - } - - /// - /// 调用WindowsAPI打开对话目录对话框 - /// - public class FolderDialog : Microsoft.Win32.CommonDialog { - /// - /// 选中的目录 - /// - public string SelectedPath { get; private set; } = string.Empty; - - public override void Reset() { - SelectedPath = string.Empty; - } - - protected override bool RunDialog(IntPtr hwndOwner) { - BrowseCallbackProc callback = new BrowseCallbackProc(BrowseCallbackHandler); - bool ok = false; - try { - var info = new BrowseInfo(); - info.pidlRoot = IntPtr.Zero; - info.hwndOwner = hwndOwner; - info.pszDisplayName = IntPtr.Zero; - info.lpszTitle = null; - info.ulFlags = 0x0153; - info.lpfn = callback; - info.lParam = IntPtr.Zero; - info.iImage = 0; - - IntPtr result = Shell32.SHBrowseForFolder(info); - if (result != IntPtr.Zero) { - IntPtr pathPtr = Marshal.AllocHGlobal(260 * Marshal.SystemDefaultCharSize); - Shell32.SHGetPathFromIDList(result, pathPtr); - - if (pathPtr != IntPtr.Zero) { - SelectedPath = Marshal.PtrToStringAuto(pathPtr); - ok = true; - Marshal.FreeHGlobal(pathPtr); - } - - Ole32.CoTaskMemFree(result); - } - } finally { - callback = null; - } - - return ok; - } - - private Int32 BrowseCallbackHandler(IntPtr hwnd, Int32 msg, IntPtr lParam, IntPtr lpData) { - switch (msg) { - case 1: - if (!string.IsNullOrEmpty(SelectedPath)) { - Int32 flag = Marshal.SystemDefaultCharSize == 1 ? 1126 : 1127; - User32.SendMessage(new HandleRef(null, hwnd), flag, 1, SelectedPath); - } - break; - case 2: - if (lParam != IntPtr.Zero) { - IntPtr pathPtr = Marshal.AllocHGlobal(260 * Marshal.SystemDefaultCharSize); - bool flag = Shell32.SHGetPathFromIDList(lParam, pathPtr); - Marshal.FreeHGlobal(pathPtr); - User32.SendMessage(new HandleRef(null, hwnd), 1125, 0, flag ? 1 : 0); - } - break; - } - - return 0; - } - } -} diff --git a/src/Views/Preference.xaml.cs b/src/Views/Preference.xaml.cs index b207960f..df3edd05 100644 --- a/src/Views/Preference.xaml.cs +++ b/src/Views/Preference.xaml.cs @@ -90,8 +90,9 @@ namespace SourceGit.Views { } private void SelectGitCloneDir(object sender, RoutedEventArgs e) { - var dialog = new Controls.FolderDialog(); - if (dialog.ShowDialog() == true) { + var dialog = new System.Windows.Forms.FolderBrowserDialog(); + dialog.ShowNewFolderButton = true; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { Models.Preference.Instance.Git.DefaultCloneDir = dialog.SelectedPath; txtGitCloneDir?.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); } diff --git a/src/Views/Widgets/Histories.xaml.cs b/src/Views/Widgets/Histories.xaml.cs index 4bcb61f8..58e05639 100644 --- a/src/Views/Widgets/Histories.xaml.cs +++ b/src/Views/Widgets/Histories.xaml.cs @@ -369,8 +369,9 @@ namespace SourceGit.Views.Widgets { saveToPatch.Icon = saveToPatchIcon; saveToPatch.Header = App.Text("CommitCM.SaveAsPatch"); saveToPatch.Click += (o, e) => { - var dialog = new Controls.FolderDialog(); - if (dialog.ShowDialog() == true) { + var dialog = new System.Windows.Forms.FolderBrowserDialog(); + dialog.ShowNewFolderButton = true; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { new Commands.FormatPatch(repo.Path, commit.SHA, dialog.SelectedPath).Exec(); } }; diff --git a/src/Views/Widgets/RevisionFiles.xaml.cs b/src/Views/Widgets/RevisionFiles.xaml.cs index b25e94ea..d4c407ed 100644 --- a/src/Views/Widgets/RevisionFiles.xaml.cs +++ b/src/Views/Widgets/RevisionFiles.xaml.cs @@ -313,8 +313,9 @@ namespace SourceGit.Views.Widgets { saveAs.Header = App.Text("SaveAs"); saveAs.IsEnabled = node.Type == Models.ObjectType.Blob; saveAs.Click += (obj, ev) => { - var dialog = new Controls.FolderDialog(); - if (dialog.ShowDialog() == true) { + var dialog = new System.Windows.Forms.FolderBrowserDialog(); + dialog.ShowNewFolderButton = true; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var full = Path.Combine(dialog.SelectedPath, Path.GetFileName(node.Path)); new Commands.SaveRevisionFile(repo, node.Path, sha, full).Exec(); } diff --git a/src/Views/Widgets/Welcome.xaml.cs b/src/Views/Widgets/Welcome.xaml.cs index b7d4e03d..7a3b3ade 100644 --- a/src/Views/Widgets/Welcome.xaml.cs +++ b/src/Views/Widgets/Welcome.xaml.cs @@ -23,8 +23,9 @@ namespace SourceGit.Views.Widgets { #region FUNC_EVENTS private void OnOpenClicked(object sender, RoutedEventArgs e) { - var dialog = new Controls.FolderDialog(); - if (dialog.ShowDialog() == true) CheckAndOpen(dialog.SelectedPath); + var dialog = new System.Windows.Forms.FolderBrowserDialog(); + dialog.ShowNewFolderButton = true; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) CheckAndOpen(dialog.SelectedPath); } private void OnOpenTerminalClicked(object sender, RoutedEventArgs e) {