Overview
I appreciate a couple of similar questions that have already been asked before:
However, I will not further understand how exactly RTTI can be used for my needs.
I also put a lot of time and effort into writing this question, so I hope it doesn't close :)
Working examples
I have several procedures below that can list property names, values, and component types in a TStrings list. The original source was not mine, I just made some minor changes to it, tidied up the code, and put them into some neat reusable procedures:
Property names are listed below, for example:
- Color
- Doublebuffered
- Included
- Height
- Width
procedure GetComponentPropertyNames(Component: TComponent; OutList: TStrings); var I: Integer; Count, Size: Integer; PropList: PPropList; PropInfo: PPropInfo; begin OutList.BeginUpdate; try OutList.Clear; Count := GetPropList(Component.ClassInfo, tkAny, nil); Size := Count * SizeOf(Pointer); GetMem(PropList, Size); try Count := GetPropList(Component.ClassInfo, tkAny, PropList); for I := 0 to Count -1 do begin PropInfo := PropList^[I]; if not (PropInfo^.PropType^.Kind = tkMethod) then begin OutList.Add(PropInfo^.Name); end; end; finally FreeMem(PropList); end; finally OutList.EndUpdate; end; end;
The following are property values, such as:
function GetComponentPropertyValue(Component: TComponent; APropName: string): string; var I: Integer; Count, Size: Integer; PropList: PPropList; PropInfo: PPropInfo; begin Count := GetPropList(Component.ClassInfo, tkAny, nil); Size := Count * SizeOf(Pointer); GetMem(PropList, Size); try Count := GetPropList(Component.ClassInfo, tkAny, PropList); for I := 0 to Count -1 do begin PropInfo := PropList^[I]; if not (PropInfo^.PropType^.Kind = tkMethod) then begin if SameText(PropInfo^.Name, APropName) then begin Result := System.Variants.VarToStr(GetPropValue(Component, PropInfo^.Name)); Exit; end; end; end; finally FreeMem(PropList); end; end; procedure GetComponentPropertyValues(Component: TComponent; OutList: TStrings); var SL: TStringList; I: Integer; begin SL := TStringList.Create; try GetComponentPropertyNames(Component, SL); for I := 0 to SL.Count -1 do begin OutList.Add(GetComponentPropertyValue(Component, SL.Strings[I])); end; finally SL.Free; end; end;
And finally, property types in string format will be displayed below, for example:
- TColor
- Boolean
- Boolean
- Integer
- Integer
function GetComponentPropertyType(Component: TComponent; APropName: string): string; var SL: TStringList; I: Integer; PropInfo: TPropInfo; PropTypeName: string; begin SL := TStringList.Create; try GetComponentPropertyNames(Component, SL); for I := 0 to SL.Count -1 do begin PropInfo := GetPropInfo(Component, SL.Strings[I])^; if SameText(PropInfo.Name, APropName) then begin PropTypeName := PropInfo.PropType^.Name; Result := PropTypeName; Exit; end; end; finally SL.Free; end; end; procedure GetComponentPropertyTypes(Component: TComponent; OutList: TStrings); var SL: TStringList; I: Integer; begin SL := TStringList.Create; try GetComponentPropertyNames(Component, SL); for I := 0 to SL.Count -1 do begin OutList.Add(GetComponentPropertyType(Component, SL.Strings[I])); end; finally SL.Free; end; end;
Next to each other, the output for each procedure described above will look something like this:
- Color | clWindow | TColor
- Doublebuffered | False | Logical
- Included | True | Logical
- Height | 25 | Integer
- Width | 75 | Integer
Question
All of the above works at this stage, there is no other problem, except that I need to read the documentation a bit to try to get a little better understanding and be able to digest it all.
My question (which has been listening to me for several days) is how to properly obtain and set additional properties. For example, take a look at this screenshot (modified for the purpose) of the Delphi Object Inspector:

Just like the previous procedures, I need the same thing as for those auxiliary properties that I highlighted in blue.
Ideally, I would like to use a function in which I can pass the component and property name, and return True if it has sub properties, so something like:
function HasSubProperty(Component: TComponent; APropName: string): Boolean; begin Result := ?? end;
I'm not sure how well this will work, although it can be seen from the screenshot, some additional properties also have auxiliary properties (such as Component> Font> Style).
Ultimately, what I would like is a way to get the names, values, and types of additional properties. So something like:
procedure GetComponentSubPropertyNames(Component: TComponent; APropName: string; OutList: TStrings); begin
When called:
GetComponentSubPropertyNames(Label1, Anchors);
Must get:
- akLeft
- akTop
- akRight
- akBottom
With similar procedures to get values โโand types it will look:
- akLeft | True | Logical
- akTop | True | Logical
- akRight | True | Logical
- akBottom | True | Logical
For additional font properties, for example:
- Charset | DEFAULT_CHARSET | TFontCharset
- Color | clWindowText | TColor
- Height | -11 | Integer
- Orientation | 0 | Integer
- Pitch | fpDefault | TFontPitch
- Quality | fqDefault | TFontQuality
- Size | 8 | Integer
Accessing another helper property (Font.Style) then creates another problem if the procedure is not used:
procedure GetComponentSubPropertySubPropertyNames(Component: TComponent; APropName, ASubPropName: string; OutList: TStrings); begin
It gets pretty dumb.
Summary
Basically, I need a way to dig into deeper level properties in order to get the names, values โโand types of them, put them in a list, and also be able to change the values.
I would appreciate it if someone could write code samples, how can I achieve this (a bonus with some comments in the code). I am sure that for some this will be a relatively simple task, but I find it very trivial.
After reading various documents and examples that still leave me rather ignorant to be honest, the main problem is not to know which types to use or how to properly create and manage them.