diff --git a/Source/LibationUiBase/IcoEncoder.cs b/Source/LibationUiBase/IcoEncoder.cs new file mode 100644 index 00000000..d6546f7f --- /dev/null +++ b/Source/LibationUiBase/IcoEncoder.cs @@ -0,0 +1,52 @@ +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Formats; + +namespace LibationUiBase +{ + public class IcoEncoder : IImageEncoder + { + public bool SkipMetadata { get; init; } = true; + + public void Encode(Image image, Stream stream) where TPixel : unmanaged, IPixel + { + // https://stackoverflow.com/a/21389253 + + using var ms = new MemoryStream(); + //Knowing the image size ahead of time removes the + //requirement of the output stream to support seeking. + image.SaveAsPng(ms); + + //Disposing of the BinaryWriter disposes the soutput stream. Let the caller clean up. + var bw = new BinaryWriter(stream); + + // Header + bw.Write((short)0); // 0-1 : reserved + bw.Write((short)1); // 2-3 : 1=ico, 2=cur + bw.Write((short)1); // 4-5 : number of images + + // Image directory + var w = image.Width; + if (w >= 256) w = 0; + bw.Write((byte)w); // 0 : width of image + var h = image.Height; + if (h >= 256) h = 0; + bw.Write((byte)h); // 1 : height of image + bw.Write((byte)0); // 2 : number of colors in palette + bw.Write((byte)0); // 3 : reserved + bw.Write((short)0); // 4 : number of color planes + bw.Write((short)0); // 6 : bits per pixel + bw.Write((int)ms.Position); // 8 : image size + bw.Write((int)stream.Position + 4); // 12: offset of image data + ms.Position = 0; + ms.CopyTo(stream); // Image data + } + + public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel + => throw new NotImplementedException(); + } +} diff --git a/Source/LoadByOS/WindowsConfigApp/FolderIcon.cs b/Source/LoadByOS/WindowsConfigApp/FolderIcon.cs index 8af33718..2b4184dc 100644 --- a/Source/LoadByOS/WindowsConfigApp/FolderIcon.cs +++ b/Source/LoadByOS/WindowsConfigApp/FolderIcon.cs @@ -1,45 +1,17 @@ -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Formats.Png; +using LibationUiBase; +using SixLabors.ImageSharp; using System; using System.IO; -using System.Runtime.InteropServices; namespace WindowsConfigApp -{ +{ internal static partial class FolderIcon { - // https://stackoverflow.com/a/21389253 + static readonly IcoEncoder IcoEncoder = new(); public static byte[] ToIcon(this Image img) { - using var ms = new MemoryStream(); - using var bw = new BinaryWriter(ms); - // Header - bw.Write((short)0); // 0-1 : reserved - bw.Write((short)1); // 2-3 : 1=ico, 2=cur - bw.Write((short)1); // 4-5 : number of images - // Image directory - var w = img.Width; - if (w >= 256) w = 0; - bw.Write((byte)w); // 0 : width of image - var h = img.Height; - if (h >= 256) h = 0; - bw.Write((byte)h); // 1 : height of image - bw.Write((byte)0); // 2 : number of colors in palette - bw.Write((byte)0); // 3 : reserved - bw.Write((short)0); // 4 : number of color planes - bw.Write((short)0); // 6 : bits per pixel - var sizeHere = ms.Position; - bw.Write((int)0); // 8 : image size - var start = (int)ms.Position + 4; - bw.Write(start); // 12: offset of image data - // Image data - img.Save(ms, new PngEncoder()); - var imageSize = (int)ms.Position - start; - ms.Seek(sizeHere, SeekOrigin.Begin); - bw.Write(imageSize); - ms.Seek(0, SeekOrigin.Begin); - - // And load it + using var ms = new MemoryStream(); + img.Save(ms, IcoEncoder); return ms.ToArray(); } @@ -57,8 +29,6 @@ namespace WindowsConfigApp File.Delete(text); } } - - refresh(); } // https://github.com/dimuththarindu/FIC-Folder-Icon-Changer/blob/master/project/FIC/Classes/IconCustomizer.cs @@ -70,7 +40,6 @@ namespace WindowsConfigApp { var desktop_ini = Path.Combine(dir, "desktop.ini"); var Icon_ico = Path.Combine(dir, "Icon.ico"); - var hidden = Path.Combine(dir, ".hidden"); //deleting existing files DeleteIcon(dir); @@ -79,28 +48,14 @@ namespace WindowsConfigApp File.WriteAllBytes(Icon_ico, icon); //writing configuration file - string[] desktopLines = { "[.ShellClassInfo]", "IconResource=Icon.ico,0", "[ViewState]", "Mode=", "Vid=", $"FolderType={folderType}" }; + string[] desktopLines = { "[.ShellClassInfo]", "ConfirmFileOp=0", "IconResource=Icon.ico,0", "[ViewState]", "Mode=", "Vid=", $"FolderType={folderType}" }; File.WriteAllLines(desktop_ini, desktopLines); - //configure file 2 - string[] hiddenLines = { "desktop.ini", "Icon.ico" }; - File.WriteAllLines(hidden, hiddenLines); + File.SetAttributes(desktop_ini, File.GetAttributes(desktop_ini) | FileAttributes.Hidden | FileAttributes.ReadOnly); + File.SetAttributes(Icon_ico, File.GetAttributes(Icon_ico) | FileAttributes.Hidden | FileAttributes.ReadOnly); - //making system files - File.SetAttributes(desktop_ini, File.GetAttributes(desktop_ini) | FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly); - File.SetAttributes(Icon_ico, File.GetAttributes(Icon_ico) | FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly); - File.SetAttributes(hidden, File.GetAttributes(hidden) | FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly); - - // this strangely completes the process. also hides these 3 hidden system files, even if "show hidden items" is checked - File.SetAttributes(dir, File.GetAttributes(dir) | FileAttributes.ReadOnly); - - refresh(); + //https://learn.microsoft.com/en-us/windows/win32/shell/how-to-customize-folders-with-desktop-ini + File.SetAttributes(dir, File.GetAttributes(dir) | FileAttributes.System); } - - private static void refresh() => SHChangeNotify(0x08000000, 0x0000, 0, 0); //SHCNE_ASSOCCHANGED SHCNF_IDLIST - - - [DllImport("shell32.dll", SetLastError = true)] - private static extern void SHChangeNotify(int wEventId, int uFlags, nint dwItem1, nint dwItem2); } } diff --git a/Source/LoadByOS/WindowsConfigApp/WinInterop.cs b/Source/LoadByOS/WindowsConfigApp/WinInterop.cs index fda076c5..61d5c2ce 100644 --- a/Source/LoadByOS/WindowsConfigApp/WinInterop.cs +++ b/Source/LoadByOS/WindowsConfigApp/WinInterop.cs @@ -14,19 +14,9 @@ namespace WindowsConfigApp public void SetFolderIcon(string image, string directory) { - string iconPath = null; - - try - { - var icon = Image.Load(image).ToIcon(); - new DirectoryInfo(directory)?.SetIcon(icon, "Music"); - } - finally - { - if (File.Exists(iconPath)) - File.Delete(iconPath); - } - } + var icon = Image.Load(image).ToIcon(); + new DirectoryInfo(directory)?.SetIcon(icon, "Music"); + } public void DeleteFolderIcon(string directory) => new DirectoryInfo(directory)?.DeleteIcon();