
A mellékelt példaprogram megnyitása előtt a DirListBox.pas-ban lévő komponenst telepítenie kell a Delphi alá. Ehhez válassza a Component - Install Component menüpontot.
A komponens a TCustomListBox osztályból származik. Rendelkezik egy Dir tulajdonsággal, amelyen keresztül megadható annak a mappának az elérési útja, amelynek tartalmát meg szeretnénk jeleníteni. A ShowDir és ShowFile logikai típusú tulajdonságok igazra vagy hamisra állításával állíthatjuk be a mappák és állományok megjelenítését. Ha mindkét tulajdonság igazra van állítva, akkor a mappák és az állományok is megjelennek, ugyanúgy, mint az intézőben. Először a mappák ABC rendben, majd az állományok, szintén ABC rendben.
A GreatIcons logikai típusú tulajdonság igazra vagy hamisra állításával befolyásolhatjuk a megjelenő ikonok méretét. Igaz érték esetén nagy méretű ikon látható.
A ListBox-ban szeretnénk képeket megjeleníteni, erre azonban a ListBox csak úgy önmagától nem képes. A Style tulajdonságát át kell állítanunk lbOwnerDrawFixed-re vagy lbOwnerDrawVariable-ra, attól függően, hogy nagy, vagy kis ikonokat akarunk használni. A Style tulajdonság értékének megváltoztatása azzal jár, hogy ezután nekünk kell gondoskodnunk az elemek megjelenítéséről. Ehhez felül kell írnunk a DrawItem és a MeasureItem metódusokat.
Először fel kell töltenünk a listát, az adott mappa tartalmával. Ezt meg kell tennünk minden egyes alkalommal, amikor a Dir, ShowDir vagy a ShowFile tulajdonságok értéke megváltozik. A lista feltöltését a ScanFiles eljárás fogja végrehajtani.
A ScanFiles eljárás
Először tennünk kell néhány biztonsági intézkedést, hogy a komponens le tudja kezelni a hibásan megadott Dir tulajdonságot.
if FDir='' then Exit;
if FDir[Length(FDir)]<>'\' then FDir:=FDir+'\';
A mappa tartalmának beolvasását két részre kell bontanunk, mappák és állományok beolvasására. Mindkettő beolvasása egy TStringList típusú változóba történik, melynek segítségével könnyedén rendezhetjük listánk tartalmát és az elemeket csak a rendezés után fogjuk az Items tulajdonságba átmásolni. A beolvasáshoz a FindFirst - FindNext párost használjuk. Kezdjük a mappákkal.
i:=0;
if FShowDir then begin
if FindFirst(FDir+'*.*',faDirectory, F)=0 then begin
repeat
if (F.Name<>'.') and (F.Name<>'..') and ((F.Attr and faDirectory)=faDirectory) then begin
DirList.Add(F.Name);
Inc(i);
end;
until (FindNext(F)<>0) or (i=32000);
FindClose(F);
end;
end;
DirList.Sort;
A beolvasás tartalmát a DirList változóban tároljuk ideiglenesen. Az i változóval megszámoljuk a beolvasott elemek számát. A ListBox Integer számú elemet tud tárolni. Ha elérjük ezt a határt (kb. 32 000), nem olvasunk be több elemet. A beolvasott listát a DirList.Sort metódussal rendezzük.
Az állományok beolvasásának algoritmusa ugyanaz, mint a mappáké, csak a keresési feltétel más.
if FindFirst(FDir+'*.*',faHidden+faSysFile+faArchive, F)=0 then
Ikon beolvasása
Icon.Handle:=ExtractAssociatedIcon(Application.Handle,PChar(FDir+Items[Index]),x);
Az ikon képét kétszer kell beolvasnunk. Egyszer a MeasureItem és egyszer pedig a DrawItem metódusban. A MeasureItem metódus csak akkor hajtódik végre, ha a GreatIcons tulajdonság értéke igaz (azaz Style= lbOwnerDrawVariable).
DrawItem metódus
Ez a metódus rajzolja ki a ListBox éppen látható elemeit. Az ikon képét az ExtractAssociatedIcon függvény segítségével tudjuk beolvasni. Egy ikon TIcon mérete nem változtatható meg, ezért át kell a képet konvertálnunk Bitmap-pé.
with Bitmap do
begin
Height:=Icon.Height;
Width:=Icon.Width;
Canvas.Draw(1,1, Icon);
if FGreatIcons=False then begin
StretchBlt(Bitmap.Canvas.Handle,0,0,15,15,Bitmap.Canvas.Handle,0,0,Width,Height,SRCCOPY);
Height:=15;
Width:=15;
end;
end;
Ha a GreatIcons tulajdonság értéke hamis, akkor az ikont 16x16-os méretben jelenítjük meg. A méret megváltoztatása a StretchBlt eljárással történik.
Ezután nincs más dolgunk, mint az ikon képét és az állományneveket megjeleníteni a ListBox-ban.
Canvas.Draw(Rect.Left+2, Rect.Top+1, Bitmap);
if FGreatIcons then
Canvas.TextOut(Bitmap.Width+4, Rect.Top+Bitmap.Height div 3, Items[Index])
else Canvas.TextOut(22, Rect.Top+2, Items[Index]);