我需要從EXE中提取所有圖標並將它們保存爲磁盤文件,但我無法使用最簡單的解決方案(ExtractIconEx),因爲我需要以某種方式提取ICO文件即使代碼在運行Windows XP的系統上運行,也可以保留大尺寸圖標。我將在稍後使用其他代碼提取想要的圖標(128x128和其他vista大小的圖標),但我需要一種方式來提取所有圖標及其所有資源,因爲它們出現在EXE中,而不管PC代碼是否運行正在運行XP,Vista或Win7。從EXE中提取所有圖標而不使用ExtractIconEx
到目前爲止,我知道圖標在RT_GROUP_ICONS。
我知道有些人在Delphi中一定是做過這個,因爲像IcoFX和資源管理器這樣的工具似乎已經做到了。我曾經記得看到一個完全開源的Delphi工具,可以做到這一點,但那是幾年前。
要重申我用ExtractIconEx所遇到的問題 - 它不會訪問整個.ico文件,它只會提取支持的圖標資源格式,這是平臺支持的任何單個分辨率(大小)。因此,在XP上,它將提取32x32或48x48圖標,但不是Vista格式的128x128圖標。
更新:這是公認的答案,解決了我的面向未來的憂慮的修改版本。如果我們所調用的函數在未來的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.
Vista圖標是256px PNG圖像,而不是128px,FWIW – 2011-05-10 19:28:56
你試過'PrivateExtractIcons'功能嗎? http://msdn.microsoft.com/en-us/library/ms648075 – RRUZ 2011-05-10 19:33:55
這是一個功能性的工作理念,但它讓我感到恐慌,它將在未來破裂(感謝MSDN!) – 2011-05-10 20:51:05