diff --git a/src/Views/Controls/FolderDialog.cs b/src/Views/Controls/FolderDialog.cs new file mode 100644 index 00000000..a048727d --- /dev/null +++ b/src/Views/Controls/FolderDialog.cs @@ -0,0 +1,151 @@ +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")] + public static extern Int32 SHGetSpecialFolderLocation(IntPtr hwnd, Int32 csidl, ref IntPtr ppidl); + + [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 Description { get; set; } + + /// + /// 选中的目录 + /// + public string SelectedPath { get; private set; } + + public FolderDialog(string descKey) { + Description = App.Text(descKey); + SelectedPath = string.Empty; + } + + public override void Reset() { + Description = string.Empty; + SelectedPath = string.Empty; + } + + protected override bool RunDialog(IntPtr hwndOwner) { + IntPtr ppidl = IntPtr.Zero; + Shell32.SHGetSpecialFolderLocation(hwndOwner, (Int32)Environment.SpecialFolder.Desktop, ref ppidl); + if (ppidl == IntPtr.Zero) { + Shell32.SHGetSpecialFolderLocation(hwndOwner, 0, ref ppidl); + if (ppidl == IntPtr.Zero) { + Models.Exception.Raise("Failed to open folder dialog!!!"); + return false; + } + } + + BrowseCallbackProc callback = new BrowseCallbackProc(BrowseCallbackHandler); + IntPtr displayName = Marshal.AllocHGlobal(260 * Marshal.SystemDefaultCharSize); + bool ok = false; + try { + var info = new BrowseInfo(); + info.pidlRoot = ppidl; + info.hwndOwner = hwndOwner; + info.pszDisplayName = displayName; + info.lpszTitle = Description; + info.ulFlags = 0x0040; + 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 { + Ole32.CoTaskMemFree(ppidl); + if (displayName != IntPtr.Zero) Marshal.FreeHGlobal(displayName); + 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/FolderBrowser.xaml b/src/Views/FolderBrowser.xaml deleted file mode 100644 index 57e24a4e..00000000 --- a/src/Views/FolderBrowser.xaml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -