diff --git a/PersonalToolBox/Models/ToolItem.cs b/PersonalToolBox/Models/ToolItem.cs index 4a15d3d..2b238b1 100644 --- a/PersonalToolBox/Models/ToolItem.cs +++ b/PersonalToolBox/Models/ToolItem.cs @@ -62,4 +62,12 @@ public class ToolItem /// 是否在软件启动时自动运行 /// public bool AutoRunOnStart { get; set; } + + /// + /// 路径是否指向 .exe 文件(仅运行时判断,不存入 JSON) + /// + [JsonIgnore] + public bool IsExePath => + !IsGroup && !string.IsNullOrWhiteSpace(ExecutablePath) && + ExecutablePath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase); } diff --git a/PersonalToolBox/Resources/app.ico b/PersonalToolBox/Resources/app.ico index f3aeb5f..0461a17 100644 Binary files a/PersonalToolBox/Resources/app.ico and b/PersonalToolBox/Resources/app.ico differ diff --git a/PersonalToolBox/Views/MainWindow.xaml b/PersonalToolBox/Views/MainWindow.xaml index 5499187..106b872 100644 --- a/PersonalToolBox/Views/MainWindow.xaml +++ b/PersonalToolBox/Views/MainWindow.xaml @@ -17,6 +17,7 @@ + @@ -93,7 +94,26 @@ - + + + + + + + @@ -102,9 +122,13 @@ - + + + + + - + diff --git a/PersonalToolBox/Views/MainWindow.xaml.cs b/PersonalToolBox/Views/MainWindow.xaml.cs index ac640d2..79adaa7 100644 --- a/PersonalToolBox/Views/MainWindow.xaml.cs +++ b/PersonalToolBox/Views/MainWindow.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Specialized; using System.ComponentModel; using System.Drawing; @@ -229,3 +230,53 @@ public class StringToIconCharConverter : IValueConverter public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException(); } + +/// +/// string (exe路径) → ImageSource: 提取 .exe 文件自身图标,带缓存 +/// +public class ExePathToIconConverter : IValueConverter +{ + private static readonly ConcurrentDictionary Cache = new(); + + public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not string path || path.Length == 0) + return null; + + if (!path.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) + return null; + + return Cache.GetOrAdd(path, key => + { + try + { + if (!File.Exists(key)) + return null; + + using var icon = System.Drawing.Icon.ExtractAssociatedIcon(key); + if (icon == null) + return null; + + using var bitmap = icon.ToBitmap(); + using var ms = new MemoryStream(); + bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + ms.Seek(0, SeekOrigin.Begin); + + var image = new BitmapImage(); + image.BeginInit(); + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = ms; + image.EndInit(); + image.Freeze(); + return image; + } + catch + { + return null; + } + }); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + => throw new NotImplementedException(); +}