Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Finding dynamic components after creation.

458 views
Skip to first unread message

Daniel Bragg

unread,
Sep 25, 2006, 3:14:04 PM9/25/06
to
I have a form that I need to populate dynamically with TLabels and
descendents of TControl. The routine to populate the form needs to be
re-entrant: if the user clicks on the Refresh button, it needs to get
rid of the old fields (and values) that are no longer referenced and add
new fields that are to be referenced, but not discard any values they've
put into fields that still remain.

My routine's declaration:

procedure TmyForm.LoadScreenComponents(const FieldName : string;
const FriendlyName : string;
const FieldType : TControlClass);
var
Lbl : TLabel;
Ctrl : TControl;

I'm doing well so far, but I am having problems with how the form
handles the TControl versus the TLabel classes. In my routine, I have
the code:

Ctrl := TControl(ScrollWindow.FindChildControl('ctrl'+FieldName));
if not assigned(Ctrl) then
begin
Ctrl := FieldType.Create(nil);
Ctrl.Name := 'ctrl'+FieldName;
ScrollWindow.InsertControl(Ctrl);
end;

This seems to be working well. The second time into the routine, it
finds my control just fine, and does not re-create it. However, the
similar code for a TLabel:

Lbl := TLabel(ScrollWindow.FindChildControl('lbl'+FieldName));
if not assigned(Lbl) then
begin
Lbl := TLabel.Create(nil);
Lbl.Name := 'lbl'+FieldName;
ScrollWindow.InsertControl(Lbl);
end;

creates it just fine, but the second time through, it is *not* found
using FindChildControl, so a new label gets created, although it is
already on the screen. As you can imagine, this is resulting in a
memory leak, and a mess on the screen (the labels are not always
overlaid one atop the other, so I am left with "label trails").

If anyone could help, I'd much appreciate it. I am using Delphi 2005
Enterprise (BDS ver 9.0.1935.22056) running on Windows XP Pro SP2.

Sincerely,

Daniel Bragg

Remy Lebeau (TeamB)

unread,
Sep 25, 2006, 5:26:26 PM9/25/06
to

"Daniel Bragg" <nos...@ccdsystems.com> wrote in message
news:Xns98497C75AD145su...@207.105.83.66...

> I have a form that I need to populate dynamically with TLabels and
> descendents of TControl. The routine to populate the form needs to
> be re-entrant: if the user clicks on the Refresh button, it needs to get
> rid of the old fields (and values) that are no longer referenced and
> add new fields that are to be referenced, but not discard any values
> they've put into fields that still remain.

You need to keep track of the objects that you create. You should put their
pointers into a container, such as a TList or TObjectList, that you can loop
through when needed. For example:

private
FScreenControls: TObjectList;

constructor TmyForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FScreenControls := TObjectList.Create(False);
end;

destructor TmyForm.Destroy;
begin
FScreenControls.Free;
inherited Destroy;
end;

procedure TmyForm.LoadScreenComponents(const FieldName : string; const
FriendlyName : string; const FieldType : TControlClass);
var

Ctrl : TControl;
I: Integer;
begin
for I := 0 to Pred(FScreenControls.Count) do
begin
Ctrl := FScreenControls[I] as TControl;
if not (Ctrl is FieldType) then Continue;
if Ctrl.Name = FieldName then Exit;
end;

Ctrl := FieldType.Create(Self);
Ctrl.Name := FieldName;
FScreenControls.Add(Ctrl);
//...
end;

> However, the similar code for a TLabel:

<snip>


> creates it just fine, but the second time through, it is *not*
> found using FindChildControl, so a new label gets created,
> although it is already on the screen.

TLabel is a non-windowed graphical control, but FindChildControl() only
looks for windowed controls. If you do not use your own container, then the
only option for searching for graphical controls is to use FindComponent()
instead. In order for that to work, you would have to assign the parent
window as the Owner for the new child objects. You can't use nil Owners
with FindComponent().


Gambit


Iain Macmillan

unread,
Sep 25, 2006, 5:39:19 PM9/25/06
to

----------
In article <Xns98497C75AD145su...@207.105.83.66>, Daniel
Bragg <nos...@ccdsystems.com> wrote:

> ScrollWindow.InsertControl(Ctrl);
Delphi help says not to call insertcontrol directly. Instead, set the
parent.

> Lbl := TLabel(ScrollWindow.FindChildControl('lbl'+FieldName));
> if not assigned(Lbl) then
> begin
> Lbl := TLabel.Create(nil);
> Lbl.Name := 'lbl'+FieldName;
> ScrollWindow.InsertControl(Lbl);
> end;
>
> creates it just fine, but the second time through, it is *not* found
> using FindChildControl,

Delphi Help also says not to confuse Controls with Components.
Child Controls are Windows. A TLabel is not a window and has no handle.


> If anyone could help, I'd much appreciate it.

Have the parent own the labels, (not nil as above).
Then use ScrollWindow.FindComponent.

Daniel Bragg

unread,
Sep 26, 2006, 11:42:09 AM9/26/06
to
"Iain Macmillan" <he...@ariesps.co.uk> wrote in
news:4518...@newsgroups.borland.com:

>
> Delphi help says not to call insertcontrol directly. Instead, set the
> parent.
>

> Delphi Help also says not to confuse Controls with Components.
> Child Controls are Windows. A TLabel is not a window and has no handle.
>

> Have the parent own the labels, (not nil as above).
> Then use ScrollWindow.FindComponent.

Thank you Iain. I was providing the Owner value in previous attempts, but
got confused when the components would not display on my object (this was
because I forgot to set the Parent as well). I have since replaced all of
my direct Insert calls with simple references to the appropriate Parent,
and all works well, and is much easier to understand.

Daniel

Daniel Bragg

unread,
Sep 28, 2006, 3:28:39 PM9/28/06
to
"Remy Lebeau \(TeamB\)" <no....@no.spam.com> wrote in
news:45184a0c$1...@newsgroups.borland.com:

> TLabel is a non-windowed graphical control, but FindChildControl()
> only looks for windowed controls. If you do not use your own
> container, then the only option for searching for graphical controls
> is to use FindComponent() instead. In order for that to work, you
> would have to assign the parent window as the Owner for the new child
> objects. You can't use nil Owners with FindComponent().

Thank you, Remy. I was providing the Owner for my controls in previous
attempts, but I had forgotten that I also needed to provide the parent.
Your instructions are of great help to me. Thank you for continuing to be
a reliable source in these newsgroups.

Daniel Bragg

0 new messages