说,如果我想从Windows可执行文件中提取图标。我可以通过在Visual Studio中打开它来获得该图标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有什么区别?我在做什么错呢?
最佳答案
ExtractIconEx
函数只能返回两种尺寸的图标:大和小。这些是相对大小,由环境定义。 “大”图标通常为32x32像素,但在某些系统配置上可能会更大。 “小”图标通常为16x16像素,但同样需要注意。唯一的保证是“小”图标比“大”图标小。如果您想知道系统的实际大小,则可以使用GetSystemMetrics
和SM_CXICON
调用“大”图标,或者使用SM_CYICON
和SM_CXSMICON
调用“小”图标的 SM_CYSMICON
函数。
操作系统内部使用“小”和“大”图标。大多数API仅处理“小”和“大”(有时也称为“大”图标)。例如,当您使用set an icon for a window时,您将设置“小”图标或“大”图标。这些是您仅有的两个选择。ExtractIconEx
函数将phIconLarge
参数设置为指向大图标的句柄数组的指针。 phIconSmall
参数设置为指向小图标的句柄数组的指针。由于您为NULL
参数传递了phIconSmall
,因此您没有得到任何小图标。 hIcons
充满了文件中“大”图标的句柄,在您的系统上,它们是32x32图标的不同位深。
ExtractAssociatedIcon
函数(及其前任兄弟)仅返回“大”图标。因此,在调用它时,应该获得与调用ExtractIconEx
相同的结果。我不太确定您是说它给您带来不同的结果。它可能与索引有关。负索引意味着ExtractIconEx
有一些特殊之处,但我不确定它们是否对ExtractAssociatedIcon
有效。该文档没有太多提示。
SHGetFileInfo
函数尽管在许多方面都更加强大,包括从任何文件系统对象中提取图标的能力,但具有相同的基本限制:它为您提供了SHGFI_LARGEICON
和SHGFI_SMALLICON
的选择。
如果您需要提取自定义尺寸的图标(即系统“小”和“大”尺寸以外的图标),则需要做更多的工作。 本质上有两个选项:
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)
{
// 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
。 就像Raymond Chen blogged about以前一样,如果
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
函数来销毁它,以免泄漏。
关于c++ - ExtractIcon和ExtractAssociatedIcon之间的区别?需要提取特定大小的图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37370241/