首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不使用ExtractIconEx从EXE中提取所有图标

不使用ExtractIconEx从EXE中提取所有图标
EN

Stack Overflow用户
提问于 2011-05-10 19:20:28
回答 2查看 8.8K关注 0票数 6

我需要从EXE中提取所有图标并将它们保存为磁盘文件,但是我不能使用最简单的解决方案(ExtractIconEx),因为我需要以一种保存大型图标的方式提取ICO文件,即使代码运行在运行Windows的系统上。稍后,我将使用其他代码提取想要的图标(128x128和其他视图大小的图标),但我需要一种方法来提取所有图标,因为它们都存在于EXE中,无论我的代码运行在PC上的是XP、Vista还是Win7。

到目前为止,我知道图标在图标中。

我知道有些人以前肯定在德尔菲做过这件事,因为像IcoFX和资源资源管理器这样的实用程序似乎已经这样做了。我记得曾经看到过一个完全开放源码的Delphi工具,可以做到这一点,但那是几年前的事了。

为了重申我对ExtractIconEx的问题-它不会访问整个.ico文件,它只会提取受支持的图标资源格式,这是平台支持的单一分辨率(大小)。例如,在XP上,它将提取一个32x32或48x48图标,而不是Vista格式的128x128图标。

更新:--这是被接受的答案的修改版本,解决了我对未来的担忧。如果我们正在调用的函数在将来的windows版本中从User32.dll中消失,我希望它能够更优雅地失败,而不是无法加载我的整个应用程序。

代码语言:javascript
运行
复制
unit ExtractIconUtils;

interface

uses Graphics,Forms,Windows;

//----------------------------------------------------------------------------
// ExtractIcons
// Call "private" MS Api to extract Icon file. This calls a publically
// documented function marked as deprecated in the MSDN documentation.
// It was no doubt Not Originally Intended to be documented, or publically
// accessed, but it provides functionality that its hard to live without.
// It exists on Windows 2000, XP, Vista, and Windows7, but might not exist
// in some future Windows version (released after year 2011).
//
// uses global   hUserDll    : THandle;
//----------------------------------------------------------------------------
function ExtractIcons(exeFilename,icoOutFileName:String;icoSize:Integer):Boolean;



var
  hUserDll    : THandle;





implementation



function ExtractIcons(exeFilename,icoOutFileName:String;icoSize:Integer):Boolean;
const
{$ifdef UNICODE}
 ExtractProcName='PrivateExtractIconsW';
{$else}
 ExtractProcName='PrivateExtractIconsA';
{$endif}
type
  TExtractFunc = function(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall;
var
  hIcon   : THandle;
  nIconId : DWORD;
  Icon    : TIcon;
  PrivateExtractIcons:TExtractFunc;
begin
  result := false;
  if (hUserDll<4) then begin
    hUserDll := LoadLibrary('user32.dll');
    if (hUserDll<4) then exit;
  end;

     { PrivateExtractIcons:
        MSDN documentation says that this function could go away in a future windows
        version, so we must try to load it, and if it fails, return false, rather than
        doing a static DLL import.
     }
    PrivateExtractIcons :=     GetProcAddress(hUserDll, ExtractProcName);

    if not Assigned(PrivateExtractIcons) then exit;

    //extract a icoSize x icoSize  icon where icoSize is one of 256,128,64,48,32,16
    if PrivateExtractIcons ( PWideChar(exeFilename),
                            0, icoSize, icoSize, @hIcon, @nIconId, 1, LR_LOADFROMFILE) <>0 then
    try
      Icon:=TIcon.Create;
      try
        Icon.Handle:=hIcon;
        Icon.SaveToFile(icoOutFileName);
        result := true;
      finally
        Icon.Free;
      end;
    finally
      DestroyIcon (hIcon);
    end;
end ;


initialization
  // none

finalization
   if (hUserDll>4) then
      FreeLibrary(hUserDll);

end.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-05-10 19:53:08

PrivateExtractIcons函数可以帮助您。可以指定要提取的图标的大小:

代码语言:javascript
运行
复制
{$IFDEF UNICODE}
    function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall ; external 'user32.dll' name 'PrivateExtractIconsW';
{$ELSE}
    function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD; stdcall ; external 'user32.dll' name 'PrivateExtractIconsA';
{$ENDIF}

procedure TMainForm.Button1Click(Sender: TObject);
var
    hIcon   : THandle;
    nIconId : DWORD;
    Icon    : TIcon;
begin
    //Extract a 128x128 icon
    if PrivateExtractIcons ('C:\Users\Public\Documents\RAD Studio\Projects\2010\Aero Colorizer\AeroColorizer.exe', 0, 128, 128, @hIcon, @nIconId, 1, LR_LOADFROMFILE) <>0 then
    try
        Icon:=TIcon.Create;
        try
            Icon.Handle:=hIcon;
            Icon.SaveToFile(ExtractFilePath(ParamStr(0))+'Aicon.ico');
        finally
            Icon.Free;
        end;
    finally
        DestroyIcon (hIcon);
    end;
end ;
票数 11
EN

Stack Overflow用户

发布于 2011-05-10 22:00:06

这是一个Delphi Praxis的工作实例。它为指定的可执行文件读取默认的RT_GROUP_ICON和相关的RT_ICON资源,并将它们保存为一个完整的多映像.ICO文件。

它似乎被256像素图像所混淆(保存无效格式),至少在XP上是这样,所以它可能需要稍微调整一下。

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

https://stackoverflow.com/questions/5955288

复制
相关文章

相似问题

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