using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using Autodesk.Revit.DB;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.Win32;
using ShrlAlgoToolkit.Core.Assists;
namespace ShrlAlgoToolkit.RevitAddins.Assists;
public static class WinDialogAssist
{
///
/// 对话框过滤器
///
/// 过滤器的名称
/// 仅扩展名,*代表所有文件
///
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}";
}
///
/// 释放命令行管理程序分配的ITEMIDLIST结构
/// Frees an ITEMIDLIST structure allocated by the Shell.
///
///
[DllImport("shell32.dll", ExactSpelling = true)]
private static extern void ILFree(IntPtr pidlList);
///
/// 返回与指定文件路径关联的ITEMIDLIST结构。
/// Returns the ITEMIDLIST structure associated with a specified file path.
///
///
///
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern IntPtr ILCreateFromPathW(string pszPath);
///
/// 打开一个Windows资源管理器窗口,其中选择了特定文件夹中的指定项目。
/// Opens a Windows Explorer window with specified items in a particular folder selected.
///
///
///
///
///
///
[DllImport("shell32.dll", ExactSpelling = true)]
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags);
///
/// 打开或在现有目录并选中相应文件
///
///
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);
}
}
///
/// 新建一个资源管理器窗口并选中文件或文件夹
///
///
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}\"");
}
///
/// 选择文件
///
///
///
///
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;
}
public static void UpdateViewDisplay(Autodesk.Revit.UI.PreviewControl _currentPreviewControl, System.Windows.Controls.Grid PreviewContainer, Document _backgroundDoc, View view, ViewDetailLevel detailLevel, DisplayStyle displayStyle)
{
if (_backgroundDoc == null || view == null) return;
_backgroundDoc.Invoke(
ts =>
{
try
{
view.DetailLevel = detailLevel;
view.DisplayStyle = displayStyle;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
// 2. 销毁旧控件
if (_currentPreviewControl != null)
{
PreviewContainer.Children.Clear();
_currentPreviewControl.Dispose();
_currentPreviewControl = null;
}
// 3. 创建新控件并加入 UI
_currentPreviewControl = new Autodesk.Revit.UI.PreviewControl(_backgroundDoc, view.Id);
PreviewContainer.Children.Add(_currentPreviewControl);
}
/////
///// 单选文件夹路径
/////
/////
//public static string GetSelectedFolderPath()
//{
// var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { Multiselect = false };
// var folderPath = dialog.ShowDialog() == true ? dialog.SelectedPath : null;
// return folderPath;
//}
/////
///// 多选文件夹路径
/////
/////
//public static string[] GetSelectedFolderPaths()
//{
// var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { Multiselect = true };
// return dialog.ShowDialog() == true ? dialog.SelectedPaths : null;
//}
///
/// 打开窗口,非模态窗口置顶显示,默认非模态
///
///
private static void ShowAhead(this Window window)
{
_ = new WindowInteropHelper(window) { Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle };
window.Show();
}
public static void ShowModeless(ObservableObject viewModel)
where T : Window, new()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var view = SingletonViewAssist.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.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 _windows = [];
public static void ShowOrActivate(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 += (_, _) => _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;
}
public static void ShowDialog(params object[] viewModelParams)
where TWindow : Window, new()
where TViewModel : class
{
var window = new TWindow();
if (viewModelParams.Length == 0)
{
window.DataContext = Activator.CreateInstance(typeof(TViewModel));
}
else
{
window.DataContext = Activator.CreateInstance(typeof(TViewModel), viewModelParams);
}
_ = new WindowInteropHelper(window) { Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle };
window.ShowDialog();
}
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 list = new List();
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;
}
}