![]() |
Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo zusammen,
die hier vorgestellte Unit beinhaltet eine Klasse zum Laden und Speichern von Icons. Die Icons können sowohl aus einer Icon Datei, als auch aus einer Resource (beliebige PE Datei) geladen werden. Die Klasse stellt dann sämtliche Einzelbilder des geladenen Icons in einer Liste zur Verfügung. Bei Bedarf können auch die entsprechenden GDI Handles zum Zeichnen des Icons (per DrawIcon) erstellt werden (CreateIconHandles auf true setzen). Das Hinzufügen, Entfernen oder Bearbeiten von Bildern wird nicht unterstüzt. Allerdings kann die Klasse beispielsweise dazu verwendet werden, um einer beliebigen PE Datei ein Icon hinzuzufügen, oder das bestehende Icon zu ersetzen. Viele Grüße Zacherl |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Hi Zacherl, das funktioniert schön:
Delphi-Quellcode:
wie soll das mit den PE - Dateien gehen,oder verstehe ich etwas anderes als Du darunter?
procedure TForm3.Button1Click(Sender: TObject);
var ir:TdxIconResource; ic:TIcon; i:Integer; begin ic := TIcon.Create; ir:=TdxIconResource.Create; ir.CreateIconHandles := true; ir.LoadFromFile('C:\Icons\IconCollection\ix_ap_all\ico-files\add.ico'); Caption := IntToStr(ir.ImageCount); For i := 0 to ir.ImageCount - 1 do begin memo1.Lines.Add(Format('H: %d W:%d NB:%d HD:',[ir.Images[i].Width,ir.Images[i].Height,ir.Images[i].Numbytes,ir.Images[i].Handle])) ; ic.Handle := ir.Images[i].Handle; canvas.Draw(i*50,i*20,ic); end; ic.Free; ir.Free; end; |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Hallo Bummi,
analog zum Laden aus einer Icon Datei, kannst du folgendes machen, um z.b. das Icon deiner eigenen EXE zu laden:
Delphi-Quellcode:
Wenn du Icons aus externen PE Dateien extrahieren willst, kannst du wie folgt vorgehen:
ir.LoadFromResource(hInstance, 'MAINICON');
Delphi-Quellcode:
Beim Speichern eines Icons in eine PE Datei funktioniert es etwas anders. Dort muss zum einen der Icon Header als RT_GROUPICON Resource angelegt werden und die Einzelbilder dann jeweils als eigene RT_ICON Resource. Deshalb übernimmt die SaveToResource() Funktion in diesem Falle den Dateinamen der Zieldatei als Parameter.
var
hModule: THandle; begin hModule := LoadLibraryEx('ExterneExeDatei.exe', 0, LOAD_LIBRARY_AS_DATAFILE); if (hModule <> 0) and (hModule <> INVALID_HANDLE_VALUE) then try ir.LoadResource(hModule, 'ICONRESOURCENAME'); finally FreeLibrary(hModule); end; end;
Delphi-Quellcode:
Wenn deine Zieldatei mehrere Icons besitzt könnte meine Methode allerdings teilweise die Einzelbilder überschreiben. Dafür habe ich bisher noch keinen Check eingebaut :)
ir.SaveToResource('ExterneExeDatei.exe', 'ICONRESOURCENAME');
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Liste der Anhänge anzeigen (Anzahl: 2)
Da ich keine Möglichkeit fand unbenannte Icongroups zu laden habe ich den Code etwas erweitert. Ich habe die geänderte Datei als dxIconUtils_modi.pas beigelegt, da ich nicht sicher bin ob die Änderungen so wie sie vorgenommen wurden für Dich akzeptabel sind.
EDIT: Rückgebaut siehe Folgepost |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Hallo Bummi,
die Funktion zum Enumerieren der Resourcen passt sehr gut dazu :) Für Erweiterungen der Unit, bzw. allgemein meiner Codes bin ich immer offen und dankbar. Danke auch für deine Demo Anwendung! Um eine unbenannte bzw. ID Resource zu laden, wäre alternativ auch folgende Lösung mit meiner originalen LoadFromResource Funktion möglich gewesen:
Delphi-Quellcode:
Wobei 12345 hier für die ID der IconGroup Resource steht. Die Windows APIs zum Laden von Resourcen erwarten einen PChar Parameter und erkennen automatisch, ob man hier wirlich einen Namen oder nur eine ID übergeben hat. Aus diesem Grund habe ich den ResourceName Parameter der LoadFromResource Funktion ebenfalls als PChar deklariert und nicht, wie man es vermutlich normalerweise machen würde, als String :)
ir.LoadFromResource('PEDatei.exe', PChar(12345));
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Danke ... ich bau das zurück, was ein didn't know :oops:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Warum die Mühe? Dafür gibts doch IconTools von Jan Peter Stotz :)
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Ja das stimmt, 1:0 für dich :)
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Hatte ganz vergessen die SaveToResource Funktion komplett zu implementieren :-D Leider gibt es momentan ab und zu noch Probleme ein Icon hinzuzufügen, wenn die EXE vorher kein Icon besessen hat. Fals jemand einen Tipp für mich hat, bitte hier posten:
![]() :arrow: SaveToResource Funktion vervollständigt Das Speichern funktioniert nun in den meisten Fällen. Achtung: Hat die neue Icon Resource mehr Einzelbilder, als die ersetzte Resource, können eventuell weitere Einzelbilder überschrieben werden.:arrow: FindIconImageIndex hinzugefügt FindIconImageIndex sucht anhand der übergebenen Maßen (und optional Farbtiefe) den Index des passendsten Einzelbildes heraus |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Ich habe mal versucht mit Hilfe der Unit das MAINICON einer bestehenden Delphi Anwendung zu ändern. Dazu habe ich den Beispielcode von Bummi in leicht abgeänderter Form verwendet. Allerdings gelingt es mir nicht das MAINICON zu ändern. Weder mit einer ICO-Datei noch mit einem Icon aus einer anderen Anwendung. Wahrscheinlich sehe ich meinen Fehler nur nicht. Könnte mir jemand auf die Sprünge helfen?
Delphi-Quellcode:
BTW: Wie kann man bei der Verwendung von IconDLL's etc. die Nummer des zu verwendenen Icons angeben, da hier der Pfad zur Datei ja immer der selbe ist?
uses
dxIconUtils; procedure TForm2.Button1Click(Sender: TObject); var ir:TdxIconResource; hModule: THandle; begin ir:=TdxIconResource.Create; //ir.CreateIconHandles := true; //ir.LoadFromFile('Testicon.ico'); hModule := LoadLibraryEx('TestPE.exe', 0, LOAD_LIBRARY_AS_DATAFILE); if (hModule <> 0) and (hModule <> INVALID_HANDLE_VALUE) then try ir.LoadFromResource(hModule, 'MAINICON'); finally FreeLibrary(hModule); end; ir.SaveToResource('AppWithNewIcon.exe', 'MAINICON'); ShowMessage(IntToStr(ir.ImageCount)); // Anzahl enthaltener Icons wird angezeigt bspw. 9, 10 etc. ir.Free; end; |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Könnte es eventuell sein, dass der Windows Icon Cache noch das alte Icon beinhaltet und deshalb keine Änderung sichtbar ist? Der Code sieht eigentlich gut aus. Was sagt denn GetLastError() nach dem Aufruf von SaveToResource()?
Für Icon DLLs oder EXEn mit ordinalen Resourcenbezeichnern, kannst du die entsprechende Nummer einfach in PChar casten:
Delphi-Quellcode:
LoadFromResource(hModule, PChar(1337));
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Also der Aufruf von GetLastError gibt Fehler 5 (Zugriff verweigert) aus. Die Datei ist aber definitiv nicht im Zugriff. Virenscanner habe ich grade testweise deaktiviert. Das Ergebnis ist dasselbe. Es sei denn Windows hat sich verschluckt. Das werde ich gleich nochmal ausprobieren.
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
So, ein Neustart von Windows hat nichts gebracht. Den IconCache schliesse ich mal aus, da ich die zu modifizierende Datei nach der Änderung in einem Resourcenviewer öffne um die Änderung zu betrachten.
Ich bin ehrlich gesagt ratlos. :? |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Also der Fehler tritt auf beim Aufruf von DeleteExistingIconResource innerhalb der SaveToResource-Funktion. Hilft dir das weiter? Die Pfade sind absolut. Ich habe die nur fürs Forum auf das wesentliche gekürzt.
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Also ich bin nicht weitergekommen beim Debuggen. Habe jetzt auch noch ein paar andere Testdateien ausprobiert und erhalte immer "Zugriff verweigert". Anbei das gewünschte Testprojekt.Vielleicht findest du ja etwas oder es funktioniert sogar auf Anhieb.
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Liste der Anhänge anzeigen (Anzahl: 1)
Hier schonmal ein temporärer Bugfix für das Problem. Werde den Code nochmal etwas überarbeiten, da die momentane Lösung etwas unsauber ist:
1) Die EnumResource* Callbacks hatten einen Fehler, bei dem Strings nicht korrekt nullterminiert wurden 2) Ich hatte versucht EndUpdateResource() aufzurufen, während die Datei noch per LoadLibraryEx() geladen war. Daher kam auch die "Zugriff verweigert" Meldung. Allerdings wurde das Delphi Icon bei mir auch nach diesen Änderungen nicht korrekt übernommen. Die CaCV.exe hatte danach einfach überhaupt kein Icon mehr. Warum das so ist, kann ich mir allerdings auch nicht erklären. Habe es daraufhin mal mit einem anderen Icon probiert und das funktioniert wunderbar (2 von 3 Resourcen Editoren hatten mit dem alten Delphi Icon, das du versuchst hinzuzufügen, ebenfals Probleme). |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
So wie es aussieht, funktioniert es erstmal. :) Danke für den Bugfix.
Wenn du schon beim Überarbeiten bist könntest du nochmal nachsehen warum die 256 x 256 Pixel Icons nicht mit übernommen werden. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
:? Bei mir hat es nicht funktioniert. Mal sehen ob ich noch etwas rausfinde woran es bei mir liegen könnte.
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Liste der Anhänge anzeigen (Anzahl: 2)
Du hast recht, die 256 x 256 Icons werden tatsächlich hinzugefügt. Allerdings werden diese falsch gekennzeichnet. Anbei mal ein Screenshot vom Resourcenviewer. Hier sieht man, das das Icon zwar vorhanden ist, allerdings wird die Größe falsch gekennzeichnet mit 13 x 0 (Bild: Iconresourcen Zieldatei nach Verwendung der dxIconUtils.png).
Der andere Screenshot (Bild: Iconresourcen Quelldatei.png) zeigt die enthaltenen Iconresourcen der Quelldatei mit den passenden Größen. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Puh da scheint einiges schief zu gehen :? Ich schaue bei Gelegenheit mal, ob ich die Fehlerursache auf die Schnelle finde. Hast du mal im Debugger geschaut, ob der GroupIcon Header für das entsprechende 256px Icon korrekte Werte beinhaltet?
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Welche Werte müsste ich denn überprüfen? Ich steige durch deinen Code leider nicht wirklich durch.
[EDIT] Ich habe mir mal die Werte für GroupHeader.idEntries[I].Width & GroupHeader.idEntries[I].Height in der SaveToResource-Funktion anzeigen lassen. Bei den Icons bis hin zu 48 x 48 Pixel stimmt der Wert. Beim 256 x 256 Pixel Icon werden wie schon im Screenshot zu sehen 13 x 0 Pixel angezeigt. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Alles klar, dann liegt der Fehler mit hoher Sicherheit schon in der Funktion, die das Icon läd. Kannst du mal probieren, das Icon als .ico Datei zu speichern? Tritt das Problem dann auch noch auf, oder nur dann, wenn das Icon aus einer Resource extrahiert wird?
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Interessant was jetzt zu Tage tritt. Lade ich das Icon direkt als 'ico'-Datei und speichere dies in die Resource erhalte ich im Resourcenviewer eine Größenangabe von 13 x 13 Pixel obwohl es in Wirklichkeit das 256 x 256 Pixel Icon ist. Die anderen Größen bis 48 x 48 Pixel sind nach wie vor in Ordnung.
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Wie ich grade gelesen habe, werden 256x256px Icons innerhalb der ICO Datei (oder Resource) als PNG abgelegt. Deshalb scheitert bei mir das Auslesen des Bitmap Headers. Um das zu Beheben, muss ich wohl einen kleinen Parser für den PNG Header schreiben, um die Maße und die Farbtiefe zu ermitteln. Der GroupIcon Header enthält diese Werte normalerweise auch, aber bei dem 256x256px Icon, sind diese auf 0 gesetzt, weshalb ich als Workaround die Werte direkt aus dem Bitmap Header ausgelesen habe.
Vermutlich sollen die 0 Werte indizieren, dass es sich um ein PNG Bild handelt. Wäre gut, wenn das jemand bestätigen könnte. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Also was ich bisher gesehen habe werden die großen Icons komprimiert abgelegt. Könnte durchaus sein das das intern als PNG erfolgt. Von daher wäre der Weg über den Parser vielleicht keine schlechte Idee.
[EDIT] Ich habe mir mal grade eine entsprechende ICO Datei im Texteditor angesehen. Dort findet man auch die typische %PNG-Kennung für das PNG-Format. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Ich wollte mal fragen ob du schon die Zeit gefunden hast etwas an der Unit zu machen?
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Zitat:
|
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Der Thread ist zwar schon was älter, aber, denk ich, nach wie vor aktuell.
Ich hab mir Zacherl's Code vorgenommen um noch ein paar extra Features dazu zu bauen. Schließlich ist aber trotzdem eine eigene Klasse dazu gekommen (siehe Anhang) Wichtiger Hinweiß: Da mein Delphi keinen nativen PNG-Support bietet, bin ich auf eine externe Lib ausgewichen. ![]() Bisher hab ich das ganze nur rudimentär getestet (oder anders gesagt: Der Compiler meckert nicht). Wer also Lust hat...... :) Natürlich sind auch Verbesserungen/Featurewünsche gern gesehen. |
AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
Liste der Anhänge anzeigen (Anzahl: 1)
Kleiner Fix beim Laden aus der Resource.
Die Tests (laden und speichern) laufen bisher gut. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz