Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen) (https://www.delphipraxis.net/170682-laden-und-speichern-von-icons-icon-parser-fuer-icon-dateien-oder-resourcen.html)

Zacherl 28. Sep 2012 12:19


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

Bummi 28. Sep 2012 13:06

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Hi Zacherl, das funktioniert schön:
Delphi-Quellcode:
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;
wie soll das mit den PE - Dateien gehen,oder verstehe ich etwas anderes als Du darunter?

Zacherl 28. Sep 2012 14:26

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:
ir.LoadFromResource(hInstance, 'MAINICON');
Wenn du Icons aus externen PE Dateien extrahieren willst, kannst du wie folgt vorgehen:
Delphi-Quellcode:
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;
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.

Delphi-Quellcode:
ir.SaveToResource('ExterneExeDatei.exe', 'ICONRESOURCENAME');
Wenn deine Zieldatei mehrere Icons besitzt könnte meine Methode allerdings teilweise die Einzelbilder überschreiben. Dafür habe ich bisher noch keinen Check eingebaut :)

Bummi 28. Sep 2012 17:42

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

Zacherl 28. Sep 2012 18:40

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:
ir.LoadFromResource('PEDatei.exe', PChar(12345));
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 :)

Bummi 28. Sep 2012 18:43

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:

MuTzE.Y85 29. Sep 2012 14:10

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 :)

Zacherl 29. Sep 2012 15:50

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Zitat:

Zitat von MuTzE.Y85 (Beitrag 1184960)
Warum die Mühe? Dafür gibts doch IconTools von Jan Peter Stotz :)

Diese Library war mir nicht bekannt. Habe sie mir mal kurz angeschaut und leider auch keine Funktion zum Speichern des Icons zurück in eine Resource gefunden. Für nonVCL Programme ist die Lib zudem auch nicht geeignet. Und mal ganz ehrlich: Irgendwas selbst zu programmieren macht um einiges mehr Spaß, als einfach nur eine fertige Komponente zu verwenden :)

MuTzE.Y85 1. Okt 2012 01:17

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Ja das stimmt, 1:0 für dich :)

Zacherl 5. Okt 2012 01:48

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:
http://www.delphipraxis.net/170834-h...festlegen.html

: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

ringli 1. Jan 2013 17:50

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:
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;
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?

Zacherl 1. Jan 2013 17:56

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));

ringli 1. Jan 2013 18:11

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.

ringli 1. Jan 2013 18:24

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. :?

Zacherl 1. Jan 2013 18:27

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Zitat:

Zitat von ringli (Beitrag 1197301)
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.

Schau mal im Debugger per Single Step, an welcher Stelle innerhalb von SaveToResource() der Fehler auftritt. Und nimm vielleicht testweise mal absolute Pfade, statt der Relativen.

ringli 1. Jan 2013 18:50

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.

Zacherl 1. Jan 2013 19:24

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Zitat:

Zitat von ringli (Beitrag 1197304)
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.

Kannst du deine Testanwendung + Source und den 2 Binaries mal hier hochladen? Ansonsten debugge mal bitte weiter, bei welchem API Aufruf innerhalb der DeleteExistingIconResources() Funktion der Fehler auftritt.

ringli 2. Jan 2013 16:45

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.

Zacherl 2. Jan 2013 19:07

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).

ringli 2. Jan 2013 19:34

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.

Zacherl 2. Jan 2013 19:49

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Zitat:

Zitat von ringli (Beitrag 1197407)
Wenn du schon beim Überarbeiten bist könntest du nochmal nachsehen warum die 256 x 256 Pixel Icons nicht mit übernommen werden.

Hat bei mir funktioniert :) Habe getestet mit dem standard Delphi XE2 Icon.

ringli 2. Jan 2013 20:15

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.

ringli 6. Jan 2013 14:48

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.

Zacherl 6. Jan 2013 15:47

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?

ringli 6. Jan 2013 19:33

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.

Zacherl 6. Jan 2013 23:58

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?

ringli 7. Jan 2013 08:07

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:

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?
Das habe ich auch mal gemacht. Ich habe dann die Ico-Datei in IcoFX geladen und erhalte die Meldung "68 Bit Bilder werden nicht unterstützt!". Entsprechend wird das 256 x 256 Pixel Icon auch nicht in IcoFX angezeigt obwohl das Icon laut Resourcenviewer vorhanden ist.

Zacherl 7. Jan 2013 09:57

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.

ringli 7. Jan 2013 10:26

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.

ringli 12. Jan 2013 15:31

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?

Zacherl 13. Jan 2013 08:51

AW: Laden und Speichern von Icons (Icon Parser, für Icon Dateien oder Resourcen)
 
Zitat:

Zitat von ringli (Beitrag 1198796)
Ich wollte mal fragen ob du schon die Zeit gefunden hast etwas an der Unit zu machen?

Negativ. Bin momentan leider noch an einem anderen Projekt am arbeiten. Ich werde hier posten, sobald ich die Unit geupdated habe.

Ghostwalker 22. Nov 2016 14:19

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.
http://pngdelphi.sourceforge.net


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.

Ghostwalker 22. Nov 2016 15:50

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 08:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz