Replaced some Icon objects with ImageSource

Merged ColumnText and Text of RowData
This commit is contained in:
Peter Kirmeier 2023-05-19 20:43:19 +02:00
parent 045fb9dd7e
commit d74e61b999
8 changed files with 173 additions and 151 deletions

View file

@ -11,10 +11,11 @@ namespace SystemTrayMenu.DataClasses
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SystemTrayMenu.Helpers;
using SystemTrayMenu.Properties;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
using Icon = System.Drawing.Icon;
internal class RowData : INotifyPropertyChanged
{
@ -45,7 +46,7 @@ namespace SystemTrayMenu.DataClasses
{
ResolvedPath = FileLnk.GetResolvedFileName(Path, out bool isLinkToFolder);
ShowOverlay = Settings.Default.ShowLinkOverlay;
Text = System.IO.Path.GetFileNameWithoutExtension(Path);
ColumnText = System.IO.Path.GetFileNameWithoutExtension(Path);
if (Settings.Default.ResolveLinksToFolders)
{
IsPointingToFolder |= isLinkToFolder || FileLnk.IsNetworkRoot(ResolvedPath);
@ -57,21 +58,21 @@ namespace SystemTrayMenu.DataClasses
if (string.IsNullOrEmpty(FileInfo.Name))
{
int nameBegin = FileInfo.FullName.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
Text = FileInfo.FullName[nameBegin..];
ColumnText = FileInfo.FullName[nameBegin..];
}
else if (FileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase) ||
FileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
{
ShowOverlay = Settings.Default.ShowLinkOverlay;
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
ColumnText = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
}
else if (!isFolder && Config.IsHideFileExtension())
{
Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
ColumnText = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name);
}
else
{
Text = FileInfo.Name;
ColumnText = FileInfo.Name;
}
}
@ -184,8 +185,6 @@ namespace SystemTrayMenu.DataClasses
internal bool ShowOverlay { get; }
internal string? Text { get; }
internal Menu? Owner { get; set; }
internal Menu? SubMenu { get; set; }
@ -340,22 +339,20 @@ namespace SystemTrayMenu.DataClasses
}
}
private void UpdateFinalIcon(Icon? icon)
private void UpdateFinalIcon(BitmapSource? icon)
{
if (icon == null)
{
icon = Resources.NotFound;
icon = Resources.NotFound.ToBitmapSource();
}
else if (HiddenEntry)
{
icon = IconReader.AddIconOverlay(icon, Resources.White50Percentage);
icon = ImagingHelper.CreateIconWithOverlay(icon, Resources.White50Percentage.ToBitmapSource());
icon?.Freeze();
}
ImageSource? imgsrc = icon?.ToImageSource();
imgsrc?.Freeze();
IconLoading = false;
ColumnIcon = imgsrc;
ColumnIcon = icon;
}
}
}

View file

@ -93,7 +93,7 @@ namespace SystemTrayMenu.Helpers
if (Properties.Settings.Default.SortByTypeAndNameWindowsExplorerSort)
{
rowDatas = rowDatas.OrderByDescending(x => x.IsFolder)
.ThenBy(x => x.Text, new WindowsExplorerSort()).ToList();
.ThenBy(x => x.ColumnText, new WindowsExplorerSort()).ToList();
}
else if (Properties.Settings.Default.SortByTypeAndDate)
{
@ -102,11 +102,11 @@ namespace SystemTrayMenu.Helpers
}
else if (Properties.Settings.Default.SortByFileExtensionAndName)
{
rowDatas = rowDatas.OrderBy(x => x.FileExtension).ThenBy(x => x.Text).ToList();
rowDatas = rowDatas.OrderBy(x => x.FileExtension).ThenBy(x => x.ColumnText).ToList();
}
else if (Properties.Settings.Default.SortByName)
{
rowDatas = rowDatas.OrderBy(x => x.Text).ToList();
rowDatas = rowDatas.OrderBy(x => x.ColumnText).ToList();
}
else if (Properties.Settings.Default.SortByDate)
{

View file

@ -1,116 +1,132 @@
// <copyright file="ImagingHelper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helpers
{
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
/// <summary>
/// Provides helper methods for imaging.
/// </summary>
public static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="output">The output stream.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
public static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false)
{
Bitmap inputBitmap = (Bitmap)Image.FromStream(input);
if (inputBitmap != null)
{
int width, height;
if (preserveAspectRatio)
{
width = size;
height = inputBitmap.Height / inputBitmap.Width * size;
}
else
{
width = height = size;
}
Bitmap newBitmap = new(inputBitmap, new Size(width, height));
if (newBitmap != null)
{
// save the resized png into a memory stream for future use
using MemoryStream memoryStream = new();
newBitmap.Save(memoryStream, ImageFormat.Png);
BinaryWriter iconWriter = new(output);
if (output != null && iconWriter != null)
{
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write(6 + 16);
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
return true;
}
}
return false;
}
return false;
}
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
public static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false)
{
using FileStream inputStream = new(inputPath, FileMode.Open);
using FileStream outputStream = new(outputPath, FileMode.OpenOrCreate);
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
}
}
}
// <copyright file="ImagingHelper.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.Helpers
{
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
/// <summary>
/// Provides helper methods for imaging.
/// </summary>
internal static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="input">The input stream.</param>
/// <param name="output">The output stream.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
internal static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false)
{
Bitmap inputBitmap = (Bitmap)Image.FromStream(input);
if (inputBitmap != null)
{
int width, height;
if (preserveAspectRatio)
{
width = size;
height = inputBitmap.Height / inputBitmap.Width * size;
}
else
{
width = height = size;
}
Bitmap newBitmap = new(inputBitmap, new Size(width, height));
if (newBitmap != null)
{
// save the resized png into a memory stream for future use
using MemoryStream memoryStream = new();
newBitmap.Save(memoryStream, ImageFormat.Png);
BinaryWriter iconWriter = new(output);
if (output != null && iconWriter != null)
{
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write(6 + 16);
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
return true;
}
}
return false;
}
return false;
}
/// <summary>
/// Converts a PNG image to a icon (ico).
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="size">The size (16x16 px by default).</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio.</param>
/// <returns>Wether or not the icon was succesfully generated.</returns>
internal static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false)
{
using FileStream inputStream = new(inputPath, FileMode.Open);
using FileStream outputStream = new(outputPath, FileMode.OpenOrCreate);
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
}
internal static RenderTargetBitmap CreateIconWithOverlay(BitmapSource originalBitmap, BitmapSource overlayBitmap)
{
DrawingVisual dVisual = new DrawingVisual();
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));
}
RenderTargetBitmap targetBitmap = new (originalBitmap.PixelWidth, originalBitmap.PixelHeight, originalBitmap.DpiX, originalBitmap.DpiY, PixelFormats.Default);
targetBitmap.Render(dVisual);
return targetBitmap;
}
}
}

View file

@ -26,7 +26,7 @@ namespace SystemTrayMenu.Resources
{
if (loadingImgSrc == null)
{
loadingImgSrc = Properties.Resources.Loading.ToImageSource();
loadingImgSrc = Properties.Resources.Loading.ToBitmapSource();
loadingImgSrc.Freeze(); // Make it accessible by any thread
}
}

View file

@ -13,7 +13,6 @@ namespace SystemTrayMenu.UserInterface
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using SystemTrayMenu.Business;
using SystemTrayMenu.DataClasses;
using SystemTrayMenu.DllImports;
@ -438,7 +437,6 @@ namespace SystemTrayMenu.UserInterface
rowData.RowIndex = index;
rowData.Owner = this;
rowData.ColumnText = rowData.Text;
rowData.SortIndex = rowData.IsAdditionalItem && Settings.Default.ShowOnlyAsSearchResult ? 99 : 0;
}

View file

@ -13,6 +13,7 @@ namespace SystemTrayMenu.Utilities
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Media.Imaging;
using SystemTrayMenu.DllImports;
/// <summary>
@ -59,7 +60,7 @@ namespace SystemTrayMenu.Utilities
string resolvedPath,
bool linkOverlay,
bool checkPersistentFirst,
Action<Icon?> onIconLoaded)
Action<BitmapSource?> onIconLoaded)
{
bool cacheHit;
Icon? icon;
@ -83,7 +84,9 @@ namespace SystemTrayMenu.Utilities
void UpdateIconInBackground()
{
Icon? icon = DictIconCache(checkPersistentFirst).GetOrAdd(key, FactoryIconFile);
onIconLoaded(icon);
BitmapSource? bitmap = icon?.ToBitmapSource();
bitmap?.Freeze();
onIconLoaded(bitmap);
}
Icon? FactoryIconFile(string keyExtension)
@ -94,7 +97,9 @@ namespace SystemTrayMenu.Utilities
else
{
cacheHit = true;
onIconLoaded(icon);
BitmapSource? bitmap = icon?.ToBitmapSource();
bitmap?.Freeze();
onIconLoaded(bitmap);
}
return cacheHit;
@ -104,7 +109,7 @@ namespace SystemTrayMenu.Utilities
string path,
bool linkOverlay,
bool checkPersistentFirst,
Action<Icon?> onIconLoaded)
Action<BitmapSource?> onIconLoaded)
{
bool cacheHit;
Icon? icon;
@ -118,7 +123,9 @@ namespace SystemTrayMenu.Utilities
{
cacheHit = true;
icon = DictIconCache(checkPersistentFirst).GetOrAdd(key, FactoryIconFolder);
onIconLoaded(icon);
BitmapSource? bitmap = icon?.ToBitmapSource();
bitmap?.Freeze();
onIconLoaded(bitmap);
}
else
{
@ -126,7 +133,9 @@ namespace SystemTrayMenu.Utilities
void UpdateIconInBackground()
{
Icon? icon = DictIconCache(checkPersistentFirst).GetOrAdd(key, FactoryIconFolder);
onIconLoaded(icon);
BitmapSource? bitmap = icon?.ToBitmapSource();
bitmap?.Freeze();
onIconLoaded(bitmap);
}
}
@ -138,7 +147,9 @@ namespace SystemTrayMenu.Utilities
else
{
cacheHit = true;
onIconLoaded(icon);
BitmapSource? bitmap = icon?.ToBitmapSource();
bitmap?.Freeze();
onIconLoaded(bitmap);
}
return cacheHit;

View file

@ -17,6 +17,7 @@ namespace SystemTrayMenu.Utilities
using System.Windows.Media.Imaging;
[ValueConversion(typeof(Icon), typeof(ImageSource))]
[ValueConversion(typeof(Icon), typeof(BitmapSource))]
public class IconToImageSourceConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

View file

@ -2,19 +2,18 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
//
// Copyright (c) 2022-2022 Peter Kirmeier
// Copyright (c) 2022-2023 Peter Kirmeier
namespace SystemTrayMenu.Utilities
{
using System;
using System.Drawing;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
using Icon = System.Drawing.Icon;
internal static class WPFExtensions
{
@ -77,11 +76,11 @@ namespace SystemTrayMenu.Utilities
}
// TODO: Find and remove any unnecessary convertions
internal static ImageSource ToImageSource(this Icon icon)
internal static BitmapSource ToBitmapSource(this Icon icon)
{
return (ImageSource)new IconToImageSourceConverter().Convert(
return (BitmapSource)new IconToImageSourceConverter().Convert(
icon,
typeof(ImageSource),
typeof(BitmapSource),
null!,
CultureInfo.InvariantCulture);
}