我很感激之前已经提出过几个类似的问题:
> 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时,我们如何获取和设置更深层次的子属性?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)