delphi RTTI 读取属性 运行期

通过RTTI给属性赋值

http://docwiki.embarcadero.com/CodeExamples/Berlin/en/Event_RTTI_Invocation_(Delphi)

http://www.cnblogs.com/del/archive/2009/10/15/1583969.html

var
  context: TRttiContext;
  method: TValue; // System.TMethod
  methodType: TRttiInvokableType;
begin
  { Get the value of the OnChange property, which is a method pointer }
  method := context.GetType(mapModel.ClassType).GetProperty('OnChange')
    .GetValue(mapModel);
 
  { Display the method code and data pair }
  Writeln(method.ToString);
 
  { Get event RTTI }
  methodType := context.GetType(method.TypeInfo) as TRttiInvokableType;
  Writeln(methodType.Name);
 
  { Invoke event }
  { The first parameter must be the procedure/method pointer in a TValue variable }
  methodType.Invoke(method, [mapModel { Sender } , nil { Area } ]);

 

读取简单属性

procedure TForm2.Button6Click(Sender: TObject);
var
  rc: TRttiContext;
  v: TValue;
  rm: TRttiMethod;
  rt: TRttiType;
  rp: TRttiProperty;
begin
  //取Btn2的属性Name 和Caption
  //分步
  rt := TRttiContext.Create.GetType(self.Button2.ClassType);
  rp := rt.GetProperty('Name');
  v := rp.GetValue(self.btn2);
  ShowMessage(v.AsString);

  //合并一步
 ShowMessage(  rt.GetProperty('Caption').GetValue(self.btn2).AsString);

end;

 

修改属性

rt.GetProperty('Caption').SetValue(Button1,'New');

 p.SetValue(Button1, TValue.FromOrdinal(TypeInfo(TAlign), Ord(alLeft))); 

 

    rc.GetType(Data.ClassType).GetField('FStatus').SetValue(Data, TValue.From(Status));

const
  eval = 'alLeft';

   p.SetValue(Panel1, TValue.FromOrdinal( p.PropertyType.Handle , Ord(alLeft)));

两种方法都可以
//  tv := TValue.FromOrdinal(p.PropertyType.Handle, GetEnumValue(p.PropertyType.Handle, eval));
//  p.SetValue(Panel1, tv);

 

//调用btn2单击方法
procedure TForm2.Button7Click(Sender: TObject);
var
  tt: TRttiType;
  rm: TRttiMethod;
begin
  tt := TRttiContext.Create.GetType(self.btn2.ClassType);
  rm := tt.GetMethod('Click');
  rm.Invoke(self.btn2, []);//空参
end;

   TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
    tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,
    tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray, tkUString,
    tkClassRef, tkPointer, tkProcedure {, tkMRecord});

 

PropInfo.PropType^.Kind = tkClass

 

aRPt: TRttiProperty;

aRPt.PropertyType.Handle就是PTypeInfo

  aRPt.PropertyType.Handle.Kind

 

设置复杂的属性字体颜色 字体 Font.Size/Font.Color

procedure TForm13.Button7Click(Sender: TObject);
var
  p : TRttiProperty;
  p2: TRttiProperty;
  c : TRttiContext;
begin
   c := TRttiContext.Create;
   try
     p := c.GetType(Panel1.ClassInfo).GetProperty('Font');
     p2 := c.GetType(p.PropertyType.Handle).GetProperty('Color');
     p2.SetValue(p.GetValue(Panel1).AsObject,clred);
   finally
     c.Free;
   end;
end;



procedure TForm13.Button8Click(Sender: TObject);
var
  p : TRttiProperty;
  p2: TRttiProperty;
  c : TRttiContext;
begin
   c := TRttiContext.Create;
   try
//        self.Panel1.Font.Style:
     p := c.GetType(Panel1.ClassInfo).GetProperty('Font');
     p2 := c.GetType(p.PropertyType.Handle).GetProperty('Size');
     p2.SetValue(p.GetValue(Panel1).AsObject,20); //this line now works.
   finally
     c.Free;
   end;
end;

 http://stackoverflow.com/questions/6006326/how-i-can-set-the-value-of-a-nested-property-using-the-rtti?answertab=votes#tab-top

 

复杂类型(集合类型)tkSet

 与控件实例无关,只是计算集合类型的字符串。获得某个控件当前某个集合属性的字符串参考System.TypInfo.GetSetProp

procedure GetOrdTypeInfo(ATypeInfo: PTypeInfo; AStrings: TStrings);
var
  OrdTypeData: PTypeData;
  I: Integer;
begin
  OrdTypeData := GetTypeData(ATypeInfo);
  AStrings.Add('------------------------------------');
  AStrings.Add('Type Name: ' + ATypeInfo^.Name);
  AStrings.Add('Type Kind: ' + GetEnumName(TypeInfo(TTypeKind),
    Integer(ATypeInfo^.Kind)));
  AStrings.Add('Data Type: ' + GetEnumName(TypeInfo(TOrdType),
    Integer(OrdTypeData^.OrdType)));
  if ATypeInfo^.Kind <> tkSet then
  begin
    AStrings.Add('Min Value: ' + IntToStr(OrdTypeData^.MinValue));
    AStrings.Add('Max Value: ' + IntToStr(OrdTypeData^.MaxValue));
  end;
  if ATypeInfo^.Kind = tkSet then
    GetOrdTypeInfo(OrdTypeData^.CompType^, AStrings);
  if ATypeInfo^.Kind = tkEnumeration then
    for I := OrdTypeData^.MinValue to OrdTypeData^.MaxValue do
      AStrings.Add(Format('  Value %d: %s', [I, GetEnumName(ATypeInfo, I)]));
end;

procedure TForm2.Button3Click(Sender: TObject);
begin
  GetOrdTypeInfo(TypeInfo(Char), Memo1.Lines);
  GetOrdTypeInfo(TypeInfo(Integer), Memo1.Lines);
  GetOrdTypeInfo(TypeInfo(TFormBorderStyle), Memo1.Lines);
  GetOrdTypeInfo(TypeInfo(TBorderIcons), Memo1.Lines);
  GetOrdTypeInfo(TypeInfo(TMyEnum), Memo1.Lines);
  GetOrdTypeInfo(TypeInfo(TDBGridOption), Memo1.Lines);
end;

 TypeInfo(TPicture);

TypeInfo(TBitmap)

DBGrid

PropertyName:Options

Type Name: TDBGridOptions
Type Kind: tkSet
Data Type: otUWord
------------------------------------
Type Name: TDBGridOption
Type Kind: tkEnumeration
Data Type: otUByte
Min Value: 0
Max Value: 14
  Value 0: dgEditing
  Value 1: dgAlwaysShowEditor
  Value 2: dgTitles
  Value 3: dgIndicator
  Value 4: dgColumnResize
  Value 5: dgColLines
  Value 6: dgRowLines
  Value 7: dgTabs
  Value 8: dgRowSelect
  Value 9: dgAlwaysShowSelection
  Value 10: dgConfirmDelete
  Value 11: dgCancelOnExit
  Value 12: dgMultiSelect
  Value 13: dgTitleClick
  Value 14: dgTitleHotTrack

 

gridEh控件

PropertyName:OptionsEh

Type Name: TDBGridEhOption
Type Kind: tkEnumeration
Data Type: otUByte
Min Value: 0
Max Value: 23
  Value 0: dghFixed3D
  Value 1: dghFrozen3D
  Value 2: dghFooter3D
  Value 3: dghData3D
  Value 4: dghResizeWholeRightPart
  Value 5: dghHighlightFocus
  Value 6: dghClearSelection
  Value 7: dghFitRowHeightToText
  Value 8: dghAutoSortMarking
  Value 9: dghMultiSortMarking
  Value 10: dghEnterAsTab
  Value 11: dghTraceColSizing
  Value 12: dghIncSearch
  Value 13: dghPreferIncSearch
  Value 14: dghRowHighlight
  Value 15: dghDblClickOptimizeColWidth
  Value 16: dghDialogFind
  Value 17: dghRecordMoving
  Value 18: dghShowRecNo
  Value 19: dghColumnResize
  Value 20: dghColumnMove
  Value 21: dghAutoFitRowHeight
  Value 22: dghHotTrack
  Value 23: dghExtendVertLines

 

通过RTTI给StringGrid单元格赋值

参考

http://stackoverflow.com/questions/15702778/how-can-i-set-get-property-value-through-rtti-for-compex-things-like-tstringgrid

var
  ctx: TRttiContext;
  rttitype: TRttiType;
  rttiprop: TRttiIndexedProperty;
  value: TValue;
begin
  rttitype := ctx.GetType(StringGrid1.ClassType);
  rttiprop := rttitype.GetIndexedProperty('Cells');
  value := rttiprop.GetValue(StringGrid1, [1, 1]);
  rttiprop.SetValue(StringGrid1, [1, 1], value.ToString + ' hello');
end;

 

判断属性类型

procedure DeserializeProperty(P: TRttiProperty; s: string);
var
  v: TValue;      
begin
  case p.PropertyType.TypeKind of
    tkInteger: v := StrToInt(s);
    tkFloat: v := StrToFloat(s);
    tkString: v := s;
  end;
  p.SetValue(self, v);
end;

 

posted on 2017-02-20 21:38  lypzxy  阅读(1003)  评论(0编辑  收藏  举报