![]() |
Systemicons und Listview
Hi!
Mal wieder ne Frage meinerseits [wie könnts nur ander sein :mrgreen:] Ich möchte zu meinen Dateien die in einer Listview angezeigt werden, die dzgh. Icons auflisten lassen. ![]() Wenn ich das aber so übernehme wie das oben im Tut geschrieben steht, führt der immer nur ein einziges Icon auf und fügt es jedem einzelnen Eintrag hinzu. Warum? Muss man einen anderen Pfad bei WindowsXp angeben damit das funzt? |
Re: Systemicons und Listview
Ich weiß nicht welchen Pfad du meinst, du suchst ja immer nur nach Dateien, zu denen du die Icons hinzufügen willst. Hast du den Code per Copy&Waste übernommen? So wie der aussieht müsste er funktionieren.
|
Re: Systemicons und Listview
Jo, habsch 8) [siehe Ahpha *räusper*]
|
Re: Systemicons und Listview
Dir ist klar: Listbox <> Listview?
|
Re: Systemicons und Listview
?
Sollte doch auch auf eine Listview anzuwenden sein oder nicht? |
Re: Systemicons und Listview
nicht auch, sondern nur
Listbox kann nicht vsIcon, vsReport und diese Sachen. |
Re: Systemicons und Listview
Ach so, sorry, ich meine natürlich Listview, nicht Listbox, Schreibfehler [korrigiert]!!!
:wall: |
Re: Systemicons und Listview
Nichts gegen die Schweizer, aber das Beispiel scheint mir ein wenig ... äh ... na, sagen wir: wenig ressourcen-schonend. Die Systemicons werden von Windows durch eine spezielle System-Imageliste zur Verfügung gestellt, an die man rankommen kann.
Das momentane Problem scheint mir zu sein, dass für jede gefundene Datei das Icon ermittelt und in die eigene Imageliste eingetragen wird. Ich habe den Code jetzt nicht 100% analysiert, aber gäbe es bspw. zwei BAT-Dateien, dann würde die Imageliste 2x das gleiche Symbol enthalten. Ich denke, da kommt man günstiger weg, wenn man besagte System-Imageliste holt und dann nur noch den Index für das jeweilige Icon ermittelt und zuweist. Wie das geht, zeigt u.a. der List-View-Beitrag in den viel gerühmten ![]() Das Wissen lässt sich IMHO auch problemlos auf die VCL übertragen. ;) |
Re: Systemicons und Listview
öhm...
Da stehen bestimmt viele interessante Sachen drin aber ich hab erstmal Schwierigkeiten durch die Grundlagen durchzusteigen... Gibts da nicht was einfacheres= |
Re: Systemicons und Listview
Na ja, evtl. sehe ich das mehr aus dem Blickwinkel des etwas fortgeschritteneren Anwenders. Ich persönlich finde es nicht allzu schwer.
1. Also, du pappst 2 Imagelisten auf deine Form, lässt sie aber komplett leer. Eine nennst du "ilSmall", die andere "ilBig". Und enorm wichtig!: Stell bei beiden im Objektinspektor die Eigenschaft "ShareImages" auf TRUE. 2. Im "OnCreate"-Ereignis deiner Form machst du folgendes:
Delphi-Quellcode:
3. Jetzt kannst du die Dateien auslesen und mit ihrem Symbol anzeigen lassen. Ich habe das auf die Schnelle via Button-Klick und nicht rekursiv machen lassen. Aber es geht ja auch nur um´s Prinzip:
procedure TForm1.FormCreate(Sender: TObject);
var hImgSm, hImgBig : HIMAGELIST; fi : TSHFileInfo; begin // Imageliste mit kleinen Symbolen ermitteln hImgSm := HIMAGELIST(SHGetFileInfo('',0,fi,sizeof(fi), SHGFI_SYSICONINDEX or SHGFI_SMALLICON)); // und an die Imageliste auf der Form übergeben if(hImgSm <> 0) then ilSmall.Handle := hImgSm; // Imageliste mit großen Symbolen ermitteln hImgBig := HIMAGELIST(SHGetFileInfo('',0,fi,sizeof(fi), SHGFI_SYSICONINDEX or SHGFI_ICON)); // und an die Imageliste auf der Form übergeben if(hImgBig <> 0) then ilBig.Handle := hImgBig; end;
Delphi-Quellcode:
Fertig. ;)
procedure TForm1.Button1Click(Sender: TObject);
var ds : TSearchRec; res : integer; li : TListItem; fi : TSHFileInfo; begin res := FindFirst('c:\*.*',faAnyFile,ds); while(res = 0) do begin if(ds.Attr and faDirectory = 0) and (ds.Name <> '.') and (ds.Name <> '..') then begin // Name der Datei eintragen li := Listview1.Items.Add; li.Caption := ds.Name; // jetzt Zugriff auf die System-Imageliste // und nur den Typennamen und das Symbol // ermitteln! ZeroMemory(@fi,sizeof(fi)); SHGetFileInfo(pchar('c:\' + ds.Name),0,fi,sizeof(fi), SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_TYPENAME); // Icon-Index zuweisen, ... li.ImageIndex := fi.iIcon; // "iIcon" ist eine Integer-Variable und erhält somit // wirklich nur den Index auf das Symbol, aber nicht // das Symbol als solches. Daher ist es nun egal, wie // oft ein Dateityp im Ordner vorkommt. // ... & Typennamen als Untereintrag hinzufügen li.SubItems.Add(fi.szTypeName); end; res := FindNext(ds); end; FindClose(ds); end; PS: Wird zwar auch in den Tutorials erwähnt, aber der Vollständigkeit halber: Gib die Imagelisten auf der Form bitte NICHT frei!. Sonst sind evtl. deine Symbole im Explorer weg. :mrgreen: Ein Neustart behebt das Problem. Allerdings dürfen die Imagelisten in dem Fall eben nicht freigegeben werden. Sie werden ja auch nicht in deinem Programm erzeugt sondern vom System zur Verfügung gestellt. |
Re: Systemicons und Listview
Hi! Danke dir!
Aber irgendwie öffnet der, wenn ich es kompilieren will, die Datei Comctrls im Quelltexteditor und meint "Datei nicht gefunden:ListActns.dcu"! Die hab ich auch wirklich gar nicht obwohl ich Delphi 5 grade neu installiert hab... P.S.: Warum steht sowas eigentlich nicht in der Source Libary :gruebel: ? |
Re: Systemicons und Listview
"ListActns"? Die einzigen Units, die ich hinzufügen musste, waren "CommCtrl" (wg. HIMAGELIST) und "ShellAPI" (wg. "SHGetFileInfo"). Ich hab´s auch bloß mit D5 probiert.
|
Re: Systemicons und Listview
Ahja und falls du deine Icons doch gekillst hast, einfach diesen Code ausführen *g*
Delphi-Quellcode:
Eigentlich wird das nur auf gerufen, wenn Dateizuordnungen sich geändert haben (und / oder die Icons geändert wurden).
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
Aber der gewünschte Effekt bleibt: Der Explorer lädt die Icons neu. ;) mfG mirage228 |
Re: Systemicons und Listview
So, das eine Problem beseitigt, kommt schon freundlicherweise das nächste:
Ich hab das ganze jetzt einfach mal per Copy'n'waste übernommen auf einem leeren Formular und hab genau das getan was du mir gesagt hast. Aber es werden einfach keine Icons angezeigt... |
Re: Systemicons und Listview
Ich verstehe das immer nicht wenn ihr schreibt
Zitat:
Und dass du die beiden Imagelisten (ilSmall, ilBig) natürlich der List-View zuweisen musst, das versteht sich wohl auch von selbst. Soll heißen: Im Objektinspektor unter "LargeImages" und "SmallImages" die entsprechende Imageliste einstellen. Ansonsten siehst du natürlich keine Bilder. Im Schweizer-Beitrag wird letzteres programmtechnisch geregelt. Zitat:
|
Re: Systemicons und Listview
Zitat:
Gar nicht drauf geachtet :wall: :wall: Steinigt mich! Asche auf mein Haupt! ~normalerweisevergessichdasnichtfrusttotal~ Naja, klappt jetzt :corky: , danke! |
Re: Systemicons und Listview
das ganze lässt sich aber nicht auf meinen Client übertragen, oder?
Der lädt ja nur eine Liste runter und keine Dateierweiterungen, sodass der das ganze nicht erkennt. Deshalb zeigt der auch immer das selbe Symbol an... Gibts dafür noch ne Mödlichkeit? Lamy |
Re: Systemicons und Listview
Also nochmal:
Soweit ich das verstanden habe, weist der jedem Eintrag das gleiche Icon zu, da der die Dateitypen überprüft, die angezeigt werden, aber da ja alle TListitems sind, kann er das entsprechende Icon nicht zuweisen. Folglich müsste man irgendwie auch den Dateityp angeben, richtig? |
Re: Systemicons und Listview
Nein, so funktioniert es nicht. Die Dateien werden mit Hilfe von "FindFirst/FindNext" ermittelt. Für jede gefundene Datei wird das Symbol ermittelt - was kein Problem ist, denn den Dateinamen hast du ja in dem Fall! Das Problem könnte und wird sein, dass das Symbol nicht erkannt wird, wenn der Pfad nicht stimmt oder nicht vollständig angegeben wurde.
"ShGetFileInfo" funktioniert IMHO leider nicht mit "Bruchstücken", sprich: bspw. nur dem Dateinamen ohne Pfad. Das hat IMHO damit zu tun, dass jede Datei (speziell EXE usw.) ihr eigenes Icon haben kann. Also muss die Funktion auch den exakten Namen wissen, damit sie dir Symbol (und ggf. andere Eigenschaften wie Typname o.ä.) zurückliefern kann. |
Re: Systemicons und Listview
Hm, wie soll ich also vorgehen? :gruebel:
|
Re: Systemicons und Listview
Moin Mathias,
Zitat:
Ich hatte erst vor kurzem dazu ein Beispiel gepostet ( ![]() |
Re: Systemicons und Listview
Ich habe gestern den ganzen Tag Codeschnipsel und Beiträge hier zu diesem Thema gelesen, weil ich in meinem FTP-Client gern Windows-Icons für die FTP-Liste nehmen möchte. Aber das Höchste, was ich bis jetzt als Index aus GetFileInfo gekriegt habe, ist 2. Das heißt, bis jetzt habe ich nur OverlayIcons zu sehen bekommen. Bitte sag mir einer, was hier falsch ist. Es ist übrigens ein MDI-Programm. Die Imagelist für die Systemicons ist im Hauptformular, die Listenansicht befindet sich auf dem jeweiligen MDIchild.
OnCreate des Hauptformulars:
Delphi-Quellcode:
Die Prozedur, die den ListView füllt:
var hIl:HIMAGELIST;
fi:TSHFileInfo; begin hIl:=HIMAGELIST(SHGetFileInfo('',0,fi,sizeof(fi), SHGFI_SYSICONINDEX or SHGFI_SMALLICON)); if(hIl<>0) then ilShellIcons.Handle:=hIl; // ShareImages ist schon zur Entwurfszeit auf true gesetzt // [...] end;
Delphi-Quellcode:
procedure RefreshList;
var fi:TSHFileInfo; Item:tListItem; begin // [...] // Programmeinstellung: Windows-Icons verwenden? if fm.Settings.FTPicons=2 then begin ZeroMemory(@fi,sizeof(TSHFileInfo)); // brauche ich das überhaupt jedes mal? // l ist vom Typ TidListItems, also das Listing des akt. Verzeichnisses. SHGetFileInfo(PChar('c:\'+l[i].FileName),0,fi,SizeOf(fi), SHGFI_SYSICONINDEX or SHGFI_SMALLICON); Item.ImageIndex:=fi.iIcon; end end; |
Re: Systemicons und Listview
Zitat:
@Thunderchild: Was war jetzt dein Problem? Du hast Dateien vom FTP-Server, die´s auf deinem Rechner u.U. nicht gibt. Und darum passen die Symbole nicht. Dann folgende Änderung (wie Christian das bereits angedeutet hat):
Delphi-Quellcode:
In der "iIcon"-Membervariablen hast du jetzt den Index des HxS-Symbols. Du kannst auch einen Dateinamen angeben. Durch das o.g. Flag und das Dateiattribut spielt´s keine Rolle ob die Datei wirklich existiert oder nicht. Es ist als würde sie existieren.
ZeroMemory(@fi,sizeof(fi));
SHGetFileInfo('.HxS', FILE_ATTRIBUTE_NORMAL, <-- Dateiattribut fi,sizeof(fi), SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES); <-- Flag PS: Ach nee, Lamy wollte das ja wissen. |
Re: Systemicons und Listview
Supi, danke. Das isses.
Da würd ich gern noch ne Frage dran hängen: Wie ich das Icon eines Ordners bekomme, habe ich schnell raus gefunden. Was hat das aber mit dem SHGFI_OPENICON auf sich? Ich hatte gehofft, das ist der aufgeklappte Ordner. Aber irgendwie geht das wieder nicht. Zurück zu meiner eigentlichen Frage: mit welchen Parametern bekomme ich nun noch das Icon des Arbeitsplatzes? Damit möchte ich die Wurzel des FTP-Directories schmücken. mfG |
Re: Systemicons und Listview
Zitat:
Zitat:
|
Re: Systemicons und Listview
Moin Thunderchild,
war eine interessante Frage mit dem Arbeitsplatzicon. Ich hab's jetzt mal so gelöst:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var fiWork : TSHFileInfo; icWork : TIcon; pidlDSK : PItemIdList; imWork : IMalloc; begin SHGetSpecialFolderLocation(0,CSIDL_DESKTOP,pidlDSK); icWork := TIcon.Create; try SHGetFileInfo(PChar(pidlDSK),0,fiWork,SizeOf(fiWork),SHGFI_PIDL or SHGFI_ICON or SHGFI_SMALLICON); icWork.Handle := fiWork.hIcon; Canvas.Draw(10,10,icWork); finally FreeAndNil(icWork); SHGetMalloc(imWork); imWork.Free(pidlDSK); end; end; |
Re: Systemicons und Listview
Danke für die Antwortarbeit. Welcher Unit kann ich denn die PItemIdList entnehmen? Ferner brauche ich nur den IconIndex. Den möchte ich beim Programmstart ermitteln und dann in einer Vari speichern. Brauche ich dann dieses imWork überhaupt noch?
Gruß |
Re: Systemicons und Listview
Du brauchst zwei Units:
Delphi-Quellcode:
Und Ja: mit dem Index geht es auch. Basierend auf Christians Code:
uses
ShlObj, // für PItemIdList ActiveX; // für IMalloc
Delphi-Quellcode:
wobei ich aber CSIDL_DESKTOP durch CSIDL_DRIVES ersetzt habe, denn im PSDK steht:
li := lv.Items.Add;
li.Caption := 'Arbeitsplatz'; if(SHGetSpecialFolderLocation(0,CSIDL_DRIVES,pidlDSK) = S_OK) then try SHGetFileInfo(pchar(pidlDSK),0,fi,sizeof(fi), SHGFI_PIDL or SHGFI_ICON or SHGFI_SYSICONINDEX); li.ImageIndex := fi.iIcon; finally SHGetMalloc(imWork); end; Zitat:
|
Re: Systemicons und Listview
Danke, es geht.
Aber nochmal nachgehakt: wozu das SHGETMALLOC? Nach meiner Doku hier übergibt das einen Zeiger an das imWork (also damit damit gearbeitet werden kann). Aber weder wird es in der Indexermittlung verwendet, noch dahinter. |
Re: Systemicons und Listview
Zitat:
Mit SHGetMalloc der Zeiger auf IMalloc geholt wird. Und IMalloc wird dazu benutzt, den im fremden Prozessraum reservierten Speicher für die PItemIdList wieder freigeben zu lassen (da der Speicher dafür ja nicht von uns reserviert wurde, sondern von Windows)... mfG mirage228 |
Re: Systemicons und Listview
Zitat:
Zitat:
btw: Das PSDK würde ich dir ohnehin als Lektüre empfehlen. |
Re: Systemicons und Listview
Was bei Delphi dabei ist.
Zitat:
|
Re: Systemicons und Listview
Wieso? Im Prinzip steht das gleiche auch in meinem Zitat:
Zitat:
|
Re: Systemicons und Listview
Moin Thunderchild,
bei IMalloc verhält es sich so ähnlich wie bei den Netapi Funktionen unter NT ff. Hier wird den Funktionen die Adresse einer Variablen übergeben, in denen die Funktion (z.B. bei NetShareEnum) dann die Adresse ihres Ergebnisses speichert, wobei die Funktion den notwendigen Speicher selber anfordert. Um diesen dann wieder freizugeben muss man NetApiBufferFree benutzen. In dem Beispiel hier entspricht dann SHGetSpecialFolderLocation der Funktion die von sich aus Speicher reserviert, und IMalloc.Free dem Aufruf von NetApiBufferFree. @Mathias: Stimmt überhaupt, ich hätte CSIDL_DRIVES nehmen müssen :oops: Dafür hast Du dann den Aufruf von Free vergessen ;-) |
Re: Systemicons und Listview
Upps, stimmt. :oops:
Ansonsten macht ja das "SHGetMalloc" nicht viel Sinn. |
Re: Systemicons und Listview
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz