Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Welche Auflösungen besitzt ein *.ico-File (https://www.delphipraxis.net/86527-welche-aufloesungen-besitzt-ein-%2A-ico-file.html)

SittingDuck 15. Feb 2007 11:04


Welche Auflösungen besitzt ein *.ico-File
 
Moin Moin ...

Ein *.ico-File kann ja Icons in in verschiedenen Auflösungen enthalten.
Wie kann man abfragen, ob z.B. ein Icon in der Auflösung 48x48 darin
enthalten ist.
Da ich über diesem Thema schwer graue Haare bekommen habe, wäre ich
über ein Beispiel sehr dankbar. :stupid:

Für Eure Mühe besten Dank ...

bitsetter 15. Feb 2007 11:43

Re: Welche Auflösungen besitzt ein *.ico-File
 
Ich weis aber nicht, ob folgenes immer funktioniert.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Icon : TIcon;
begin
  Icon:= TIcon.Create;
  try
    if OpenPictureDialog1.Execute then
    begin
      if FileExists(OpenPictureDialog1.FileName) then
      begin
        Icon.loadfromfile(OpenPictureDialog1.FileName);
        Caption := 'Breite: '+ inttostr(Icon.width);
        Caption := Caption+ '  Höhe: '+ inttostr(Icon.Height);
      end;
    end;
  finally
    Icon.Free;
  end;
end;

SittingDuck 15. Feb 2007 12:07

Re: Welche Auflösungen besitzt ein *.ico-File
 
Hi ...

Nee, hift leider nicht, denn es wird immer 32x32 zurückgegeben,
auch wenn das Icon höhere Auflösungen enthält. Ich glaube das
muss über GetIconInfo ablaufen.

Das Handle auf mein Icon in meiner gewünschten Auflösung bekomme ich so:
(aus den 'Abgründen' des Internets) :P

Delphi-Quellcode:
function GethIcon(FileName: String; icoSize: Cardinal; icoIndex: integer = 0): Cardinal;
var DeskTopISF: IShellFolder; IExIcon: IExtractIcon; PathPidl: PItemIDList; hIconL, hIconS: HIcon;
begin
 Result := 0;
 {this function uses the IExtractIcon to get an e.g. 48x48 icon Handle
 from a file that Has the Icon Bitmaps in it, like an Icon File (.ICO),
 an executable (.EXE) and a library (.DLL)}

 if SHGetDesktopFolder(DeskTopISF) <> NOERROR then Exit;
 PathPidl := nil;
 if DeskTopISF.GetUIObjectOf(0, 1, PathPidl, IID_IExtractIconA, nil, IExIcon) <> NOERROR then Exit;
 if (IExIcon.Extract(PChar(FileName), icoIndex, hIconL, hIconS,
     icoSize or (16 shl 16)) = NOERROR) and (hIconL <> 0) then Result := hIconL;
 DestroyIcon(hIconS);
end;
Das funktioniert (leider) auch, wenn die entsprechende Datei kein Icon in meiner gewünschten Auflösung besitzt. Windows vergrößert das Icon dann und das möchte ich (in besserer Qualität) lieber selber machen.
Hinterher geht das wohl nicht mehr, deshalb möchte ich irgendwie vorher erfragen ob z.B. ein 48x48-Icon enthalten ist und falls nicht, dann lese ich lieber das 32x32-Icon aus und vergrößere es selber (per gr32)

Dankbar für jeden weitern Ansatz, grüßt ...

SittingDuck 15. Feb 2007 12:36

Re: Welche Auflösungen besitzt ein *.ico-File
 
Liste der Anhänge anzeigen (Anzahl: 1)
So ...

Um das mal zu verdeutlichen ein Bild im Anhang

1. FireFox oben links: 48x48 im Icon vorhanden und korrekt angezeigt
2. FireFox oben rechts 32x32 ausgelesen und von mir auf 48x48 vergrößert
3. Halo-Icon unten links von Windows vergrößert :evil:
4. Halo-Icon unten rechts als 32x32 ausgelesen und von mir vergrößert

Nummer 3 ist leider pixelig, weil die Auflösung im Icon nicht vorhanden ist und genau das möchte ich im Vorfeld abfangen und lieber über die GR32-Lib vergrößern, weil Nummer 4 in diesem Fall besser aussieht.

bitsetter 16. Feb 2007 07:38

Re: Welche Auflösungen besitzt ein *.ico-File
 
Liste der Anhänge anzeigen (Anzahl: 1)
Jetzt verstehe ich auch erst, was du eigentlich erreichen möchtest.

Zitat:

Zitat von SittingDuck
3. Halo-Icon unten links von Windows vergrößert Evil or Very Mad
4. Halo-Icon unten rechts als 32x32 ausgelesen und von mir vergrößert

Nummer 3 ist leider pixelig, weil die Auflösung im Icon nicht vorhanden ist und genau das möchte ich im Vorfeld abfangen und lieber über die GR32-Lib vergrößern, weil Nummer 4 in diesem Fall besser aussieht.

Du kannst ja mal Halo mit dem Programm Resource Hacker öffnen, und du wirst sehen, dass Halo auch 3 Icone von 48X48 in verschiedenen Farbtiefen besitzt. Auf meinem Bild kannst du sehen, dass Icon Nr. 9 also das Richtige für dich gewesen wäre.
Eine Möglichkeit wäre, wenn du deine Icone als Bilder aus der Resource extrahiest. Was anderes macht Windows auch nicht. Du kannst ja mal die Suche benutzen um herrauszufinden, wie man Icon Resourcen auslesen kann.

SittingDuck 16. Feb 2007 10:36

Re: Welche Auflösungen besitzt ein *.ico-File
 
Moin Moin ...

Das stimmt, was Du sagst und mir war bewust, das das Halo-Icon auch im entsprechenden 48x48 Format vorliegt. (vielleicht ein etwas unglückliches Beispiel) Meine Routine von oben hätte in diesem Falle auch das korrekte Icon herausgezogen.
Aber: Wehe wenn eine Exe-Datei kein Icon im gewünschten Format besitzt ! Dann kommt es zu meinem Pixel-Effekt bei dem Windows, intern mit einer 'lausigen' Stretch-Routine das vergrößerte (nicht vorhandene) Icon zurückgibt.
So ... weil ich meine, das die GR32-Truppe das besser kann, möchte ich vorher wissen, ob die Auflösung überhaupt in der Exe vorhanden ist.

Die Idee mit dem Resourcen-Auslesen ist schon klar ... und zu diesem Thema habe ich auch schon kistenweise Routinen getestet, aber am Ende kommen sie immer mit einem von Windows gestreckten Icon um die Ecke ... :evil:
Deshalb beeindruckt mich ja auch diese Mini-Routine von oben, welche ich nach ewig langer Suche im Internet gefunden habe. Diese 'frisst' praktisch alles was an Dateien daherkommt, ohne die 'LoadLibrary'-Befehle und einen Nachteil konnte ich bisher nicht feststellen. (unbedingt ein Tipp für die CodeLib !!!)

Da das ursprüngliche Problem noch besteht bin ich für weitere Ideen immer sehr dankbar ...

bitsetter 17. Feb 2007 00:32

Re: Welche Auflösungen besitzt ein *.ico-File
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin,

mein Programm habe ich jetzt fertiggestellt, also dei den Dateien die ich getestet habe, hat es funktioniert. Kannst ja mal testen ob es zu gebrauchen ist.

EDIT: einen Fehler behoben

SittingDuck 17. Feb 2007 08:31

Re: Welche Auflösungen besitzt ein *.ico-File
 
Großartig so weit !!! Tolle Arbeit bitsetter. :thumb: Die Routine macht genau das, was ich alleine so nicht hinbekommen habe ... Besten Dank dafür ! Exe und Dll's klappen auf Anhieb. Bei reinen *.ico-Dateien ist das Programm leider immer der Meinung es gäbe keine 48x48-Icone. Haben die ein anderes Format ?

Schöne sonnige Tage, wünscht ...

bitsetter 17. Feb 2007 09:23

Re: Welche Auflösungen besitzt ein *.ico-File
 
Liste der Anhänge anzeigen (Anzahl: 1)
Schön, dass es bei dir funktioniert, ich werde heute nochmal sehen, ob man da was machen kann. Auf jeden Fall enthält ein Icon ja normalerweise keine Ressourcen, daher wird es nicht funktionieren.

EDIT: Jetzt habe ich noch ein Programm, dass feststellen kann ob in ".ico" Dateien Icone mit einer Auflösung von 48X48 (und auch andere Auflösungen) enthalten sind. Bei den von mir getesteten Iconen, hat es jedenfalls funktioniert.

bitsetter 18. Feb 2007 23:43

Re: Welche Auflösungen besitzt ein *.ico-File
 
Mit folgender Routine kann man prüfen, ob sich in *.ico- oder in PE- Dateien mit Ressourcen wie *.exe *.dll usw., sich Icone in einer bestimmten Auflösung befinden.
Die Funktion HasIcoSize() könnte man also vor der von SittingDuck gesendeten Routine aufrufen. Bei den von mir getesteten Dateien hat es bis jetzt funktioniert.
Falls noch einer Fehler in der Funktion findet, dann kann er sich ja dazu äußern, ich werde diese dann beheben.

Delphi-Quellcode:
type
  TResID = record
    ResInt: integer;
    ResString: AnsiString;
    isInteger: boolean;
end;

type
   PResID = ^TResID;

function EnumResIcon(Module: THandle; resType: PChar; HasIconGroup: PBool): bool; stdcall;
begin
  if resType = RT_GROUP_ICON then
  begin
    HasIconGroup^:= true;
    result:= false;
  end
  else
    result:= true;
end;

function EnumIconNames(Module: THandle; ResType, ResName: PChar; ResID: PResID): bool; stdcall;
begin
  if integer(resName)< $FFFF then
  begin
    ResID^.ResInt:= integer(ResName);
    ResID^.isInteger:= true;
  end
  else
  begin
    SetString(ResID^.ResString, ResName, Length(ResName));
    ResID^.isInteger:= false;
  end;
  result:= false;
end;

function HasIcoSize(IconPfad: AnsiString; IconSize: Byte): boolean;
var
  IconNr, IconAnzahl: byte;
  Next: cardinal;
  IconStream: TFileStream;
  ResStream: TResourceStream;
  Buffer: array of byte;
  FileExt: AnsiString;
  Lib: THandle;
  HasIcons: LongBool;
  ResID: TResID;
begin
  result:= false;
  if FileExists(IconPfad) then
  begin
    FileExt:= UpperCase(ExtractFileExt(IconPfad));
    if (FileExt= '.ICO') or (FileExt= '.CUR') then
    begin
      IconStream:= TFileStream.Create(IconPfad, fmOpenRead);
      try
        if IconStream.Seek(4, soFromCurrent)= 4 then
        if IconStream.Read(IconAnzahl, 1)= 1 then
        if IconStream.Seek(0, soFromBeginning)= 0 then
        begin
          Next:= 6;
          setlength(Buffer, IconAnzahl* 16);
          if IconStream.Read(Buffer[0], length(Buffer))= Length(Buffer) then
            for IconNr:= 1 to IconAnzahl do
            begin
              if (Buffer[Next]= IconSize) and (Buffer[Next+ 1]= IconSize) then
              begin
                result:= true;
                break;
              end;
              inc(Next, 16);
            end;
        end;
      finally
        IconStream.Free;
      end;
    end
    else
    begin
      Lib:= LoadLibraryEx(PChar(IconPfad), 0, LOAD_LIBRARY_AS_DATAFILE);
      if Lib<> 0 then
      try
        HasIcons:= false;
        EnumResourceTypes(Lib, @EnumResIcon, integer(@HasIcons));
        if HasIcons then
        begin
          EnumResourceNames(Lib, RT_GROUP_ICON, @EnumIconNames, integer(@ResID));
          if ResID.isInteger then
            ResStream:= TResourceStream.CreateFromID(Lib, ResID.ResInt, RT_GROUP_ICON)
          else
            ResStream:= TResourceStream.Create(Lib, ResID.ResString, RT_GROUP_ICON);
          try
            IconAnzahl:= byte(pointer(cardinal(ResStream.Memory)+ 4)^);
            Next:= 6;
            for IconNr:= 1 to IconAnzahl do
            begin
              if (byte(pointer(cardinal(ResStream.Memory)+ Next)^)= IconSize) and
                (byte(pointer(cardinal(ResStream.Memory)+ Next+ 1)^)= IconSize) then
              begin
                result:= true;
                break;
              end;
              inc(Next, 14);
            end;
          finally
            ResStream.Free;
          end;
        end;
      finally
        windows.FreeLibrary(Lib);
      end;
    end;
  end;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.execute then
  if HasIcoSize(OpenDialog1.FileName, 48)then
    Showmessage('Die Datei hat Icone mit mit einer Größe von 48 X 48')
  else
    Showmessage('Die Datei hat KEINE Icone mit mit einer Größe von 48 X 48')
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:40 Uhr.
Seite 1 von 2  1 2      

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