Einzelnen Beitrag anzeigen

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