delphi - 使用 RTTI 从 tkSet 类型获取可能值和当前值

标签 delphi rtti

可能有人已经问过这个问题,但还没有找到,所以问题就在这里:

我想解析组件的 tkSet 属性(在我们的例子中为 Panel1),但我不知道如何正确执行此操作。我能够使用 rContext.FindType() 找到该集合的基本枚举类型,但我几乎确定有一些更优雅/简单的方法可以做到这一点。从那时起我就完全迷失了。我应该仔细检查该枚举类型的值,并根据组件的当前属性值检查每个值。

procedure TForm12.GetProperties2;
var
  rContext: TRttiContext;
  rType: TRttiType;
  rProp: TRttiProperty;
begin
  rType := rContext.GetType(Panel1.ClassType);

  for rProp in rType.GetProperties do
  begin
    if (rProp.Visibility in [mvPublished]) and (rProp.PropertyType.TypeKind in [tkSet]) and (rProp.Name = 'Anchors') then
    begin
      Memo1.Lines.Add('Name: ' + rProp.Name);
      Memo1.Lines.Add('PropertyType: ' + rProp.PropertyType.ToString);
      Memo1.Lines.Add('Value: ' + rProp.GetValue(Panel1).ToString);
      Memo1.Lines.Add('QualifiedName: ' + rProp.PropertyType.QualifiedName);
      Memo1.Lines.Add('ElementType: ' + rContext.FindType(rProp.PropertyType.QualifiedName).AsSet.ElementType.ToString);
      // here comes the desired results
      Memo1.Lines.Add('Possible values:');
      Memo1.Lines.Add(' 0 > akLeft');
      Memo1.Lines.Add(' 1 > akTop');
      Memo1.Lines.Add(' 2 > akRight');
      Memo1.Lines.Add(' 3 > akBottom');
      Memo1.Lines.Add('Present values:');
      Memo1.Lines.Add(' 0 > akLeft');
      Memo1.Lines.Add(' 1 > akTop');
      Memo1.Lines.Add('');
    end;
  end;
end;

另一个可能的问题是没有基本枚举类型的设置属性,例如,如果您查看 TPanel.StyleElements 属性,您可以看到 TStyleElements 的声明如下:

TStyleElements = set of (seFont, seClient, seBorder);

在这种情况下,ElementType 不起作用。

所以问题是如何使用 RTTI 上下文解析 tkSet 类型属性以获得所需的结果?

最佳答案

使用基本的 TypInfo 非常容易。

procedure PrintSet(const v: TValue); // v contains a value from a set type
var
  enumType: PTypeInfo;
  enumData: PTypeData;
  buffer: set of Byte; // biggest possible set type
  i: Integer;
begin
  buffer := [];
  v.ExtractRawData(@buffer);
  enumType := v.TypeInfo.TypeData.CompType^;
  enumData := enumType.TypeData;
  for i := enumData.MinValue to enumData.MaxValue do
    Writeln(GetEnumName(enumType, i) + ' = ' + (i in buffer).ToString(TUseBoolStrs.True));
end;

字节集是可能的最大集合类型,因此我们可以将其用作所有内容都适合的缓冲区,然后使用TValue.ExtractRawData方法编写为实际集合类型所包含的数据量很大。其他所有内容都通过之前将其设置为空而归零。

然后我们可以使用枚举类型的类型数据来获取最小值和最大值。由于非连续枚举类型没有类型信息,我们不需要处理这一点,实际上只处理那些与经典位掩码二进制兼容的类型。

关于delphi - 使用 RTTI 从 tkSet 类型获取可能值和当前值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55612038/

相关文章:

delphi - FreePascal RTTI。有没有办法调用方法?

delphi - 我应该引用字段或属性名称吗?

delphi - 对于静态数组,使用 RTTI 获取记录字段类型失败

c++ - 显式调用基本复制构造函数 => RTTI 信息丢失。漏洞?

java instanceof 和 ocaml 匹配

multithreading - 将任意数据存储到对象实例中

delphi - 如何在 Delphi 中将 TPageControl 选项卡分解为单独的文件?

image - 使用自定义图像网格

Delphi-调用Win API

Java 泛型 "upcast"到非参数化类型