Author: Jonas Bilinkevicius
How to obtain a list of all published property names and types defined in a
component
Answer:
Solve 1:
1 function GetComponentProperties(Instance: TPersistent; AList: TStrings):
2 Integer;
3 var
4 I, Count: Integer;
5 PropInfo: PPropInfo;
6 PropList: PPropList;
7 begin
8 Result := 0;
9 Count := GetTypeData(Instance.ClassInfo)^.PropCount;
10 if Count > 0 then
11 begin
12 GetMem(PropList, Count * SizeOf(Pointer));
13 try
14 GetPropInfos(Instance.ClassInfo, PropList);
15 for I := 0 to Count - 1 do
16 begin
17 PropInfo := PropList^[I];
18 if PropInfo = nil then
19 Break;
20 if IsStoredProp(Instance, PropInfo) then
21 begin
22 {
23 case PropInfo^.PropType^.Kind of
24 tkInteger:
25 tkMethod:
26 tkClass:
27 ...
28 end;
29 }
30 end;
31 Result := AList.Add(PropInfo^.Name);
32 end;
33 finally
34 FreeMem(PropList, Count * SizeOf(Pointer));
35 end;
36 end;
37 end;
Solve 2:
38 uses
39 TypInfo
40
41 procedure ListProperties(AInstance: TPersistent; AList: TStrings);
42 var
43 i: integer;
44 pInfo: PTypeInfo;
45 pType: PTypeData;
46 propList: PPropList;
47 propCnt: integer;
48 tmpStr: string;
49 begin
50 pInfo := AInstance.ClassInfo;
51 if (pInfo = nil) or (pInfo^.Kind <> tkClass) then
52 raise Exception.Create('Invalid type information');
53 pType := GetTypeData(pInfo); {Pointer to TTypeData}
54 AList.Add('Class name: ' + pInfo^.Name);
55 {If any properties, add them to the list}
56 propCnt := pType^.PropCount;
57 if propCnt > 0 then
58 begin
59 AList.Add(EmptyStr);
60 tmpStr := IntToStr(propCnt) + ' Propert';
61 if propCnt > 1 then
62 tmpStr := tmpStr + 'ies'
63 else
64 tmpStr := tmpStr + 'y';
65 AList.Add(tmpStr);
66 FillChar(tmpStr[1], Length(tmpStr), '-');
67 AList.Add(tmpStr);
68 {Get memory for the property list}
69 GetMem(propList, sizeOf(PPropInfo) * propCnt);
70 try
71 {Fill in the property list}
72 GetPropInfos(pInfo, propList);
73 {Fill in info for each property}
74 for i := 0 to propCnt - 1 do
75 AList.Add(propList[i].Name + ': ' + propList[i].PropType^.Name);
76 finally
77 FreeMem(propList, sizeOf(PPropInfo) * propCnt);
78 end;
79 end;
80 end;
81
82 function GetPropertyList(AControl: TPersistent; AProperty: string): PPropInfo;
83 var
84 i: integer;
85 props: PPropList;
86 typeData: PTypeData;
87 begin
88 Result := nil;
89 if (AControl = nil) or (AControl.ClassInfo = nil) then
90 Exit;
91 typeData := GetTypeData(AControl.ClassInfo);
92 if (typeData = nil) or (typeData^.PropCount = 0) then
93 Exit;
94 GetMem(props, typeData^.PropCount * SizeOf(Pointer));
95 try
96 GetPropInfos(AControl.ClassInfo, props);
97 for i := 0 to typeData^.PropCount - 1 do
98 begin
99 with Props^[i]^ do
100 if (Name = AProperty) then
101 result := Props^[i];
102 end;
103 finally
104 FreeMem(props);
105 end;
106 end;
And calling this code by:
ListProperties(TProject(treeview1.items[0].data), memo3.lines);
My tProject is defined as
107 type
108 TProject = class(tComponent)
109 private
110 FNaam: string;
111 procedure SetNaam(const Value: string);
112 public
113 constructor Create(AOwner: tComponent);
114 destructor Destroy;
115 published
116 property Naam: string read FNaam write SetNaam;
117 end;
Also note the output, there seem to be 2 standard properties (Name and Tag) !
Memo3
Class name: TProject
3 Properties
-------------------
Name: TComponentName
Tag: Integer
Naam: String
|