Initial TaskbarLauncher release baseline
This commit is contained in:
127
Services/IconService.cs
Normal file
127
Services/IconService.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using TaskbarLauncher.Models;
|
||||
|
||||
namespace TaskbarLauncher.Services;
|
||||
|
||||
public static class IconService
|
||||
{
|
||||
private const uint ShgfiIcon = 0x000000100;
|
||||
private const uint ShgfiLargeIcon = 0x000000000;
|
||||
private const uint ShgfiSmallIcon = 0x000000001;
|
||||
private const uint ShgfiUseFileAttributes = 0x000000010;
|
||||
private const uint FileAttributeDirectory = 0x00000010;
|
||||
private const uint FileAttributeNormal = 0x00000080;
|
||||
|
||||
public static ImageSource? GetIcon(LauncherItem item, bool large)
|
||||
{
|
||||
ImageSource? explicitIcon = TryLoadIcon(item.IconPath, large, useAttributes: false);
|
||||
if (explicitIcon is not null)
|
||||
{
|
||||
return explicitIcon;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(item.Target))
|
||||
{
|
||||
ImageSource? targetIcon = TryLoadIcon(item.Target, large, useAttributes: false);
|
||||
if (targetIcon is not null)
|
||||
{
|
||||
return targetIcon;
|
||||
}
|
||||
}
|
||||
|
||||
return item.Type switch
|
||||
{
|
||||
LauncherItemType.Folder => TryLoadIcon("folder", large, useAttributes: true, isDirectory: true),
|
||||
LauncherItemType.Website => TryLoadIcon(".url", large, useAttributes: true),
|
||||
LauncherItemType.File => TryLoadIcon(".txt", large, useAttributes: true),
|
||||
LauncherItemType.Menu => TryLoadIcon("folder", large, useAttributes: true, isDirectory: true),
|
||||
_ => TryLoadIcon(".exe", large, useAttributes: true)
|
||||
};
|
||||
}
|
||||
|
||||
private static ImageSource? TryLoadIcon(string? path, bool large, bool useAttributes, bool isDirectory = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
uint flags = ShgfiIcon | (large ? ShgfiLargeIcon : ShgfiSmallIcon);
|
||||
uint attributes = isDirectory ? FileAttributeDirectory : FileAttributeNormal;
|
||||
if (useAttributes)
|
||||
{
|
||||
flags |= ShgfiUseFileAttributes;
|
||||
}
|
||||
|
||||
IntPtr result = SHGetFileInfo(path, attributes, out ShFileInfo fileInfo, (uint)Marshal.SizeOf<ShFileInfo>(), flags);
|
||||
if (result == IntPtr.Zero || fileInfo.IconHandle == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageSource image = Imaging.CreateBitmapSourceFromHIcon(
|
||||
fileInfo.IconHandle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
|
||||
image.Freeze();
|
||||
DestroyIcon(fileInfo.IconHandle);
|
||||
return image;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
using Icon? icon = File.Exists(path) ? Icon.ExtractAssociatedIcon(path) : null;
|
||||
if (icon is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageSource image = Imaging.CreateBitmapSourceFromHIcon(
|
||||
icon.Handle,
|
||||
Int32Rect.Empty,
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
image.Freeze();
|
||||
return image;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern IntPtr SHGetFileInfo(
|
||||
string path,
|
||||
uint fileAttributes,
|
||||
out ShFileInfo fileInfo,
|
||||
uint fileInfoSize,
|
||||
uint flags);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool DestroyIcon(IntPtr icon);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct ShFileInfo
|
||||
{
|
||||
public IntPtr IconHandle;
|
||||
public int IconIndex;
|
||||
public uint Attributes;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string DisplayName;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
|
||||
public string TypeName;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user