Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set/get property value through RTTI for compex things like TStringGrid.Cells?

Tags:

delphi

rtti

I have values stored in xml and lua code and accessing object's properties through RTTI.

var
  o, v: TValue; // o is current object
  a: TStringDynArray; // params as array
  ctx: TRttiContext;
  tt: TRttiType;
  p: TRttiProperty;
  pt: PTypeInfo;
begin
...
  ctx := TRttiContext.Create;
  try
    o := GetLastClassInParams(ctx, obj, a, param_idx);
    tt := ctx.GetType(o.TypeInfo);
    if high(a) < param_idx then
        raise Exception.Create(S_FN + S_NOP);
    p := tt.GetProperty(a[param_idx]);
    if p = nil then
        raise Exception.Create(S_FN + S_PNE + a[param_idx]);
    pt := p.PropertyType.Handle;
    case p.PropertyType.TypeKind of
      tkInteger: v := TValue.From<integer>(integer(Value));
      tkEnumeration: v := TValue.FromOrdinal(pt, GetEnumValue(pt, VarToStr(Value)));
      tkUString: v := TValue.From<string>(VarToStr(Value));
      tkFloat: v := TValue.From<double>(double(Value));
      tkSet: begin
          temp_int := StringToSet(pt, VarToStr(Value));
          TValue.Make(@temp_int, pt, v);
        end;
    else v := TValue.FromVariant(Value);
    end;
    p.SetValue(o.AsObject, v);

I can work with many properties like Width, Lines.Text of TMemo etc, even with Panels[0].Width of TStatusBar (where Panels is TCollection descendant), but thing like TStringGrid.Cells[x, y] is something I can't solve. There is help on Embarcadero and some functions like GetIndexedProperty (maybe that is what I need), but explanation there as good as "Gets Indexed Property".

How to set and get TStringGrid.Cells[x,y] through RTTI at runtime if I have values stored as strings like "Cells[1,1]"?

like image 535
user2091150 Avatar asked Mar 29 '13 11:03

user2091150


1 Answers

Here's the simplest example I can think off to get and set the values from a string grid using RTTI:

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

I excised the error checking for the sake of simplicity. I'm going to assume that you already know how to check for errors.

like image 115
David Heffernan Avatar answered Oct 15 '22 20:10

David Heffernan