AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi SHGetFileInfo : Programmicon in Imagelist kopieren
Thema durchsuchen
Ansicht
Themen-Optionen

SHGetFileInfo : Programmicon in Imagelist kopieren

Ein Thema von lume96 · begonnen am 15. Jun 2004 · letzter Beitrag vom 16. Jun 2004
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von lume96
lume96

Registriert seit: 14. Sep 2003
Ort: Rognac/Marseille - Frankreich
128 Beiträge
 
Delphi 7 Professional
 
#1

SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 13:20
Hallo,

Als Erstes möchte ich mich mal bedanken. Bin schon seit einiger Zeit regelmäßiger Besucher der DP und habe viel Hilfe gefunden. Um Anderen zu helfen, reichen meine Delphi-Kenntnisse leider noch nicht aus.

Leider habe ich hier ein Problem, das ich nicht selbst lösen kann :

Es handelt sich um eine Funktion, die die Icon eines Programmes zu einer ImageList hinzufügen soll. Die Sache ist etwas umständlich programmiert; ich hatte anfangs eine kompaktere Version, bin aber nach und nach mehr ins Detail gegangen, um den Fehler zu finden.

Die Idee ist Folgende:
1) Eine ImageList (ImgLst, width und height = 32) im MainForm.
2) Die Funktion AddFileIconToImgList wird aufgerufen (Parameter ist der Programmname) und gibt als Ergebnis den ImageIndex de Icon in der ImageList zurück.

Das Problem ist, dass das beim ersten Aufruf gut funktioniert, dann aber nicht mehr.
z.B.:
Delphi-Quellcode:
AddFileIconToImgList('c:\windows\expolorer.exe’);
AddFileIconToImgList(
'c:\windows\expolorer.exe’);
Beim ersten Aufruf wird 0 als Index zurückgegeben, beim zweiten Aufruf 1. In der ImageList befinden sich auch zwei Bitmaps, das erste ist die Explorericon, das zweite Bitmap ist allerdings ‚leer’ (einfach nur weiss).


Delphi-Quellcode:
function TFrm_Main.AddFileIconToImgList(FName : string):integer;
var
   FileInfo   : TSHFileInfo;
   tmpImgLst   : TImageList;
   tmpBitmap : TBitmap;
begin

   tmpBitmap := TBitmap.Create;
   tmpBitmap.Height := 32;
   tmpBitmap.Width := 32;
   tmpImgLst := TImageList.Create(self);
   tmpImgLst.Width := 32;
   tmpImgLst.Height := 32;

   tmpImgLst.Handle := SHGetFileInfo(PChar(FName),0,FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);
   tmpImgLst.GetBitmap(FileInfo.iIcon,tmpBitmap);
   tmpImgLst.Free;

   Result := ImgList.Add(tmpBitmap,nil);

   tmpBitmap.Free;

end;
Hat jemand 'ne Idee, warum das nicht läuft ?

Danke für Eure Hilfe.
LM
Lutz Meyer
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#2

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 14:02
Warum es nicht läuft, kann ich dir nicht sagen. Will ich auch nicht , denn du kommst besser weg, wenn du keine eigene Imageliste erzeugst, sondern gleich auf die Symbole aus dem System zugreifst. Es ist noch gar nicht solange her: klick. Dieser Weg ist IMHO besser, wobei ich dir aber den kompletten Beitrag als Lektüre empfehlen würde!

Wenn nämlich in deiner Liste mehrere Dateien mit dem gleichen Symbol auftauchen, dann würdest du entsprechend oft das gleiche Symbol in der Imageliste haben. Nicht zu vergessen, dass wahrscheinlich auch die Performance bzw. die Ressourcen darunter leiden.
Mit dem o.g. Weg greifst du stattdessen auf die Symbole zurück, die auch im Explorer angezeigt werden. Und statt Icons zu erzeugen, lässt du dir nur den Indexwert geben, und fertig.

Bei der List-View musst du dann allerdings die Einstellung "ShareImages" im Objektinspektor auf true setzen. btw: Beim Tree-View ist es übrigens einfacher, da brauchst du überhaupt keine TImageList auf der Form.
  Mit Zitat antworten Zitat
Benutzerbild von lume96
lume96

Registriert seit: 14. Sep 2003
Ort: Rognac/Marseille - Frankreich
128 Beiträge
 
Delphi 7 Professional
 
#3

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 15:09
Zitat von MathiasSimmack:
Warum es nicht läuft, kann ich dir nicht sagen.
Schade, hätte mich ja schon mal interessiert.

Na ja, habe mir den von Dir erwähnten Artikel durchgelesen und Deine dort angebotene Lösung übernommen. Funktioniert einwandfrei.

Also noch mal vielen Dank für den Hinweis (hatte zwar vor dem posten gesucht, den angegebenen Artikel aber wohl übersehen ).
Lutz Meyer
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:24
Moin Lume,

erst einmal herzlich willkommen hier in der Delphi-PRAXiS.

Was mir als erstes aufgefallen ist:
SHGetFileInfo liefert im gezeigten Zusammenhang nur 0 (Fehler) oder <> 0 (Erfolgreicher Aufruf) zurück.
Den Rückgabewert an das ImageList Handle zu übergeben hat also keinen Sinn.

Ausserdem fehlt ein Resourcenschutzblock (try/finally) für die Bitmap.
Zudem solltest Du die Imagelist nicht in der Routine erzeugen, wenn Du sie auch ausserhalb verwenden willst.

Wieso der erste Aufruf funktioniert hat ist mir allerdings ein Rätsel, denn mit

tmpImgLst.GetBitmap(FileInfo.iIcon,tmpBitmap); rufst Du ein Bild aus der Imagelist ab und kopierst es in die Bitmap. FileInfo.iIcon hat mit Deiner Imagelist aber nichts zu tun, sondern bezieht sich auf die Systemimagelist.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#5

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:25
Endlich mal einer, der sich nicht mit einer Lösung zufrieden gibt, sondern wissen will warum seine nicht funktioniert hat.

Also, grundsätzlich ist dein Code schon in Ordnung, wenn für meinen Geschmack auch das try/finally fehlt. Das eigentliche Problem dürfte aber auch bei dir die Sache mit der System-Imageliste gewesen sein. Prinzipiell greifst du in dieser Zeile auf das Handle der System-Imageliste zu
Delphi-Quellcode:
tmpImgLst.Handle := SHGetFileInfo(PChar(FName),0,
  FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);
und weil du die Imageliste danach freigibst
tmpImgLst.Free; "zerstörst" du damit auch die Systemsymbole. Natürlich nur temporär, aber du müsstest doch eigentlich bemerkt haben, dass im Explorer und im Startmenü (bspw.) alle großen Icons fehlen. Zumindest hat mein Windows 98 recht pingelig reagiert.

Jedenfalls klappt dadurch der erste Aufruf immer, aber durch das Freigeben der Imageliste existieren beim zweiten Aufruf natürlich gar keine Symbole mehr, und du erhältst nur die leere, weiße Bitmap. Gereicht hätte ein kleines
tmpImgLst.ShareImages := true; nach dem Erzeugen der Imageliste. Im Prinzip das, was ich in meinem ersten Beitrag schon kurz ansprach
Zitat:
Bei der List-View musst du dann allerdings die Einstellung "ShareImages" im Objektinspektor auf true setzen.
Das gilt natürlich auch für Imagelisten, die (wie hier) im Programm erzeugt werden.


Ich hätte deine Funktion bspw. so geschrieben:
Delphi-Quellcode:
function TForm1.AddFileIconToImgList(FName : string):integer;
var
  FileInfo : TSHFileInfo;
  tmpImgLst : TImageList;
  tmpBitmap : TBitmap;
begin
  tmpBitmap := TBitmap.Create;
  tmpImgLst := TImageList.Create(self);
  try
    tmpBitmap.Height := 32;
    tmpBitmap.Width := 32;
    tmpImgLst.Width := 32;
    tmpImgLst.Height := 32;
    tmpImgLst.ShareImages := true;

    tmpImgLst.Handle := SHGetFileInfo(PChar(FName),0,
      FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);
    tmpImgLst.GetBitmap(FileInfo.iIcon,tmpBitmap);

    Result := ImageList1.Add(tmpBitmap,nil);
  finally
    tmpImgLst.Free;
    tmpBitmap.Free;
  end;
end;

// und als Beispielaufruf -->
procedure TForm1.FormCreate(Sender: TObject);
const
  szFiles : array[1..3]of string =
    ('c:\windows\explorer.exe',
     'c:\tools\smc.exe',
     'c:\programme\VSHIK 2003\VSHIK_EULA.rtf');
var
  li : TListItem;
  i : integer;
begin
  for i := low(szFiles) to high(szFiles) do
  begin
    li := ListView1.Items.Add;
    li.Caption := szFiles[i];
    li.ImageIndex := AddFileIconToImgList(szFiles[i]);
  end;
end;
aber wie gesagt: Wenn du stattdessen, wie empfohlen, direkt auf die System-Imageliste zugreifst, arbeitest du weitaus effizienter und sparst Ressourcen.

Deine Idee funktioniert zwar jetzt auch, aber du füllst eben (langsam aber sicher) deine Imageliste mit Symbolen, evtl. eben auch mehrfach mit den gleichen Symbolen. Und das wäre sowohl performance- als auch speichertechnisch irgendwann ein Nachteil.


Edit: Upps, Kamerad Seehase, wo kommen Sie denn her? Immer diese Drängler.
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#6

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:29
Zitat von Christian Seehase:
Wieso der erste Aufruf funktioniert hat ist mir allerdings ein Rätsel, denn mit

tmpImgLst.GetBitmap(FileInfo.iIcon,tmpBitmap); rufst Du ein Bild aus der Imagelist ab und kopierst es in die Bitmap. FileInfo.iIcon hat mit Deiner Imagelist aber nichts zu tun, sondern bezieht sich auf die Systemimagelist.
Ich denke, das passt schon, denn er hat das Handle der System-Imageliste ja vorher ermittelt:
Zitat:
Delphi-Quellcode:
tmpImgLst.Handle := SHGetFileInfo(PChar(FName),0,
      FileInfo,sizeof(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:35
Moin Mathias,

Zitat von MathiasSimmack:
Ich denke, das passt schon, denn er hat das Handle der System-Imageliste ja vorher ermittelt:


gemäss meinem PSDK nicht
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
MathiasSimmack
(Gast)

n/a Beiträge
 
#8

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:41
Gemäß meinem schon. Nicht unbedingt auf den ersten Blick zu sehen, aber da steht´s:
s. PSDK zu SHGetFileInfo

SHGFI_SYSICONINDEX
Retrieve the index of a system image list icon. If successful, the index is copied to the iIcon member of psfi. The return value is a handle to the system image list. Only those images whose indices are successfully copied to iIcon are valid. Attempting to access other images in the system image list will result in undefined behavior.



Ich habe auch nur das vom Februar letzten Jahres.
Was ist eigentlich bei Microsoft los?
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#9

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 17:46
Moin Mathias,

stimmt hast Du wahr

Ich les' in so einem Falle den Abschnitt Return Value

Zitat von MathiasSimmack:
Ich habe auch nur das vom Februar letzten Jahres.
Was ist eigentlich bei Microsoft los?
vermutlich lohnt sich ein aktuelleres komplettes nicht, da es nur spezifische Änderungen gegeben hat (SP1a für XP z.B.), und für die es dann gesonderte einzelne Updates des PSDK gibt.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Benutzerbild von lume96
lume96

Registriert seit: 14. Sep 2003
Ort: Rognac/Marseille - Frankreich
128 Beiträge
 
Delphi 7 Professional
 
#10

Re: SHGetFileInfo : Programmicon in Imagelist kopieren

  Alt 15. Jun 2004, 18:32
Mit dem try/finally ist schon klar, eigentlich baue ich die immer mit ein, sobald ich irgendwo ein "Create" benutze. In diesem Fall nicht, wird aber nachgeholt, versprochen.

Ich hatte mir die SHGetFileInfo in der Win32 Prog. Ref. angesehen und dort gelesen, dass ich das Handle der SystemImageList zurückbekomme, deshalb mein
tmpImgLst.Handle := SHGetFileInfo(....); Hatte natürlich völlig übersehen/nicht bedacht, dass ich durch mein
tmpImgLst.free; die SystemimageList "zerstöre". Jetzt ist mir auch klar warum nach dem ersten Aufruf nichts mehr lief.

Konnte allerdings auf meinem Rechner (XP SP1) keine Nebeneffekte feststellen (pb mit den Desktop-icons, etc...).

Wie auch immer, danke für Zusatzinfos; bin doch ein stück schlauer als vorher.
Lutz Meyer
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:48 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