【问题标题】:Delphi - Getting property values with GetPropValue()Delphi - 使用 GetPropValue() 获取属性值
【发布时间】:2017-08-20 19:34:54
【问题描述】:

我正在使用Delphi的GetPropValue()函数来获取TControl类型的某些对象的某些属性的值。当我得到ValueOpacity等简单的属性值时,一切正常,但是当我使用firemonkey时,有一些扩展属性,比如RotationCenter,它有RotationCenter.X和@987654327 @,甚至TextSettings中的文本属性,在这些带有子类型的属性中我无法获取值。

在这个例子中,我得到了正确的值:

If IsPublishedProp (Component_cc, 'Value') then
  EditValue.Text: = GetPropValue (Component_cc, 'Value', true);

在哪里Component_cc:TControl;并且是动态创建的,它也可以是任何类型的 Firemonkey 组件(到目前为止一切正常,一切正常)。

当我需要使用下面的表格时,它不起作用。

If IsPublishedProp (Component_cc, 'RotationCenter.X') then
  EditRotationCenterX.Text: = GetPropValue (CC_component, 'RotationCenter.X', true);

有谁知道用这个函数扩展这些属性的方法吗?

【问题讨论】:

  • 您需要深入了解结构。请求 X 属性 TPosition 对象。

标签: delphi firemonkey


【解决方案1】:

首先,CC_component 的RotationCenter 属性实际上是TPosition 类的一个实例,它继承自TPersistent

其次,调用IsPublishedProp时不能使用点分符号。

您可以使用GetObjectProp 首先检索内部TPosition 实例,然后从那里访问X 属性:

(假设一个简单的 FMX 应用程序具有一个表单,其中包含一个名为 Button1TButton 和一个名为 EditRotationCenterXTEdit。)

procedure TForm1.Button1Click(Sender: TObject);

var
   CC_component : TComponent;
   CC_component_RotationCenter : TPosition;

begin
   CC_component := Button1;

   if IsPublishedProp(CC_component, 'RotationCenter') then
      begin
         CC_component_RotationCenter := TPosition(GetObjectProp(CC_component, 'RotationCenter'));
         EditRotationCenterX.Text := CC_component_RotationCenter.X.ToString;
      end
end;

更新,对于 Set 类型的属性:

对于 Set 类型的属性,您需要使用 GetOrdProp 检索其序数值。这将是表示当前值中包含哪些元素的位数组。然后,您只需测试是否设置了适当的位。这是我更喜欢的方法。

或者,您可以使用GetSetProp,它将返回集合当前值中元素的文本表示。例如,如果 Set 的值为[TCorner.BottonLeft, TCorner.TopRight],您将返回字符串值“TopRight,BottonLeft”。然后检查目标元素的名称是否出现在返回的字符串中的任何位置。如果将来更改 Delphi RTL 或 FMX 库,此方法很容易失败。

(此示例将名为 Rectangle1TRectangle 形状和名为 cbCornerBottonRightTCheckBox 添加到上面的简单 FMX 应用程序中:)

procedure TForm1.Button1Click(Sender: TObject);

var
   CC_component : TComponent;
   CC_component_Corners : nativeint;

   CC_component_CornersAsString : string;

begin
   CC_component := Rectangle1;
   if IsPublishedProp(CC_component, 'Corners') then
      begin
         // Using this method will make your code less sensitive to 
         // changes in the ordinal values of the Set's members or      
         // changes to names of the enumeration elements.      
         //       
         CC_component_Corners := GetOrdProp(CC_component,'Corners');

         cbCornerBottonRight.IsChecked := ((1 shl ord(TCorner.BottomRight)) and CC_component_Corners) <> 0;


         // This approach may break if the names of the elements of
         // the TCorner enumeration are ever changed.  (BTW, they have
         // been in the past:  "cvTopLeft", "cvTopRight", "cvBottomLeft",
         // and "cvBottomRight" are now deprecated)
         //       
         CC_component_CornersAsString := GetSetProp(CC_component,'Corners');

         cbCornerBottonRight.IsChecked := CC_component_CornersAsString.IndexOf('BottomRight') >= 0;
      end;
end;

【讨论】:

  • 嗨,戴夫。我只是想寻求更多帮助,我按照您教的方式理解并管理了各种属性,但是对于某些属性,例如 Corners,我无法获得值。我是这样做的:if IsPublishedProp(Component_cc, 'Corners') then begin Cornersv := TCorner(GetObjectProp(Componente_cc, 'Corners')); ckCornerBottonRight.IsChecked := Cornersv.crBottomRight; end o erro é este: E2010 不兼容的类型:'Boolean' 和 'TCorner'。 ckCornerBottonRight 是一个TCheckbox
  • Corners 属性不是对象实例;它是 Set 类型。它需要与TPosition 对象实例完全不同的操作。我已经更新了答案,包括如何获取 Set 类型的属性的值。
  • 另外,您可能需要更新您的问题,以便包含有关 Set 类型属性的扩展。
  • 太棒了!完美运行!谢谢。
  • 我相信同样的原则也适用于元素的字体、背景和边框属性。
【解决方案2】:

在谈到旧的 RTTI 时,您可以这样做。你需要更深入地了解结构。请求 TPosition 对象的 X 属性:

var
  O: TObject;
  X: Integer;
begin
  if PropIsType(Component_cc, 'RotationCenter', tkClass) then
  begin
    O := GetObjectProp(Component_cc, 'RotationCenter');
    if Assigned(O) and PropIsType(O, 'X', tkInteger) then
      X := GetOrdProp(O, 'X');
  end;
end;

【讨论】:

  • 如果您已经拥有TPosition 对象,那么当您可以直接读取它时,不值得使用RTTI 读取它的X 属性。 S := RotationCenter.X.ToString;
  • 谢谢维多利亚!
  • @Remy,因此不值得使用 RTTI 来获取 TPosition 对象然后:) 我明白你的意思(不应该使用 RotationCenter 变量这样的东西)。您可以放弃对从我复制的答案的评论(使用更不安全的类型转换)。我正要及时删除这个..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 2013-06-01
  • 2013-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多