Autor Beitrag
Backslash
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 17:28 
Hallo an alle,

ich habe ein Problem worauf ich eigentlich auch nach längerem Suchen keine Antwort hier im Forum gefunden habe. Vielleicht wisst ihr wie ich eine Lösung für mein Problem finden kann.


Ich hab eine Listview, der ich den Handle der Systemiconliste zugewiesen habe um Dateiicons anzeigen zu können. Das funktioniert alles prima, wenn ich mit Findfirst nach Dateien in einem Verzeichnis suche und mit SHGetFileInfo den Iconindex ermittle. Dann muss ich nurnoch beim Ondata-Ereignis der Listbox den Iconindex des entsprechenden Eintrags setzen, den ich anzeigen will.

Leider hab ich auch eine zweite Listview. Dort sollen Dateien angezeigt werden, die nicht unbedingt auf der Festplatte existieren, da ich einen Archiver programmiere, mit dem sich Dateien zu einem Archiv hinzufügen lassen.

Mein Problem:

Wie bekomme ich den Iconindex für eine beliebige Dateierweiterung vom Betriebssystem um später für diese Erweiterung in meiner Listview das entsprechende Icon selektieren zu können? Als Beispiel könnte die Erweiterung ".bat" dienen.

Vielen Dank für eure Hilfe

Backslash

PS: hoffentlich weiß einer Rat :)
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Fr 14.04.06 17:44 
Hallo,

dammy.txt tuts auch :wink: oder?
:arrow:
Icons von Dateiendungen auslesen

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 18:08 
Danke, die Anzeige funktioniert. War wirklich eine gute idee mit dummy.txt *g* Hab die Funktion jetzt für jede beliebige Dateierweiterung verallgemeinert:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
// Iconindex einer Dateierweiterung herausfinden
function GetIconIndexOf(FileExt : string) : Integer;
var
  Info: TSHFileInfo;
  aFile : String;
begin
  aFile := 'dummy' + FileExt;
  SHGetFileInfo(PChar(aFile), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo),
            SHGFI_ICON or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES);
  Result := Info.IIcon;
end;


Leider tritt bei mir ein Problem auf. Wenn ich in der Listview Dateien markiere, verlieren einige Dateien mit einer bestimmten Endung ihre Icons komplett. Also da ist dann weiß, wo vorher Icons waren. was mache ich falsch?
Einloggen, um Attachments anzusehen!
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 18:38 
Nachtrag: Im Listview können bei mir einige tausend Dateien mit dem OnData ereignis angezeigt werden. Jedenfalls passiert mit der operation etwas ziemlich komisches. Wenn ich Listvieweinträge markiere und kein Icon angezeigt und ich dann anschließend über die Toolbar des Programms fahre sind dort alle icons weg und die Anwendung stürzt mir total hart hab mit der Meldung "Leinwand/Bild erlaubt kein Zeichnen".

Tolles Beispiel *g* Hab alles genauso gemacht wie es erklärt wurde. :-(
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Fr 14.04.06 18:52 
Hallo,

aus dem Screenshoot und Deinem Code kann man die Fehlerursache nicht feststellen,
vermute das an einer anderer Stelle in Deinem Code der Fehler verursacht wird.

Führst Du einen Code aus wenn ein Item markiert wird?, wenn ja, wie sieht der aus?
Es sieht mir danach aus das ein ImageIndex größer ListView1.SmallImages.Count-1 zugewiesen wird, dann hat man diese weiße Fläche wo vorher das Icon war.
Lass Dir doch mal den ImageIndex des markierten Items ausgeben.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 19:06 
gute Idee. werd ich machen. Beim Markieren der Items wird das On-Data Ereignis ausgeführt. Und da wird eigentlich nur

Item.ImageIndex = DateiRecord^.ImageIndex

ausgeführt. Der Dateirecord ist ein Pointer auf den Record mit den Dateidaten. Die Iconindexe ermittle ich vorher für jeden dateityp, damit ich das nicht jedes mal beim ondata-ereignis machen muss.

Werds mal testen. Achja, bei kleineren Listen gehts einwandfrei. Ich vermute das liegt daran, da ich mit unterschiedlichen Codes für mehrere Listviews die Icons ermitteln lasse. VIelen Dank für die Hilfe :)
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 19:16 
So, das Problem tritt immer noch auf. Es scheint aber nur bei sehr großen Listen da zu sein.

Hier mal ein Bild, indem die Item-Captions entsprechend dem Itemindex angezeigt werden. wie man sieht, werden markierte Icons immer noch mit dem gleichen Iconindex angezeigt. Und dann stürtzt mir die Anwendung wieder ab, wenn ich in der Toolbar über die Icons fahre.
Einloggen, um Attachments anzusehen!
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Fr 14.04.06 20:51 
So, ich hab das Problem jetzt eingekreist. Also beim Formcreate weise ich die Icons ganz normal zu. Wenn ich jetzt beim Ondata-Ereignis einfach von Hand den Imageindex auf 1 oder 2 oder so setze, funktioniert das alles super. Die Icons werden auch angezeigt.


Ich denke der Fehler liegt daran, dass die Funktion SHGetFileInfo mehrere tausend Mal für jede einzelne Datei zum Ermitteln des Iconindex aufgerufen wird. Wenn ich nur ein paar hundert Dateien hab, tritt der Fehler nicht auf.

Gibt es vielleicht eine andere Möglichkeit den Iconindex für Dateitypen zu ermitteln? Wenn ich bei so vielen Dateien die Funktion vom Betriebssystem aufrufe, dann erhalte ich sogar einen Ressource-Overflow vom Betriebbssystem und in der Taskleiste sehen die Icons anschließend auch nicht mehr gut aus. ;) Also der Fehler liegt nich daran dass ich irgendwo ein Speicherleck in der Anwendung habe. Die liegt eindeutig in der Häufigkeit wie oft ich SHGetFileinfo aufrufe.

EDIT:

Ich wollte nicht noch ein posting erstellen. Sieht etwas eintönig aus. Hab das Problem über einen anderen Thread im Forum gelöst. Das war ja gar nicht so schwer. Nur die Übergabeparameter weiter oben in der SHGetFileInfo für die Icontypen sind falsch.

Hier mal die korrigierte Funktion, mit der auch ein paar tausend bis zehntausend Dateien endlich richtig angezeigt werden:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
// Iconindex einer Dateierweiterung herausfinden
function GetIconIndexOf(FileName : string) : Integer;
var
  aFile : string;
  Info  : TSHFileInfo;
begin
  aFile := ExtractFileExt(FileExt);
  ZeroMemory(@Info, SizeOf(TSHFileInfo));
  SHGetFileInfo(PChar(aFile), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo),
                SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES);
  Result := Info.IIcon;
end;
Lannes
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Fr 14.04.06 23:06 
Hallo,

hab den Fehler jetzt auch reproduzieren können.

Die Übergabeparameter SHGFI_ICON or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES nutze ich(und andere, wenn man sich mal im WWW umschaut) seit längerem, das Problem damit ist mir bisher noch nicht aufgefallen, liegt wahrscheinlich daran das ich selten soviel Einträge in einer ListView anzeigen lasse.

Hast Du Informationen über die Ursache des Fehlers, wenn man die Übergabeparameter SHGFI_ICON or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES anstelle von SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES benutzt?

Übrigens hab ich eben festgestellt das man SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES sowohl für SmallImages als auch LargeImages verwenden kann.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
Backslash Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202

WIN XP
Delphi 5 Ent, Delphi 2005 Prof
BeitragVerfasst: Sa 15.04.06 13:41 
Infos über die Ursache mit den Übergabeparametern habe ich nicht. Eigentlich bin ich nur hergegangen und hab erstmal die Anwendung soweit reduziert, dass ich die Funktion zur Ermittlung des Iconindex nicht aufrufe. Dann war der Fehler weg. Schließlich hab ich gesehen dass der Fehler immer nur auftritt wenn ich die SHGetFileInfo zu oft aufrufe. Dann hab ich im Forum nochmal nach dem thema gesucht und per zufall irgend einen anderen Thread gefunden, in dem die anderen Übergabeparameter verwendet wurden. Jetzt funktioniert es einwandfrei. Die Lösung hab ich ja gepostet *g*. Ehrlichkgesagt kann ich mir nicht vorstellen woran das liegt. Jedenfalls "zufall sei dank" hab ich das Problem jetzt gelöst und die Anwendung läuft einwandfrei ohne Abstürze :)

Vielen Dank nochmal für deine Hinweise. Ohne die hätt ich es nicht geschafft.