This is similar to your other RTTI issue, where you are accessing a control's TextSettings.Font
property via RTTI. The same thing applies for any nested-property, like Stroke.Color
, etc.
For each nested sub-property, you have to get the containing object, repeating as needed until you reach the desired sub-object, then you can get/set its property values as needed.
So, in this case, you have to use GetObjectProp()
to get the Stroke
property object, then you can use SetPropValue()
to set that object's properties. For example:
uses
..., TypInfo;
var
Componente_cc: TControl;
procedure TfrmPrincipal.AlteraPropriedades;
var
Stroke: TObject;
begin
if IsPublishedProp(Componente_cc, 'Stroke') then
begin
Stroke := GetObjectProp(Componente_cc, 'Stroke');
if Stroke <> nil then
SetPropValue(Stroke, 'Color', ...);
end;
end;
Or, to avoid a double RTTI lookup of the named property:
uses
..., TypInfo;
var
Componente_cc: TControl;
procedure TfrmPrincipal.AlteraPropriedades;
var
PropInfo: PPropInfo;
Stroke: TObject;
begin
PropInfo := GetPropInfo(Componente_cc, 'Stroke', [tkClass]);
if PropInfo <> nil then
begin
Stroke := GetObjectProp(Componente_cc, PropInfo);
if Stroke <> nil then
SetPropValue(Stroke, 'Color', ...);
end;
end;
Note that a more powerful Enhanced RTTI was introduced in Delphi 2010 (this RTTI is not limited to just published properties, like old-style RTTI is), for example:
uses
..., System.Rtti;
var
Componente_cc: TControl;
procedure TfrmPrincipal.AlteraPropriedades;
var
Ctx: TRttiContext;
Prop: TRttiProperty;
Stroke: TObject;
begin
Ctx := TRttiContext.Create;
Prop := Ctx.GetType(Componente_cc.ClassType).GetProperty('Stroke');
if (Prop <> nil) and (Prop.PropertyType.TypeKind = tkClass) {and (Prop.Visibility = mvPublished)} then
begin
Stroke := Prop.GetValue(Componente_cc).AsObject;
if Stroke <> nil then
begin
Prop := Ctx.GetType(Stroke.ClassType).GetProperty('Color');
if (Prop <> nil) {and (Prop.Visibility = mvPublished)} then
Prop.SetValue(Stroke, ...);
end;
end;
end;
However, it is better to just access sub-properties directly once you have access to a higher-level object, for example:
uses
..., TypInfo;
var
Componente_cc: TControl;
procedure TfrmPrincipal.AlteraPropriedades;
var
PropInfo: PPropInfo;
Stroke: TStrokeBrush;
begin
PropInfo := GetPropInfo(Componente_cc, 'Stroke', [tkClass]);
if PropInfo <> nil then
begin
Stroke := GetObjectProp(Componente_cc, PropInfo, TStrokeBrush) as TStrokeBrush;
if Stroke <> nil then
Stroke.Color := ...; // <-- no RTTI needed!
end;
end;
Or:
uses
..., System.Rtti;
var
Componente_cc: TControl;
procedure TfrmPrincipal.AlteraPropriedades;
var
Ctx: TRttiContext;
Prop: TRttiProperty;
Stroke: TStrokeBrush;
begin
Ctx := TRttiContext.Create;
Prop := Ctx.GetType(Componente_cc.ClassType).GetProperty('Stroke');
if (Prop <> nil) and (Prop.PropertyType.TypeKind = tkClass) {and (Prop.Visibility = mvPublished)} then
begin
Stroke := Prop.GetValue(Componente_cc).AsObject as TStrokeBrush;
if Stroke <> nil then
Stroke.Color := ...; // <-- no RTTI needed!
end;
end;