比方说,如果我想从股票Windows可执行文件中提取一个图标。我可以通过在Visual中打开图标ID来获得它:
然后我会对48x48大小的图标感兴趣:
所以我的假设是:
HICON hIcons[4];
::ExtractIconEx(L"mstsc.exe", -13011, hIcons, NULL, 4);
hIconLogo = hIcons[3];
但是,当我运行它时,该方法只返回3个图标:
其中只有一个是我所需要的32x32版本。
然后,我找到了我这样调用的ExtractAssociatedIconEx API:
WORD wIcnId = -13011;
WORD wIcnInd = 3;
hIconLogo = ::ExtractAssociatedIconEx(hInst, L"mstsc.exe", &wIcnInd, &wIcnId);
但这也给了我一些我没想到的其他图标。
那么,这两个API之间有什么区别呢?我做错什么了?
发布于 2016-05-24 16:34:00
ExtractIconEx函数只能返回两种大小的图标:大图标和小图标。它们是由环境定义的相对大小。“大”图标是经典的32x32像素,但在某些系统配置中可能更大。一个“小”图标是经典的16x16像素,但同样的警告也适用。唯一的保证是“小”图标比“大”图标小。如果您想知道系统上的实际大小,可以用GetSystemMetrics
函数调用SM_CXICON
和SM_CYICON
来表示“大”图标,或者调用SM_CXSMICON
和SM_CYSMICON
表示“小”图标。
操作系统在内部到处使用“小”和“大”图标;大多数API只处理“小”和“大”(偶尔也称为“大”图标)。例如,当您在为窗口设置图标上设置“小”图标或“大”图标时。这是你唯一的两个选择。
ExtractIconEx
函数将phIconLarge
参数设置为指向大图标句柄数组的指针。phIconSmall
参数设置为指向小图标句柄数组的指针。因为您为NULL
参数传递了phIconSmall
,所以没有得到任何小图标。hIcons
中填充了文件中“大”图标的句柄,在您的系统中,这些图标是32x32图标的不同位深度。
ExtractAssociatedIcon函数(及其Ex兄弟)只返回“大”图标。因此,当您调用它时,您应该得到与调用ExtractIconEx
的方式相同的结果。我不太确定你是说它会给你带来不同的结果。这可能与指数有关。负指数对ExtractIconEx
意味着一些特殊的东西,但我不确定它们对ExtractAssociatedIcon
是否有效。这些文档并没有给出多少提示。
SHGetFileInfo函数虽然在许多意义上更强大,包括从任何文件系统对象中提取图标的能力,但它具有相同的基本限制:它为您提供了SHGFI_LARGEICON
和SHGFI_SMALLICON
的选择。
如果您需要提取自定义大小的图标(即系统的“小”和“大”大小以外的图标),那么您需要做更多的工作。本质上有两个选项:
SHIL_SMALL
(一般为16x16)、SHIL_LARGE
(一般为32x32)、SHIL_EXTRALARGE
(一般为48x48)和SHIL_JUMBO
(通常为256x256--仅限于Vista及更高版本)。因此,如果您要求SHIL_EXTRALARGE
,您将得到48x48图标,您正在寻找。这里仍然需要SHGetFileInfo
函数,但这一次将检索shell图像列表中所需图标的索引。使用SHGFI_SYSICONINDEX
选项检索它。
完全未经测试的示例代码,编译器从未碰过:
HICON ExtractExtraLargeIcon(LPCTSTR pszPath)
{
// Determine the index of the desired icon
// in the system image list.
SHGETFILEINFO sfi;
SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
// Retrieve the system image list.
// (To get 48x48 icons, we use `SHIL_EXTRALARGE`.)
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;
}
}
// Oops! We failed.
return NULL;
}
SHDefExtractIcon
。正如一段时间前的SHDefExtractIcon
一样,如果IExtractIcon::Extract
(上面的代码示例试图使用的内容)失败了,那么IExtractIcon::Extract
将是您更强大的后盾。此函数的强大功能是它的nIconSize
参数,它指定要提取的图标的实际大小。
改编雷蒙德的例子:
HICON ExtractArbitrarySizeIcon(LPCTSTR pszPath, int size)
{
HICON hIcon;
if (SHDefExtractIcon(pszPath, 1, 0, &hIcon, NULL, size) == S_OK)
{
return hIcon;
}
return NULL; // failure
}
无论您做什么,请记住,每当API函数返回H图标时,它都会将该资源的所有权传递给您。这意味着,当您完成图标时,您必须通过调用DestroyIcon
函数来销毁它,以避免泄漏。
https://stackoverflow.com/questions/37370241
复制相似问题