Вопрос такой- как можно заменить иконку готового приложения программным методом
т.е есть файлик с расширением ico и есть exe файл
надо заменить иконку exe файла на икону *.ico
пробовал при помощи UpdateResourse - не получается
может кто подскажет?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
15-12-2008 03:38
всё работает. вот тот-же самый код с минимальными изменениями:
function IsValidIcon(P: Pointer; Size: Cardinal): Boolean;
var
ItemCount: Cardinal;
begin
Result := False;
if Size < Cardinal(SizeOf(Word) * 3) then
Exit;
if (PChar(P)[0] = 'M') and (PChar(P)[1] = 'Z') then
Exit;
ItemCount := PIcoHeader(P).ItemCount;
if Size < Cardinal((SizeOf(Word) * 3) + (ItemCount * SizeOf(TIcoItem))) then
Exit;
P := @PIcoHeader(P).Items;
while ItemCount > Cardinal(0) do begin
if (Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) < Cardinal(PIcoItem(P).Offset)) or
(Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) > Cardinal(Size)) then
Exit;
Inc(PIcoItem(P));
Dec(ItemCount);
end;
Result := True;
end;
var
H: THandle;
M: HMODULE;
R: HRSRC;
Res: HGLOBAL;
GroupIconDir, NewGroupIconDir: PGroupIconDir;
I: Integer;
wLanguage: Word;
fh: Cardinal;
Ico: PIcoHeader;
N: Cardinal;
NewGroupIconDirSize: LongInt;
begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then
Error('Only supported on Windows NT and above');
Ico := nil;
try
{ Load the icons }
fh := FileOpen(IcoFileName, fmOpenRead);
try
N := GetFileSize(fh, nil);
if Cardinal(N) > Cardinal($100000) then { sanity check }
Error('Icon file is too large');
GetMem(Ico, N);
FileRead(fh, ico^, N);
finally
FileClose(fh);
end;
{ Ensure the icon is valid }
if not IsValidIcon(Ico, N) then
Error('Icon file is invalid');
{ Update the resources }
H := BeginUpdateResource(PChar(FileName), False);
if H = 0 then
error('BeginUpdateResource failed (1)');
try
M := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
if M = 0 then
error('LoadLibraryEx failed (1)');
try
{ Load the 'MAINICON' group icon resource }
R := FindResource(M, 'MAINICON', RT_GROUP_ICON);
if R = 0 then
error('FindResource failed (1)');
Res := LoadResource(M, R);
if Res = 0 then
error('LoadResource failed (1)');
GroupIconDir := LockResource(Res);
if GroupIconDir = nil then
error('LockResource failed (1)');
{ Delete 'MAINICON' }
//if not GetResourceLanguage(M, RT_GROUP_ICON, 'MAINICON', wLanguage) then
// Error('GetResourceLanguage failed (1)');
if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', wLanguage, nil, 0) then
error('UpdateResource failed (1)');
{ Delete the RT_ICON icon resources that belonged to 'MAINICON' }
for I := 0 to GroupIconDir.ItemCount-1 do begin
//if not GetResourceLanguage(M, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), wLanguage) then
// Error('GetResourceLanguage failed (2)');
if not UpdateResource(H, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), LANG_NEUTRAL, nil, 0) then
error('UpdateResource failed (2)');
end;
{ Build the new group icon resource }
NewGroupIconDirSize := 3*SizeOf(Word)+Ico.ItemCount*SizeOf(TGroupIconDirItem);
GetMem(NewGroupIconDir, NewGroupIconDirSize);
try
{ Build the new group icon resource }
NewGroupIconDir.Reserved := GroupIconDir.Reserved;
NewGroupIconDir.Typ := GroupIconDir.Typ;
NewGroupIconDir.ItemCount := Ico.ItemCount;
for I := 0 to NewGroupIconDir.ItemCount-1 do begin
NewGroupIconDir.Items[I].Header := Ico.Items[I].Header;
NewGroupIconDir.Items[I].Id := I+1; //assumes that there aren't any icons left
end;
{ Update 'MAINICON' }
for I := 0 to NewGroupIconDir.ItemCount-1 do
if not UpdateResource(H, RT_ICON, MakeIntResource(NewGroupIconDir.Items[I].Id), 1033, Pointer(DWORD(Ico) + Ico.Items[I].Offset), Ico.Items[I].Header.ImageSize) then
error('UpdateResource failed (3)');
{ Update the icons }
if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', 1033, NewGroupIconDir, NewGroupIconDirSize) then
error('UpdateResource failed (4)');
finally
FreeMem(NewGroupIconDir);
end;
finally
FreeLibrary(M);
end;
except
EndUpdateResource(H, True); { discard changes }
raise;
end;
if not EndUpdateResource(H, False) then
error('EndUpdateResource failed');
finally
FreeMem(Ico);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
UpdateIcons('c:\res.exe', 'c:\icon.ico');
end;
08-11-2006 08:32 | Комментарий к предыдущим ответам
Невозможно использовать данный пример, так как не понятна структура TFile.
А что там такого непонятного? Ну замените его на TFileStream или на TMemoryStream. Из исходника отлично видно что ни для чего кроме считывания всего файла в переменную Ico этот TFile не используется.
function IsValidIcon(P: Pointer; Size: Cardinal): Boolean;
var
ItemCount: Cardinal;
begin
Result := False;
if Size < Cardinal(SizeOf(Word) * 3) then
Exit;
if (PChar(P)[0] = 'M') and (PChar(P)[1] = 'Z') then
Exit;
ItemCount := PIcoHeader(P).ItemCount;
if Size < Cardinal((SizeOf(Word) * 3) + (ItemCount * SizeOf(TIcoItem))) then
Exit;
P := @PIcoHeader(P).Items;
while ItemCount > Cardinal(0) do begin
if (Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) < Cardinal(PIcoItem(P).Offset)) or
(Cardinal(PIcoItem(P).Offset + PIcoItem(P).Header.ImageSize) > Cardinal(Size)) then
Exit;
Inc(PIcoItem(P));
Dec(ItemCount);
end;
Result := True;
end;
var
H: THandle;
M: HMODULE;
R: HRSRC;
Res: HGLOBAL;
GroupIconDir, NewGroupIconDir: PGroupIconDir;
I: Integer;
wLanguage: Word;
F: TFile;
Ico: PIcoHeader;
N: Cardinal;
NewGroupIconDirSize: LongInt;
begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then
Error('Only supported on Windows NT and above');
Ico := nil;
try
{ Load the icons }
F := TFile.Create(IcoFileName, fdOpenExisting, faRead, fsRead);
try
N := F.CappedSize;
if Cardinal(N) > Cardinal($100000) then { sanity check }
Error('Icon file is too large');
GetMem(Ico, N);
F.ReadBuffer(Ico^, N);
finally
F.Free;
end;
{ Ensure the icon is valid }
if not IsValidIcon(Ico, N) then
Error('Icon file is invalid');
{ Update the resources }
H := BeginUpdateResource(PChar(FileName), False);
if H = 0 then
ErrorWithLastError('BeginUpdateResource failed (1)');
try
M := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
if M = 0 then
ErrorWithLastError('LoadLibraryEx failed (1)');
try
{ Load the 'MAINICON' group icon resource }
R := FindResource(M, 'MAINICON', RT_GROUP_ICON);
if R = 0 then
ErrorWithLastError('FindResource failed (1)');
Res := LoadResource(M, R);
if Res = 0 then
ErrorWithLastError('LoadResource failed (1)');
GroupIconDir := LockResource(Res);
if GroupIconDir = nil then
ErrorWithLastError('LockResource failed (1)');
{ Delete 'MAINICON' }
if not GetResourceLanguage(M, RT_GROUP_ICON, 'MAINICON', wLanguage) then
Error('GetResourceLanguage failed (1)');
if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', wLanguage, nil, 0) then
ErrorWithLastError('UpdateResource failed (1)');
{ Delete the RT_ICON icon resources that belonged to 'MAINICON' }
for I := 0 to GroupIconDir.ItemCount-1 do begin
if not GetResourceLanguage(M, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), wLanguage) then
Error('GetResourceLanguage failed (2)');
if not UpdateResource(H, RT_ICON, MakeIntResource(GroupIconDir.Items[I].Id), wLanguage, nil, 0) then
ErrorWithLastError('UpdateResource failed (2)');
end;
{ Build the new group icon resource }
NewGroupIconDirSize := 3*SizeOf(Word)+Ico.ItemCount*SizeOf(TGroupIconDirItem);
GetMem(NewGroupIconDir, NewGroupIconDirSize);
try
{ Build the new group icon resource }
NewGroupIconDir.Reserved := GroupIconDir.Reserved;
NewGroupIconDir.Typ := GroupIconDir.Typ;
NewGroupIconDir.ItemCount := Ico.ItemCount;
for I := 0 to NewGroupIconDir.ItemCount-1 do begin
NewGroupIconDir.Items[I].Header := Ico.Items[I].Header;
NewGroupIconDir.Items[I].Id := I+1; //assumes that there aren't any icons left
end;
{ Update 'MAINICON' }
for I := 0 to NewGroupIconDir.ItemCount-1 do
if not UpdateResource(H, RT_ICON, MakeIntResource(NewGroupIconDir.Items[I].Id), 1033, Pointer(DWORD(Ico) + Ico.Items[I].Offset), Ico.Items[I].Header.ImageSize) then
ErrorWithLastError('UpdateResource failed (3)');
{ Update the icons }
if not UpdateResource(H, RT_GROUP_ICON, 'MAINICON', 1033, NewGroupIconDir, NewGroupIconDirSize) then
ErrorWithLastError('UpdateResource failed (4)');
finally
FreeMem(NewGroupIconDir);
end;
finally
FreeLibrary(M);
end;
except
EndUpdateResource(H, True); { discard changes }
raise;
end;
if not EndUpdateResource(H, False) then
ErrorWithLastError('EndUpdateResource failed');
finally
FreeMem(Ico);
end;
end;
Для прояснения ситуации обьясняю- я пишу прожку для склейки файлов, сама склейка вроде как работает осталось добавить возможность изменения иконки результирующего файла
P.S спасибо всем кто помогает, приду домой все попробую а счас нет возможности все проверить
в таком случае я обычно беру ресторатора (Restorator) и им меняю все что нужно.
я думаю в твоем случае тебе надо получить список и адреса (возможно еще и графическое представление) ресурсов.
потом производишь присвоение нужному ресурсу нужное значение и сохраняешь ехе-шник
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.