tags:

views:

91

answers:

1

Hi,

//I do not know how to ask the question better...//

I registred new class of my own (TDisplay). Inside of this class is one object (TRectangle - also of my own), which is created in the constructor of TCustomDisplay - predecestor of TDisplay.

When I put TDisplay on the form, I can edit all published properties of both my objects (TDisplay, TRectangle) as usual, but only TDisplay is set up according to the object inspector. TRectangle remains in its default values (left 0, Top 0 right 30, bottom 20), in spite of it, that these properties are set to left 0, Top 0 right 100, bottom 100.

What should I check to make it run correctly?

thanx

P.S When the properties defined in object inspector are actually loaded into an object?

Here is the sample code ("short one"). It is not "clean" so please, be tolerant...

TRectangle = class(TComponent)
  private
    FOnAdjustContent: TNotifyEvent;
    FLeft, FRight, FBottom, FTop:Integer;
    FoutLeft, FoutRight, FoutBottom, FoutTop:integer;
    FinLeft, FinRight, FinBottom, FinTop:integer;
    FAligning:TAligning;
    FAdjustContent:TAdjustContent;
    FAnchors:TAnchors;
    FList:Tlist;
    FRectangleContainer:TRectangleContainer;
    FParentRectangle:TRectangle;
    FdLeft, FdTop, FdBottom, FdRight: integer;
 //   function FindParent(AName:string):TRectangle;


  public    
    constructor Create(AOwner:TComponent);override;
    destructor Destroy; override;
    procedure Assign(Source : TPersistent); override;
  published
    property AdjustContent:TAdjustContent read FAdjustContent write SetAdjustContent;
    property Aligning:TAligning read FAligning write SetAlign;
    property Anchors:TAnchors read FAnchors write SetAnchors;
    .
    .
    .   
  end; 



TTextObject = class (TRectangle)
  public
      procedure   Assign(Source : TPersistent); override;
  published
      property AlignmentInCell:integer read FAlignmentInCell write FAlignmentInCell;
      property Brush:TBrush read FBrush write FBrush;
      property CanMove:Boolean read FCanMove write FCanmove;
      .
      .
      .
  end;





TCustomDisplay = class (TCustomControl)
  private
     FRootTextObject:TTextObject;
     procedure SetRootTextObject(Value:TTextObject);
  protected
  public
     constructor Create(AOwner:TComponent); override;
     destructor  Destroy; override;
     procedure Assign(Source:TPersistent); override;
  published
     property RootTextObject:TTextObject read FRootTextObject write SetRootTextObject;
  end;



  TDesignDisplay = class (TCustomDisplay)
    protected
     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    public
     procedure Paint; override; 
    end;

  TDisplay = class (TCustomDisplay)
     private

        function  GetFirstMovable: TTextObject;
     protected
        procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
        procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
        procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
     public
        procedure Paint; override;
     end;


procedure Register;
begin
  RegisterComponents('My Palette', [TDisplay, TDesignDisplay]);
end;



constructor TCustomDisplay.Create(AOwner:TComponent);
  var i:integer;
  begin
  inherited;

  FRootTextObject:=TTextObject.Create(Self);
//  ShowMessage(FRootTextObject.Name);
//  FRootTextObject.Name:='Root';
  FRootTextObject.OnAdjustContent:=DoAdjustContent;

//  FRootTextObject.Right:=Width;
//  FRootTextObject.Bottom:=Height;
  FRootTextObject.CanMove:=False;
  TabStop:=True;
  end;



procedure TCustomDisplay.SetRootTextObject(Value:TTextObject);
begin
  FRootTextObject.Assign(Value);
end;




procedure TRectangle.Assign(Source: TPersistent);
var ARectangle:TRectangle;
begin
  if Source is TRectangle then
    begin
   ARectangle:=Source as TRectangle;

 //  Name:=ARectangle.Name;
  // FRect:=Rectangle.Rect;
   FLeft:=ARectangle.Left;
   FTop:=ARectangle.Top;
   FRight:=ARectangle.Right;
   FBottom:=ARectangle.Bottom;
   FoutLeft:=ARectangle.outLeft;
   FoutTop:=ARectangle.outTop;
   FoutRight:=ARectangle.outRight;
   FoutBottom:=ARectangle.outBottom;
   FinLeft:=ARectangle.inLeft;
   FinTop:=ARectangle.inTop;
   FinRight:=ARectangle.inRight;
   FinBottom:=ARectangle.inBottom;
   end
   else
    inherited;
end;



procedure TTextObject.Assign(Source : TPersistent);
var ATextObject:TTextObject;
begin
      inherited;
      if Source is TTextObject then
        begin
        ATextObject:=Source as TTextObject;

        AlignmentInCell:=ATextObject.AlignmentInCell;
        AttachedWP:=ATextObject.AttachedWP;
        Brush.Assign(ATextObject.Brush);
        Caption:=ATextObject.Caption;
        Font.Assign(ATextObject.Font);
        Painting.Assign(ATextObject.Painting);
        Pen.Assign(ATextObject.Pen);
        RichString:=ATextObject.RichString;
        StateDrawing:=ATextObject.StateDrawing;
        TabState:=ATextObject.TabState;
        TextFormat:=ATextObject.TextFormat;
        Thickness:=ATextObject.Thickness;
        Transparent:=ATextObject.Transparent;
        Value:=ATextObject.Value;
        WPname:=ATextObject.WPname;
        end;         
end;
+6  A: 

Make sure TRectangle is derived from TPersistent class or one of its descendant classes. Also make sure you implemented Assign method for TRectangle, and all the published properties of TRectangle are assigned inside Assign method.

NOTE: If your class is derived from TComponent, and is used as a child component inside another component, you should call SetSubComponent(True) when the object is created.

The code should look something like this:

Interface section:

  type    
    TRectangle = class(TComponent)
      private
        FTop,
        FBottom,
        FLeft,
        FRight   : Integer;
      public
        procedure Assign(Source: TPersistent); override;
      published
        property Bottom: Integer read FBottom write FBottom;
        property Left: Integer read FLeft write FLeft;
        property Right: Integer read FRight write FRight;
        property Top: Integer read FTop write FTop;
      end;

      TDisplay = class(TComponent)
      private
        FRectangle : TRectangle;
        procedure SetRectangle(Value: TRectangle);
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property Rectangle: TRectangle read FRectangle write SetRectangle;
      end;

Implementation section:

{ TRectangle }

procedure TRectangle.Assign(Source: TPersistent);
begin
  if Source is TRectangle then
  begin
    FBottom := TRectangle(Source).Bottom;
    FLeft := TRectangle(Source).Left;
    FRight := TRectangle(Source).Right;
    FTop := TRectangle(Source).Top;
  end
  else
    inherited;
end;

{ TDisplay }

constructor TDisplay.Create(AOwner: TComponent);
begin
  inherited;
  FRectangle := TRectangle.Create(Self);
  FRectangle.Parent := Self;
  FRectangle.SetSubComponent(True);
end;

destructor TDisplay.Destroy;
begin
  inherited;
end;

procedure TDisplay.SetRectangle(Value: TRectangle);
begin
  FRectangle.Assign(Value);
end;
vcldeveloper
I edited my code to resemble your code. It does not work well. Difference is, that in the constructor of TRectangle I set Fright:= 30, Fbottom:= 20. And it still uses these values... I suppose, that instruction Showmessage(Value.Right) in the SetRectangle procedure should show 100, instead of 30. In my case it doesnt...Thanx very much anyway. Ah, what is very interesting: TRectangle is TComponent. If the name of of the Trectangle differs from that in object inspector. SetRectangle is not executed...
lyborko
Can you provide a sample code that reproduces your problem?
vcldeveloper
OK... I'll try... I put it in the answers...
lyborko
OK, the problem is you are defining TTextObject as a TComponent descendant, and are using it as a subcomponent in TCustomDisplay, but you have not called SetSubComponent for the created object inside constructor of TCustomDisplay: FRootTextObject := TTextObject.Create(Self);FRootTextObject.SetSubComponent(True);I edited my original answer to include this note too.
vcldeveloper
I edited my code according to your great advice and it works fine... :-)))) Thank you very much for your interest and effort. Thumbs up...
lyborko