Delphi és Win32 API – Nem csak Delphi felhasználóknak: I. rész

A Borland Delphi rendszer számos, a Windowsban (és a Linuxban) használt rendszereszközhöz tartalmaz komponenseket, osztályokat. Mégis érhetetlen módon több elem hiányzik belőle, melyek sokszor vagy csak ritkán, de jól jönnének egy program fejlesztése során. Most induló cikksorozatunkban ilyen komponenseket fogunk készíteni. A sorozatot más programnyelvek használóinak is ajánlom, hiszen a bemutatott Windows API függvények bizonyára más nyelveken is elérhetőek.

Tallózás a mappák között – 1.

Elsőként egy hiányzó dialógusablakról lesz szó. Bizonyára már mindenki találkozott a „Tallózás a mappák között” vagy angol Windowsokban a „Browse for folders” feliratú ablakkal. A Dialogs palettát kutatva ezt mégsem tudjuk elérni. Lássuk, akkor miként tudunk ezen változtatni.

 

A megoldáshoz az SHBrowseForFolder függvényt hívjuk segítségül, mely a shell32.dll-ben található. Használatához a Windows és a ShlObj unitokra lesz szükség. A függvény deklarációja a következő:

function SHBrowseForFolder(var lpbi:

    TBrowseInfo): PItemIDList;

Talán jól gondolom, hogy nem sokkal kerültünk közelebb a dologhoz, sem a paraméter típusa, sem a visszatérési érték nem mond sokat. Vizsgáljuk meg a paramétert. Ez nem más, mint egy rekord, mely a következő mezőket tartalmazza:

TBrowseInfo = record
    hwndOwner
: HWND;
    pidlRoot: PItemIDList;
    pszDisplayName: PAnsiChar;
    lpszTitle: PAnsiChar;
    ulFlags: UINT;
    lpfn: TFNBFFCallBack;
    lParam: LPARAM;
    iImage: Integer;
end;

 

A mezők jelentése sorrendben:

  • hwndOwner: a Windowsban minden egyes ablaknak (ablak alatt itt vezérlőket is értek, mint például egy TEdit, vagy egy TMemo) egy saját egyedi azonosítószáma van. A legtöbb Windows API függvény ezen azonosítószámot kéri paraméterként, hogy egy ablakot azonosítson, amennyiben valamilyen műveletet kell vele végezni (pl.: átszínezni). Itt most annak az ablaknak kell az azonosítója, amelyik a megjelenő ablak tulajdonosa lesz. Ez azt jelenti nagyvonalakban, hogy ezzel az ablakkal fogja tartani a kapcsolatot, mindenféle műveletre ezt az ablakot használja fel (nem ebben jeleníti meg!).
  • pidlRoot: Ebben a paraméterben lehet megadni, hogy melyik mappa legyen az ablakban a gyökérmappa. Ez lehet egy rendszermappa, mint például az Asztal, vagy a Sajátgép, de lehet egy fájlrendszer mappa is, például C:\WINNT\. A paraméter típusa persze nem egyszerű karakterlánc. Mivel a Windows 95-től a C:, D:, stb. felett is találhatóak ú.n. rendszermappák, ezért a mappaneveket egy másfajta struktúrában tárolják. Ezek az ID listák. A rendszermappáknak egyedi ID kódjuk van, a többi mappának maga a neve a kód.
  • pszDisplayName: a függvény visszatérésekor ide kerül beírásra a kiválasztott mappa megjelenítéshez használt név. A használat során ezt egy MAX_PATH konstans méretű, karakterekből álló tömbre kell állítani.
  • lpszTitle: Az itt megadott karakterlánc fog megjelenni az ablak tetején (nem a címsorában!).
  • ulFlags: a SysObj unitban több konstans is definiálva van, amelyeket itt kombinálva lehet használni. Ezen felül az Internet Explorer 4.0, illetve 5.0-val telepítésre kerülő shell32.dll számos új konstanst is elfogad. A teljesség kedvéért most valamennyi konstans értékét is leírom:

BIF_RETURNONLYFSDIRS            = $0001;

Nem engedi, hogy a felhasználó egy fájlrendszer mappán kívül bármi mást is kiválasszon. Ez azt jelenti, hogy se nyomtatót, se másik számítógépet, stb. nem választhat ki.

BIF_DONTGOBELOWDOMAIN           = $0002;

Nem jeleníti meg az aktuális domainen kívül található hálózati mappákat.

BIF_STATUSTEXT                  = $0004;

A címsor alatt egy státuszsornak szúr be helyet. A státuszsor szövege a lpfn paraméterben megadott callback függvényen keresztül módosítható. Fontos, hogy ez a státuszsor nem egyenértékű a TStatusBar által adott látvánnyal, sokkal inkább egy egyszerű TLabel szerű megjelenítéshez hasonlít.

BIF_RETURNFSANCESTORS           = $0008;

Léteznek speciális mappák, amelyek bár fizikailag is léteznek a merevlemezen, mégis speciális feladatuk van. Ilyen például a Recycled, vagy a %WINDIR%\Tasks mappa. Ha nem akarjuk, hogy a felhasználó ilyen mappákat ki tudjon választani, akkor használjuk ezt az opciót.

BIF_EDITBOX                     = $0010;

Ha a shell32.dll 4.71 vagy újabb verziójával rendelkezünk, akkor lehetőségünk van az ablak aljába egy egysoros beviteli mezőt megjeleníteni. Ebbe a mezőbe a felhasználó maga írhatja be a kiválasztott mappa nevét, ha ez számára könnyebb megoldás.

BIF_VALIDATE                    = $0020;

A fenti opcióval együtt használva a rendszer ellenőrizni fogja a kiválasztott mappa helyességét. A hiba tényét jelzi a callback függvényben.

BIF_NEWDIALOGSTYLE              = $0040;

A shell32.dll 5.00 vagy újabb használatával ez az flag rengeteg új funkciót ad az ablakhoz: az ablak átméretezhető, új mappát lehet létrehozni, meglevőt törölni, az elemek helyi menüi is megjelennek, stb.

BIF_BROWSEINCLUDEURLS           = $0080;

A BIF_BROWSEINCLUDEFILES, BIF_EDITBOX és a BIF_NEWDIALOGSTYLE konstansok használata mellett ezzel a flaggel a mappákban található internet-parancsikonok (*.url) is kiválaszthatóak.

BIF_BROWSEFORCOMPUTER           = $1000;

A felhasználó egy számítógépen kívül mást nem tud kiválasztani. Ez akkor hasznos, ha gyökérnek a "Számítógépek a hálózatban" rendszermappát adjuk meg.

BIF_BROWSEFORPRINTER            = $2000;

A fentihez hasonlóan csak nyomtatót enged kiválasztani.

BIF_BROWSEINCLUDEFILES          = $4000;

A mappákon kívül a bennük levő fájlokat is megjelenítni, mintha azok almappák lennének. Használatához minimum shell32.dll 4.71 szükséges.

BIF_SHAREABLE                   = $8000;

Távoli számítógépek megosztott erőforrásait is megjeleníti az ablak ennek a flag-nek az alkalmazásával. 5.0-s shell32.dll és a BIF_EDITBOX, valamint a BIF_NEWDIALOGSTYLE flagek használata szükséges.

  • lpfn: Ez egy ún. callback függvényre mutat. Egy callback függvény segítségével lehet - többek között - eseményvezérelt működést megvalósítani. Ha valami történik az ablakban (kiválasztanak egy elemet, stb.), akkor ezen eseményeket e függvény segítségével jelzi a Windows a programunknak.
  • lParam: Ez egy tetszőleges értékű LongInt típusú paraméter, melyet a callback függvénynek minden módosítás nélkül át fog adni. Nagyon fontos lesz számunkra, amikor megírjuk a komponenst.
  • iImage: Globálisan létezik egy TImagesList, amely a rendszerikonokat tartalmazza (mappa ikon, fájlikonok, stb.). Ezen paraméterben adja vissza a függvény, hogy a kiválasztott elemhez melyik ikon tartozik ebben a rendszer listában.

 

A callback függvény deklarációja:

function CallBack(Wnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer stdcall;

Paraméterek:

  • Wnd: a megjelenített ablak azonosítója, ismertebb nevén leírója. Ezt a leírót használhatjuk, ha a SendMessage Windows API függvénnyel a következő üzenetek valamelyikét küldjük:
    • BFFM_ENABLEOK: Az ablak OK gombját engedélyezi/tiltja. Az engedélyezéshez a SendMessage lParam paraméterét egy nullától különböző értékre állítsuk, a tiltáshoz pedig nullára.
    • BFFM_SETSELECTION: Egy megadott mappát választhatunk ki vele. Részletesebben most nem foglalkozunk vele, de azt leírom, hogy az lParam–nek egy PChar stringet kell adni, mely a kiválasztandó mappa elérési útját tartalmazza, a wParam–ot pedig egyre kell állítani.
    • BFFM_SETSTATUSTEXT: Ha a flageknél használtuk a BIF_STATUSTEXT konstanst, akkor az lParam–nak egy PChar értéket adva a SendMessage–ben, beállíthatjuk annak szövegét.
  • uMsg: az eseményt azonosító konstans:
    • BFFM_INITIALIZED: az ablakot a rendszer teljes mértékben inicializálta, kész a megjelenítésre. A függvény lParam értéke nulla.
    • BFFM_SELCHANGED: a felhasználó kiválasztott egy elemet. Az elem a már említett ID listával azonosítható a függvény lParam paraméterében.
    • BFFM_VALIDATEFAILED: a BIF_VALIDATE flag használata mellett ezzel az üzenettel jelzi a rendszer, hogy a felhasználó hibás nevet írt be a beviteli mezőbe. az lParam egy PCharra mutat, mely a hibás nevet tartalmazza. Ha a függvény visszatérési értékét nullára állítjuk, akkor az ablak minden további nélkül becsukódik, mintha a "Mégse" gombra klikkeltek volna.
  • lParam: a lehetséges értékeket már az imént leírtam.
  • lpData: az SHBrowseForFolder lParam paraméterében megadott érték. Ez később, a komponens megírása során lesz érdekes.

A BFFM_VALIDATEFAILED üzenet kivételével a függvény nullát kell, hogy visszaadjon.

Ezzel áttekintettük a száraz API-szintű ismereteket.

Következő számunkban a komponens megépítése előtt még átnézünk néhány egyszerűbb függvényt, amelyeket felhasználunk a komponens megírása során. Aki pedig úgy érzi, az kezdjen hozzá a megíráshoz, aki pedig türelmetlen, az töltse le a már kész példányt a http://www.gsc.hu címről.

Geiger Tamás