Bux
Bux

Reputation: 57

Handle pointers to components created inside a loop

First of all: sorry for my english, hope to be able to explain what I need. Also consider I'm new to Delphi. Thanks in advance to everyone who'll try to help me.

I have this situation:

a global var

atd : array of ^TLabel

Some procedures that ADD dynamically labels to a scrollbox

Below you'll find one of them

procedure LabelINIT();
var L : Tlabel;
begin

....

while not DATASET.EOF do
  begin
    L := TLabel.Create(Self);
    L.Parent := ScrollBox3;
    L.Height := 13;
    L.Width := 30;
    L.Left := atd[DATASET.FIELDS[0].ASINTEGER].Left;
    L.Top := atd[DATASET.FIELDS[0].ASINTEGER].Top + 3
    ...
    atd[DATASET.FIELDS[0].ASINTEGER] := @L;
    DATASET.NEXT;
  end; 

.....

end;

ATD should store the address of the last inserted label... but in reality it stores the address of L variable, so on every new loop ATD points to the new L created at the beggining of the while. Worst of all when out of the procedure I can't use values in ATD 'cause they reference to invalid addresses (L is a local var).

I'd like to know if there's a way to point directly to the created label instead of pointing to a variable that's a copy of it.

In other words what I'd like to do is: create a LABEL - FIND ITS OWN ADDRESS - POINT to IT

What I've done is: create a LABEL, set a VARIABLE = LABEL, POINT TO THE VAR

Upvotes: 0

Views: 864

Answers (1)

David Heffernan
David Heffernan

Reputation: 613013

Let's look at the code you have:

procedure LabelINIT;
var 
  L: TLabel;
begin
  ....
  atd[DATASET.FIELDS[0].ASINTEGER] := @L;
  ....
end; 

Now, L is a local variable. And so @L is the address of that local variable. When LabelINIT returns, that address is no longer valid because the variables life has ended.

The information that you are missing is that a variable of type TLabel is in fact a pointer already. That variable is a pointer to the object instance. Any variable in Delphi of a type that inherits from TObject is a pointer to the object instance.

So, the solution is simple. Change the global variable as so:

atd: array of TLabel;

This is an array of pointers to label instances.

Change the assignment to atd to be like so:

atd[DATASET.FIELDS[0].ASINTEGER] := L;

Although I've referred to these variables as being pointers, they are more commonly referred to as references in Delphi-speak. In due course I think you'll come round to that terminology, but I used pointer in this answer to make it explicitly clear what these things are.

From the documentation:

A variable of a class type is actually a pointer that references an object. Hence more than one variable can refer to the same object. Like other pointers, class-type variables can hold the value nil. But you don't have to explicitly dereference a class-type variable to access the object it points to. For example, SomeObject.Size := 100 assigns the value 100 to the Size property of the object referenced by SomeObject; you would not write this as SomeObject^.Size := 100.

Upvotes: 4

Related Questions