diff --git a/MainWindowViewModel.cs b/MainWindowViewModel.cs index af21545..e936723 100644 --- a/MainWindowViewModel.cs +++ b/MainWindowViewModel.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; @@ -33,6 +34,19 @@ namespace DrillTools private bool _isStartupDrillTapeFile; private bool _canGeneratePpDrillTape; + private const int SwRestore = 9; + private const int SvsiSelect = 0x1; + private const int SvsiDeselectOthers = 0x4; + private const int SvsiEnsureVisible = 0x8; + private const int SvsiFocused = 0x10; + private const int SelectFileFlags = SvsiSelect | SvsiDeselectOthers | SvsiEnsureVisible | SvsiFocused; + + [DllImport("user32.dll")] + private static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + /// /// 刀具列表 /// @@ -1223,15 +1237,11 @@ M30"; return; } - // 使用 explorer.exe 的 /select 参数来打开文件资源管理器并选中文件 - ProcessStartInfo startInfo = new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = $"/select,\"{filePath}\"", - UseShellExecute = true - }; + string fullFilePath = Path.GetFullPath(filePath); + if (TrySelectFileInOpenExplorerWindow(fullFilePath)) + return; - Process.Start(startInfo); + OpenNewExplorerWindowAndSelectFile(fullFilePath); } catch (Exception ex) { @@ -1239,6 +1249,138 @@ M30"; } } + private static bool TrySelectFileInOpenExplorerWindow(string filePath) + { + string? directory = Path.GetDirectoryName(filePath); + if (string.IsNullOrWhiteSpace(directory)) + return false; + + string normalizedDirectory = NormalizeDirectoryPath(directory); + Type? shellType = Type.GetTypeFromProgID("Shell.Application"); + if (shellType == null) + return false; + + object? shell = null; + try + { + shell = Activator.CreateInstance(shellType); + if (shell == null) + return false; + + dynamic shellApplication = shell; + foreach (dynamic window in shellApplication.Windows()) + { + if (!IsExplorerWindow(window)) + continue; + + string? windowDirectory = GetExplorerWindowDirectory(window); + if (string.IsNullOrWhiteSpace(windowDirectory) + || !string.Equals(NormalizeDirectoryPath(windowDirectory), normalizedDirectory, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + if (SelectFileInExplorerWindow(window, filePath)) + return true; + } + } + catch + { + return false; + } + finally + { + if (shell != null && Marshal.IsComObject(shell)) + Marshal.FinalReleaseComObject(shell); + } + + return false; + } + + private static bool IsExplorerWindow(dynamic window) + { + try + { + string fullName = Convert.ToString(window.FullName) ?? string.Empty; + return string.Equals(Path.GetFileName(fullName), "explorer.exe", StringComparison.OrdinalIgnoreCase); + } + catch + { + return false; + } + } + + private static string? GetExplorerWindowDirectory(dynamic window) + { + try + { + string path = Convert.ToString(window.Document.Folder.Self.Path) ?? string.Empty; + if (!string.IsNullOrWhiteSpace(path)) + return path; + } + catch + { + // 回退到 LocationURL,兼容部分 Explorer 窗口取不到 Folder.Self.Path 的情况。 + } + + try + { + string locationUrl = Convert.ToString(window.LocationURL) ?? string.Empty; + if (Uri.TryCreate(locationUrl, UriKind.Absolute, out Uri? uri) && uri.IsFile) + return uri.LocalPath; + } + catch + { + return null; + } + + return null; + } + + private static bool SelectFileInExplorerWindow(dynamic window, string filePath) + { + try + { + dynamic document = window.Document; + dynamic fileItem = document.Folder.ParseName(Path.GetFileName(filePath)); + if (fileItem == null) + { + document.Refresh(); + fileItem = document.Folder.ParseName(Path.GetFileName(filePath)); + } + + if (fileItem == null) + return false; + + document.SelectItem(fileItem, SelectFileFlags); + IntPtr handle = new IntPtr(Convert.ToInt64(window.HWND)); + ShowWindow(handle, SwRestore); + SetForegroundWindow(handle); + return true; + } + catch + { + return false; + } + } + + private static string NormalizeDirectoryPath(string path) + { + return Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + } + + private static void OpenNewExplorerWindowAndSelectFile(string filePath) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = "explorer.exe", + Arguments = $"/select,\"{filePath}\"", + UseShellExecute = true + }; + + Process.Start(startInfo); + } + /// /// 生成刀具直径列表文件 ///