Discussion:
Control "" has no parent (second)
(too old to reply)
Hubert Rétif
2004-01-19 15:25:41 UTC
Permalink
Hi,

I have tried to follow the advices from a previous thread but had not the
expected success in my particular case. When I put my component on a Form,
sometimes it works (but after compiling, it creates 2 times a SubComponent)
and some other times I got the message "Control "" has no parent".

May I ask to have a look to my code and tell me what I am missing?
(public.attachments: FilterGrid, with D6)

Thanks, Hubert.
David Powell
2004-01-19 15:38:29 UTC
Permalink
Bit rusty on this but have you implemented:

function GetChildOwner: TComponent; override;

function TMyCustomControl.GetChildOwner: TComponent;
begin
Result := Self;
end;
Post by Hubert Rétif
Hi,
I have tried to follow the advices from a previous thread but had not the
expected success in my particular case. When I put my component on a Form,
sometimes it works (but after compiling, it creates 2 times a
SubComponent)
Post by Hubert Rétif
and some other times I got the message "Control "" has no parent".
May I ask to have a look to my code and tell me what I am missing?
(public.attachments: FilterGrid, with D6)
Thanks, Hubert.
Hubert Rétif
2004-01-19 16:28:32 UTC
Permalink
Post by David Powell
function GetChildOwner: TComponent; override;
function TMyCustomControl.GetChildOwner: TComponent;
begin
Result := Self;
end;
I have just tried to see how I could use your advice, but so far it did not
improve my situation.
Constantine Yannakopoulos
2004-01-21 14:19:18 UTC
Permalink
Author := "Hubert Ritif";

| I have tried to follow the advices from a previous thread but had not
| the expected success in my particular case. When I put my component
| on a Form, sometimes it works (but after compiling, it creates 2
| times a SubComponent) and some other times I got the message "Control
| "" has no parent".
|
| May I ask to have a look to my code and tell me what I am missing?
| (public.attachments: FilterGrid, with D6)

You shouldn't move all the code that creates the subcomponents to
CreateWnd. This is not correct because CreateWnd can be called many
times during the lifetime of the control.

If you get the "Control '' has no parent" message you must find the
line that causes the premature creation of the window handle in the
constructor and move *only* that to CreateWnd.
--
Constantine
Hubert Rétif
2004-01-21 16:36:19 UTC
Permalink
Post by Constantine Yannakopoulos
If you get the "Control '' has no parent" message you must find the
line that causes the premature creation of the window handle in the
constructor and move *only* that to CreateWnd.
I have moved all the component code to a Unit in order to better follow what
happens. I found out that the message is generated by the procedure below,
more exactly by executing R := CellRect(RawColumn, 0); Just here CreateWnd
is called and then produces the message. I should probably do something
there, but it is (still) not enough clear to me what.

procedure TFilterColumns.UpdateFilterPositions;
var
I: Integer;
RawColumn: Integer;
R: TRect;
begin
for I := 0 to Count - 1 do
with TGridData(Grid) do
begin
RawColumn := DataToRawColumn(I);
R := CellRect(RawColumn, 0);
if not IsRectEmpty(R) then
begin
Items[I].FFilter.Visible := True;
Items[I].FFilter.Left := R.Left;
Items[I].FFilter.Width := ColWidths[RawColumn];
end
else
Items[I].FFilter.Visible := False;
end;
end;

Latest Version always in public.attachments...

Thanks, Hubert.
Constantine Yannakopoulos
2004-01-23 08:29:38 UTC
Permalink
Author := "Hubert Ritif";

| I have moved all the component code to a Unit in order to better
| follow what happens. I found out that the message is generated by the
| procedure below, more exactly by executing R := CellRect(RawColumn,
| 0); Just here CreateWnd is called and then produces the message. I
| should probably do something there, but it is (still) not enough
| clear to me what.

Add this code in UpdateFilterPositions (inline):

| procedure TFilterColumns.UpdateFilterPositions;
| var
| I: Integer;
| RawColumn: Integer;
| R: TRect;
| begin

if not Grid.HandleAllocated then Exit;

| for I := 0 to Count - 1 do
| with TGridData(Grid) do
| begin
| RawColumn := DataToRawColumn(I);
| R := CellRect(RawColumn, 0);
| if not IsRectEmpty(R) then
| begin
| Items[I].FFilter.Visible := True;
| Items[I].FFilter.Left := R.Left;
| Items[I].FFilter.Width := ColWidths[RawColumn];
| end
| else
| Items[I].FFilter.Visible := False;
| end;
| end;

and then override TGridData.CreateWnd like this:

procedure TGridData.CreateWnd; // override
begin
inherited;
Columns.UpdateFilterPositions;
end;
--
Constantine
Hubert Rétif
2004-01-23 10:40:18 UTC
Permalink
Thanks Constantine. With your latest 2 advices (see in public.attachments),
it works perfectly now in design mode. I can drop the component on a Form,
add columns to the Grid and Filters are added automatically, all of this
with no error messages.

But..., compiling the Unit where the Form is and executing it does not work
as expected. Two problems has appeared:

1. The columns created in design mode have disappeared. Also data are not
displayed.

2. A second FilterPanel has been created on top of the component.
Hubert Rétif
2004-01-22 07:50:03 UTC
Permalink
I have traced more exactly what happened:

FGridData := TGridData.Create(Self);
with FGridData do
begin
Parent := Self;
|
---> constructor TFilterColumn.Create(Collection: TCollection);
|
---> procedure TFilterColumns.Update(Item: TCollectionItem);
|
---> UpdateFilterPositions;
for I := 0 to Count - 1 do
with TGridData(Grid) do
begin
RawColumn := DataToRawColumn(I);
R := CellRect(RawColumn, 0);
|
---> CreateWnd;
inherited; --->
"Control "" has no parent"
Florent Ouchet
2004-01-22 08:49:26 UTC
Permalink
I have such a message when i am designing my own component. Finally i found
that if you try to access the control's handle before the parent's is ready
to make it's one. For example you may not access the Font property or any
property using the handle before the parent of the control is unable to make
it's handle.

Florent.
Post by Hubert Rétif
FGridData := TGridData.Create(Self);
with FGridData do
begin
Parent := Self;
|
---> constructor TFilterColumn.Create(Collection: TCollection);
|
---> procedure TFilterColumns.Update(Item: TCollectionItem);
|
---> UpdateFilterPositions;
for I := 0 to Count - 1 do
with TGridData(Grid) do
begin
RawColumn := DataToRawColumn(I);
R := CellRect(RawColumn, 0);
|
---> CreateWnd;
inherited; --->
"Control "" has no parent"
Hubert Rétif
2004-01-23 07:57:43 UTC
Permalink
Post by Florent Ouchet
I have such a message when i am designing my own component. Finally i found
that if you try to access the control's handle before the parent's is ready
to make it's one. For example you may not access the Font property or any
property using the handle before the parent of the control is unable to make
it's handle.
OK, in between I have understood that it has something to do with what you
mentionned. Now, in order to find the solution for my problem, I have a more
precise question:

constructor MyComponent.Create(aOwner: TComponent);
begin
inherited Create(aOwner);

MyPanel := TMyPanel.Create(Self);
with MyPanel do
begin
Parent := Self;
Name := 'MyPanel';
Align := alTop;
Height := 50;
SetSubComponent(True);
end;

MyDataGrid := TMyDataGrid.Create(Self);
with MyDataGrid do
begin
Parent := Self;
Name := 'MyDataGrid';
Align := alClient;
SetSubComponent(True);
end;
end;

I have heard that I should use CreateWnd to be sure that all is created in
the right way. The problem is that I don't know how (documentation does not
help). Can someone explain me how CreateWnd works and what triggers its
call?

In the above case, by MyPanel, it seems that CreateWnd is never called (does
not disturb me because I have no problem with this part). By MyDataGrid,
executing Parent := Self enables (I already don't understand why there...)
the call of some other creates (columns and other objects) and finally calls
Update (TCollection). Then CreateWnd is called and brings the error message
"Control "" has no Parent".

Can someone explain me what I should do?

Thanks,
Hubert.
Loading...