gpt4 book ai didi

delphi - 使用 SetPropValue() 和 RTTI 与 Delphi Tokyo 更改组件属性

转载 作者:行者123 更新时间:2023-12-02 05:34:10 28 4
gpt4 key购买 nike

我使用下面的代码在运行时创建的组件中使用 RTTI 和 Delphi 10.2 Tokyo 设置属性,一切正常,因为示例的属性是 TypeLine,因为我可以直接访问它。

Componente_cc Is a variable that can be instantiated with any class, be it TLabel, TButton, TEdit... or any other. In the case below I'm instantiating it as being a TLine.

Var 
Componente_cc: TControl;

procedure TfrmPrincipal.AlteraPropriedades;
begin
if IsPublishedProp(Componente_cc, 'LineType') then
SetPropValue(Componente_cc, 'LineType', 'Diagonal');
end;

但是,我不明白当有子属性时该怎么办,例如Stroke,它有Kind颜色帽子破折号 等。如何使用 SetPropValue() 函数更改这些属性的值。为了更好地理解,我简化了示例代码,但在我的系统的一般上下文中,我需要使用 RTTI,当然直接通过代码更改属性会很简单,但我确实需要RTTI

最佳答案

这类似于您的 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在 Delphi 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;

但是,一旦您有权访问更高级别的对象,最好直接访问子属性,例如:

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;

关于delphi - 使用 SetPropValue() 和 RTTI 与 Delphi Tokyo 更改组件属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45987321/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com