Mohamad
Mohamad

Reputation: 1117

ClassInfo function in Delphi 7

When I define a class like this in Delphi 7:

  TPerson = class(TObject)
  private
    FLName: string;
    FFName: string;
    FAge: integer;
    FBDate: TDate;
  public
  published
    property FName: string read FFName write FFName;
    property LName: string read FLName write FLName;
    property Age: integer read FAge write FAge;
    property BDate: TDate read FBDate write FBDate;
  end;

procedure ListComponentProperties(AObject: TObject; Strings: TStrings);
var
  Count, Size, I: Integer;
  List: PPropList;
  PropInfo: PPropInfo;
  PropValue: string;
begin
  Count := GetPropList(AObject.ClassInfo, tkAny, List);
  Size  := Count * SizeOf(Pointer);
  GetMem(List, Size);
  try
    Count := GetPropList(AObject.ClassInfo, tkAny, List);
    for I := 0 to Count - 1 do
    begin
      PropInfo := List^[I];
      PropValue := VarToStr(GetPropValue(AObject, PropInfo^.Name));
    end;
  finally
    FreeMem(List);
  end;
end;

and I want to get a list of its published properties with ListComponentProperties an error message will be displayed.The error is related to the following command and AObject.ClassInfo:

Count := GetPropList(AObject.ClassInfo, tkAny, List);

Any help would be greatly appreciated.

Upvotes: 0

Views: 2069

Answers (2)

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28540

In addition to using $M compiler directive, you can derive your classes from any class that has RTTI info enabled.

One of such classes is TPersistent that should be used as base class for any class that needs to have assignment and streaming capabilities.

TPersistent encapsulates the behavior common to all objects that can be assigned to other objects, and that can read and write their properties to and from a form file (.xfm or .dfm file).

Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that need to be saved to a stream or have their properties assigned to other objects.

In practice that means that if you want to use TPerson class as published property of some component that can be edited in IDE via Object Inspector and streamed to form file (.dfm) your class must have TPersistent as ancestor in it's class hierarchy.

type
  TPersonComponent = class(TComponent)
  protected
    FPerson: TPerson;
    procedure SetPerson(AValue: TPerson);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Person: TPerson read FPerson write SetPerson;
  end;

constructor TPersonComponent.Create(AOwner: TComponent);
begin
  inherited;
  FPerson := TPerson.Create;
end;

destructor TPersonComponent.Destroy;
begin
  FPerson.Free;
  inherited;
end;

procedure TPersonComponent.SetPerson(AValue: TPerson);
begin
  FPerson.Assign(AValue);
end;

If you use class declared as TPerson = class(TObject) in above example, its properties (even though published and with RTTI information turned on) will not be saved into .dfm file when TPersonComponent is edited in Object Inspector.

Upvotes: 2

David Heffernan
David Heffernan

Reputation: 613461

You have to enable RTTI for that type. By default it is not enabled. Declare the type like this:

type
  {$M+}
  TPerson = class(TObject)
  ....
  end;
  {$M-}

Your initial call to GetPropList is also wrong. It must read:

Count := GetPropList(AObject.ClassInfo, tkAny, nil);

If you enabled warnings the compiler would have told you that you were passing an uninitialized variable.

I've not checked any more of your code. There may be more errors.

Upvotes: 2

Related Questions