From c2132e3772ed99c80be00ca437b250c45b9d7e72 Mon Sep 17 00:00:00 2001 From: bao-qian Date: Tue, 3 May 2016 23:21:03 +0100 Subject: [PATCH] Fix file associated icon --- Plugins/Wox.Plugin.Everything/Main.cs | 26 +----- Wox.Infrastructure/Image/ImageLoader.cs | 115 +++++++++++++++--------- Wox.Plugin/Result.cs | 2 +- Wox/Images/app_error.png | Bin 0 -> 10360 bytes Wox/Wox.csproj | 3 + 5 files changed, 78 insertions(+), 68 deletions(-) create mode 100644 Wox/Images/app_error.png diff --git a/Plugins/Wox.Plugin.Everything/Main.cs b/Plugins/Wox.Plugin.Everything/Main.cs index 2b79949eb9..8ee17eafa9 100644 --- a/Plugins/Wox.Plugin.Everything/Main.cs +++ b/Plugins/Wox.Plugin.Everything/Main.cs @@ -16,8 +16,6 @@ namespace Wox.Plugin.Everything public class Main : IPlugin, IPluginI18n, IContextMenu, ISavable { private readonly EverythingAPI _api = new EverythingAPI(); - private static readonly List ImageExts = new List { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" }; - private static readonly List ExecutableExts = new List { ".exe" }; private const string EverythingProcessName = "Everything"; private const string PortableEverything = "PortableEverything"; @@ -74,7 +72,7 @@ namespace Wox.Plugin.Everything Result r = new Result(); r.Title = Path.GetFileName(path); r.SubTitle = path; - r.IcoPath = GetIconPath(s); + r.IcoPath = path; r.Action = c => { bool hide; @@ -131,28 +129,6 @@ namespace Wox.Plugin.Everything return results; } - private string GetIconPath(SearchResult s) - { - var ext = Path.GetExtension(s.FullPath); - if (s.Type == ResultType.Folder) - { - return "Images\\folder.png"; - } - else if (!string.IsNullOrEmpty(ext)) - { - if (ImageExts.Contains(ext.ToLower())) - { - return "Images\\image.png"; - } - else if (ExecutableExts.Contains(ext.ToLower())) - { - return s.FullPath; - } - } - - return "Images\\file.png"; - } - [DllImport("kernel32.dll")] private static extern int LoadLibrary(string name); diff --git a/Wox.Infrastructure/Image/ImageLoader.cs b/Wox.Infrastructure/Image/ImageLoader.cs index bbea213101..ae5aab337a 100644 --- a/Wox.Infrastructure/Image/ImageLoader.cs +++ b/Wox.Infrastructure/Image/ImageLoader.cs @@ -17,9 +17,11 @@ namespace Wox.Infrastructure.Image { public static class ImageLoader { - private static readonly ConcurrentDictionary _imageSources = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary ImageSources = new ConcurrentDictionary(); + private static readonly string DefaultIcon = Path.Combine(Wox.ProgramPath, "Images", "app.png"); + private static readonly string ErrorIcon = Path.Combine(Wox.ProgramPath, "Images", "app_error.png"); - private static readonly List ImageExts = new List + private static readonly string[] ImageExtions = { ".png", ".jpg", @@ -30,16 +32,6 @@ namespace Wox.Infrastructure.Image ".ico" }; - private static readonly List SelfExts = new List - { - ".exe", - ".lnk", - ".ani", - ".cur", - ".sln", - ".appref-ms" - }; - private static readonly ImageCache _cache; private static readonly BinaryStorage _storage; @@ -54,34 +46,67 @@ namespace Wox.Infrastructure.Image _storage.Save(); } - private static ImageSource GetIcon(string fileName) + private static ImageSource ShellIcon(string fileName) { try { - Icon icon = GetFileIcon(fileName) ?? Icon.ExtractAssociatedIcon(fileName); + Icon icon = GetFileIcon(fileName); if (icon != null) { - return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, - new Int32Rect(0, 0, icon.Width, icon.Height), BitmapSizeOptions.FromEmptyOptions()); + var image = ImageFromIcon(icon); + return image; + } + else + { + return ImageSources[ErrorIcon]; } } catch (System.Exception e) { Log.Error(e); + return ImageSources[ErrorIcon]; } - - return null; } + private static ImageSource ImageFromIcon(Icon icon) + { + var image = Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + new Int32Rect(0, 0, icon.Width, icon.Height), + BitmapSizeOptions.FromEmptyOptions()); + return image; + } + + private static ImageSource AssociatedIcon(string path) + { + try + { + Icon icon = Icon.ExtractAssociatedIcon(path); + if (icon != null) + { + var image = ImageFromIcon(icon); + return image; + } + else + { + return ImageSources[ErrorIcon]; + } + } + catch (System.Exception e) + { + Log.Error(e); + return ImageSources[ErrorIcon]; + } + } public static void PreloadImages() { - var path = Path.Combine(Wox.ProgramPath, "Images", "app.png"); - _imageSources[path] = new BitmapImage(new Uri(path)); + ImageSources[DefaultIcon] = new BitmapImage(new Uri(DefaultIcon)); + ImageSources[ErrorIcon] = new BitmapImage(new Uri(ErrorIcon)); Task.Factory.StartNew(() => { Stopwatch.Debug("Preload images from cache", () => { - _cache.TopUsedImages.AsParallel().Where(i => !_imageSources.ContainsKey(i.Key)).ForAll(i => + _cache.TopUsedImages.AsParallel().Where(i => !ImageSources.ContainsKey(i.Key)).ForAll(i => { var img = Load(i.Key); if (img != null) @@ -91,7 +116,7 @@ namespace Wox.Infrastructure.Image // this line made it possible // should be changed the Dispatcher.InvokeAsync in the future img.Freeze(); - _imageSources[i.Key] = img; + ImageSources[i.Key] = img; } }); }); @@ -100,16 +125,15 @@ namespace Wox.Infrastructure.Image } public static ImageSource Load(string path) - { + { ImageSource image; if (string.IsNullOrEmpty(path)) { - path = Path.Combine(Wox.ProgramPath, "Images", "app.png"); - image = _imageSources[path]; + image = ImageSources[ErrorIcon]; } - else if (_imageSources.ContainsKey(path)) + else if (ImageSources.ContainsKey(path)) { - image = _imageSources[path]; + image = ImageSources[path]; } else { @@ -118,37 +142,44 @@ namespace Wox.Infrastructure.Image if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { image = new BitmapImage(new Uri(path)); - _imageSources[path] = image; + ImageSources[path] = image; } - else if (File.Exists(path) && Path.IsPathRooted(path)) + else if (Path.IsPathRooted(path)) { - if (SelfExts.Contains(ext)) + if (Directory.Exists(path)) { - image = GetIcon(path); - _imageSources[path] = image; + image = ShellIcon(path); + ImageSources[path] = image; } - else if (ImageExts.Contains(ext)) + else if (File.Exists(path)) { - image = new BitmapImage(new Uri(path)); - _imageSources[path] = image; + if (ImageExtions.Contains(ext)) + { + image = new BitmapImage(new Uri(path)); + ImageSources[path] = image; + } + else + { + image = AssociatedIcon(path); + ImageSources[path] = image; + } } else { - path = Path.Combine(Wox.ProgramPath, "Images", "app.png"); - image = _imageSources[path]; + image = ImageSources[ErrorIcon]; } } else { - path = Path.Combine(Wox.ProgramPath, "Images", Path.GetFileName(path)); - if (File.Exists(path)) + var defaultDirectoryPath = Path.Combine(Wox.ProgramPath, "Images", Path.GetFileName(path)); + if (File.Exists(defaultDirectoryPath)) { - image = new BitmapImage(new Uri(path)); + image = new BitmapImage(new Uri(defaultDirectoryPath)); + ImageSources[path] = image; } else { - path = Path.Combine(Wox.ProgramPath, "Images", "app.png"); - image = _imageSources[path]; + image = ImageSources[ErrorIcon]; } } } diff --git a/Wox.Plugin/Result.cs b/Wox.Plugin/Result.cs index aba637b01a..3f550c9b59 100644 --- a/Wox.Plugin/Result.cs +++ b/Wox.Plugin/Result.cs @@ -49,7 +49,7 @@ namespace Wox.Plugin set { _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && Path.IsPathRooted(IcoPath)) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath)) { IcoPath = Path.Combine(value, IcoPath); } diff --git a/Wox/Images/app_error.png b/Wox/Images/app_error.png new file mode 100644 index 0000000000000000000000000000000000000000..5106d6e8a9e2a152d6d5e712155ac101666b093f GIT binary patch literal 10360 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 + + PreserveNewest + Designer MSBuild:Compile