Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Systemicons und Listview (https://www.delphipraxis.net/21893-systemicons-und-listview.html)

Lamy 9. Mai 2004 17:15


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.

http://www.swissdelphicenter.ch/de/showcode.php?id=421

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?

alcaeus 9. Mai 2004 17:19

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.

Lamy 9. Mai 2004 17:23

Re: Systemicons und Listview
 
Jo, habsch 8) [siehe Ahpha *räusper*]

Luckie 9. Mai 2004 17:28

Re: Systemicons und Listview
 
Dir ist klar: Listbox <> Listview?

Lamy 9. Mai 2004 17:30

Re: Systemicons und Listview
 
?

Sollte doch auch auf eine Listview anzuwenden sein oder nicht?

alcaeus 9. Mai 2004 17:31

Re: Systemicons und Listview
 
nicht auch, sondern nur
Listbox kann nicht vsIcon, vsReport und diese Sachen.

Lamy 9. Mai 2004 17:32

Re: Systemicons und Listview
 
Ach so, sorry, ich meine natürlich Listview, nicht Listbox, Schreibfehler [korrigiert]!!!
:wall:

MathiasSimmack 9. Mai 2004 18:10

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 Win32-API-Tutorials.

Das Wissen lässt sich IMHO auch problemlos auf die VCL übertragen. ;)

Lamy 9. Mai 2004 18:28

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=

MathiasSimmack 9. Mai 2004 18:55

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:
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;
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:
Delphi-Quellcode:
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;
Fertig. ;)


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.

Lamy 9. Mai 2004 19:13

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: ?

MathiasSimmack 9. Mai 2004 19:52

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.

mirage228 9. Mai 2004 20:07

Re: Systemicons und Listview
 
Ahja und falls du deine Icons doch gekillst hast, einfach diesen Code ausführen *g*

Delphi-Quellcode:
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
Eigentlich wird das nur auf gerufen, wenn Dateizuordnungen sich geändert haben (und / oder die Icons geändert wurden).
Aber der gewünschte Effekt bleibt: Der Explorer lädt die Icons neu. ;)

mfG
mirage228

Lamy 9. Mai 2004 23:36

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...

MathiasSimmack 10. Mai 2004 07:55

Re: Systemicons und Listview
 
Ich verstehe das immer nicht wenn ihr schreibt
Zitat:

Ich hab das ganze jetzt einfach mal per Copy'n'waste übernommen auf einem leeren Formular
Ich nehme einfach mal an, die "OnCreate"- und "OnClick"-Prozeduren hast du nicht komplett übernommen, sondern du hast den Grundcode mit deinem Delphi erstellt (sprich: z.B. Doppelklick auf einen leeren Teil der Form, damit Delphi die Prozedur erstellt), und dann hast du den Inhalt der Prozedur aus meinem Posting übernommen?


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:

Delphi-Quellcode:
ListView1.SmallImages := ImageList1;

Ich hab´s nicht erwähnt, weil ich es nicht für erwähnenswert hielt

Lamy 10. Mai 2004 14:21

Re: Systemicons und Listview
 
Zitat:

Zitat von MathiasSimmack
Und dass du die beiden Imagelisten (ilSmall, ilBig) natürlich der List-View zuweisen musst, das versteht sich wohl auch von selbst.
Ich hab´s nicht erwähnt, weil ich es nicht für erwähnenswert hielt

Ach du schei**...


Gar nicht drauf geachtet :wall: :wall:


Steinigt mich!
Asche auf mein Haupt!

~normalerweisevergessichdasnichtfrusttotal~

Naja, klappt jetzt :corky: , danke!

Lamy 10. Mai 2004 16:21

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

Lamy 26. Mai 2004 17:17

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?

MathiasSimmack 27. Mai 2004 08:54

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.

Lamy 28. Mai 2004 16:08

Re: Systemicons und Listview
 
Hm, wie soll ich also vorgehen? :gruebel:

Christian Seehase 28. Mai 2004 16:49

Re: Systemicons und Listview
 
Moin Mathias,

Zitat:

Zitat von MathiasSimmack
"ShGetFileInfo" funktioniert IMHO leider nicht mit "Bruchstücken",

doch, man kann auch nur die Extension nehmen, und erhält dann das korrekte Handle auf das Icon in der Systemimagelist zurück.
Ich hatte erst vor kurzem dazu ein Beispiel gepostet (Hier im Forum suchenSHGetFileInfo)

Thunderchild 1. Jun 2004 15:31

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:
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;
Die Prozedur, die den ListView füllt:
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;

MathiasSimmack 1. Jun 2004 16:29

Re: Systemicons und Listview
 
Zitat:

Zitat von Christian Seehase
doch, man kann auch nur die Extension nehmen, und erhält dann das korrekte Handle auf das Icon in der Systemimagelist zurück.

Stimmt, mein Fehler :oops:. Ich hatte vergessen, dass es das Flag SHGFI_USEFILEATTRIBUTES gibt.

@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:
  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
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.

PS: Ach nee, Lamy wollte das ja wissen.

Thunderchild 1. Jun 2004 22:45

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

MathiasSimmack 1. Jun 2004 22:49

Re: Systemicons und Listview
 
Zitat:

Zitat von Thunderchild
Was hat das aber mit dem SHGFI_OPENICON auf sich? Ich hatte gehofft, das ist der aufgeklappte Ordner.

Ist es normalerweise auch. Ich habe das Ding in der Tree-View-Demo benutzt, und es war aufgeklappt. Bei einigen Spezialordnern (Favoriten, usw.) gibt es IMHO aber keine aufgeklappte Variante.

Zitat:

mit welchen Parametern bekomme ich nun noch das Icon des Arbeitsplatzes?
Puh. Kannst du nicht was einfaches fragen? ;)

Christian Seehase 2. Jun 2004 19:59

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;

Thunderchild 3. Jun 2004 23:38

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ß

MathiasSimmack 4. Jun 2004 08:40

Re: Systemicons und Listview
 
Du brauchst zwei Units:
Delphi-Quellcode:
uses
  ShlObj,   // für PItemIdList
  ActiveX;  // für IMalloc
Und Ja: mit dem Index geht es auch. Basierend auf Christians Code:
Delphi-Quellcode:
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;
wobei ich aber CSIDL_DESKTOP durch CSIDL_DRIVES ersetzt habe, denn im PSDK steht:
Zitat:

CSIDL_DRIVES
The virtual folder representing My Computer, [...]
Das andere wäre dieses Symbol, dass du auch in der Schnellstartleiste siehst, bzw. als Root im Windows-Explorer. Aber das Symbol des Arbeitsplatzes (das auf dem Desktop) ist bei mir ein anderes.

Thunderchild 4. Jun 2004 09:30

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.

mirage228 4. Jun 2004 09:52

Re: Systemicons und Listview
 
Zitat:

Zitat von Thunderchild
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.

Also,
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

MathiasSimmack 4. Jun 2004 10:35

Re: Systemicons und Listview
 
Zitat:

Zitat von Thunderchild
Nach meiner Doku hier übergibt das einen Zeiger [...]

Was für eine Doku hast du denn? Sag jetzt nicht: Das PSDK, denn da steht´s drin:
Zitat:

This interface must be used to free memory that was allocated by the Shell or to allocate memory that will be freed by the Shell.
Im Prinzip das, was mirage schrieb.

btw: Das PSDK würde ich dir ohnehin als Lektüre empfehlen.

Thunderchild 4. Jun 2004 12:15

Re: Systemicons und Listview
 
Was bei Delphi dabei ist.
Zitat:

Retrieves a pointer to the shell's IMalloc interface. A shell extension must use this interface to allocate memory that is later freed by the shell.
Entweder ist das einfach nur unglücklich formuliert oder ich bin nicht in der Lage, das korrekt zu übersetzen. Denn so wie ich das verstehe ist das genau das Umgedrehte von dem, was Deine Doku sagt; es belegt den Speicher ("used to allocate memory"), der später frei gegeben werden muß ("that is later freed"). :roll:

MathiasSimmack 4. Jun 2004 12:59

Re: Systemicons und Listview
 
Wieso? Im Prinzip steht das gleiche auch in meinem Zitat:
Zitat:

Zitat von MathiasSimmack
Zitat:

This interface must be used to free memory that was allocated by the Shell or to allocate memory that will be freed by the Shell.


Christian Seehase 4. Jun 2004 20:56

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 ;-)

MathiasSimmack 5. Jun 2004 09:36

Re: Systemicons und Listview
 
Upps, stimmt. :oops:
Ansonsten macht ja das "SHGetMalloc" nicht viel Sinn.

Thunderchild 5. Jun 2004 14:35

Re: Systemicons und Listview
 
Zitat:

Zitat von MathiasSimmack
Zitat:

This interface must be used to free memory that was allocated by the Shell or to allocate memory that will be freed by the Shell.

Was so ein kleines Wörtchen alles anrichten kann. :roteyes:


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