Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Fehler: "Invalid property path" bei eigener Komponente (https://www.delphipraxis.net/188902-fehler-invalid-property-path-bei-eigener-komponente.html)

roth 18. Apr 2016 15:16

Fehler: "Invalid property path" bei eigener Komponente
 
hallo,

Ich versuche eine eigene Komponente zu schreiben welche eine Liste mit Objekte verwaltet. Diese Objekte haben jeweils ein Bitmap. Über einen ComponentEdior kann ich die Elemente problemlos hinzufügen. Die Eigenschaften werden auch alle in das .dfm geschrieben. Nur nach dem neu laden der Form kommt der "Invalid property path" Fehler für das Bitmap.Data property.

Hier meine Klassen: (destructor etc. ist noch nicht implementiert)

Delphi-Quellcode:

type
  TBSMultiImageList = class;

  TBSImageInfo = class(TComponent)
  private
    FCaption      : String;
    FBitmap       : TBitmap;
    FImageIndex   : Integer;
    FParent       : TBSMultiImageList;
    procedure SetBitmap(const Value: TBitmap);
    procedure SetParent(const AValue: TBSMultiImageList);
  strict protected
     procedure ReadState(Reader: TReader); override;
    procedure SetParentComponent(AParent: TComponent); override;
  public
    constructor Create(AOwner: TComponent); reintroduce;
    procedure AssignTo(Dest: TPersistent); override;
    function GetParentComponent: TComponent; override;
    function HasParent: Boolean; override;
    property Parent: TBSMultiImageList read FParent write SetParent;
  published
    property Bitmap: TBitmap read FBitmap write SetBitmap;
    property ImageIndex: Integer read FImageIndex write FImageIndex;
    property Caption: String read FCaption write FCaption;
  end;

  TBSMultiImageList = class(TComponent)
  private
    FImages : TList<TBSImageInfo>;
    function GetImageCount: Integer;
    function GetImage(AIndex: Integer): TBSImageInfo;
  strict protected
    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure AddImage(var AImage: TBSImageInfo);
    property ImageCount: Integer read GetImageCount;
    property Images[AIndex: Integer]: TBSImageInfo read GetImage;
  end;


procedure Register;


implementation


{ Globale Funktionen }

procedure Register;
begin
  RegisterClass(TBSImageInfo);
  RegisterNoIcon([TBSImageInfo]);
  RegisterComponents('Test', [TBSMultiImageList]);
end;

{ TBSMultiImageList }

procedure TBSMultiImageList.AddImage(var AImage: TBSImageInfo);
begin
  FImages.Add(AImage);
  AImage.FParent := Self;
end;

constructor TBSMultiImageList.Create(AOwner: TComponent);
begin
  inherited;
  FImages := TList<TBSImageInfo>.Create;
end;

procedure TBSMultiImageList.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
  ix: Integer;
  info : TBSImageInfo;
begin
  for ix := 0 to FImages.Count - 1 do begin
    info := FImages[ix];
    Proc(info);
  end;
end;

function TBSMultiImageList.GetImage(AIndex: Integer): TBSImageInfo;
begin
  Result := FImages[AIndex];
end;

function TBSMultiImageList.GetImageCount: Integer;
begin
  Result := FImages.Count;
end;


{ TBSImageInfo }

procedure TBSImageInfo.AssignTo(Dest: TPersistent);
begin
  if Dest is TBSImageInfo then begin
    TBSImageInfo(Dest).Bitmap := Bitmap;
    TBSImageInfo(Dest).Caption   := Caption;
    TBSImageInfo(Dest).ImageIndex := ImageIndex;
  end
  else inherited AssignTo(Dest);
end;

constructor TBSImageInfo.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FBitmap       := TBitmap.Create;
  FBitmap.Width := 16;
  FBitmap.Height := 16;
  FCaption          := '<Bezeichnung>';
end;

function TBSImageInfo.GetParentComponent: TComponent;
begin
  if Parent <> nil
    then Result := Parent
    else Result := inherited GetParentComponent;
end;

function TBSImageInfo.HasParent: Boolean;
begin
  Result := Assigned(FParent);
end;

procedure TBSImageInfo.ReadState(Reader: TReader);
begin
  inherited ReadState(Reader);
  if Reader.Parent is TBSMultiImageList
    then Parent := TBSMultiImageList(Reader.Parent);
end;

procedure TBSImageInfo.SetBitmap(const Value: TBitmap);
begin
  FBitmap.Assign(Value);
end;

procedure TBSImageInfo.SetParent(const AValue: TBSMultiImageList);
begin
  if AValue <> Parent then begin
    if Parent <> nil
      then Parent.RemoveImage(Self);
    if AValue <> nil
      then AValue.AddImage(Self);
  end;
end;

procedure TBSImageInfo.SetParentComponent(AParent: TComponent);
begin
  if not (csLoading in ComponentState) and (AParent is TBSMultiImageList)
    then Parent := (AParent as TBSMultiImageList);
end;

initialization
  RegisterClass(TBSImageInfo);

end.
Erkennt jemand der Fehler?

Danke

Uwe Raabe 18. Apr 2016 15:24

AW: Fehler: "Invalid property path" bei eigener Komponente
 
Warum
Delphi-Quellcode:
constructor Create(AOwner: TComponent); reintroduce;
und nicht
Delphi-Quellcode:
override
?

Das Streaming-System kennt dein Create nicht und verwendet das virtuelle von TComponent. Dadurch wird FBitmap nicht erzeugt und SetBitmap bringt einen Fehler.

himitsu 18. Apr 2016 15:36

AW: Fehler: "Invalid property path" bei eigener Komponente
 
Der DFM-Reader will die Property einer SubKomponente (TPersistent) einlesen, aber diese Subkomponente existiert nicht.
Der Reader erstellt keine SubKomponenten. Das mußt du machen.

Vermutung: Deine TBSMultiImageList versucht eine/mehrere TBSImageInfo einzulesen, aber du hast vergessen die Instanzen zu erstellen.

roth 18. Apr 2016 16:34

AW: Fehler: "Invalid property path" bei eigener Komponente
 
Klar gehört da override und nicht reintroduce hin:roll:. Danke!


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz