Files

223 lines
8.0 KiB
C#
Raw Permalink Normal View History

2025-09-16 16:06:41 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
namespace Szmedi.RevitToolkit.Approval.Assists
{
public static class WinDialogAssists
{
private static Dictionary<Type, Window> _windows = new Dictionary<Type, Window>();
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;
}
//private static T instance;
//private static readonly object padlock = new();
//public static T GetInstance(out bool IsNewCreate)
//{
// IsNewCreate = false;
// //double-check locking
// if (instance == null)
// {
// IsNewCreate = true;
// lock (padlock)
// {
// instance ??= new T();
// instance.Closed += OnWindowClosed;
// }
// }
// return instance;
//}
//private static void OnWindowClosed(object sender, EventArgs e)
//{
// instance = null;
//}
public static class LazySingleton<T>
where T : class, new()
{
private static readonly Lazy<T> instance = new(() => new T(), LazyThreadSafetyMode.ExecutionAndPublication);
public static T Instance => instance.Value;
}
/// <summary>
/// 对话框过滤器
/// </summary>
/// <param name="title">过滤器的名称</param>
/// <param name="extensions">仅扩展名,如xlsx,*代表所有文件</param>
/// <returns></returns>
public static string CreateFilter(string title, params string[] extensions)
{
if (extensions[0] == "*")
{
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 += ";";
}
}
return $"{title}({str})|{str}";
}
/// <summary>
/// 释放命令行管理程序分配的ITEMIDLIST结构
/// Frees an ITEMIDLIST structure allocated by the Shell.
/// </summary>
/// <param name="pidlList"></param>
[DllImport("shell32.dll", ExactSpelling = true)]
public 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)]
public 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)]
public 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="filePath"></param>
public static void ExploreFile(string filePath)
{
Process proc = new();
proc.StartInfo.FileName = "explorer";
//打开资源管理器
proc.StartInfo.Arguments = @"/select," + filePath;
//选中"notepad.exe"这个程序,即记事本
proc.Start();
}
/// <summary>
/// 打开窗口,非模态窗口置顶显示,默认非模态
/// </summary>
/// <returns></returns>
public static void ShowAhead(this Window window)
{
_ = new WindowInteropHelper(window)
{
Owner = Process.GetCurrentProcess().MainWindowHandle
};
window.Show();
}
}
}