mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-06-02 18:44:56 +12:00
Refactored resource file management..
Remove use of resx file Resource files are marked as "Resource" instead Resources are loaded via resource dictionaries (either from code behind or XAML directly through binding) Reduce amount of required image conversions Also fix overlay of 50 percent transparency (is now rendered half transparent correct instead of adding "white fog") Remove obsolete image as rendering is done directly in code Also fix rendering of link indicator at correct image position Also remove setting Icons of all Windows (as default is application icon anyway)
This commit is contained in:
parent
7cbad2bbdc
commit
de483c874c
|
@ -1,7 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2022-2022 Peter Kirmeier -->
|
||||
<!-- Copyright (c) 2022-2023 Peter Kirmeier -->
|
||||
<Application
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:SystemTrayMenu"
|
||||
x:Class="SystemTrayMenu.App" ShutdownMode="OnExplicitShutdown" />
|
||||
x:Class="SystemTrayMenu.App" ShutdownMode="OnExplicitShutdown">
|
||||
|
||||
<Application.Resources>
|
||||
<BitmapImage x:Key="ApplicationImage" UriSource="../Resources/SystemTrayMenu.png" />
|
||||
|
||||
<BitmapImage x:Key="ApplicationIconImage" UriSource="../Resources/SystemTrayMenu.ico" />
|
||||
<BitmapImage x:Key="LinkArrowIconImage" UriSource="../Resources/LinkArrow.ico" />
|
||||
<BitmapImage x:Key="LoadingIconImage" UriSource="../Resources/Loading.ico" />
|
||||
<BitmapImage x:Key="NotFoundIconImage" UriSource="../Resources/NotFound.ico" />
|
||||
</Application.Resources>
|
||||
|
||||
</Application>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
namespace SystemTrayMenu
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using SystemTrayMenu.Business;
|
||||
|
@ -18,18 +20,21 @@ namespace SystemTrayMenu
|
|||
/// </summary>
|
||||
public partial class App : Application, IDisposable
|
||||
{
|
||||
private readonly Menus menus = new();
|
||||
private Menus? menus;
|
||||
private JoystickHelper? joystickHelper;
|
||||
private bool isDisposed;
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
AppRestart.BeforeRestarting += Dispose;
|
||||
|
||||
Activated += (_, _) => IsActiveApp = true;
|
||||
Deactivated += (_, _) => IsActiveApp = false;
|
||||
Startup += (_, _) =>
|
||||
{
|
||||
menus = new();
|
||||
menus.Startup();
|
||||
|
||||
if (Settings.Default.SupportGamepad)
|
||||
|
@ -55,17 +60,35 @@ namespace SystemTrayMenu
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads an Icon from the application's Resources.
|
||||
/// Note: Only allowed to be called after App's Startup event.
|
||||
/// </summary>
|
||||
/// <param name="resourceName">Absolute file path from root directory.</param>
|
||||
/// <returns>New Icon object.</returns>
|
||||
internal static Icon LoadIconFromResource(string resourceName)
|
||||
{
|
||||
using (Stream stream = GetResourceStream(new("pack://application:,,,/" + resourceName, UriKind.Absolute)).Stream)
|
||||
{
|
||||
return new(stream);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!isDisposed)
|
||||
{
|
||||
if (joystickHelper != null)
|
||||
{
|
||||
joystickHelper.KeyPressed -= menus.KeyPressed;
|
||||
if (menus != null)
|
||||
{
|
||||
joystickHelper.KeyPressed -= menus.KeyPressed;
|
||||
}
|
||||
|
||||
joystickHelper.Dispose();
|
||||
}
|
||||
|
||||
menus.Dispose();
|
||||
menus?.Dispose();
|
||||
|
||||
isDisposed = true;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ namespace SystemTrayMenu
|
|||
FolderOptions.Initialize();
|
||||
|
||||
using App app = new ();
|
||||
app.InitializeComponent();
|
||||
isStartup = false;
|
||||
Log.WriteApplicationRuns();
|
||||
app.Run();
|
||||
|
|
|
@ -12,13 +12,12 @@ namespace SystemTrayMenu
|
|||
using SystemTrayMenu.Properties;
|
||||
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using static SystemTrayMenu.Utilities.IconReader;
|
||||
using Icon = System.Drawing.Icon;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
private static readonly Icon SystemTrayMenu = new(Properties.Resources.SystemTrayMenu, (int)SystemParameters.SmallIconWidth, (int)SystemParameters.SmallIconHeight);
|
||||
private static readonly Icon? IconRootFolder = GetIconAsIcon(Path, Path, false, true, IconSize.Small);
|
||||
private static readonly Icon? IconRootFolder = IconReader.GetRootFolderIcon(Path);
|
||||
private static Icon? applicationIcon;
|
||||
|
||||
private static bool readDarkModeDone;
|
||||
private static bool isDarkMode;
|
||||
|
@ -70,7 +69,14 @@ namespace SystemTrayMenu
|
|||
}
|
||||
else
|
||||
{
|
||||
return SystemTrayMenu;
|
||||
if (applicationIcon == null)
|
||||
{
|
||||
Icon icon = App.LoadIconFromResource("Resources/SystemTrayMenu.ico");
|
||||
applicationIcon = new(icon, (int)SystemParameters.SmallIconWidth, (int)SystemParameters.SmallIconHeight);
|
||||
icon.Dispose();
|
||||
}
|
||||
|
||||
return applicationIcon;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace SystemTrayMenu.DataClasses
|
|||
if (!cacheHit)
|
||||
{
|
||||
IconLoading = true;
|
||||
ColumnIcon = SystemTrayMenu.Resources.StaticResources.LoadingImgSrc; // TODO: Maybe add rotation animation like for the loading Menu icon? (See: pictureBoxLoading, LoadingRotation)
|
||||
ColumnIcon = (ImageSource?)Application.Current.Resources["LoadingIconImage"]; // TODO: Maybe add rotation animation like for the loading Menu icon? (See: pictureBoxLoading, LoadingRotation)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,11 +343,11 @@ namespace SystemTrayMenu.DataClasses
|
|||
{
|
||||
if (icon == null)
|
||||
{
|
||||
icon = Resources.NotFound.ToBitmapSource();
|
||||
icon = (BitmapSource)Application.Current.Resources["NotFoundIconImage"];
|
||||
}
|
||||
else if (HiddenEntry)
|
||||
{
|
||||
icon = ImagingHelper.CreateIconWithOverlay(icon, Resources.White50Percentage.ToBitmapSource());
|
||||
icon = ImagingHelper.ApplyOpactiy(icon, 0.5d);
|
||||
icon?.Freeze(); // Make it accessible for any thread
|
||||
}
|
||||
|
||||
|
|
|
@ -115,18 +115,44 @@ namespace SystemTrayMenu.Helpers
|
|||
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders an image on top of an image.
|
||||
/// </summary>
|
||||
/// <param name="originalBitmap">Base image (remains unchanged).</param>
|
||||
/// <param name="overlayBitmap">Image on top (remains unchanged).</param>
|
||||
/// <returns>Rendered image.</returns>
|
||||
internal static RenderTargetBitmap CreateIconWithOverlay(BitmapSource originalBitmap, BitmapSource overlayBitmap)
|
||||
{
|
||||
DrawingVisual dVisual = new DrawingVisual();
|
||||
DrawingVisual dVisual = new ();
|
||||
using (DrawingContext dc = dVisual.RenderOpen())
|
||||
{
|
||||
dc.DrawImage(originalBitmap, new (0, 0, originalBitmap.PixelWidth, originalBitmap.PixelHeight));
|
||||
dc.DrawImage(overlayBitmap, new (0, 0, overlayBitmap.PixelWidth, overlayBitmap.PixelHeight));
|
||||
dc.DrawImage(overlayBitmap, new (0, 0, originalBitmap.PixelWidth, originalBitmap.PixelHeight));
|
||||
}
|
||||
|
||||
RenderTargetBitmap targetBitmap = new (originalBitmap.PixelWidth, originalBitmap.PixelHeight, originalBitmap.DpiX, originalBitmap.DpiY, PixelFormats.Default);
|
||||
targetBitmap.Render(dVisual);
|
||||
return targetBitmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a flat the alpha channel value for an image.
|
||||
/// </summary>
|
||||
/// <param name="originalBitmap">Base image (remains unchanged).</param>
|
||||
/// <param name="opacity">Opacity value.</param>
|
||||
/// <returns>Rendered image.</returns>
|
||||
internal static RenderTargetBitmap ApplyOpactiy(BitmapSource originalBitmap, double opacity)
|
||||
{
|
||||
DrawingVisual dVisual = new ();
|
||||
using (DrawingContext dc = dVisual.RenderOpen())
|
||||
{
|
||||
dc.PushOpacity(opacity);
|
||||
dc.DrawImage(originalBitmap, new(0, 0, originalBitmap.PixelWidth, originalBitmap.PixelHeight));
|
||||
}
|
||||
|
||||
RenderTargetBitmap targetBitmap = new(originalBitmap.PixelWidth, originalBitmap.PixelHeight, originalBitmap.DpiX, originalBitmap.DpiY, PixelFormats.Default);
|
||||
targetBitmap.Render(dVisual);
|
||||
return targetBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
113
Properties/Resources.Designer.cs
generated
113
Properties/Resources.Designer.cs
generated
|
@ -1,113 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SystemTrayMenu.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SystemTrayMenu.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon LinkArrow {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("LinkArrow", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon Loading {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Loading", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon NotFound {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("NotFound", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon SystemTrayMenu {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("SystemTrayMenu", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon White50Percentage {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("White50Percentage", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="White50Percentage" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\White50Percentage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="SystemTrayMenu" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\SystemTrayMenu.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="NotFound" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\NotFound.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Loading" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Loading.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="LinkArrow" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\LinkArrow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,85 +0,0 @@
|
|||
// <copyright file="StaticResources.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace SystemTrayMenu.Resources
|
||||
{
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SystemTrayMenu.Utilities;
|
||||
|
||||
internal static class StaticResources
|
||||
{
|
||||
internal static readonly Icon LoadingIcon = Properties.Resources.Loading;
|
||||
|
||||
private static readonly object ApplicationImgSrcLock = new();
|
||||
private static readonly object LoadingImgSrcLock = new ();
|
||||
|
||||
private static ImageSource? applicationgImgSrc;
|
||||
private static ImageSource? loadingImgSrc;
|
||||
|
||||
public static ImageSource? ApplicationImgSrc
|
||||
{
|
||||
get
|
||||
{
|
||||
if (applicationgImgSrc == null)
|
||||
{
|
||||
lock (ApplicationImgSrcLock)
|
||||
{
|
||||
if (applicationgImgSrc == null)
|
||||
{
|
||||
applicationgImgSrc = LoadFromAssemblyManifestResources("Resources.SystemTrayMenu.png");
|
||||
applicationgImgSrc?.Freeze(); // Make it accessible for any thread
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return applicationgImgSrc;
|
||||
}
|
||||
}
|
||||
|
||||
public static ImageSource LoadingImgSrc
|
||||
{
|
||||
get
|
||||
{
|
||||
if (loadingImgSrc == null)
|
||||
{
|
||||
lock (LoadingImgSrcLock)
|
||||
{
|
||||
if (loadingImgSrc == null)
|
||||
{
|
||||
loadingImgSrc = Properties.Resources.Loading.ToBitmapSource();
|
||||
loadingImgSrc.Freeze(); // Make it accessible for any thread
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loadingImgSrc;
|
||||
}
|
||||
}
|
||||
|
||||
private static ImageSource? LoadFromAssemblyManifestResources(string name)
|
||||
{
|
||||
Assembly myassembly = Assembly.GetExecutingAssembly();
|
||||
string myname = myassembly.GetName().Name ?? string.Empty;
|
||||
|
||||
using (Stream? imgstream = myassembly.GetManifestResourceStream(myname + "." + name))
|
||||
{
|
||||
if (imgstream != null)
|
||||
{
|
||||
BitmapImage imageSource = new();
|
||||
imageSource.BeginInit();
|
||||
imageSource.StreamSource = imgstream;
|
||||
imageSource.EndInit();
|
||||
|
||||
return imageSource;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
|
@ -126,32 +126,23 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\SystemTrayMenu.ico" />
|
||||
<None Remove="Resources\HowToOpenSettings.png" />
|
||||
<Resource Include="Resources\SystemTrayMenu.ico" />
|
||||
<Resource Include="Resources\SystemTrayMenu.png" />
|
||||
<Resource Include="Resources\LinkArrow.ico" />
|
||||
<Resource Include="Resources\Loading.ico" />
|
||||
<Resource Include="Resources\HowToOpenSettings.png" />
|
||||
<None Remove="Resources\SystemTrayMenu.png" />
|
||||
<EmbeddedResource Include="Resources\SystemTrayMenu.png" />
|
||||
<Resource Include="Resources\NotFound.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2022-2022 Peter Kirmeier -->
|
||||
<!-- Copyright (c) 2022-2023 Peter Kirmeier -->
|
||||
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:u="clr-namespace:SystemTrayMenu.Utilities"
|
||||
xmlns:local="clr-namespace:SystemTrayMenu.UserInterface"
|
||||
x:Class="SystemTrayMenu.UserInterface.AboutBox"
|
||||
mc:Ignorable="d" Title="{u:Translate 'About SystemTrayMenu'}" Height="513" Width="418" ResizeMode="NoResize" SizeToContent="Height">
|
||||
<DockPanel>
|
||||
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" DockPanel.Dock="Top">
|
||||
<Image x:Name="ImagePictureBox" Width="32" Height="32" Margin="3" />
|
||||
<Image Width="32" Height="32" Margin="3" Source="{StaticResource ApplicationImage}" />
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Label x:Name="AppTitleLabel" Content="%title%" Padding="0" Margin="3"/>
|
||||
<Label x:Name="AppDescriptionLabel" Content="%description%" Padding="0" Margin="3"/>
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.Win32;
|
||||
using SystemTrayMenu.Resources;
|
||||
using SystemTrayMenu.Utilities;
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,9 +38,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
InitializeComponent();
|
||||
|
||||
ImagePictureBox.Source = StaticResources.ApplicationImgSrc;
|
||||
Icon = StaticResources.ApplicationImgSrc;
|
||||
|
||||
Loaded += AboutBox_Load;
|
||||
|
||||
TabPanelDetails.Visibility = Visibility.Collapsed;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
namespace SystemTrayMenu.UserInterface
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Threading;
|
||||
using H.NotifyIcon.Core;
|
||||
|
||||
|
@ -12,6 +13,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
private readonly Dispatcher dispatchter = Dispatcher.CurrentDispatcher;
|
||||
private readonly TrayIconWithContextMenu notifyIcon = new ();
|
||||
private Icon? loadingIcon;
|
||||
|
||||
public AppNotifyIcon()
|
||||
{
|
||||
|
@ -35,11 +37,13 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
notifyIcon.Icon = IntPtr.Zero;
|
||||
notifyIcon.Dispose();
|
||||
loadingIcon?.Dispose();
|
||||
}
|
||||
|
||||
public void LoadingStart()
|
||||
{
|
||||
notifyIcon.Icon = Resources.StaticResources.LoadingIcon.Handle;
|
||||
loadingIcon ??= App.LoadIconFromResource("Resources/Loading.ico");
|
||||
notifyIcon.Icon = loadingIcon.Handle;
|
||||
}
|
||||
|
||||
public void LoadingStop()
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
xmlns:u="clr-namespace:SystemTrayMenu.Utilities"
|
||||
x:Class="SystemTrayMenu.UserInterface.HowToOpenSettingsWindow"
|
||||
mc:Ignorable="d" Title="{u:Translate 'Hint'}" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" WindowStyle="SingleBorderWindow" ShowInTaskbar="True" ResizeMode="NoResize">
|
||||
|
||||
<Window.Resources>
|
||||
<BitmapImage x:Key="HowToOpenSettingsImage" UriSource="../Resources/HowToOpenSettings.png" />
|
||||
</Window.Resources>
|
||||
|
@ -19,7 +20,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Margin="5" MaxWidth="{Binding ElementName=image, Path=ActualWidth}" x:Name="label" TextWrapping="Wrap" Text="{u:Translate 'The settings menu can also be opened by right-clicking the icon in the system tray at the bottom right, in case you can no longer open it via the menu.'}" />
|
||||
<TextBlock Grid.Row="0" Margin="5" MinWidth="200" MaxWidth="{Binding ElementName=image, Path=ActualWidth}" x:Name="label" TextWrapping="Wrap" Text="{u:Translate 'The settings menu can also be opened by right-clicking the icon in the system tray at the bottom right, in case you can no longer open it via the menu.'}" />
|
||||
<Image Grid.Row="1" Margin="10" x:Name="image" Source="{StaticResource HowToOpenSettingsImage}" Stretch="None"/>
|
||||
<CheckBox Grid.Row="2" Margin="5" x:Name="checkBoxDontShowThisHintAgain" Content="???" />
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
namespace SystemTrayMenu.UserInterface
|
||||
{
|
||||
using System.Windows;
|
||||
using SystemTrayMenu.Resources;
|
||||
using SystemTrayMenu.Utilities;
|
||||
|
||||
/// <summary>
|
||||
|
@ -19,8 +18,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
InitializeComponent();
|
||||
|
||||
Icon = StaticResources.ApplicationImgSrc;
|
||||
|
||||
// TODO: Find a way to escape ' within inline single quotes markup string in XAML
|
||||
checkBoxDontShowThisHintAgain.Content = Translator.GetText("Don't show this hint again.");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:stm="clr-namespace:SystemTrayMenu"
|
||||
xmlns:u="clr-namespace:SystemTrayMenu.Utilities"
|
||||
xmlns:local="clr-namespace:SystemTrayMenu.UserInterface"
|
||||
x:Class="SystemTrayMenu.UserInterface.Menu"
|
||||
mc:Ignorable="d" ResizeMode="NoResize" WindowStyle="None" Topmost="True" Background="Transparent" AllowsTransparency="True" SizeToContent="WidthAndHeight" ShowInTaskbar="False" SnapsToDevicePixels="True" UseLayoutRounding="True"
|
||||
|
@ -135,7 +136,7 @@
|
|||
</Setter>
|
||||
</Style>
|
||||
</DockPanel.Resources>
|
||||
<Label x:Name="labelStatus" Content="0 items" Padding="0" DockPanel.Dock="Left" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,10,0" Foreground="{x:Static stm:MenuDefines.ColorIcons}"/>
|
||||
<Label x:Name="labelStatus" Content="{u:Translate 'loading'}" Padding="0" DockPanel.Dock="Left" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,10,0" Foreground="{x:Static stm:MenuDefines.ColorIcons}"/>
|
||||
|
||||
<Image x:Name="pictureBoxLoading" Width="18" Height="18" DockPanel.Dock="Right"
|
||||
HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5" d:Visibility="Visible" Visibility="Collapsed">
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
if (ParentMenu == null)
|
||||
{
|
||||
// Should never happen as each parent menu must have a valid entry which's owner is set
|
||||
throw new ArgumentNullException(new (nameof(ParentMenu)));
|
||||
throw new ArgumentNullException(new (nameof(ParentMenu)));
|
||||
}
|
||||
|
||||
Level = RowDataParent.Level + 1;
|
||||
|
@ -108,11 +108,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
buttonOpenFolder.Visibility = Visibility.Collapsed;
|
||||
buttonSettings.Visibility = Visibility.Collapsed;
|
||||
buttonRestart.Visibility = Visibility.Collapsed;
|
||||
|
||||
labelStatus.Content = Translator.GetText("loading");
|
||||
|
||||
// Todo: use embedded resources that we can assign image in XAML already
|
||||
pictureBoxLoading.Source = SystemTrayMenu.Resources.StaticResources.LoadingImgSrc;
|
||||
pictureBoxLoading.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
using Microsoft.Win32;
|
||||
using SystemTrayMenu.Helpers;
|
||||
using SystemTrayMenu.Properties;
|
||||
using SystemTrayMenu.Resources;
|
||||
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using Windows.ApplicationModel;
|
||||
|
@ -34,8 +33,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
InitializeComponent();
|
||||
|
||||
Icon = StaticResources.ApplicationImgSrc;
|
||||
|
||||
PreviewKeyDown += HandlePreviewKeyDown;
|
||||
|
||||
Translate();
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
x:Class="SystemTrayMenu.UserInterface.TaskbarLogo"
|
||||
mc:Ignorable="d" WindowStyle="None" ResizeMode="NoResize" Width="38" Height="38" Topmost="True" Background="Transparent" AllowsTransparency="True">
|
||||
<Image x:Name="ImagePictureBox" Width="32" Height="32" Margin="3"/>
|
||||
<Image Width="32" Height="32" Margin="3" Source="{StaticResource ApplicationImage}"/>
|
||||
</Window>
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// Copyright (c) 2022-2022 Peter Kirmeier
|
||||
// Copyright (c) 2022-2023 Peter Kirmeier
|
||||
|
||||
namespace SystemTrayMenu.UserInterface
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SystemTrayMenu.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Logic of Taskbar window.
|
||||
|
@ -24,13 +21,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
Assembly myassembly = Assembly.GetExecutingAssembly();
|
||||
string myname = myassembly.GetName().Name ?? string.Empty;
|
||||
|
||||
ImagePictureBox.Source = StaticResources.ApplicationImgSrc;
|
||||
Icon = Imaging.CreateBitmapSourceFromHIcon(
|
||||
Config.GetAppIcon().Handle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
|
||||
Title = myname;
|
||||
|
||||
Closed += (_, _) => Application.Current.Shutdown();
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2022-2022 Peter Kirmeier -->
|
||||
<!-- Copyright (c) 2022-2023 Peter Kirmeier -->
|
||||
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:u="clr-namespace:SystemTrayMenu.Utilities"
|
||||
xmlns:local="clr-namespace:SystemTrayMenu.UserInterface"
|
||||
x:Class="SystemTrayMenu.UserInterface.UpdateWindow"
|
||||
mc:Ignorable="d" Title="{u:Translate 'New version available!'}" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" MinWidth="600" MinHeight="400" WindowStyle="ToolWindow" ShowInTaskbar="False">
|
||||
<Grid>
|
||||
|
|
|
@ -6,12 +6,8 @@
|
|||
|
||||
namespace SystemTrayMenu.UserInterface
|
||||
{
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SystemTrayMenu.Helpers.Updater;
|
||||
using SystemTrayMenu.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// Logic of Update window.
|
||||
|
@ -22,8 +18,6 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
InitializeComponent();
|
||||
|
||||
Icon = StaticResources.ApplicationImgSrc;
|
||||
|
||||
label.Content = ((string)label.Content) + " " + GitHubUpdate.LatestVersionName;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,14 @@ namespace SystemTrayMenu.Utilities
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SystemTrayMenu.DllImports;
|
||||
using SystemTrayMenu.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides static methods to read system icons for folders and files.
|
||||
|
@ -23,12 +25,7 @@ namespace SystemTrayMenu.Utilities
|
|||
{
|
||||
private static readonly ConcurrentDictionary<string, BitmapSource> IconDictPersistent = new();
|
||||
private static readonly ConcurrentDictionary<string, BitmapSource> IconDictCache = new();
|
||||
|
||||
internal enum IconSize
|
||||
{
|
||||
Large = 0, // 32x32 pixels
|
||||
Small = 1, // 16x16 pixels
|
||||
}
|
||||
private static readonly BitmapSource? OverlayImage = (BitmapSource?)Application.Current.Resources["LinkArrowIconImage"];
|
||||
|
||||
// see https://github.com/Hofknecht/SystemTrayMenu/issues/209.
|
||||
internal static bool IsPreloading { get; set; } = true;
|
||||
|
@ -52,7 +49,6 @@ namespace SystemTrayMenu.Utilities
|
|||
Action<BitmapSource?> onIconLoaded)
|
||||
{
|
||||
bool cacheHit;
|
||||
BitmapSource? icon;
|
||||
string key;
|
||||
string extension = Path.GetExtension(path);
|
||||
if (IsExtensionWithSameIcon(extension))
|
||||
|
@ -64,7 +60,7 @@ namespace SystemTrayMenu.Utilities
|
|||
key = path;
|
||||
}
|
||||
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out BitmapSource? icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
{
|
||||
cacheHit = false;
|
||||
|
@ -97,9 +93,8 @@ namespace SystemTrayMenu.Utilities
|
|||
Action<BitmapSource?> onIconLoaded)
|
||||
{
|
||||
bool cacheHit;
|
||||
BitmapSource? icon;
|
||||
string key = path;
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) &&
|
||||
if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out BitmapSource? icon) &&
|
||||
!DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon))
|
||||
{
|
||||
cacheHit = false;
|
||||
|
@ -134,83 +129,74 @@ namespace SystemTrayMenu.Utilities
|
|||
return cacheHit;
|
||||
}
|
||||
|
||||
internal static Icon? GetIconAsIcon(string path, string resolvedPath, bool linkOverlay, bool isFolder, IconSize? forceSize = null)
|
||||
internal static Icon? GetRootFolderIcon(string path)
|
||||
{
|
||||
IconSize size;
|
||||
if (forceSize.HasValue)
|
||||
{
|
||||
size = forceSize.Value;
|
||||
}
|
||||
else if (Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f)
|
||||
{
|
||||
// IconSize.Large returns another folder icon than windows explorer
|
||||
size = IconSize.Large;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = IconSize.Small;
|
||||
}
|
||||
NativeMethods.SHFILEINFO shFileInfo = default;
|
||||
bool linkOverlay = false;
|
||||
bool largeIcon = false;
|
||||
uint flags = GetFlags(linkOverlay, largeIcon);
|
||||
uint attribute = NativeMethods.FileAttributeDirectory;
|
||||
IntPtr imageList = NativeMethods.Shell32SHGetFileInfo(path, attribute, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), flags);
|
||||
return GetIcon(path, linkOverlay, shFileInfo, imageList);
|
||||
}
|
||||
|
||||
internal static BitmapSource? TryGetIconAsBitmapSource(string path, string resolvedPath, bool linkOverlay, bool isFolder)
|
||||
{
|
||||
BitmapSource? result = null;
|
||||
Icon? icon;
|
||||
if (Path.GetExtension(path).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
|
||||
if (!isFolder && Path.GetExtension(path).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
icon = Icon.ExtractAssociatedIcon(path);
|
||||
if (icon != null)
|
||||
{
|
||||
result = CreateBitmapSourceFromIcon(icon);
|
||||
icon.Dispose();
|
||||
}
|
||||
}
|
||||
else if (File.Exists(resolvedPath) &&
|
||||
else if (!isFolder && File.Exists(resolvedPath) &&
|
||||
Path.GetExtension(resolvedPath).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
icon = Icon.ExtractAssociatedIcon(resolvedPath);
|
||||
if (linkOverlay && icon != null)
|
||||
if (icon != null)
|
||||
{
|
||||
icon = AddIconOverlay(icon, Properties.Resources.LinkArrow);
|
||||
result = CreateBitmapSourceFromIcon(icon);
|
||||
icon.Dispose();
|
||||
|
||||
if (linkOverlay && OverlayImage != null)
|
||||
{
|
||||
result = ImagingHelper.CreateIconWithOverlay(result, OverlayImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NativeMethods.SHFILEINFO shFileInfo = default;
|
||||
uint flags = GetFlags(linkOverlay, size);
|
||||
bool largeIcon = // Note: large returns another folder icon than windows explorer
|
||||
Scaling.Factor >= 1.25f ||
|
||||
Scaling.FactorByDpi >= 1.25f ||
|
||||
Properties.Settings.Default.IconSizeInPercent / 100f >= 1.25f;
|
||||
uint flags = GetFlags(linkOverlay, largeIcon);
|
||||
uint attribute = isFolder ? NativeMethods.FileAttributeDirectory : NativeMethods.FileAttributeNormal;
|
||||
IntPtr imageList = NativeMethods.Shell32SHGetFileInfo(path, attribute, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), flags);
|
||||
icon = GetIcon(path, linkOverlay, shFileInfo, imageList);
|
||||
if (icon != null)
|
||||
{
|
||||
result = CreateBitmapSourceFromIcon(icon);
|
||||
icon.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BitmapSource GetIconAsBitmapSource(string path, string resolvedPath, bool linkOverlay, bool isFolder)
|
||||
{
|
||||
Icon? icon = GetIconAsIcon(path, resolvedPath, linkOverlay, isFolder, null);
|
||||
|
||||
BitmapSource bitmapSource;
|
||||
if (icon != null)
|
||||
{
|
||||
bitmapSource = icon.ToBitmapSource();
|
||||
icon.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmapSource = Properties.Resources.NotFound.ToBitmapSource();
|
||||
}
|
||||
|
||||
BitmapSource? bitmapSource = TryGetIconAsBitmapSource(path, resolvedPath, linkOverlay, isFolder);
|
||||
bitmapSource ??= (BitmapSource)Application.Current.Resources["NotFoundIconImage"];
|
||||
bitmapSource.Freeze(); // Make it accessible for any thread
|
||||
return bitmapSource;
|
||||
}
|
||||
|
||||
private static Icon AddIconOverlay(Icon originalIcon, Icon overlay)
|
||||
{
|
||||
using Bitmap target = new(originalIcon.Width, originalIcon.Height, PixelFormat.Format32bppArgb);
|
||||
using Graphics graphics = Graphics.FromImage(target);
|
||||
graphics.DrawIcon(originalIcon, 0, 0);
|
||||
graphics.DrawIcon(overlay, new(0, 0, originalIcon.Width + 2, originalIcon.Height + 2));
|
||||
target.MakeTransparent(target.GetPixel(1, 1));
|
||||
IntPtr hIcon = target.GetHicon();
|
||||
Icon icon = (Icon)Icon.FromHandle(hIcon).Clone();
|
||||
NativeMethods.User32DestroyIcon(hIcon);
|
||||
return icon;
|
||||
}
|
||||
|
||||
private static ConcurrentDictionary<string, BitmapSource> DictIconCache(bool checkPersistentFirst)
|
||||
=> checkPersistentFirst ? IconDictPersistent : IconDictCache;
|
||||
|
||||
|
@ -226,7 +212,7 @@ namespace SystemTrayMenu.Utilities
|
|||
return isExtensionWithSameIcon;
|
||||
}
|
||||
|
||||
private static uint GetFlags(bool linkOverlay, IconSize size)
|
||||
private static uint GetFlags(bool linkOverlay, bool largeIcon)
|
||||
{
|
||||
uint flags = NativeMethods.ShgfiIcon | NativeMethods.ShgfiSYSICONINDEX;
|
||||
if (linkOverlay)
|
||||
|
@ -234,7 +220,7 @@ namespace SystemTrayMenu.Utilities
|
|||
flags += NativeMethods.ShgfiLINKOVERLAY;
|
||||
}
|
||||
|
||||
if (size == IconSize.Small)
|
||||
if (!largeIcon)
|
||||
{
|
||||
flags += NativeMethods.ShgfiSMALLICON;
|
||||
}
|
||||
|
@ -279,13 +265,22 @@ namespace SystemTrayMenu.Utilities
|
|||
|
||||
if (!linkOverlay)
|
||||
{
|
||||
NativeMethods.User32DestroyIcon(hIcon);
|
||||
_ = NativeMethods.User32DestroyIcon(hIcon);
|
||||
}
|
||||
|
||||
NativeMethods.User32DestroyIcon(shFileInfo.hIcon);
|
||||
_ = NativeMethods.User32DestroyIcon(shFileInfo.hIcon);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private static BitmapSource CreateBitmapSourceFromIcon(Icon icon)
|
||||
{
|
||||
return (BitmapSource)new IconToImageSourceConverter().Convert(
|
||||
icon,
|
||||
typeof(BitmapSource),
|
||||
null!,
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,10 @@
|
|||
namespace SystemTrayMenu.Utilities
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
using Icon = System.Drawing.Icon;
|
||||
|
||||
internal static class WPFExtensions
|
||||
{
|
||||
|
@ -74,15 +71,5 @@ namespace SystemTrayMenu.Utilities
|
|||
{
|
||||
return child == null ? new() : child.TransformToAncestor(parent).Transform(new ());
|
||||
}
|
||||
|
||||
// TODO: Find and remove any unnecessary convertions
|
||||
internal static BitmapSource ToBitmapSource(this Icon icon)
|
||||
{
|
||||
return (BitmapSource)new IconToImageSourceConverter().Convert(
|
||||
icon,
|
||||
typeof(BitmapSource),
|
||||
null!,
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue