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 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) {
BrowseCallbackProc callback = new BrowseCallbackProc(BrowseCallbackHandler);
IntPtr displayName = Marshal.AllocHGlobal(260 * Marshal.SystemDefaultCharSize);
bool ok = false;
try {
var info = new BrowseInfo();
info.pidlRoot = IntPtr.Zero;
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 {
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;
}
}
}