284 lines
9.6 KiB
C#
284 lines
9.6 KiB
C#
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using System.Runtime.InteropServices;
|
||
using System.Windows;
|
||
using System.Windows.Interop;
|
||
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
|
||
using Microsoft.Win32;
|
||
|
||
using ShrlAlgoToolkit.Core.Assists;
|
||
|
||
namespace ShrlAlgoToolkit.RevitAddins.Assists;
|
||
|
||
public static class WinDialogHelper
|
||
{
|
||
/// <summary>
|
||
/// 对话框过滤器
|
||
/// </summary>
|
||
/// <param name="filterName">过滤器的名称</param>
|
||
/// <param name="extensions">仅扩展名,*代表所有文件</param>
|
||
/// <returns></returns>
|
||
public static FileDialog SetFilter(this FileDialog dialog, string filterName, params string[] extensions)
|
||
{
|
||
if (extensions[0] == "*")
|
||
{
|
||
dialog.Filter = "所有文件(*)|*";
|
||
//return "所有文件(*)|*";
|
||
}
|
||
|
||
var str = string.Empty;
|
||
for (var i = 0; i < extensions.Length; i++)
|
||
{
|
||
var extension = extensions[i];
|
||
str += $"*.{extension}";
|
||
if (i < extensions.Length - 1)
|
||
{
|
||
str += ";";
|
||
}
|
||
}
|
||
dialog.Filter = $"{filterName}({str})|{str}";
|
||
return dialog;
|
||
//return $"{filterName}({str})|{str}";
|
||
}
|
||
/// <summary>
|
||
/// 释放命令行管理程序分配的ITEMIDLIST结构
|
||
/// Frees an ITEMIDLIST structure allocated by the Shell.
|
||
/// </summary>
|
||
/// <param name="pidlList"></param>
|
||
[DllImport("shell32.dll", ExactSpelling = true)]
|
||
private static extern void ILFree(IntPtr pidlList);
|
||
/// <summary>
|
||
/// 返回与指定文件路径关联的ITEMIDLIST结构。
|
||
/// Returns the ITEMIDLIST structure associated with a specified file path.
|
||
/// </summary>
|
||
/// <param name="pszPath"></param>
|
||
/// <returns></returns>
|
||
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||
private static extern IntPtr ILCreateFromPathW(string pszPath);
|
||
/// <summary>
|
||
/// 打开一个Windows资源管理器窗口,其中选择了特定文件夹中的指定项目。
|
||
/// Opens a Windows Explorer window with specified items in a particular folder selected.
|
||
/// </summary>
|
||
/// <param name="pidlList"></param>
|
||
/// <param name="cild"></param>
|
||
/// <param name="children"></param>
|
||
/// <param name="dwFlags"></param>
|
||
/// <returns></returns>
|
||
[DllImport("shell32.dll", ExactSpelling = true)]
|
||
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags);
|
||
|
||
/// <summary>
|
||
/// 打开或在现有目录并选中相应文件
|
||
/// </summary>
|
||
/// <param name="fileFullName"></param>
|
||
static public void OpenFolderAndSelectFile(string fileFullName)
|
||
{
|
||
if (string.IsNullOrEmpty(fileFullName))
|
||
throw new ArgumentNullException(nameof(fileFullName));
|
||
fileFullName = Path.GetFullPath(fileFullName);
|
||
var pidlList = ILCreateFromPathW(fileFullName);
|
||
if (pidlList == IntPtr.Zero) return;
|
||
try
|
||
{
|
||
Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0));
|
||
}
|
||
finally
|
||
{
|
||
ILFree(pidlList);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 新建一个资源管理器窗口并选中文件或文件夹
|
||
/// </summary>
|
||
/// <param name="fileOrFolderPath"></param>
|
||
public static void ExploreFile(string fileOrFolderPath)
|
||
{
|
||
//Process proc = new();
|
||
//proc.StartInfo.FileName = "explorer";
|
||
////打开资源管理器
|
||
//proc.StartInfo.Arguments = @"/select," + fileOrFolderPath;
|
||
////选中"notepad.exe"这个程序,即记事本
|
||
//proc.Start();
|
||
|
||
System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{fileOrFolderPath}\"");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择文件
|
||
/// </summary>
|
||
/// <param name="title"></param>
|
||
/// <param name="extensions"></param>
|
||
/// <returns></returns>
|
||
public static string GetSelectedFilePath(string title, params string[] extensions)
|
||
{
|
||
OpenFileDialog dialog =
|
||
new()
|
||
{
|
||
CheckFileExists = true,
|
||
|
||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||
};
|
||
dialog.SetFilter(title, extensions);
|
||
return dialog.ShowDialog() == true ? dialog.FileName : null;
|
||
}
|
||
|
||
///// <summary>
|
||
///// 单选文件夹路径
|
||
///// </summary>
|
||
///// <returns></returns>
|
||
//public static string GetSelectedFolderPath()
|
||
//{
|
||
// var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { Multiselect = false };
|
||
|
||
// var folderPath = dialog.ShowDialog() == true ? dialog.SelectedPath : null;
|
||
|
||
// return folderPath;
|
||
//}
|
||
|
||
///// <summary>
|
||
///// 多选文件夹路径
|
||
///// </summary>
|
||
///// <returns></returns>
|
||
//public static string[] GetSelectedFolderPaths()
|
||
//{
|
||
// var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { Multiselect = true };
|
||
|
||
// return dialog.ShowDialog() == true ? dialog.SelectedPaths : null;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 打开窗口,非模态窗口置顶显示,默认非模态
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private static void ShowAhead(this Window window)
|
||
{
|
||
_ = new WindowInteropHelper(window) { Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle };
|
||
window.Show();
|
||
}
|
||
|
||
public static void ShowModeless<T>(ObservableObject viewModel)
|
||
where T : Window, new()
|
||
{
|
||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||
var view = SingletonViewAssist<T>.GetInstance(out var isNewCreate);
|
||
if (isNewCreate)
|
||
{
|
||
view.DataContext = viewModel;
|
||
view.ShowAhead();
|
||
}
|
||
view.Activate();
|
||
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
|
||
|
||
//AssemblyLoaderHelpers loaderUtil = new(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
|
||
//loaderUtil.HookAssemblyResolve();
|
||
//try
|
||
//{
|
||
// var view = SingletonViewAssist<Command>.GetInstance(out var isNewCreate);
|
||
// if (isNewCreate)
|
||
// {
|
||
// view.DataContext = viewModel;
|
||
// view.ShowAhead();
|
||
// }
|
||
// view.Activate();
|
||
//}
|
||
//catch (Exception ex)
|
||
//{
|
||
// LogAssist.ToLog($"{ex.Source}:{ex.StackTrace}");
|
||
//}
|
||
//finally
|
||
//{
|
||
// loaderUtil.UnhookAssemblyResolve();
|
||
//}
|
||
}
|
||
//private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
||
//{
|
||
// if (!args.Name.Contains("Xaml.Behaviors"))
|
||
// {
|
||
// return null;
|
||
// }
|
||
|
||
// var assemblyFile = Path.Combine(
|
||
// Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
|
||
// "Microsoft.Xaml.Behaviors.dll"
|
||
// );
|
||
// return File.Exists(assemblyFile) ? Assembly.LoadFrom(assemblyFile) : null;
|
||
//}
|
||
private static Dictionary<Type, Window> _windows = [];
|
||
public static void ShowOrActivate<TWindow, TViewModel>(params object[] viewModelParams)
|
||
where TWindow : Window, new()
|
||
where TViewModel : class
|
||
{
|
||
var windowType = typeof(TWindow);
|
||
if (!_windows.ContainsKey(windowType) || _windows[windowType] == null)
|
||
{
|
||
//CloseAllWindowsExcept(windowType);
|
||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||
_windows[windowType] = new TWindow();
|
||
_windows[windowType].Closed += WindowClosed;
|
||
_windows[windowType].Closed += (sender, args) => _windows[windowType] = null;
|
||
if (_windows[windowType].DataContext == null || !(_windows[windowType].DataContext is TViewModel))
|
||
{
|
||
if (viewModelParams.Length == 0)
|
||
{
|
||
_windows[windowType].DataContext = Activator.CreateInstance(typeof(TViewModel));
|
||
}
|
||
else
|
||
{
|
||
_windows[windowType].DataContext = Activator.CreateInstance(typeof(TViewModel), viewModelParams);
|
||
}
|
||
}
|
||
_ = new WindowInteropHelper(_windows[windowType]) { Owner = Process.GetCurrentProcess().MainWindowHandle };
|
||
_windows[windowType].Show();
|
||
}
|
||
else
|
||
{
|
||
_windows[windowType].Activate();
|
||
}
|
||
}
|
||
private static void WindowClosed(object sender, EventArgs e)
|
||
{
|
||
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
|
||
}
|
||
|
||
|
||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||
{
|
||
StackFrame[] frames = new StackTrace().GetFrames();
|
||
if (frames == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
string name = new AssemblyName(args.Name).Name;
|
||
List<string> list = new List<string>();
|
||
for (int i = 0; i < frames.Length; i++)
|
||
{
|
||
MethodBase method = frames[i].GetMethod();
|
||
if ((object)method.DeclaringType == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
string directoryName = Path.GetDirectoryName(method.DeclaringType.Assembly.Location);
|
||
if (list.Contains(directoryName))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
list.Add(directoryName);
|
||
foreach (string item in Directory.EnumerateFiles(directoryName, "*.dll"))
|
||
{
|
||
if (name == Path.GetFileNameWithoutExtension(item))
|
||
{
|
||
return Assembly.LoadFile(item);
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|