0

Currently doing some research on RTTI in delphi.

The problem that arises is the following.

For this example I have a TPanel component (created from code and the owner is passed by the invoke method) Now the TPanel is cast to a TObject (to keep the methods I use generic).

Now I try to set that property via the SetXXXXXXProp function (XXXXXX is any of the following (ord, variant, str, method.... basically I tried all of the SetProperty functions.)

But for some odd reason the message I receive is that there is no Parent property. How can I set my Parent property??

So I hope any of you can give me a 'Pointer' in the right direction.

class procedure TComponentsCreator.AddParent(obj, parent : TObject);
var
  count : integer;
  propList: PPropList;
  I: Integer;

  method : TMethod;
begin

  count := GetPropList(obj, propList);

  for I := 0 to count -1 do
    begin

      WriteLn(propList[i]^.Name);

      if (CompareStr(LowerCase(String(propList[i]^.Name)), LowerCase('Parent')) = 0) then
        begin
          SetObjectProp(obj, String(propList[i]^.Name), parent);
        end;
    end;
end;    
Blaatz0r
  • 1,205
  • 1
  • 12
  • 24

1 Answers1

1

You are using the old style RTTI which was designed for the .dfm streaming mechanism. When you call GetPropList the list returned contains the published properties. You are looking for Parent which is public but not published.

You could use the new style RTTI to achieve this but that would seem to be unnecessary. RTTI is needed when the member or type that you wish to operate on is not known at compile time. However, you do know the member. It is TControl.Parent. So you can write

(obj as TControl).Parent := parent;

If for some reason, you felt compelled to use RTTI, then the simplest way to write the code that I can find is:

procedure SetControlParent(obj, parent: TObject);
var
  ctx: TRttiContext;
  typ: TRttiType;
  prop: TRttiProperty;
begin
  typ := ctx.GetType(obj.ClassType);
  prop := typ.GetProperty('Parent');
  prop.SetValue(obj, parent);
end;

I've omitted any error checking here, but I expect that you would not do the same in real code.


As a minor aside, your call to CompareStr is needlessly complex. If you wish to use case insensitive comparison use CompareText. If you wish to compare for equality use SameText. You could replace that code more clearly and simply like this:

if SameText(propList[I]^.Name, 'Parent') then
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • As i've already stated in my previous comment. I've already used the fix from this link I've found on stackoverlow. http://stackoverflow.com/questions/16948114/get-a-sub-property-of-a-component-in-delphi-using-rtti?rq=1 – Blaatz0r Oct 14 '14 at 12:59
  • Hard to see how that question relates to this one. Also very hard to see why you want to use RTTI for something that you know at compile time. – David Heffernan Oct 14 '14 at 13:04
  • In the case of a TPanel I know that at realtime but if i use multiple other components then I would have found myself in rewriting and checking everything for relations to a TControl/TWinControl. That is something i'm not going to do. Anyways everything works fine now as it should. – Blaatz0r Oct 14 '14 at 14:02
  • You don't need to know that it is a panel. But you do know that it is a `TControl`. Because otherwise `Parent` is meaningless. So you do know what you need to know at compile time. – David Heffernan Oct 14 '14 at 14:05