这是我我找的一个文件提取图标和修改图标的单元自己研究一下
unit Icons;
interface
uses Windows;
type
PByte = ^Byte;
PBitmapInfo = ^BitmapInfo;
/// These first two structs represent how the icon information is stored
/// when it is bound into a EXE or DLL file. Structure members are WORD
/// aligned and the last member of the structure is the ID instead of
/// the imageoffset.
type
PMEMICONDIRENTRY = ^TMEMICONDIRENTRY;
TMEMICONDIRENTRY = packed record
bWidth: Byte;
bHeight: Byte;
bColorCount: Byte;
bReserved: Byte;
wPlanes: Word;
wBitCount: Word;
dwBytesInRes: DWORD;
nID: Word;
end;
type
PMEMICONDIR = ^TMEMICONDIR;
TMEMICONDIR = packed record
idReserved: Word;
idType: Word;
idCount: Word;
idEntries: Array[0..15] of TMEMICONDIRENTRY;
end;
/// These next two structs represent how the icon information is stored
/// in an ICO file.
type
PICONDIRENTRY = ^TICONDIRENTRY;
TICONDIRENTRY = packed record
bWidth: Byte;
bHeight: Byte;
bColorCount: Byte;
bReserved: Byte;
wPlanes: Word;
wBitCount: Word;
dwBytesInRes: DWORD;
dwImageOffset: DWORD;
end;
type
PICONDIR = ^TICONDIR;
TICONDIR = packed record
idReserved: Word;
idType: Word;
idCount: Word;
idEntries: Array[0..0] of TICONDIRENTRY;
end;
/// The following two structs are for the use of this program in
/// manipulating icons. They are more closely tied to the operation
/// of this program than the structures listed above. One of the
/// main differences is that they provide a pointer to the DIB
/// information of the masks.
type
PICONIMAGE = ^TICONIMAGE;
TICONIMAGE = packed record
Width,
Height,
Colors: UINT;
lpBits: Pointer;
dwNumBytes: DWORD;
pBmpInfo: PBitmapInfo;
end;
type
PICONRESOURCE = ^TICONRESOURCE;
TICONRESOURCE = packed record
nNumImages: UINT;
IconImages: Array[0..15] of TICONIMAGE;
end;
type
TPageInfo = packed record
Width: Byte;
Height: Byte;
ColorQuantity: Integer;
Reserved: DWORD;
PageSize: DWORD;
PageOffSet: DWORD;
end;
type
TPageDataHeader = packed record
PageHeadSize: DWORD;
XSize: DWORD;
YSize: DWORD;
SpeDataPerPixSize: Integer;
ColorDataPerPixSize: Integer;
Reserved: DWORD;
DataAreaSize: DWORD;
ReservedArray: Array[0..15] of char;
end;
type
TIcoFileHeader = packed record
FileFlag: Array[0..3] of byte;
PageQuartity: Integer;
PageInfo: TPageInfo;
end;
type
TStringList = class(TObject)
private
SList: Array of String;
public
Count: Integer;
constructor Create;
procedure Add(S: String);
function Strings(Index: Integer): String;
end;
function SaveIcon(Filename: String; FileIco: String): Boolean;
function ExtractIconFromFile(ResFileName: string; IcoFileName: string; nIndex: string): Boolean;
function WriteIconResourceToFile(hFile: hwnd; lpIR: PICONRESOURCE): Boolean;
function UpdateApplicationIcon(srcicon : PChar; destexe : PChar) : Boolean;
function AWriteIconToFile(bitmap: hBitmap; Icon: hIcon; szFileName: string): Boolean;
implementation
constructor TStringList.Create;
begin
Count := 0;
SetLength(SList, Count +1);
end;
procedure TStringList.Add(S: String);
begin
SetLength(SList, Count +1);
SList[Count] := S;
Inc(Count);
end;
function TStringList.Strings(Index: Integer): String;
begin
Result := SList[Index];
end;
//==============================================================================
function StrToInt(X: String): Integer;
var
V, Code: Integer;
begin
Val(X, V, Code);
StrToInt := V;
end;
function IntToStr(X: Integer): String;
var
S: String;
begin
Str(X, S);
IntToStr := S;
end;
function ExtractFilePath(FileName: string): string;
begin
Result := '';
while Pos('/', FileName) <> 0 do
begin
Result := Result + Copy(FileName, 1, 1);
Delete(FileName, 1, 1);
end;
end;
function EnumResourceNamesProc(Module: HMODULE; ResType: PChar; ResName: PChar; lParam: TStringList): Integer; stdcall;
var
ResourceName: String;
begin
if hiword(Cardinal(ResName)) = 0 then
begin
ResourceName := IntToStr(loword(Cardinal(ResName)));
end else
begin
ResourceName := ResName;
end;
lParam.Add(ResourceName);
Result := 1;
end;
function SaveIcon(Filename: String; FileIco: String): Boolean;
var
hExe: THandle;
i: Integer;
SL: TStringList;
const
RT_GROUP_ICON = MakeIntResource(DWORD(RT_ICON + DIFFERENCE));
begin
Result := False;
SL := TStringList.Create;
hExe := LoadLibraryEx(PChar(Filename), 0, LOAD_LIBRARY_AS_DATAFILE); // SL
if hExe = 0 then Exit;
EnumResourceNames(hExe, RT_GROUP_ICON, @EnumResourceNamesProc, Integer(SL));
if SL.Count = 0 then
begin
SL.Free;
//MessageBox(0, 'No Icons found in the EXE/DLL', 'Error', MB_ICONERROR);
Exit;
end;
//Icons.ExtractIconFromFile(Filename, FileIco, SL.Strings(i));
for i := 0 to SL.Count -1 do
begin
Icons.ExtractIconFromFile(Filename, SL.Strings(i) + '.ico', SL.Strings(i));
//Icons.ExtractIconFromFile(Filename, FileIco, SL.Strings(i));
//MessageBox(0,PChar(ExtractFilePath(Filename)+SL.Strings(i)),'',64);
end;
FreeLibrary(hExe);
SL.Free;
Result := True;
end;
function SysErrorMessage(ErrorCode: Integer): string;
var
Len: Integer;
Buffer: array[0..255] of Char;
begin
Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer, SizeOf(Buffer), nil);
while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do Dec(Len);
SetString(Result, Buffer, Len);
end;
function WriteICOHeader(hFile: THandle; nNumEntries: UINT): Boolean;
type
TFIcoHeader = record
wReserved: WORD;
wType: WORD;
wNumEntries: WORD;
end;
var
IcoHeader: TFIcoHeader;
dwBytesWritten: DWORD;
begin
Result := False;
IcoHeader.wReserved := 0;
IcoHeader.wType := 1;
IcoHeader.wNumEntries := WORD(nNumEntries);
if not WriteFile(hFile, IcoHeader, SizeOf(IcoHeader), dwBytesWritten, nil) then
begin
//MessageBox(0, pchar(SysErrorMessage(GetLastError)), 'Error', MB_ICONERROR);
Result := False;
Exit;
end;
if dwBytesWritten <> SizeOf(IcoHeader) then
Exit;
Result := True;
end;
function CalculateImageOffset(lpIR: PICONRESOURCE; nIndex: UINT): DWORD;
var
dwSize: DWORD;
i: Integer;
begin
dwSize := 3 * SizeOf(WORD);
inc(dwSize, lpIR.nNumImages * SizeOf(TICONDIRENTRY));
for i := 0 to nIndex - 1 do
inc(dwSize, lpIR.IconImages.dwNumBytes);
Result := dwSize;
end;
function WriteIconResourceToFile(hFile: hwnd; lpIR: PICONRESOURCE): Boolean;
var
i: UINT;
dwBytesWritten: DWORD;
ide: TICONDIRENTRY;
dwTemp: DWORD;
begin
Result := False;
for i := 0 to lpIR^.nNumImages - 1 do
begin
/// Convert internal format to ICONDIRENTRY
ide.bWidth := lpIR^.IconImages.Width;
ide.bHeight := lpIR^.IconImages.Height;
ide.bReserved := 0;
ide.wPlanes := lpIR^.IconImages.pBmpInfo.bmiHeader.biPlanes;
ide.wBitCount := lpIR^.IconImages.pBmpInfo.bmiHeader.biBitCount;
if ide.wPlanes * ide.wBitCount >= 8 then
ide.bColorCount := 0
else
ide.bColorCount := 1 shl (ide.wPlanes * ide.wBitCount);
ide.dwBytesInRes := lpIR^.IconImages.dwNumBytes;
ide.dwImageOffset := CalculateImageOffset(lpIR, i);
if not WriteFile(hFile, ide, sizeof(TICONDIRENTRY), dwBytesWritten, nil) then
Exit;
if dwBytesWritten <> sizeof(TICONDIRENTRY) then
Exit;
end;
for i := 0 to lpIR^.nNumImages - 1 do
begin
dwTemp := lpIR^.IconImages.pBmpInfo^.bmiHeader.biSizeImage;
lpIR^.IconImages.pBmpInfo^.bmiHeader.biSizeImage := 0;
if not WriteFile(hFile, lpIR^.IconImages.lpBits^, lpIR^.IconImages.dwNumBytes, dwBytesWritten, nil) then
Exit;
if dwBytesWritten <> lpIR^.IconImages.dwNumBytes then
Exit;
lpIR^.IconImages.pBmpInfo^.bmiHeader.biSizeImage := dwTemp;
end;
Result := True;
end;
function AWriteIconToFile(bitmap: hBitmap; Icon: hIcon; szFileName: string): Boolean;
var
fh: file of byte;
IconInfo: _ICONINFO;
PageInfo: TPageInfo;
PageDataHeader: TPageDataHeader;
IcoFileHeader: TIcoFileHeader;
BitsInfo: tagBITMAPINFO;
p: pointer;
PageDataSize: integer;
begin
Result := False;
GetIconInfo(Icon, IconInfo);
AssignFile(fh, szFileName);
FileMode := 1;
Reset(fh);
GetDIBits(0, Icon, 0, 32, nil, BitsInfo, DIB_PAL_COLORS);
GetDIBits(0, Icon, 0, 32, p, BitsInfo, DIB_PAL_COLORS);
PageDataSize := SizeOf(PageDataHeader) + BitsInfo.bmiHeader.biBitCount;
PageInfo.Width := 32;
PageInfo.Height := 32;
PageInfo.ColorQuantity := 65535;
Pageinfo.Reserved := 0;
PageInfo.PageSize := PageDataSize;
PageInfo.PageOffSet := SizeOf(IcoFileHeader);
IcoFileHeader.FileFlag[0] := 0;
IcoFileHeader.FileFlag[1] := 0;
IcoFileHeader.FileFlag[2] := 1;
IcoFileHeader.FileFlag[3] := 0;
IcoFileHeader.PageQuartity := 1;
IcoFileHeader.PageInfo := PageInfo;
FillChar(PageDataHeader, SizeOf(PageDataHeader), 0);
PageDataHeader.XSize := 32;
PageDataHeader.YSize := 32;
PageDataHeader.SpeDataPerPixSize := 0;
PageDataHeader.ColorDataPerPixSize := 32;
PageDataHeader.PageHeadSize := SizeOf(PageDataHeader);
PageDataHeader.Reserved := 0;
PageDataHeader.DataAreaSize := BitsInfo.bmiHeader.biBitCount;
BlockWrite(fh, IcoFileHeader, SizeOf(IcoFileHeader));
BlockWrite(fh, PageDataHeader, SizeOf(PageDataHeader));
BlockWrite(fh, p, BitsInfo.bmiHeader.biBitCount);
CloseFile(fh);
end;
function AdjustIconImagePointers(lpImage: PICONIMAGE): Bool;
begin
if lpImage = nil then
begin
Result := False;
exit;
end;
lpImage.pBmpInfo := PBitMapInfo(lpImage^.lpBits);
lpImage.Width := lpImage^.pBmpInfo^.bmiHeader.biWidth;
lpImage.Height := (lpImage^.pBmpInfo^.bmiHeader.biHeight) div 2;
lpImage.Colors := lpImage^.pBmpInfo^.bmiHeader.biPlanes * lpImage^.pBmpInfo^.bmiHeader.biBitCount;
Result := true;
end;
function ExtractIconFromFile(ResFileName: string; IcoFileName: string; nIndex: string): Boolean;
var
h: HMODULE;
lpMemIcon: PMEMICONDIR;
lpIR: TICONRESOURCE;
src: HRSRC;
Global: HGLOBAL;
i: integer;
hFile: hwnd;
begin
Result := False;
hFile := CreateFile(pchar(IcoFileName), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if hFile = INVALID_HANDLE_VALUE then Exit;
h := LoadLibraryEx(pchar(ResFileName), 0, LOAD_LIBRARY_AS_DATAFILE);
if h = 0 then exit;
try
src := FindResource(h, pchar(nIndex), RT_GROUP_ICON);
if src = 0 then
Src := FindResource(h, Pointer(StrToInt(nIndex)), RT_GROUP_ICON);
if src <> 0 then
begin
Global := LoadResource(h, src);
if Global <> 0 then
begin
lpMemIcon := LockResource(Global);
if Global <> 0 then
begin
try
lpIR.nNumImages := lpMemIcon.idCount;
// Write the header
//for i := 0 to lpMemIcon^.idCount - 1 do
for i := 0 to lpMemIcon^.idCount - 1 do
begin
src := FindResource(h, MakeIntResource(lpMemIcon^.idEntries.nID), RT_ICON);
if src <> 0 then
begin
Global := LoadResource(h, src);
if Global <> 0 then
begin
try
lpIR.IconImages.dwNumBytes := SizeofResource(h, src);
except
//MessageBox(0, PChar('Unable to Read Icon'), 'NTPacker', MB_ICONERROR);
Result := False;
Exit;
//ExitProcess(0);
end;
GetMem(lpIR.IconImages.lpBits, lpIR.IconImages.dwNumBytes);
CopyMemory(lpIR.IconImages.lpBits, LockResource(Global), lpIR.IconImages.dwNumBytes);
if not AdjustIconImagePointers(@(lpIR.IconImages)) then exit;
end;
end;
end;
if WriteICOHeader(hFile, lpIR.nNumImages) then
if WriteIconResourceToFile(hFile, @lpIR) then
Result := True;
finally
for i := 0 to lpIR.nNumImages - 1 do
if assigned(lpIR.IconImages.lpBits) then
FreeMem(lpIR.IconImages.lpBits);
end;
end;
end;
end;
finally
FreeLibrary(h);
end;
CloseHandle(hFile);
end;
function UpdateApplicationIcon(srcicon : PChar; destexe : PChar) : Boolean;
type
PICONDIRENTRYCOMMON = ^ICONDIRENTRYCOMMON;
ICONDIRENTRYCOMMON = packed record
bWidth : Byte; // Width, in pixels, of the image
bHeight : Byte; // Height, in pixels, of the image
bColorCount : Byte; // Number of colors in image (0 if >=8bpp)
bReserved : Byte; // Reserved ( must be 0)
wPlanes : Word; // Color Planes
wBitCount : Word; // Bits per pixel
dwBytesInRes : DWord; // How many bytes in this resource?
end;
PICONDIRENTRY = ^ICONDIRENTRY;
ICONDIRENTRY = packed record
common : ICONDIRENTRYCOMMON;
dwImageOffset : DWord; // Where in the file is this image?
end;
PICONDIR = ^ICONDIR;
ICONDIR = packed record
idReserved : Word; // Reserved (must be 0)
idType : Word; // Resource Type (1 for icons)
idCount : Word; // How many images?
idEntries : ICONDIRENTRY; // An entry for each image (idCount of 'em)
end;
PGRPICONDIRENTRY = ^GRPICONDIRENTRY;
GRPICONDIRENTRY = packed record
common : ICONDIRENTRYCOMMON;
nID : Word; // the ID
end;
PGRPICONDIR = ^GRPICONDIR;
GRPICONDIR = packed record
idReserved : Word; // Reserved (must be 0)
idType : Word; // Resource type (1 for icons)
idCount : Word; // How many images?
idEntries : GRPICONDIRENTRY; // The entries for each image
end;
var
hFile : Integer;
id : ICONDIR;
pid : PICONDIR;
pgid : PGRPICONDIR;
uRead : DWord;
nSize : DWord;
pvFile : PByte;
hInst : LongInt;
begin
Result := False;
hFile := CreateFile(srcicon, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hFile > 0 then
begin
ReadFile(hFile, id, sizeof(id), uRead, nil);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
GetMem(pid, sizeof(ICONDIR) + sizeof(ICONDIRENTRY));
GetMem(pgid, sizeof(GRPICONDIR) + sizeof(GRPICONDIRENTRY));
ReadFile(hFile, pid^, sizeof(ICONDIR) + sizeof(ICONDIRENTRY), uRead, nil);
move(pid^, pgid^, sizeof(GRPICONDIR));
pgid^.idEntries.common := pid^.idEntries.common;
pgid^.idEntries.nID := 1;
nSize := pid^.idEntries.common.dwBytesInRes;
GetMem(pvFile, nSize);
SetFilePointer(hFile, pid^.idEntries.dwImageOffset, nil, FILE_BEGIN);
ReadFile(hFile, pvFile^, nSize, uRead, nil);
CloseHandle(hFile);
hInst:=BeginUpdateResource(destexe, False);
if hInst > 0 then
begin
UpdateResource(hInst, RT_ICON, MAKEINTRESOURCE(1), LANG_NEUTRAL, pvFile, nSize);
EndUpdateResource(hInst, False);
result := True;
end;
FreeMem(pvFile);
FreeMem(pgid);
FreeMem(pid);
end;
end;
end.