最直接路径是用Icon构造函数加载图片再保存,但需确保源图尺寸为16×16、32×32、48×48或256×256,且PixelFormat为Format32bppArgb,否则抛ArgumentException;必须用Icon.Save(),禁用Bitmap.Save()改后缀或Icon.FromHandle()。

用 Icon 构造函数加载图片再保存,是最直接的路径
不是所有图片都能直接变 .ico,C# 的 Icon 类只接受特定尺寸和位深的图像。常见错误是传入一张 1920×1080 的 PNG,结果抛出 ArgumentException: Parameter is not valid. —— 这是因为 Icon 构造函数底层调用 GDI+,要求源图必须是矩形、支持 Alpha(如 PNG),且尺寸最好是 16×16、32×32、48×48 或 256×256。
- 先用
Bitmap加载原始图,再按需缩放(别依赖自动缩放) - 确保目标尺寸是标准图标尺寸之一,否则构造
Icon会失败 - 保存时必须用
Icon.Save(),不能用Bitmap.Save()并改后缀——那样只是假.ico,Windows 不认
Icon.FromHandle() 容易误用,慎选
有人看到文档里有 Icon.FromHandle() 就想绕过构造函数限制,但它只适用于已存在的 Windows 图标句柄(比如从资源中提取),对托管 Bitmap 对象无效。直接传 bitmap.GetHicon() 看似可行,但会引发资源泄漏:GDI 句柄没释放,多次调用后可能触发 OutOfMemoryException。
- 除非你明确在操作 Win32 API 或从资源加载,否则别碰
FromHandle -
GetHicon()返回的句柄必须配对调用DestroyIcon(),C# 不自动管理 - 日常转换用
new Icon(bitmap)更安全、语义清晰
多尺寸 ICO 文件得手动拼装,Icon 类不支持自动嵌入
Windows 的 .ico 文件可包含多个尺寸/位深的图像(比如同时含 16×16 和 256×256),但 C# 内置的 Icon 类只能表示单个图像帧。你用 new Icon(bitmap) 创建的实例,无论输入图多大,保存出来都只有一个尺寸。
- 要生成真·多尺寸 ICO,得用第三方库如
Magick.NET或手写 ICO 格式二进制头(不推荐) - 简单场景下,生成 256×256 单尺寸图标已足够适配高分屏,Win10/11 会自动缩放
- 若必须多尺寸,建议用命令行工具
convert(ImageMagick)预处理:magick input.png -define icon:auto-resize="256,128,64,48,32,16" output.ico
Alpha 通道丢失?检查 Bitmap 构造方式和像素格式
透明背景变黑,大概率是源图读取时丢了 Alpha。比如用 Bitmap(string) 加载 PNG,内部可能转成 PixelFormat.Format32bppRgb(无 Alpha),导致后续 Icon 构造时透明信息被抹掉。
- 加载时显式指定像素格式:
new Bitmap(original)(复制原图)比new Bitmap(path)更可靠 - 保存前验证:
bitmap.PixelFormat应为Format32bppArgb,否则强制转换:var argb = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); - ICO 本身支持 Alpha,但老系统(XP)只认 XOR/MASK 方式,现代开发不用考虑
实际转换逻辑就这几步:加载 → 缩放到标准尺寸 → 确保带 Alpha → 构造 Icon → 调用 Save()。最容易卡住的是第一步的尺寸校验和最后一步的格式误判——其他语言封装了这些细节,C# 得自己盯紧。


















