Author: Tomas Rutkauskas
I have an application that uses RTTI to access object properties. Is it possible to
interprete property values like TColor as their textual values (ie clRed) instead
of an integer? Is there anything in a property's RTTI to indicate it's a type
TColor and not just an integer?
Answer:
This should get you there:
1 unit PropertyList;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 StdCtrls,
8 Buttons;
9
10 type
11 TMyStream = class(TFileStream)
12 private
13 FFred: integer;
14 published
15 property Fred: integer read FFred write FFred;
16 end;
17 type
18 TFrmPropertyList = class(TForm)
19 SpeedButton1: TSpeedButton;
20 ListBox1: TListBox;
21 procedure SpeedButton1Click(Sender: TObject);
22 private
23 { Private declarations }
24 public
25 { Public declarations }
26 end;
27
28 var
29 FrmPropertyList: TFrmPropertyList;
30
31 implementation
32
33 {$R *.DFM}
34
35 uses
36 TypInfo;
37
38 procedure ListProperties(AInstance: TPersistent; AList: TStrings);
39 var
40 i: integer;
41 pInfo: PTypeInfo;
42 pType: PTypeData;
43 propList: PPropList;
44 propCnt: integer;
45 tmpStr: string;
46 begin
47 pInfo := AInstance.ClassInfo;
48 if (pInfo = nil) or (pInfo^.Kind <> tkClass) then
49 raise Exception.Create('Invalid type information');
50 pType := GetTypeData(pInfo); {Pointer to TTypeData}
51 AList.Add('Class name: ' + pInfo^.Name);
52 {If any properties, add them to the list}
53 propCnt := pType^.PropCount;
54 if propCnt > 0 then
55 begin
56 AList.Add(EmptyStr);
57 tmpStr := IntToStr(propCnt) + ' Propert';
58 if propCnt > 1 then
59 tmpStr := tmpStr + 'ies'
60 else
61 tmpStr := tmpStr + 'y';
62 AList.Add(tmpStr);
63 FillChar(tmpStr[1], Length(tmpStr), '-');
64 AList.Add(tmpStr);
65 {Get memory for the property list}
66 GetMem(propList, sizeOf(PPropInfo) * propCnt);
67 try
68 {Fill in the property list}
69 GetPropInfos(pInfo, propList);
70 {Fill in info for each property}
71 for i := 0 to propCnt - 1 do
72 AList.Add(propList[i].Name + ': ' + propList[i].PropType^.Name);
73 finally
74 FreeMem(propList, sizeOf(PPropInfo) * propCnt);
75 end;
76 end;
77 end;
78
79 function GetPropertyList(AControl: TPersistent; AProperty: string): PPropInfo;
80 var
81 i: integer;
82 props: PPropList;
83 typeData: PTypeData;
84 begin
85 Result := nil;
86 if (AControl = nil) or (AControl.ClassInfo = nil) then
87 Exit;
88 typeData := GetTypeData(AControl.ClassInfo);
89 if (typeData = nil) or (typeData^.PropCount = 0) then
90 Exit;
91 GetMem(props, typeData^.PropCount * SizeOf(Pointer));
92 try
93 GetPropInfos(AControl.ClassInfo, props);
94 for i := 0 to typeData^.PropCount - 1 do
95 begin
96 with Props^[i]^ do
97 if (Name = AProperty) then
98 result := Props^[i];
99 end;
100 finally
101 FreeMem(props);
102 end;
103 end;
104
105 procedure TFrmPropertyList.SpeedButton1Click(Sender: TObject);
106 var
107 c: integer;
108 begin
109 ListProperties(self, ListBox1.Items);
110 for c := 0 to ComponentCount - 1 do
111 begin
112 ListBox1.Items.Add(EmptyStr);
113 ListProperties(Components[c], ListBox1.Items);
114 end;
115 end;
116
117 end.
|