delphi – 当使用RTTI时,我们如何获取和设置更深层次的子属性?

delphi – 当使用RTTI时,我们如何获取和设置更深层次的子属性?,第1张

概述概观 我很感激之前已经提出过几个类似的问题: > Get/Set sub properties ussing RTTI > Get a sub property of a component in Delphi using RTTI > how i can set the value of a nested property using the RTTI > How can I set/get p 概观

我很感激之前已经提出过几个类似的问题:

> Get/Set sub properties ussing RTTI
> Get a sub property of a component in Delphi using RTTI
> how i can set the value of a nested property using the RTTI
> How can I set/get property value through RTTI for compex things like TStringGrid.Cells?

但是,我没有进一步了解如何将RTTI用于我的需求.

我也花了很多时间和精力来写这个问题所以我希望它不会被关闭:)

工作实例

我在下面有几个过程可以输出到TStrings列表中的组件的属性名称,值和类型.原始来源不是我的,我只是做了一些小改动,整理了代码并将它们放入一些整洁的可重用程序:

下面将输出属性名称,例如:

color DoubleBuffered Enabled 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,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;

以下将输出属性值,例如:

clWindow False True 25 75
function GetComponentPropertyValue(Component: TComponent; APropname: string): string;var  I: Integer;  Count,Size: Integer;  PropList: PPropList;  PropInfo: PPropInfo;begin  Count := GetPropList(Component.ClassInfo,nil);  Size  := Count * SizeOf(Pointer);  GetMem(PropList,Size);  try    Count := GetPropList(Component.ClassInfo,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;

最后,下面将以字符串格式输出属性类型,例如:

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;

并排上面调用的每个过程的输出将显示如下:

color | clWindow | Tcolor DoubleBuffered | False | Boolean Enabled | True | Boolean Height | 25 | Integer WIDth | 75 | Integer

以上所有这些都是有效的,除了我需要花一些时间阅读文档以尝试获得更好的理解并能够消化它之外没有其他问题.

我的问题(现在一直困扰我几天)是如何正确获取和设置子属性.例如,看一下Delphi Object Inspector的截图(为了目的而修改):

就像之前显示的程序一样,我需要对以蓝色突出显示的子属性发生同样的事情.

理想情况下,我想要的是一个函数,我可以传递一个组件和一个属性名称,如果它有子属性,则返回True,如下所示:

function HasSubProperty(Component: TComponent; APropname: string): Boolean;begin  Result := ??end;

虽然从屏幕截图中可以看出,我不确定这会有多好,但是一些子属性也有子属性(例如Component> Font> Style).

最终我想要的是一种检索子属性的名称,值和类型的方法.所以类似于:

procedure GetComponentSubPropertynames(Component: TComponent; APropname: string;  OutList: TStrings);begin  //end;

被叫时:

GetComponentSubPropertynames(Label1,Anchors);

应检索:

akleft aktop akRight akBottom

使用类似的过程来获取值和类型将如下所示:

akleft | True | Boolean aktop | True | Boolean akRight | True | Boolean akBottom | True | Boolean

对于Font子属性,例如:

Charset | DEFAulT_CHARSET | TFontCharset color | clWindowText | Tcolor Height | -11 | Integer OrIEntation | 0 | Integer Pitch | fpDefault | TFontPitch Quality | fqDefault | TFontQuality Size | 8 | Integer

访问另一个子属性(Font.Style)然后引起另一个问题,除非使用这样的过程:

procedure GetComponentSubPropertySubPropertynames(Component: TComponent; APropname,ASubPropname: string; OutList: TStrings);begin  //end;

这变得相当愚蠢.

摘要

基本上我需要一种挖掘更深层次属性的方法来获取它们的名称,值和类型,将它们放在列表中,并且还能够更改值.

我很感激,如果有人可以写一些代码样本,我将如何实现这一点(代码中的一些评论奖励).我相信一些这将是一个相对容易的任务,但我发现它确实非常微不足道.

到目前为止阅读了各种文档和示例仍然让我相当坦白,主要关注的是不知道使用什么类型或如何正确地创建和管理它们.

解决方法 像TFont,TAction,TPopupMenu这样的子属性是已经在像Tbutton这样的所有者组件中创建的组件(类).

要知道属性类型,请使用PropInfo.PropType ^ .Kind

请参阅Delphi帮助

TypInfo.PTypeInfo Type

TypInfo.TTypeKind

以下是您请求的代码示例:

function HasSubProperty(Component: TComponent; APropname: string): Boolean;var PropInfo: TPropInfo;begin  PropInfo := GetPropInfo(Component,APropname)^;  Result := PropInfo.PropType^.Kind in [tkClass,tkSet,tkRecord]end;

获取子类的示例

function GetSubPropClass(Component: TComponent; APropname: string):TComponent;    var PropInfo: PPropInfo;        AObject : TObject;    begin      Result := nil;      PropInfo := GetPropInfo(Component,APropname);      if PropInfo.PropType^.Kind in [tkClass] then      begin        AObject := GetobjectProp(Component,PropInfo);        if Assigned(AObject) then          Result := TComponent(AObject);      end;    end;

示例使用它

procedure TForm1.button1Click(Sender: TObject);var AComp : TComponent;begin  AComp := GetSubPropClass(Form1,'TFont',ListBox4.Items);  if AComp <> nil then    GetComponentPropertynames(AComp);end;

UPDATE

此代码将帮助您了解SET属性

function GetComponentPropertyValue(Component: TComponent; APropname: string): string;var  I,X: Integer;  Count,Size: Integer;  PropList: PPropList;  PropInfo: PPropInfo;  PropTypeInf : PTypeInfo;  SetList : TStrings;  Setname,SetVal : string;begin  Count := GetPropList(Component.ClassInfo,PropList);    for I := 0 to Count -1 do    begin     PropTypeInf := PropList^[I]^.PropType^;     PropInfo := PropList^[I];      if not (PropInfo^.PropType^.Kind = tkMethod) then      begin        if SameText(PropInfo^.name,APropname) then        begin          if (PropInfo^.PropType^.Kind = tkSet) then          begin            try              SetList := TStringList.Create;              SetList.CommaText := System.Variants.VarToStr(GetPropValue(Component,PropInfo^.name));              for X := 0 to 255 do              begin                Setname := GetSetElementname(GetTypeData(PropTypeInf)^.CompType^,X);                if Containsstr(Setname,'UITypes') then break;                SetVal := Setname + ' = ' + IfThen(SetList.IndexOf(Setname)<>-1,'True','False');                if Result = '' then                  Result := SetVal else                  Result := Result + ',' + SetVal;              end;            finally              SetList.Free;            end;          end else            Result := System.Variants.VarToStr(GetPropValue(Component,PropInfo^.name));          Exit;        end;      end;    end;  finally    FreeMem(PropList);  end;end;
总结

以上是内存溢出为你收集整理的delphi – 当使用RTTI时,我们如何获取和设置更深层次的子属性?全部内容,希望文章能够帮你解决delphi – 当使用RTTI时,我们如何获取和设置更深层次的子属性?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1273482.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存