【发布时间】:2016-05-16 19:04:21
【问题描述】:
正如问题的标题所说,我正在尝试从文件中提取特定的图标层,然后将其保存为具有透明度的 ico 文件(与源图标一样)。
有很多与图标提取相关的问题,但这是特定于我使用 SHDefExtractIcon 函数应用的以下代码。
我的问题是生成的 .ico 文件的颜色不对,它生成了一种一半可怕的透明度,另一方面,生成的 .png 文件保存得很好。
这是生成的 PNG 文件:
这是生成的 ICO 文件:
这是 Windows API 的限制,还是我做错了什么?
C#:
[DllImport("Shell32.dll", SetLastError = false)]
public static extern int SHDefExtractIcon(string iconFile, int iconIndex, uint flags, ref IntPtr hiconLarge, ref IntPtr hiconSmall, uint iconSize);
IntPtr hiconLarge = default(IntPtr);
SHDefExtractIcon("C:\\file.exe", 0, 0, hiconLarge, null, 256);
// ToDO: Handle HRESULT.
Icon ico = Icon.FromHandle(hiconLarge);
Bitmap bmp = ico.ToBitmap();
// Save as .png with transparency. success.
bmp.Save("C:\\ico.png", ImageFormat.Png);
// 1st intent: Save as .ico with transparency. failure.
//' Transparency is ok but it generates a false icon, it's .png with modified extension to .ico.
bmp.Save("C:\\ico1.ico", ImageFormat.Icon);
// 2nd intent: Save as .ico with transparency. failure. Wrong transparency.
using (MemoryStream ms = new MemoryStream()) {
ico.Save(ms);
using (FileStream fs = new FileStream("C:\\ico2.ico", FileMode.CreateNew)) {
ms.WriteTo(fs);
}
// ToDO: Destroy hiconLarge here with DestroyIcon function.
}
VB.NET:
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
<DllImport("Shell32.dll", SetLastError:=False)>
Public Shared Function SHDefExtractIcon(ByVal iconFile As String,
ByVal iconIndex As Integer,
ByVal flags As UInteger,
ByRef hiconLarge As IntPtr,
ByRef hiconSmall As IntPtr,
ByVal iconSize As UInteger
) As Integer
End Function
Dim hiconLarge As IntPtr
SHDefExtractIcon("C:\file.exe", 0, 0, hiconLarge, Nothing, 256)
' ToDO: Handle HRESULT.
Dim ico As Icon = Icon.FromHandle(hiconLarge)
Dim bmp As Bitmap = ico.ToBitmap()
' Save as .png with transparency. success.
bmp.Save("C:\ico.png", ImageFormat.Png)
' 1st intent: Save as .ico with transparency. failure.
' Transparency is ok but it generates a false icon, it's .png with modified extension to .ico.
bmp.Save("C:\ico1.ico", ImageFormat.Icon)
' 2nd intent: Save as .ico with transparency. failure. Wrong transparency.
Using ms As New MemoryStream
ico.Save(ms)
Using fs As New FileStream("C:\ico2.ico", FileMode.CreateNew)
ms.WriteTo(fs)
End Using
End Using
' ToDO: Destroy hiconLarge here with DestroyIcon function.
【问题讨论】:
-
假设 PNG 确实保存正确,为什么您怀疑
SHDefExtractIconAPI 调用不起作用?另外,您能否详细说明“失败”的含义(屏幕截图会有所帮助)。 (侧节点:如果Image.Save找不到用于保存的编解码器,it uses png by default。) -
对我来说很好。摆脱内存流,只需使用
ico.Save(fs)Icon 类型知道如何将自己保存到文件中。 -
也许只有我一个人,但我认为生成的 .ico 文件看起来很棒。
-
请注意,使用
ToBitmap并不能保持透明度,很可能是您面临的问题。
标签: c# .net vb.net winapi icons