这与您的other RTTI issue类似,您可以通过RTTI访问控件的TextSettings.Font
属性。同样的道理也适用于任何嵌套的属性,如Stroke.Color
等
对于每个嵌套子属性,你必须得到包含的对象,根据需要,直到达到所需的子对象,然后你重复可以根据需要获取/设置其属性值。
所以,在这种情况下,你必须使用GetObjectProp()
得到Stroke
属性对象,那么你可以使用SetPropValue()
来设置对象的属性。例如:
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;
或者,要避免命名属性的双重RTTI查找:
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;
注意,一个更强大的Enhanced RTTI德尔福2010年被引入(这RTTI不限于刚刚出版属性,如旧式RTTI是),例如:
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;
但是,最好还是直接访问子属性,一旦你有机会获得更高级别的Ø bject,例如:
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;
或者:
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;
你好@Remy,当你说有自2010年以来一个更强大的RTTI指的是你的第二个例子吗?直接访问属性? – Anderson
我正在使用RTTI,因为它是我能找到的唯一解决方案,我的问题是所讨论的软件类似于IDE,用户添加控件并更改属性,调整大小等,因此组件正被添加到在运行时,他们可以是任何类,我试图做一个函数来添加所有类型的组件,另一个来获取属性,另一个来设置属性,所以我创建了TControl类型的对象,并在其中类,问题是在TControl我没有直接访问所有属性,所以我使用了RTTI。 – Anderson
@Anderson:直接访问属性与RTTI无关,这只是普通的面向对象编程。 “PPropInfo”的使用并不新鲜,它始终可用。 'System.TypInfo'单元实现的旧式RTTI已被[System.Rtti'单元实现的增强RTTI(http://docwiki.embarcadero.com/RADStudio/en/Working_with_RTTI_Index)取代。 –