Reuse open Explorer window when selecting files
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
@@ -33,6 +34,19 @@ namespace DrillTools
|
|||||||
private bool _isStartupDrillTapeFile;
|
private bool _isStartupDrillTapeFile;
|
||||||
private bool _canGeneratePpDrillTape;
|
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);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刀具列表
|
/// 刀具列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1223,15 +1237,11 @@ M30";
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 explorer.exe 的 /select 参数来打开文件资源管理器并选中文件
|
string fullFilePath = Path.GetFullPath(filePath);
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo
|
if (TrySelectFileInOpenExplorerWindow(fullFilePath))
|
||||||
{
|
return;
|
||||||
FileName = "explorer.exe",
|
|
||||||
Arguments = $"/select,\"{filePath}\"",
|
|
||||||
UseShellExecute = true
|
|
||||||
};
|
|
||||||
|
|
||||||
Process.Start(startInfo);
|
OpenNewExplorerWindowAndSelectFile(fullFilePath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成刀具直径列表文件
|
/// 生成刀具直径列表文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user