Solved

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

Posted on 2004-04-29
5
337 Views
Last Modified: 2010-04-05
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
Comment
Question by:mavrj
  • 2
  • 2
5 Comments
 
LVL 3

Expert Comment

by:MikProg
ID: 10948790
A piece of code where you call Test and Prepare. (and i think you swap body of them)
0
 
LVL 1

Author Comment

by:mavrj
ID: 10948852
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
 
LVL 17

Accepted Solution

by:
geobul earned 250 total points
ID: 10952126
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
 
LVL 3

Expert Comment

by:MikProg
ID: 10956324
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
 
LVL 17

Expert Comment

by:geobul
ID: 10956777
Yes, exactly - overriding Loaded is the way to go. I had no time for testing yesterday (last night actually :-).
0

Featured Post

ScreenConnect 6.0 Free Trial

Discover new time-saving features in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Intraweb submit form as a POST request 4 304
Delphi component that can load a DLL in design time? 8 64
select query - oracle 16 100
How to convert memory stream to PDF file 6 59
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question