Entwickler-Ecke

Windows API - ...Icon für eine beliebige Datei holen


Popov - Fr 30.01.04 01:00
Titel: ...Icon für eine beliebige Datei holen
Es gibt zwei Möglichkeiten Icons aus EXE, DLL und ICO Dateien zu extrahieren: mit API Funktion ExtractIcon [http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/resources/icons/iconreference/iconfunctions/extracticon.asp] und mit API Funktion ExtractAssociatedIcon [http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/resources/icons/iconreference/iconfunctions/extractassociatedicon.asp].

Das ist ein Beispiel wie es mit ExtractAssociatedIcon geht:

Bei ExtractIcon können nur Icons aus den oben angegebenen Dateien extrahiert werden, d.h. die Datei muß Icons enthalten. Enhällt eine Datei, z.B. "c:\autoexec.bat", selbst kein Icons, dann kann man mit ExtractAssociatedIcon einen im System registriertes Icon für die Datei holen.

Hier muß man nicht wissen wieviel Icons die Datei enthällt (wenn erwünscht, dann kann man es mit ExtractIcon [http://www.delphiforum.de/viewtopic.php?p=125375&sid=f8d41dbea1f04fc95d9042f57f3a082f#125375] machen [siehe die TotalNumberOfIcons Funktion]). Wird eine höhere Zahl angegeben wie es Icons in der EXE, DLL oder ICO gibt, dann wird das erste Icon zurückgegeben (also keine Fehlermeldung, sondern ein falsches Icon). Enthällt die Datei sellbst kein Icon (z.B. "c:\config.sys"), dann wird das Icon zurückgegeben wie es in der Registry vereinbart wurde.

Aus diesem Grund liefere ich zwei Varianten zum holen eines Icon. Die Einfache: da es bei TXT oder DOC keinen Sinn macht eine Indexzahl anzugeben, wird in dieser Version keine Indexzahl verlangt. Bei EXE, DLL und ICO wird in dieser Version immer das erste Icon zurückgegeben. Dann die normale Variante: hier kann angegeben werden welches Icon in der Reihe zurückgegeben wird. Bei TXT oder DOC wird das registrierte Icon zurückgegeben; Index hat also keinen Einfluß. Bei EXE, DLL und ICO wird das X'te Icon zurückgeliefert:

Einfache Variante:

Die Funktion erwartet zwei Parameter:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
uses
  ShellApi;

// Einfache Variante: Gibt den Icon ...
// - einer EXE, DLL oder ICO zurück (in dieser Variante den ersten Icon)
// - den in der Reg mit Datei verknüpften Icon (bei TXT z.B. von Notepad.exe)
procedure GetAssociatedIconFromFileA(const FileName: String; Icon: TIcon);
var
  Index: Word;
begin
  Index := 0;
  Icon.Handle:= ExtractAssociatedIcon(HInstance, PChar(FileName), Index);
end;


Beispiel :

Icon für die "autoexec.bat" suchen und auf Formular zeichnen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button1Click(Sender: TObject);
var
  AIcon: TIcon;
begin
  AIcon := TIcon.Create;
  try
    GetAssociatedIconFromFileA('c:\autoexec.bat', AIcon);
    Canvas.Draw(00, AIcon);
  finally
    AIcon.Free;
  end;
end;



Normale Variante:

Die Funktion erwartet drei Parameter:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
uses
  ShellApi;

// Normale Variante: Gibt den Icon ...
// - einer EXE, DLL oder ICO zurück (in dieser Variante den X'ten Icon)
// - den in der Reg mit Datei verknüpften Icon (bei TXT z.B. von Notepad.exe)
procedure GetAssociatedIconFromFileB(const FileName: String; Index: Word;
  Icon: TIcon);
var
  Index2: Word;
begin
  Index2 := Index;
  Icon.Handle:= ExtractAssociatedIcon(HInstance, PChar(FileName), Index2);
end;


Beispiel :

Das zweite Icon für die "explorer.exe" suchen und auf Formular zeichnen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.Button1Click(Sender: TObject);
var
  AIcon: TIcon;
begin
  AIcon := TIcon.Create;
  try
    GetAssociatedIconFromFileB('c:\win98se\explorer.exe'1, AIcon);
    Canvas.Draw(00, AIcon);
  finally
    AIcon.Free;
  end;
end;


Popov - Fr 30.01.04 01:50

Spasshalber noch paar Möglichkeiten. Es geht hier nicht mehr drum ein Icon zu holen, sondern wie es übergeben wird. In den oberen Funktionen wird das TIcon Objekt als Parameter übergeben. Hier zwei Möglichkeiten wie es als Wert übergeben werden kann. Um es übersichtlicher zu machen wird hier nur die Einfache-Variante angewandt (es wird also kein Icon-Index übergeben).

Zuerst die Objektübergabe. Ich mag sie nicht, da hier ganz sicher vergessen wird das Objekt wieder frei zu geben. Aber es ist möglich:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function GetIconX1(const FileName: String): TIcon;
var
  Index: Word;
begin
  Index := 0;
  Result := TIcon.Create;
  Result.Handle := ExtractAssociatedIcon(HInstance, PChar(FileName), Index);
end;


Beispiel:

Hier kann das Icon direkt übergeben werden:


Delphi-Quelltext
1:
2:
3:
...
   Form1.Icon := GetIconX1('c:\windows\explorer.exe');
...


oder


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
  AIcon: TIcon;
begin
  try
    AIcon := GetIcon1('c:\windows\explorer.exe');
    Canvas.Draw(00, AIcon);
  finally
    AIcon.Free;
  end;
end;


Dann noch die Icon-Handle Übergabe. Die Methode ist besser, da hier nur ein Integerwert übergeben wird. Das Icon muß aber bereits in der Abrufroutine initialisiert worden sein.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function GetIconX2(const FileName: String): THandle;
var
  Index: Word;
begin
  Index := 0;
  Result := ExtractAssociatedIcon(HInstance, PChar(FileName), Index);
end;


Beispiel:

Hier wird das Handle übergeben:


Delphi-Quelltext
1:
2:
3:
...
   Form1.Icon.Handle := GetIconX2('c:\windows\explorer.exe');
...


oder


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  AIcon: TIcon;
begin
  AIcon := TIcon.Create;
  try
    AIcon.Handle := GetIcon1('c:\windows\explorer.exe');
    Canvas.Draw(00, AIcon);
  finally
    AIcon.Free;
  end;
end;