208 lines
6.5 KiB
C#
208 lines
6.5 KiB
C#
|
|
using System;
|
|
using System.Windows.Forms;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Diagnostics;
|
|
|
|
namespace mpvnet
|
|
{
|
|
public partial class FolderBrowser : CommonDialog
|
|
{
|
|
BetterFolderBrowserDialog _dialog = new BetterFolderBrowserDialog();
|
|
|
|
public string SelectedPath {
|
|
get => _dialog.FileName;
|
|
set => _dialog.FileName = value;
|
|
}
|
|
|
|
public new DialogResult ShowDialog()
|
|
{
|
|
return _dialog.ShowDialog(GetOwnerHandle()) ? DialogResult.OK : DialogResult.Cancel;
|
|
}
|
|
|
|
public static IntPtr GetOwnerHandle()
|
|
{
|
|
IntPtr foregroundWindow = GetForegroundWindow();
|
|
GetWindowThreadProcessId(foregroundWindow, out var procID);
|
|
|
|
using (var proc = Process.GetCurrentProcess())
|
|
if (proc.Id == procID)
|
|
return foregroundWindow;
|
|
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern IntPtr GetForegroundWindow();
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
|
|
protected override bool RunDialog(IntPtr hwndOwner) => _dialog.ShowDialog(hwndOwner);
|
|
|
|
public override void Reset() { }
|
|
|
|
class BetterFolderBrowserDialog
|
|
{
|
|
OpenFileDialog ofd = null;
|
|
|
|
public BetterFolderBrowserDialog()
|
|
{
|
|
ofd = new OpenFileDialog();
|
|
|
|
ofd.Filter = "Folders|" + "\n";
|
|
ofd.AddExtension = false;
|
|
ofd.CheckFileExists = false;
|
|
ofd.DereferenceLinks = true;
|
|
ofd.Multiselect = false;
|
|
}
|
|
|
|
public string FileName {
|
|
get => ofd.FileName;
|
|
set {
|
|
if (Directory.Exists(value))
|
|
ofd.InitialDirectory = value;
|
|
}
|
|
}
|
|
|
|
public bool ShowDialog() => ShowDialog(IntPtr.Zero);
|
|
|
|
public bool ShowDialog(IntPtr hWndOwner)
|
|
{
|
|
bool flag = false;
|
|
|
|
var r = new Reflector("System.Windows.Forms");
|
|
|
|
uint num = 0;
|
|
Type typeIFileDialog = r.GetTypo("FileDialogNative.IFileDialog");
|
|
object dialog = r.Call(ofd, "CreateVistaDialog");
|
|
r.Call(ofd, "OnBeforeVistaDialog", dialog);
|
|
|
|
uint options = Convert.ToUInt32(r.CallAs(typeof(FileDialog), ofd, "GetOptions"));
|
|
options |= Convert.ToUInt32(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 = Convert.ToUInt32(parameters[1]);
|
|
|
|
try
|
|
{
|
|
int num2 = Convert.ToInt32(r.CallAs(typeIFileDialog, dialog, "Show", hWndOwner));
|
|
flag = 0 == num2;
|
|
}
|
|
finally
|
|
{
|
|
r.CallAs(typeIFileDialog, dialog, "Unadvise", num);
|
|
GC.KeepAlive(pfde);
|
|
}
|
|
|
|
return flag;
|
|
}
|
|
}
|
|
|
|
class WindowWrapper : IWin32Window
|
|
{
|
|
IntPtr _hwnd;
|
|
|
|
public IntPtr Handle => _hwnd;
|
|
|
|
public WindowWrapper(IntPtr handle) => _hwnd = handle;
|
|
}
|
|
|
|
class Reflector
|
|
{
|
|
string m_ns;
|
|
Assembly m_asmb;
|
|
|
|
public Reflector(string ns) : this(ns, ns) { }
|
|
|
|
public Reflector(string an__1, string ns)
|
|
{
|
|
m_ns = ns;
|
|
m_asmb = null;
|
|
|
|
foreach (AssemblyName aN__2 in Assembly.GetExecutingAssembly().GetReferencedAssemblies())
|
|
{
|
|
if (aN__2.FullName.StartsWith(an__1))
|
|
{
|
|
m_asmb = Assembly.Load(aN__2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Type GetTypo(string typeName)
|
|
{
|
|
Type type = null;
|
|
string[] names = typeName.Split('.');
|
|
|
|
if (names.Length > 0)
|
|
type = m_asmb.GetType(m_ns + Convert.ToString(".") + names[0]);
|
|
|
|
for (int i = 1; i < names.Length; i++)
|
|
type = type.GetNestedType(names[i], BindingFlags.NonPublic);
|
|
|
|
return type;
|
|
}
|
|
|
|
public object New(string name, params object[] parameters)
|
|
{
|
|
Type type = GetTypo(name);
|
|
ConstructorInfo[] ctorInfos = type.GetConstructors();
|
|
|
|
foreach (ConstructorInfo ci in ctorInfos)
|
|
{
|
|
try {
|
|
return ci.Invoke(parameters);
|
|
} catch { }
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public object Call(object obj, string func, params object[] parameters)
|
|
{
|
|
return Call2(obj, func, parameters);
|
|
}
|
|
|
|
public object Call2(object obj, string func, object[] parameters)
|
|
{
|
|
return CallAs2(obj.GetType(), obj, func, parameters);
|
|
}
|
|
|
|
public object CallAs(Type type, object obj, string func, params object[] parameters)
|
|
{
|
|
return CallAs2(type, obj, func, parameters);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public object Get(object obj, string prop) => GetAs(obj.GetType(), obj, prop);
|
|
|
|
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);
|
|
}
|
|
|
|
public object GetEnum(string typeName, string name)
|
|
{
|
|
Type type = GetTypo(typeName);
|
|
FieldInfo fieldInfo = type.GetField(name);
|
|
return fieldInfo.GetValue(null);
|
|
}
|
|
}
|
|
}
|
|
}
|