【问题标题】:How can I load a program icon in C#如何在 C# 中加载程序图标
【发布时间】:2013-07-23 17:49:18
【问题描述】:

我有一些程序的路径(例如资源管理器),如何获取程序图标,将其转换为 png/jpeg,然后在 PictureBox 中显示?

我有这样的事情:

string filePath = "C:\\myfile.exe";
Icon TheIcon = IconFromFilePath(filePath);
if (TheIcon != null) {

 // But then I don't know what to do...

}

public Icon IconFromFilePath(string filePath){
 Icon programicon = null;
 try {
  programicon = Icon.ExtractAssociatedIcon(filePath);
 }
 catch { } 
 return programicon;
}

我发现了类似的东西here。这是图标。如何创建 32 位图标?

【问题讨论】:

  • 如果你成功获得了你想要的图标。 PictureBox.Image = myIcon 应该可以工作。 - 还将 PictureBox.SizeMode 设置为 Stretch/Center/etc
  • 但是如何先保存呢?我不用转换(PictureBox可以加载ico文件?)?
  • 似乎对我有用。
  • 您的代码调用了一个名为IconFromFilePath 的函数。该函数在哪里定义?我从未听说过它,它肯定不是 .NET BCL 的一部分。

标签: c# icons


【解决方案1】:

如果您知道在哪里查找,代码会非常简单。从Icon class 开始,因为这基本上就是您在这里所追求的。

如果你浏览它的方法,你会遇到一个看起来很有趣的ExtractAssociatedIcon。它接受一个字符串参数,该参数指定包含图标的文件的路径,例如可执行文件。

这样就为您提供了一个Icon 对象,现在您只需将其显示在一个图片框中。您不必将其转换为 PNG 或 JPEG,位图可以正常工作。并且有一个内置的成员函数:ToBitmap

将新位图分配给PictureBox.Image 属性是您显示它所需要做的所有事情。

【讨论】:

  • 好的。成功了...但是现在我遇到了这个问题:图标处于 256 色模式,如何创建 32 位图标?
  • 同样的问题。 Icon.ExtractAssociatedIcon 仅读取单个图标“视图”(我不知道如何命名嵌入单个图标的不同图像)。我真的需要获得完整的图标流。
  • 您不能将不同的图像嵌入到单个图标中。 @Mui,您的意思是不同的尺寸吗?或者可能是位深度? ExtractAssociatedIcon 将提取具有外壳使用的大小和位深度的图标,这通常是您想要的。如果您需要不同格式的图标,那么您将需要跳过一些额外的环节,要么从 Windows API P/Invoking 其他函数,要么手动探索资源文件。 Icon 类是基于 COM 的,不支持 256x256 像素的图标。如果您需要更多帮助,请提出一个新问题。
  • @Cody Gray 是的,通过视图或图像,我的意思是单个图标的“视觉表示”(即大小、颜色深度和位)。如果可能,我需要从 exe 文件中提取用于创建 exe 文件的确切 .ico 内容。
  • 我不知道您所说的“用于创建 exe 文件的确切 .ico 内容”是什么意思。您不会创建带有 ICO 内容的 EXE 文件。无论如何,我最近写了another answer 关于从文件中提取非默认大小的图标。旨在与 EXE 文件一起使用。如果你有一个独立的 ICO 文件,或者作为资源嵌入到你自己的 EXE 中的 ICO 文件,你可以简单地调用 LoadImage 函数,传递所需的宽度和高度值。无法控制获得的位深度;操作系统会根据您的显示特性为您提供正确的操作系统。
【解决方案2】:

这个问题可能很老,但这是我的答案。 这是我在从任何 exe 文件中提取完整的 256 x 256 图标时使用的完整代码 sn-p。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace IconUtils
{
    internal static class ExtractIcon
    {
       [UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
       [SuppressUnmanagedCodeSecurity]
        internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern IntPtr LockResource(IntPtr hResData);

       [DllImport("kernel32.dll", SetLastError = true)]
       public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
       [SuppressUnmanagedCodeSecurity]
       public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);


       private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
       private readonly static IntPtr RT_ICON = (IntPtr)3;
       private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;

       public static Icon ExtractIconFromExecutable(string path)
       {
           IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
           var tmpData = new List<byte[]>();

           ENUMRESNAMEPROC callback = (h, t, name, l) =>
           {
               var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);

               // Calculate the size of an entire .icon file.

               int count = BitConverter.ToUInt16(dir, 4);  // GRPICONDIR.idCount
               int len = 6 + 16 * count;                   // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
               for (int i = 0; i < count; ++i)
                   len += BitConverter.ToInt32(dir, 6 + 14 * i + 8);   // GRPICONDIRENTRY.dwBytesInRes

               using (var dst = new BinaryWriter(new MemoryStream(len)))
               {
                   // Copy GRPICONDIR to ICONDIR.

                   dst.Write(dir, 0, 6);

                   int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count

                   for (int i = 0; i < count; ++i)
                   {
                       // Load the picture.

                       ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12);    // GRPICONDIRENTRY.nID
                       var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);

                       // Copy GRPICONDIRENTRY to ICONDIRENTRY.

                       dst.Seek(6 + 16 * i, 0);

                       dst.Write(dir, 6 + 14 * i, 8);  // First 8bytes are identical.
                       dst.Write(pic.Length);          // ICONDIRENTRY.dwBytesInRes
                       dst.Write(picOffset);           // ICONDIRENTRY.dwImageOffset

                       // Copy a picture.

                       dst.Seek(picOffset, 0);
                       dst.Write(pic, 0, pic.Length);

                       picOffset += pic.Length;
                   }

                   tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
               }
               return true;
           };
           EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
           byte[][] iconData = tmpData.ToArray();
           using (var ms = new MemoryStream(iconData[0]))
           {
               return new Icon(ms);
           }
       }
       private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
       {
           // Load the binary data from the specified resource.

           IntPtr hResInfo = FindResource(hModule, name, type);

           IntPtr hResData = LoadResource(hModule, hResInfo);

           IntPtr pResData = LockResource(hResData);

           uint size = SizeofResource(hModule, hResInfo);

           byte[] buf = new byte[size];
           Marshal.Copy(pResData, buf, 0, buf.Length);

           return buf;
       }
   }
}

用法:

Icon ExeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(@"C:\Windows\explorer.exe");

来源:https://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 2012-07-30
    • 1970-01-01
    相关资源
    最近更新 更多