Author: Jonas Bilinkevicius
I'm using a component which is able to save the caption of components to a textfile
and then retrieve it again. This works quite nice since if one wants another
language one can just change some captions and load the desired language. The only
problem is that it is using only the well known Windows controls and is also
checking if a component is of a certain type. Of course I want to be able to use it
for all components, so how would I be able to check all the components on a form
for caption properties (even if it is e.g. in a item of a component) without having
to do type checking etc.?
Answer:
You can use functions from the TypInfo unit. You'll need a GetPropInfo to get
information about the property, GetStrProp and SetStrProp functions to read and set
a new caption for components. The example below is a component which can save the
captions of all components on a form to the text file and load them back after the
form was loaded. There is also a design time component editor which you need to
save and load captions (see a popup menu over the component).
1 {The main component}
2 TMyCaptionReader = class(TComponent)
3 protected
4 FFileName: string;
5 procedure Loaded; override;
6 public
7 constructor Create(AOwner: TComponent); override;
8 procedure ReadCaptions;
9 procedure WriteCaptions;
10 published
11 property FileName: string read FFileName write FFileName;
12 end;
13
14 {The component editor}
15 TMyCaptionReaderEditor = class(TDefaultEditor)
16 public
17 procedure ExecuteVerb(Index: Integer); override;
18 function GetVerb(Index: Integer): string; override;
19 function GetVerbCount: Integer; override;
20 end;
21
22 { ... }
23
24 procedure TMyCaptionReaderEditor.ExecuteVerb(Index: Integer);
25 begin
26 case Index of
27 0: TMyCaptionReader(Component).WriteCaptions;
28 1: TMyCaptionReader(Component).ReadCaptions;
29 else
30 inherited ExecuteVerb(Index)
31 end;
32 end;
33
34 function TMyCaptionReaderEditor.GetVerb(Index: Integer): string;
35 begin
36 case Index of
37 0: Result := 'Write Captions...';
38 1: Result := 'Read Captions...'
39 else
40 Result := inherited GetVerb(Index);
41 end;
42 end;
43
44 function TMyCaptionReaderEditor.GetVerbCount: Integer;
45 begin
46 Result := 2;
47 end;
48
49 constructor TMyCaptionReader.Create(AOwner: TComponent);
50 begin
51 inherited Create(AOwner);
52 FFileName := 'TheFile.txt';
53 end;
54
55 procedure TMyCaptionReader.Loaded;
56 begin
57 inherited Loaded;
58 ReadCaptions;
59 end;
60
61 procedure TMyCaptionReader.ReadCaptions;
62 var
63 XStrings: TStringList;
64 XComponent: TComponent;
65 XPropInfo: PPropInfo;
66 XName, XCaption: string;
67 i, XPos: integer;
68 begin
69 if not FileExists(FFileName) then
70 exit;
71 XStrings := TStringList.Create;
72 try
73 XStrings.LoadFromFile(FFileName);
74 for i := 0 to XStrings.Count - 1 do
75 begin
76 XPos := pos('=', XStrings[i]);
77 if XPos > -1 then
78 begin
79 XName := copy(XStrings[i], 0, XPos - 1);
80 XCaption := copy(XStrings[i], XPos + 1, length(XStrings[i]) - 1);
81 XComponent := Owner.FindComponent(XName);
82 if Assigned(XComponent) then
83 begin
84 XPropInfo := GetPropInfo(XComponent, 'Caption');
85 if Assigned(XPropInfo) then
86 SetStrProp(XComponent, 'Caption', XCaption);
87 end;
88 end;
89 end;
90 finally
91 XStrings.Free;
92 end;
93 end;
94
95 procedure TMyCaptionReader.WriteCaptions;
96 var
97 XStrings: TStringList;
98 XComponent: TComponent;
99 XPropInfo: PPropInfo;
100 XCaption: string;
101 i: integer;
102 begin
103 XStrings := TStringList.Create;
104 try
105 if Assigned(Owner) then
106 begin
107 for i := 0 to Owner.ComponentCount - 1 do
108 begin
109 XComponent := Owner.Components[i];
110 if Assigned(XComponent) then
111 begin
112 try
113 XPropInfo := GetPropInfo(XComponent, 'Caption');
114 if Assigned(XPropInfo) then
115 begin
116 XCaption := GetStrProp(XComponent, 'Caption');
117 XStrings.Add(XComponent.Name + '=' + XCaption);
118 end;
119 except
120 end;
121 end;
122 end;
123 end;
124 XStrings.SaveToFile(FFileName);
125 finally
126 XStrings.Free;
127 end;
128 end;
129
130 //Here's how the Register procedure could be:
131
132 procedure register;
133 begin
134 RegisterComponents('My Components', [TMyCaptionReader]);
135 RegisterComponentEditor(TMyCaptionReader, TMyCaptionReaderEditor);
136 end;
|