Delphi - Osztály hierarchia lekérdezése

1. rész

forráskód letöltése
A Delphi Help-jében minden komponensnél megtaláljuk azt az információt, hogy mely osztályokból van származtatva. De mi a helyzet azokkal a komponensekkel, amik nem a Delphi részei, vagyis később telepítettük őket. A mellékelt példában egy olyan Delphi kiegészítést készítünk, amely egy ablakban hierarchikusan megjeleníti az összes TComponent-ből származó komponenst. A listában megjelennek az egyénileg telepített komponensek is, és minden komponensről megtudhatjuk, hogy melyik komponens csomagban található meg. A példaprogram kipróbálásához telepítse a ClassTreePackage.dpk-t a Delphi alá.

A telepítés után létrejön egy Animare menü a Help menü előtt, benne egy Delphi Class Tree menüponttal. Ha már telepített korábban Delphi kiegészítéseket, amelyek cégünktől származnak, akkor az új menüpont a többi után jelenik meg.

A Delphi kiegészítéssel már több előző cikkünk is foglalkozik, így most csak a lényegi részt írjuk le részletesen.
A Form-on, amiben az adatokat megjelenítjük található egy TComboBox, és egy TTreeView komponens. A ComboBox-ban a komponensek, illetve osztályok ABC sorrendben vannak felsorolva, innen könnyedén kikereshetjük azt az osztályt, amire kíváncsiak vagyunk. A TTreeView-ben hierarchikusan vannak elrendezve az osztályok, de itt is ABC sorrendben.
A komponens csomagokat, és a bennük található komponenseket az IOTAPackageServices interfészen keresztül kérdezhetjük le. Ehhez a BorlandDEServices interfészt kell felhasználnunk, amit a Delphi IDE inicializál.
var
  PackageServices: IOTAPackageServices;
...
  if Assigned(BorlandIDEServices) then begin
    PackageServices:=(BorlandIDEServices as IOTAPackageServices);
A GetPackageCount függvénnyel lekérdezhetjük a komponens csomagok számát. Egy ciklussal végigmegyünk az összes komponens csomagon, és az azokban található komponens osztályokról megállapítjuk azokat az osztályokat, amikből származik. Tehát a ciklus eleje a következő:
      with PackageServices do begin
        for i:=0 to GetPackageCount-1 do begin
A komponens csomagban található komponensek száma a GetComponentCount függvényel kérdezhető le. Ennek egy paramétere van, a komponens csomag sorszáma. Egy belső while ciklusban végigmegyünk a komponens listán:
          t:=0;
          while t<GetComponentCount(i) do begin
A komponens neve a GetComponentName függvénnyel kérdezhető le. Az első paraméter a csomag sorszáma, a második pedig a komponens sorszáma, a csomagon belül. A visszakapott értéket eltároljuk a compname változóban.
            compname:=GetComponentName(i, t);
A cl változó TClass típusú. Ennek segítségével állapítjuk meg a komponens osztály szülő osztályait. Ehhez viszont először a FindClass függvénnyel le kell kérdezni a komponens osztályt. A függvény paramétere az osztály neve, vagyis jelen esetben a komponens neve.
            cl:=FindClass(compname);
Egy ciklusban a szülő osztályok neveit kigyűjtjük, és az anch TStringList típusú listában eltároljuk.
            while Assigned(cl) do begin
              anch.Insert(0, cl.ClassName);
              cl:=cl.ClassParent;
            end;
Az osztályokat el kell tárolni a TreeView-ben és a ComboBox-ban. Egy ciklussal végigmegyünk az előbb elkészített listán. A 3. elemtől indulunk, mivel az első két elem minden esetben a TObject és a TPersistent. A FindClassNode függvénnyel megnézzük, hogy az osztály neve szerepel-e már a TreeView listában. Ez a függvény a TForm1 osztályban van deklarálva, lejjebb részletesen is megnézzük. Most elég annyi, hogy a függvény visszatérési értéke egy TTreeNode objektum, amiben az osztály neve tárolva van, vagy nil, ha még nincs tárolva. A visszatérési értéket a TreeNode változóban tároljuk. Ha az osztály neve már tárolva van, akkor a ParentNode változónak átadjuk a TreeNode értékét, ellenkező esetben felvesszük az elemet a listára a TreeView komponens AddChldObject függvényével. Azért ezzel, mert ennek van egy plusz paramétere, egy pointer arra az adatra, amit az elem mellé el szeretnénk tárolni. Mivel a pointer is tulajdonképpen egy szám, ezért mi ezt arra használjuk fel, hogy a komponens csomag sorszámát tároljuk benne. Erre később lesz szükségünk. Az osztály nevét még felvesszük a ComboBox-ba is, kivéve a TComponent osztályt, ami minden esetben a 3. a listában.
            ParentNode:=nil;
            for c:=2 to anch.Count-1 do begin
              TreeNode:=FindClassNode(anch[c]);
              if Assigned(TreeNode) then begin
                ParentNode:=TreeNode;
              end else begin
                clname:=anch[c];
                ParentNode:=TreeView1.Items.AddChildObject(ParentNode, clname, Pointer(i));
                if c>2 then ComboBox1.Items.Append(clname);
              end;
            end;
Miután az összes osztályt felvettük a listára, a TreeView-t sorba rendezzük az AlphaSort eljárással, és az első elemet (TComponent) kinyitjuk.
      TreeView1.AlphaSort;
      TreeView1.Items[0].Expand(false);

Fent már szóltunk a FindClassName függvényről. Ez mindössze annyit tesz, hogy egy ciklussal végigmegy a TreeView elemein, és összehasonlítja azok szövegét a paraméterként megkapott osztály névvel. Ha megtalálta a keresett nevet, akkor az aktuális elemmel tér vissza, ellenkező esetben az eredmény nil. Amikor kiválasztunk egy elemet a ComboBox-ból, akkor szintén ezt a függvényt használjuk az osztály megkereséséhez.

Amikor kiválasztunk egy osztály nevet a listából, akkor a Form alján elhelyezett StatusBar-ban megjelenik a csomag neve, és az abban található komponensek száma. Ezekhez az adatokhoz szintén az IOTAPackageServices interfészen keresztül fogunk hozzáférni. A TreeView OnChange eseményénél megkapjuk a Node paraméterben a kiválasztott elem objektumát. Ennek data property-jében van eltárolva annak a komponens csomagnak a sorszáma, amiben az osztály található. A GetPackageName függvénnyel lekérdezzük a csomag nevét, a már előzőleg is használt GetComponentCOunt függvénnyel pedig a benne tárolt komponensek számát.

Osztály hierarchia lekérdezése cikksorozat

Osztály hierarchia lekérdezése - 1. rész

Osztály hierarchia lekérdezése - 2. rész