我正在尝试从中提取图标imageres.dll。特别是“我的电脑”或“这台电脑”图标。问题是在Win7和Win10之间,图标编号发生了变化。然而,图标组却没有(109)。有没有办法获取该图标组,然后让计算机确定要使用该组的哪个图标,就像它确定要为我的应用程序使用哪个图标一样?
这是我用来通过索引获取特定图标的代码:
public class GetIcon {
public static Icon Extract(string file, int number) {
IntPtr large;
IntPtr small;
ExtractIconEx(file, number, out large, out small, 1);
try {
return Icon.FromHandle(small);
}
catch {
return null;
}
}
[DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);
}
Run Code Online (Sandbox Code Playgroud)
谢谢。
有几种方法可以做到这一点。最可靠、也可能最耗时(假设您找不到现有库)的方法是解析 PE 文件(即 .exe、.dll)并自行提取相关图标组数据。这是该格式的一个很好的资源:https ://msdn.microsoft.com/en-us/library/ms809762.aspx
第二种方法可以使用 Windows 函数轻松完成,但有一个警告。它仅适用于与您的应用程序具有相同位类型的 PE 文件。因此,例如,如果您的应用程序是 64 位,则它只能在 64 位 PE 文件上运行。
这是我刚刚编写的一个函数 - 基于此:https://msdn.microsoft.com/en-us/library/windows/desktop/ms648051(v=vs.85).aspx#_win32_Sharing_Icon_Resources,它需要一个文件名,组编号和所需的图标大小,并返回 System.Drawing.Icon
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32.dll")]
static extern IntPtr FindResource(IntPtr hModule, int lpName, int lpType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll")]
static extern IntPtr LockResource(IntPtr hResData);
[DllImport("user32.dll")]
static extern int LookupIconIdFromDirectoryEx(byte[] presbits, bool fIcon, int cxDesired, int cyDesired, uint Flags);
[DllImport("user32.dll")]
static extern IntPtr CreateIconFromResourceEx(byte[] pbIconBits, uint cbIconBits, bool fIcon, uint dwVersion, int cxDesired, int cyDesired, uint uFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
const int RT_GROUP_ICON = 14;
const int RT_ICON = 0x00000003;
private System.Drawing.Icon GetIconFromGroup(string file, int groupId, int size)
{
IntPtr hExe = LoadLibrary(file);
if(hExe != IntPtr.Zero)
{
IntPtr hResource = FindResource(hExe, groupId, RT_GROUP_ICON);
IntPtr hMem = LoadResource(hExe, hResource);
IntPtr lpResourcePtr = LockResource(hMem);
uint sz = SizeofResource(hExe, hResource);
byte[] lpResource = new byte[sz];
Marshal.Copy(lpResourcePtr, lpResource, 0, (int)sz);
int nID = LookupIconIdFromDirectoryEx(lpResource, true, size, size, 0x0000);
hResource = FindResource(hExe, nID, RT_ICON);
hMem = LoadResource(hExe, hResource);
lpResourcePtr = LockResource(hMem);
sz = SizeofResource(hExe, hResource);
lpResource = new byte[sz];
Marshal.Copy(lpResourcePtr, lpResource, 0, (int)sz);
IntPtr hIcon = CreateIconFromResourceEx(lpResource, sz, true, 0x00030000, size, size, 0);
System.Drawing.Icon testIco = System.Drawing.Icon.FromHandle(hIcon);
return testIco;
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
该过程基本上是这样的:
LoadLibrary加载.exe或.dll文件RT_GROUP_ICON获取资源的句柄和数据LookupIconIdFromDirectoryEx,以获得图标索引ExtractIconEx,或者仅使用图标索引重复步骤 2,然后RT_ICON使用 来CreateIconFromResourceEx获取图标句柄。| 归档时间: |
|
| 查看次数: |
3409 次 |
| 最近记录: |