Deleting folders with custom icons no longer triggers system file warning
This commit is contained in:
parent
2b672f86be
commit
02371f2221
52
Source/LibationUiBase/IcoEncoder.cs
Normal file
52
Source/LibationUiBase/IcoEncoder.cs
Normal file
@ -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<TPixel>(Image<TPixel> image, Stream stream) where TPixel : unmanaged, IPixel<TPixel>
|
||||||
|
{
|
||||||
|
// 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<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel<TPixel>
|
||||||
|
=> throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,45 +1,17 @@
|
|||||||
using SixLabors.ImageSharp;
|
using LibationUiBase;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
using SixLabors.ImageSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace WindowsConfigApp
|
namespace WindowsConfigApp
|
||||||
{
|
{
|
||||||
internal static partial class FolderIcon
|
internal static partial class FolderIcon
|
||||||
{
|
{
|
||||||
// https://stackoverflow.com/a/21389253
|
static readonly IcoEncoder IcoEncoder = new();
|
||||||
public static byte[] ToIcon(this Image img)
|
public static byte[] ToIcon(this Image img)
|
||||||
{
|
{
|
||||||
using var ms = new MemoryStream();
|
using var ms = new MemoryStream();
|
||||||
using var bw = new BinaryWriter(ms);
|
img.Save(ms, IcoEncoder);
|
||||||
// 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();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +29,6 @@ namespace WindowsConfigApp
|
|||||||
File.Delete(text);
|
File.Delete(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dimuththarindu/FIC-Folder-Icon-Changer/blob/master/project/FIC/Classes/IconCustomizer.cs
|
// 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 desktop_ini = Path.Combine(dir, "desktop.ini");
|
||||||
var Icon_ico = Path.Combine(dir, "Icon.ico");
|
var Icon_ico = Path.Combine(dir, "Icon.ico");
|
||||||
var hidden = Path.Combine(dir, ".hidden");
|
|
||||||
|
|
||||||
//deleting existing files
|
//deleting existing files
|
||||||
DeleteIcon(dir);
|
DeleteIcon(dir);
|
||||||
@ -79,28 +48,14 @@ namespace WindowsConfigApp
|
|||||||
File.WriteAllBytes(Icon_ico, icon);
|
File.WriteAllBytes(Icon_ico, icon);
|
||||||
|
|
||||||
//writing configuration file
|
//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);
|
File.WriteAllLines(desktop_ini, desktopLines);
|
||||||
|
|
||||||
//configure file 2
|
File.SetAttributes(desktop_ini, File.GetAttributes(desktop_ini) | FileAttributes.Hidden | FileAttributes.ReadOnly);
|
||||||
string[] hiddenLines = { "desktop.ini", "Icon.ico" };
|
File.SetAttributes(Icon_ico, File.GetAttributes(Icon_ico) | FileAttributes.Hidden | FileAttributes.ReadOnly);
|
||||||
File.WriteAllLines(hidden, hiddenLines);
|
|
||||||
|
|
||||||
//making system files
|
//https://learn.microsoft.com/en-us/windows/win32/shell/how-to-customize-folders-with-desktop-ini
|
||||||
File.SetAttributes(desktop_ini, File.GetAttributes(desktop_ini) | FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly);
|
File.SetAttributes(dir, File.GetAttributes(dir) | FileAttributes.System);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,19 +14,9 @@ namespace WindowsConfigApp
|
|||||||
|
|
||||||
public void SetFolderIcon(string image, string directory)
|
public void SetFolderIcon(string image, string directory)
|
||||||
{
|
{
|
||||||
string iconPath = null;
|
var icon = Image.Load(image).ToIcon();
|
||||||
|
new DirectoryInfo(directory)?.SetIcon(icon, "Music");
|
||||||
try
|
}
|
||||||
{
|
|
||||||
var icon = Image.Load(image).ToIcon();
|
|
||||||
new DirectoryInfo(directory)?.SetIcon(icon, "Music");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (File.Exists(iconPath))
|
|
||||||
File.Delete(iconPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteFolderIcon(string directory)
|
public void DeleteFolderIcon(string directory)
|
||||||
=> new DirectoryInfo(directory)?.DeleteIcon();
|
=> new DirectoryInfo(directory)?.DeleteIcon();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user