2

我有一些程序的路径(例如资源管理器),如何获取程序图标,将其转换为 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;
}

我在这里找到了类似的东西。这是图标。如何创建 32 位图标?

256 种颜色

4

2 回答 2

9

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

如果你浏览它的方法,你会发现一个非常有趣的ExtractAssociatedIcon. 它接受一个字符串参数,该参数指定包含图标的文件的路径,例如可执行文件。

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

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

于 2013-07-24T10:13:08.063 回答
0

这个问题可能很老,但这是我的答案。这是我用于从任何 exe 文件中提取完整的 256 x 256 图标的完整代码片段。

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

于 2020-06-05T03:20:11.683 回答