fix: 修复任务栏固定和右键菜单图标不显示问题

This commit is contained in:
2026-01-17 16:26:16 +08:00
parent 50955e84c7
commit 74ca8e4d57
4 changed files with 416 additions and 47 deletions

View File

@@ -1,66 +1,115 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace TimerApp
{
public static class IconGenerator
{
public static Icon GenerateClockIcon()
[DllImport("user32.dll", SetLastError = true)]
private static extern bool DestroyIcon(IntPtr hIcon);
public static Icon GenerateClockIcon(int size = 64)
{
int size = 64;
if (size < 16)
size = 16;
using (Bitmap bmp = new Bitmap(size, size))
using (Graphics g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.Transparent);
// 绘制闹钟主体
int margin = 4;
int clockSize = size - margin * 2;
Rectangle rect = new Rectangle(margin, margin, clockSize, clockSize);
DrawClock(g, size);
// 外圈
using (Pen pen = new Pen(Color.White, 4))
{
g.DrawEllipse(pen, rect);
}
// 两个耳朵 (闹钟铃)
using (Brush earBrush = new SolidBrush(Color.White))
{
// 左耳
g.FillPie(earBrush, 0, 0, size/2, size/2, 200, 50);
// 右耳
g.FillPie(earBrush, size/2, 0, size/2, size/2, 290, 50);
}
// 重绘外圈盖住耳朵连接处
using (Brush bgBrush = new SolidBrush(Color.FromArgb(30, 30, 30))) // 深色背景
{
g.FillEllipse(bgBrush, rect);
}
using (Pen pen = new Pen(Color.White, 3))
{
g.DrawEllipse(pen, rect);
}
// 指针
Point center = new Point(size / 2, size / 2);
using (Pen handPen = new Pen(Color.LightGreen, 3))
{
handPen.EndCap = LineCap.Round;
// 时针
g.DrawLine(handPen, center, new Point(center.X + 10, center.Y - 10));
// 分针
g.DrawLine(handPen, center, new Point(center.X, center.Y - 18));
}
// 转换为图标
// 注意GetHicon 需要释放
IntPtr hIcon = bmp.GetHicon();
return Icon.FromHandle(hIcon);
try
{
using Icon icon = Icon.FromHandle(hIcon);
return (Icon)icon.Clone();
}
finally
{
DestroyIcon(hIcon);
}
}
}
public static void WriteClockIco(string filePath, int size = 256)
{
byte[] icoBytes = CreateClockIcoBytes(size);
File.WriteAllBytes(filePath, icoBytes);
}
private static byte[] CreateClockIcoBytes(int size)
{
if (size <= 0)
size = 256;
if (size > 256)
size = 256;
if (size < 16)
size = 16;
byte[] pngBytes;
using (Bitmap bmp = new Bitmap(size, size))
using (Graphics g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.Transparent);
DrawClock(g, size);
using var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Png);
pngBytes = ms.ToArray();
}
using var icoStream = new MemoryStream(6 + 16 + pngBytes.Length);
using (var bw = new BinaryWriter(icoStream, System.Text.Encoding.UTF8, leaveOpen: true))
{
bw.Write((ushort)0);
bw.Write((ushort)1);
bw.Write((ushort)1);
bw.Write((byte)(size == 256 ? 0 : size));
bw.Write((byte)(size == 256 ? 0 : size));
bw.Write((byte)0);
bw.Write((byte)0);
bw.Write((ushort)1);
bw.Write((ushort)32);
bw.Write((uint)pngBytes.Length);
bw.Write((uint)(6 + 16));
}
icoStream.Write(pngBytes, 0, pngBytes.Length);
return icoStream.ToArray();
}
private static void DrawClock(Graphics g, int size)
{
int margin = Math.Max(2, size / 16);
int clockSize = size - margin * 2;
Rectangle rect = new Rectangle(margin, margin, clockSize, clockSize);
using (Brush earBrush = new SolidBrush(Color.White))
{
g.FillPie(earBrush, 0, 0, size / 2, size / 2, 200, 50);
g.FillPie(earBrush, size / 2, 0, size / 2, size / 2, 290, 50);
}
using (Pen pen = new Pen(Color.White, Math.Max(2, size / 16)))
{
g.DrawEllipse(pen, rect);
}
Point center = new Point(size / 2, size / 2);
using (Pen handPen = new Pen(Color.LightGreen, Math.Max(2, size / 22)))
{
handPen.EndCap = LineCap.Round;
g.DrawLine(handPen, center, new Point(center.X + Math.Max(2, size * 10 / 64), center.Y - Math.Max(2, size * 10 / 64)));
g.DrawLine(handPen, center, new Point(center.X, center.Y - Math.Max(3, size * 18 / 64)));
}
}
}