2023-02-28 15:57:27 -07:00

107 lines
3.7 KiB
C#

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace WindowsConfigApp
{
internal static partial class FolderIcon
{
// https://stackoverflow.com/a/21389253
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
return ms.ToArray();
}
public static void DeleteIcon(this DirectoryInfo directoryInfo) => DeleteIcon(directoryInfo.FullName);
public static void DeleteIcon(string dir)
{
string[] array = new string[3] { "desktop.ini", "Icon.ico", ".hidden" };
foreach (string path in array)
{
string text = Path.Combine(dir, path);
if (File.Exists(text))
{
File.SetAttributes(text, File.GetAttributes(text) | FileAttributes.Normal);
new FileInfo(text).IsReadOnly = false;
File.Delete(text);
}
}
refresh();
}
// https://github.com/dimuththarindu/FIC-Folder-Icon-Changer/blob/master/project/FIC/Classes/IconCustomizer.cs
public static void SetIcon(this DirectoryInfo directoryInfo, byte[] icon, string folderType)
=> SetIcon(directoryInfo.FullName, icon, folderType);
public static void SetIcon(string dir, byte[] icon, string folderType)
{
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);
//copying Icon file //overwriting
File.WriteAllBytes(Icon_ico, icon);
//writing configuration file
string[] desktopLines = { "[.ShellClassInfo]", "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);
//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();
}
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);
}
}