Solved

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

Posted on 2004-04-29
5
334 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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

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 The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

758 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now