如何通过RTTI设置/获取像TStringGrid.Cells这样的复杂属性的值?

7

我在xml和lua代码中存储了值,并通过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);

我可以使用许多属性,如TMemo的WidthLines.Text,甚至是TStatusBar中的Panels[0].Width(其中Panels是TCollection的后代),但是像TStringGrid.Cells[x, y]这样的东西我无法解决。Embarcadero上有帮助文档和一些函数,如GetIndexedProperty(也许这就是我需要的),但是那里的解释像"Gets Indexed Property"一样简略。
如果我有类似于"Cells[1,1]"的字符串存储的值,那么如何在运行时通过RTTI设置和获取TStringGrid.Cells[x,y]
1个回答

6

以下是我能想到的最简单的例子,使用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');

为了简化代码,我省略了错误检查。我假设您已经知道如何检查错误。


谢谢。有没有办法找出何时应该使用GetIndexedProperty和GetProperty? - user2091150
1
好的,我猜您正在解析这样的文本:Cells[1,1] := ...。如果是这样,那么 [] 的存在告诉您它是一个索引属性。您还可以使用 TRttiType.GetIndexedProperties 并检查您的属性是否在该列表中。 - David Heffernan
是的,但我很好奇Delphi是否知道属性是否被索引,也许RTTI可以以某种方式返回IsIndexed。谢谢。 - user2091150
我查找了,但是找不到这样的属性。 - David Heffernan
因为存在问题:TStatusBar.Panels[x]是属性,尝试读取为GetIndexedProperty('Panels')时为空,而TStringGrid.Cells[x,y]是索引属性,尝试读取为GetProperty('Cells')时为空。我不能将索引和非索引属性都放入数组中进行搜索,因为它们具有不同的类型。而且,数组值是由不同函数使用的确切类型。或者 - 我可以这样做,但没有意义。唯一的选择是同时获取它们并通过nil或非nil来决定。 - user2091150
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接