Author: Jonas Bilinkevicius
Does anyone know if there is an easy way to load the value of a component's
property directly from its resource without creating the component? Something like:
if ReadPropertyValue('Form1.Button1', 'width') > 1000 then
ShowMessage('You are about to create a big button!');
Answer:
1 function TForm1.ReadProp(r: TReader): string;
2 begin3 result := '';
4 {Determine the value type of the property, read it with the appropriate method5 of TReader and convert it to string. Not all value types are implemented here6 but you get the idea.}7 case r.NextValue of8 vaInt8, vaInt16, vaInt32:
9 result := IntToStr(r.ReadInteger);
10 vaExtended:
11 result := FloatToStr(r.ReadFloat);
12 vaString:
13 result := r.ReadString;
14 else15 r.SkipValue; {Not implemented}16 end;
17 end;
18 19 procedure TForm1.ReadRes(PropPath: string; r: TReader);
20 var21 p: string;
22 begin23 {Skip the class name}24 r.ReadStr;
25 {Construct the property path}26 if PropPath = '' then27 p := r.ReadStr
28 else29 p := PropPath + '.' + r.ReadStr;
30 {Read all properties and its values and fill them into the memo}31 whilenot r.EndOfList do32 Memo1.Lines.Add(p + '.' + r.ReadStr + ' = ' + ReadProp(r));
33 {Skip over the end of the list of the properties of this component}34 r.CheckValue(vaNull);
35 {Recursively read the properties of all sub-components}36 whilenot r.EndOfList do37 begin38 ReadRes(p, r);
39 r.CheckValue(vaNull);
40 end;
41 end;
42 43 procedure TForm1.Button1Click(Sender: TObject);
44 var45 strm: TResourceStream;
46 Reader: TReader;
47 begin48 strm := TResourceStream.Create(HInstance, 'TForm1', RT_RCDATA);
49 Reader := TReader.Create(strm, 1024);
50 try51 Memo1.Clear;
52 Reader.ReadSignature;
53 ReadRes('', Reader);
54 finally55 Reader.Free;
56 strm.Free;
57 end;
58 end;
Only one small problem.
r.SkipValue was protected (in D5) but I hacked that out with the following code:
59 type60 THackReader = class(TReader);
61 { ... }62 THackReader(r).SkipValue;
And now it works like a charm.