[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 350
  • Last Modified:

Can't create TreeNodes while in Create constructor of a TWinControl

I designed a new visual component (TWinComponent) that contains a TreeView. When I create a node in the Create constructor (after initialization of the TreeView), I can't use this Node in latter procedure. i.e. when inserting a new node (Child or Sibling) if works fine in the create constructor but failed (raise various exception) when added in other function. Here is the Example that failed:

TTest = class(TWinControl)
    private
       fTreeView : TTreeView;
       fNode1 : TTreeNode;
       fNode2 : TTreeNode;
    public
       constructor Create(AOwner : TComponent); override;
       destructor Destroy; override;
       procedure Test(AString : String);
    end;

constructor TTest.Create(AOwner: TComponent);
begin
     inherited;
     fTreeView := TTreeView.Create(Self);
     fTreeView.Parent := Self;
     fTreeView.Align := alClient;
     fTreeView.ReadOnly := True;

     fNode1 := fTreeView.Items.Add(nil,'Node1');
     fNode2 := fTreeView.Items.AddChild(fNode1,'Node2'); //This works fine
end;

procedure TTest.Test(AString : String);
var
   ANode : TTreeNode;
begin
       ANode := fTreeView.Items.AddChild(fNode1,AString); // This yield to various Exception
       // ... Perform various operation
end;

Alternatively the following work around works fine.

TTest = class(TWinControl)
    private
       fTreeView : TTreeView;
       fNode1 : TTreeNode;
       fNode2 : TTreeNode;
       fPrepared : Boolean;
       procedure Prepare;
    public
       constructor Create(AOwner : TComponent); override;
       destructor Destroy; override;
       procedure Test(AString : String);
    end;

constructor TTest.Create(AOwner: TComponent);
begin
     inherited;
     fTreeView := TTreeView.Create(Self);
     fTreeView.Parent := Self;
     fTreeView.Align := alClient;
     fTreeView.ReadOnly := True;
     fPrepared := False;
end;

procedure TTest.Test(AString : String);
begin
       fNode1 := fTreeView.Items.Add(nil,'Node1');
       fNode2 := fTreeView.Items.AddChild(fNode1,'Node2'); //This works fine
       fPrepared := true;
end;

procedure TTest.Prepare;
var
   ANode : TTreeNode;
begin
       if not fPrepared then
            Prepare;
       ANode := fTreeView.Items.AddChild(fNode1,AString); // This yield to various Exception
       // ... Perform various operation
end;

Note: the TTest is registered in the VCL Palette and dropped in the form during design.
0
mavrj
Asked:
mavrj
  • 2
  • 2
1 Solution
 
MikProgCommented:
A piece of code where you call Test and Prepare. (and i think you swap body of them)
0
 
mavrjAuthor Commented:
Good point ! Sorry for the mistake. Tried to make it to simple :-)

Read:

procedure TTest.Prepare;
begin
       fNode1 := fTreeView.Items.Add(nil,'Node1');
       fNode2 := fTreeView.Items.AddChild(fNode1,'Node2'); //This works fine
       fPrepared := true;
end;

procedure TTest.Test(AString : String);
var
   ANode : TTreeNode;
begin
       if not fPrepared then
            Prepare;
       ANode := fTreeView.Items.AddChild(fNode1,AString); // This yield to various Exception
       // ... Perform various operation
end;
0
 
geobulCommented:
Hi,

Perhaps the reason is in the streaming mechanism when you are saving/loading your component.

1. When you drop your component on a form these two nodes are created by the constructor(design-time).
2. When you save/run your project these two nodes are already there (created automatically because they were saved/streamed) and
fNode1 := fTreeView.Items.Add(nil,'Node1');
actually fails to add a new node and fNode1 remaims unititialized.
3. When you execute your Test method it raises an AV because fNode1 is nil (or points somewhere else).

I might be wrong, of course.

Regards, Geo
0
 
MikProgCommented:
geobul>You forget to write solution code

TTest = class(TWinControl)
    private
       fTreeView : TTreeView;
       fNode1 : TTreeNode;
       fNode2 : TTreeNode;
    protected
       procedure Loaded; override;
    public
       constructor Create(AOwner : TComponent); override;
       destructor Destroy; override;
       procedure Test(AString : String);
    end


procedure TTest.Loaded;
begin
   fNode1:=fTreeView.Items.GetFirstNode;
   fNode2:=fNode2.GetFirstChild;
end;
0
 
geobulCommented:
Yes, exactly - overriding Loaded is the way to go. I had no time for testing yesterday (last night actually :-).
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now