首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ExtractIcon与ExtractAssociatedIcon的差异?需要提取特定大小的图标

ExtractIcon与ExtractAssociatedIcon的差异?需要提取特定大小的图标
EN

Stack Overflow用户
提问于 2016-05-22 03:29:39
回答 1查看 5.6K关注 0票数 2

比方说,如果我想从股票Windows可执行文件中提取一个图标。我可以通过在Visual中打开图标ID来获得它:

然后我会对48x48大小的图标感兴趣:

所以我的假设是:

代码语言:javascript
运行
复制
HICON hIcons[4];
::ExtractIconEx(L"mstsc.exe", -13011, hIcons, NULL, 4);
hIconLogo = hIcons[3];

但是,当我运行它时,该方法只返回3个图标:

其中只有一个是我所需要的32x32版本。

然后,我找到了我这样调用的ExtractAssociatedIconEx API:

代码语言:javascript
运行
复制
WORD wIcnId = -13011;
WORD wIcnInd = 3;
hIconLogo = ::ExtractAssociatedIconEx(hInst, L"mstsc.exe", &wIcnInd, &wIcnId);

但这也给了我一些我没想到的其他图标。

那么,这两个API之间有什么区别呢?我做错什么了?

EN

Stack Overflow用户

回答已采纳

发布于 2016-05-24 16:34:00

ExtractIconEx函数只能返回两种大小的图标:大图标和小图标。它们是由环境定义的相对大小。“大”图标是经典的32x32像素,但在某些系统配置中可能更大。一个“小”图标是经典的16x16像素,但同样的警告也适用。唯一的保证是“小”图标比“大”图标小。如果您想知道系统上的实际大小,可以用GetSystemMetrics函数调用SM_CXICONSM_CYICON来表示“大”图标,或者调用SM_CXSMICONSM_CYSMICON表示“小”图标。

操作系统在内部到处使用“小”和“大”图标;大多数API只处理“小”和“大”(偶尔也称为“大”图标)。例如,当您在为窗口设置图标上设置“小”图标或“大”图标时。这是你唯一的两个选择。

ExtractIconEx函数将phIconLarge参数设置为指向大图标句柄数组的指针。phIconSmall参数设置为指向小图标句柄数组的指针。因为您为NULL参数传递了phIconSmall,所以没有得到任何小图标。hIcons中填充了文件中“大”图标的句柄,在您的系统中,这些图标是32x32图标的不同位深度。

ExtractAssociatedIcon函数(及其Ex兄弟)只返回“大”图标。因此,当您调用它时,您应该得到与调用ExtractIconEx的方式相同的结果。我不太确定你是说它会给你带来不同的结果。这可能与指数有关。负指数对ExtractIconEx意味着一些特殊的东西,但我不确定它们对ExtractAssociatedIcon是否有效。这些文档并没有给出多少提示。

SHGetFileInfo函数虽然在许多意义上更强大,包括从任何文件系统对象中提取图标的能力,但它具有相同的基本限制:它为您提供了SHGFI_LARGEICONSHGFI_SMALLICON的选择。

如果您需要提取自定义大小的图标(即系统的“小”和“大”大小以外的图标),那么您需要做更多的工作。本质上有两个选项:

  1. 调用SHGetImageList函数,这是另一个shell帮助函数,但它检索包含图标的shell图像列表。它为图标大小提供了更多的选项:SHIL_SMALL (一般为16x16)、SHIL_LARGE (一般为32x32)、SHIL_EXTRALARGE (一般为48x48)和SHIL_JUMBO (通常为256x256--仅限于Vista及更高版本)。因此,如果您要求SHIL_EXTRALARGE,您将得到48x48图标,您正在寻找。

这里仍然需要SHGetFileInfo函数,但这一次将检索shell图像列表中所需图标的索引。使用SHGFI_SYSICONINDEX选项检索它。

完全未经测试的示例代码,编译器从未碰过:

代码语言:javascript
运行
复制
    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;
    }
  1. 您的另一个选项是自己从文件中提取所需的大小图标。虽然图标资源格式有很好的文档记录,而且很多人都用这些知识编写了一堆丑陋的提取代码并将其发布到互联网上,但有一种更简单的方法:SHDefExtractIcon

正如一段时间前的SHDefExtractIcon一样,如果IExtractIcon::Extract (上面的代码示例试图使用的内容)失败了,那么IExtractIcon::Extract将是您更强大的后盾。此函数的强大功能是它的nIconSize参数,它指定要提取的图标的实际大小。

改编雷蒙德的例子:

代码语言:javascript
运行
复制
    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函数来销毁它,以避免泄漏。

票数 19
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37370241

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档