Files
2025-09-16 16:06:41 +08:00

223 lines
8.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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();
}
}
}