Author: Jonas Bilinkevicius
How can I get all classes that are currently registered in my application? Example:
If I have a form with no components on it and I do something like ReadComponentRes
and that *.dfm has a TEdit in it, I get an exception that TEdit is of unknown
class. If I put one TEdit on that form and do ReadComponentRes again, everything
goes OK. So, I guess TEdit is registered somewhere. Now I would like to find all
registered classes so I would know which classes I can use in my *.dfm.
Answer:
There is no way to get at classes registered via RegisterClasses, since the list
holding these is private to the classes unit. You can get at the classes registered
on a form, however, since those use a table connected to the form classes class
record. The following is based on some spelunking in the classes unit:
1 {defined in classes.pas}2 type3 PFieldClassTable = ^TFieldClassTable;
4 TFieldClassTable = packedrecord5 Count: Smallint;
6 Classes: array[0..8191] of ^TPersistentClass;
7 end;
8 9 function GetFieldClassTable(AClass: TClass): PFieldClassTable; assembler;
10 asm
11 MOV EAX, [EAX].vmtFieldTable
12 or EAX, EAX
13 JE @@1
14 MOV EAX, [EAX + 2].Integer
15 @@1:
16 end;
17 {end of quote from classes.pas}18 19 procedure TForm1.Button1Click(Sender: TObject);
20 21 procedure Display(const S: string);
22 begin23 memo1.lines.add(S);
24 end;
25 26 var27 pFCT: PFieldClassTable;
28 aClass: TClass;
29 i: SmallInt;
30 begin31 memo1.clear;
32 aClass := Classtype;
33 while aClass < > TPersistent do34 begin35 Display('Registered classes for class ' + aClass.Classname);
36 pFCT := GetFieldClasstable(aClass);
37 ifnot Assigned(pFCT) then38 Display(' No classes registered')
39 else40 begin41 Display(format(' %d classes registered', [pFCT^.Count]));
42 for i := 0 to pFCT^.Count - 1 do43 Display(' ' + pFCT^.Classes[i]^.ClassName);
44 end;
45 aClass := aClass.ClassParent;
46 end;
47 end;