ExtractIconEx
函数只能返回两种尺寸的图标:大图标和小图标。这些是相对大小,由环境定义。 "大"图标经典上是32x32像素,但在某些系统配置中可能更大。 "小"图标经典上是16x16像素,但同样适用于相同的警告。唯一的保证是“小”图标比“大”图标要小。如果您想知道在您的系统上实际大小,您可以使用SM_CXICON
和SM_CYICON
来调用GetSystemMetrics
函数以获取“大”图标,或者使用SM_CXSMICON
和SM_CYSMICON
获取“小”图标。
操作系统在内部的各处都使用“小”和“大”图标;大多数API仅处理“小”和“大”(有时也称为“大”)图标。例如,当你
为窗口设置图标 时,你只能设置“小”图标或“大”图标。这是你唯一的两个选择。
ExtractIconEx
函数将
phIconLarge
参数设置为指向一组大图标句柄的指针。
phIconSmall
参数设置为指向一组小图标句柄的指针。由于你对
phIconSmall
参数传递了
NULL
,所以没有得到任何小图标。
hIcons
填充了文件中“大”图标的句柄,这些图标在您的系统上是不同深度的32x32图标。
ExtractAssociatedIcon
函数(以及它的Ex版本)只返回“大”图标。因此,当你调用它时,应该会得到与调用
ExtractIconEx
相同的结果。我不确定你是否在说它提供了
不同的结果。这可能与索引有关。负索引对
ExtractIconEx
有特殊含义,但我不确定它们对
ExtractAssociatedIcon
是否有效。文档没有给出太多提示。
虽然
SHGetFileInfo
函数在许多方面更加强大,包括从
任何文件系统对象中提取图标的能力,但它具有相同的基本限制:它只提供
SHGFI_LARGEICON
和
SHGFI_SMALLICON
的选择。
"If you need to extract icons of custom sizes (i.e., something other than the system's "small" and "large" sizes), then you'll need to do more work. There are essentially two options:
1. 调用
SHGetImageList
函数,这是另一个shell帮助函数,但它检索包含图标的shell图像列表。它为图标大小提供了更多选项:
SHIL_SMALL
(通常为16x16),
SHIL_LARGE
(通常为32x32),
SHIL_EXTRALARGE
(通常为48x48)和
SHIL_JUMBO
(通常为256x256-仅适用于Vista及更高版本)。因此,如果您要求
SHIL_EXTRALARGE
,则会获得您要查找的48x48图标。"
你仍需要使用
SHGetFileInfo
函数,但这次是为了检索所需图标在shell图像列表中的索引。使用
SHGFI_SYSICONINDEX
选项来检索。
完全未经测试的示例代码,从未被编译器触及:
HICON ExtractExtraLargeIcon(LPCTSTR pszPath)
{
SHGETFILEINFO sfi;
SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
IImageList* piml;
if (SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&piml) == S_OK)
{
HICON hIcon;
if (piml->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon) == S_OK)
{
return hIcon;
}
}
return NULL;
}
- 您的另一个选择是自己从文件中提取所需大小的图标。尽管图标资源格式已经有了很好的文档说明,并且各种人已经使用这些知识编写了一堆丑陋的提取代码并发布在互联网上,但有一种更简单的方法:
SHDefExtractIcon
。
正如Raymond Chen之前所述,SHDefExtractIcon
是您更强大的后备方案,如果IExtractIcon::Extract
(上面的代码示例尝试使用此函数)失败。该函数的强大之处在于它的nIconSize
参数,该参数指定要提取的图标的实际大小。
根据Raymond的示例进行调整:
HICON ExtractArbitrarySizeIcon(LPCTSTR pszPath, int size)
{
HICON hIcon;
if (SHDefExtractIcon(pszPath, 1, 0, &hIcon, NULL, size) == S_OK)
{
return hIcon;
}
return NULL; // failure
}
无论你做什么,记住每当 API 函数返回 HICON 时,它都会将该资源的所有权转移给你。这意味着,当你完成对图标的使用后,必须通过调用
DestroyIcon
函数来销毁它,以避免泄漏。
LoadImage
获取特定大小的图标。 - Jonathan Potter::LoadImage(::LoadLibrary(L"mstsc.exe"), MAKEINTRESOURCE(13011), IMAGE_ICON, 48, 48, LR_LOADFROMFILE);
它会抛出访问冲突异常,但是::LoadImage(::LoadLibrary(L"mstsc.exe"), L"#13011", IMAGE_ICON, 48, 48, LR_LOADFROMFILE);
返回值是NULL
。 - c00000fd