tags:

views:

121

answers:

1

Hi,

I created my own Component : TPage , which Contains Subcomponent TPaper (TPanel). The problem is, that when I put controls such as TMemo or TButton on the TPaper (which fills up nearly whole area), the controls do not load at all. see example below

TPaper = class(TPanel)
  protected
      constructor Create(AOwner: TComponent);override;
      destructor Destroy;override;
  public
      procedure Paint; override;
  end;





TPage = class(TCustomControl)
   private
      FPaper:TPaper;
   protected
      procedure CreateParams(var Params:TCreateParams); override;
   public
      constructor Create(AOwner: TComponent);override;
      destructor Destroy;override;

   published
      property Paper: TPaper read FPaper write FPaper;
   end;




constructor TPage.Create(AOwner: TComponent);
  begin
  inherited Create(AOwner);

  PaperOrientation:=poPortrait;
  PaperSize:=psA4;
  PaperBrush:=TBrush.Create;
  PaperBrush.Color:=clWhite;
  PDFDocument:=Nil;
  FPaper:=TPaper.Create(Self);
  FPaper.Parent:=Self;
  FPaper.SetSubComponent(True);
  end;

... Memo1 is parented in TPaper (TPanel) at design-time, but after pressing "Run" it does not exist.

procedure TForm1.btn1Click(Sender: TObject);
begin
if not Assigned(Memo1) then ShowMessage('I do not exist');   //Memo1 is nil
end;

Have you any idea what's wrong?

Thanks a lot

P.S Delphi 7

When I put TMemo inside TPaper and save the unit (Unit1), after inspection of associated dfm file, there is no trace of TMemo component. (Thats why it can not load to app.)

+1  A: 

Serge is right. Delphi only streams components that are owned by the Form they reside in. In order to avoid the EClassNotfound Exception, which occurs during reading of the form file (You should now at least see a Tpaper component in your dfm file) you must register the class by using the RegisterClass function (in the unit Classes). A good place for this would be in the initialisation section of your unit.

If setting the owner of Tpaper to a Form is not an option, then you can still get Delphi to stream your subcomponents by overriding the Getchildren and GetChildOwner methods and applying the logic TCustomForm uses:

TPage = class
 ...
public
  procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  function GetChildOwner:TComponent; override;
end;



procedure TPage.GetChildren(Proc: TGetChildProc; Root: TComponent);  // this is copied
var                                                                  // from 
  I: Integer;                                                        // TCustomForm
  OwnedComponent: TComponent;
begin
  inherited GetChildren(Proc, Root);
  if Root = Self then
    for I := 0 to ComponentCount - 1 do
    begin
      OwnedComponent := Components[I];
      if not OwnedComponent.HasParent then Proc(OwnedComponent);
    end;
end;

function TPage.GetChildOwner: TComponent;
begin
  inherited;
  Result:=Self;
end;
iamjoosy
Thanks for answer. I tried to implement this snippet into my code, but it works not as I expected. Inserted component inside TPaper does not appera in dfm file at all. I have found TComponentStyle in help:csSubComponent The component is a subcomponent of the component that is the value of its Owner property. Unlike top-level components, subcomponents are not saved with the form or data module in which they reside. Instead, a subcomponent appears as the value of a published property of its Owner, and its published properties and events are saved in the form file with the owning component.
lyborko
I presume, that I cannnot expect that any TWinCOntrol inserted in TPaper will be saved in dfm file.
lyborko
How do you insert the memo into Tpaper? If you do it like:AMemo:=Tmemo.create(FPaper) then it is clear, that it gets not stream into the dfm. Try AMemo:=TMemo.create(MyPage), and see if this works.
iamjoosy
At design time. I put TPAge on the form. It has also TPaper inside. It is fine. Then I put any VCL Control (TMemo etc) in the subcomopnent TPaper. It looks also fine. But when I press Run button, application runs, but TMemo disapears. So I close apps and I see my precious TMemo reside inside TPaper. So I did this trick: I saved Unit1 somewhere, then I opened Unit1.dfm and I did not see any TMemo object "descrition". No wonder I did not load. It happens most probably because of the argument I wrote earilier.I do not want to create TMemo inside programmaticaly. It will work that way I bet.
lyborko