Delphi - 使用GetPropValue()获取属性值

And*_*son 4 delphi firemonkey

我正在使用Delphi的GetPropValue()函数来获取某些类型对象的某些属性的值TControl.一切正常,当我得到简单的属性值,例如Value,Opacity等等,但我使用firemonkey有一些扩展属性,比如RotationCenter,它有RotationCenter.XRotationCenter.Y,甚至是在文本的特性 TextSettings,这些特性与子类型我无法获得价值.

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

If IsPublishedProp (Component_cc, 'Value') then
  EditValue.Text: = GetPropValue (Component_cc, 'Value', true);
Run Code Online (Sandbox Code Playgroud)

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

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

If IsPublishedProp (Component_cc, 'RotationCenter.X') then
  EditRotationCenterX.Text: = GetPropValue (CC_component, 'RotationCenter.X', true);
Run Code Online (Sandbox Code Playgroud)

有没有人知道通过这个功能扩展这些属性的方法?

Dav*_*son 6

首先,CC_component的RotationCenter属性实际上是一个TPosition降序的类的实例TPersistent.

其次,调用时不能使用点分表示法IsPublishedProp.

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

(假设一个简单的FMX应用程序,其中一个表单包含一个TButton被调用的Button1和一个TEdit被调用的EditRotationCenterX.)

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;
Run Code Online (Sandbox Code Playgroud)

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

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

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

(这个例子从上面添加一个TRectangle名为Rectangle1和一个TCheckBox调用的形状cbCornerBottonRight到简单的FMX App :)

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;
Run Code Online (Sandbox Code Playgroud)


Vic*_*ria 5

在谈到旧RTTI时,您可以这样做.你需要深入了解结构.索要X属性TPosition对象:

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;
Run Code Online (Sandbox Code Playgroud)

  • 如果你已经有了'TPosition`对象,那么当你可以直接读它时,不值得使用RTTI读取它的`X`属性.`S:= RotationCenter.X.ToString;` (3认同)