delphi – 不使用 ExtractIconEx 从 EXE 中提取所有图标
我需要从 EXE 中提取所有图标并将它们保存为磁盘文件,但我无法使用最简单的解决方案( ExtractIconEx ),因为我需要以保留大尺寸图标的方式提取 ICO 文件,即使代码在运行 Windows XP 的系统上运行。稍后我将使用其他代码提取所需的图标(128x128 和其他 vista 大小的图标),但我需要一种方法来提取所有图标及其所有资源,因为它们存在于 EXE 中,无论我的代码是否在 PC 上运行运行的是 XP、Vista 或 Win7。
到目前为止我知道图标位于 RT_GROUP_ICONS 中.
我知道有些人以前一定在 Delphi 中这样做过,因为像 IcoFX 和资源浏览器这样的实用程序似乎已经这样做了。我记得曾经看到过一个完全开源的 Delphi 工具可以做到这一点,但那是几年前的事了。
重申一下我在 ExtractIconEx 中遇到的问题 - 它不会访问整个 .ico 文件,它只会提取支持的图标资源格式,即平台支持的单一分辨率(大小)。例如,在 XP 上,它将提取 32x32 或 48x48 图标,但不会提取 Vista 格式的 128x128 图标。
更新:这是已接受答案的修改版本,解决了我对 future 的担忧。如果我们调用的函数在未来的 Windows 版本中从 User32.dll 中消失,我希望它能够更优雅地失败,而不是无法加载整个应用程序。
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.
最佳答案
PrivateExtractIcons功能可以帮助你。您可以指定要提取的图标的大小:
{$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 ;
delphi – 不使用 ExtractIconEx 从 EXE 中提取所有图标 https://www.gzza.com/1257.html
本网站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。原创内容除特殊说明外,转载本站文章请注明出处。
如有侵权、不妥之处,联系删除。 Email:master@gzza.com
本网站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。原创内容除特殊说明外,转载本站文章请注明出处。
如有侵权、不妥之处,联系删除。 Email:master@gzza.com
THE END