PDA

Ver la Versión Completa : Error "A control cannot have itself as its parent"


leg128
05-05-2016, 18:40:56
Buenos dias, les comento... estoy tratando de crear objetos(botones, edit y demas cosas que se me ocurran) en una grilla.. cuando ejecuto el programa recibo este error al hacer la llamada a mi procedimiento
"A control cannot have itself as its parent"

la llamada es
stgboton(1, StringGrid1, 'hola', EventoClick, 5 );

el procedimiento es este
procedure stgboton(objeto:integer; Grid : TStringGrid; txtcaption:string; evento:TNotifyEvent; columna:integer);
var
i: Integer;
Btn: TObject;

begin
for i := Grid.FixedRows to Grid.RowCount -2 do
begin
if objeto = 1 then
begin
with TButton (btn) do
begin
Create(nil);
Caption := txtboton;
Width := 87;
Name := 'Button' + IntToStr(i);
BoundsRect:= Grid.CellRect(Columna, i);
ControlStyle := [csClickEvents];
onclick := evento;
Tag := i;
parent:= grid;
end;
Grid.Objects[Columna,i] := Btn;

end;
end;
end;

Alguna idea de como puedo solucionarlo? saludos.

Caminante
05-05-2016, 19:51:38
Hola
Porque pones TButton(btn)??? No veo que crees el objeto (btn) en ninguna parte.

AgustinOrtu
05-05-2016, 20:09:29
No estas asignando ningun valor a la variable Btn, a la que luego le aplicas un casting a TButton usando el with

gatosoft
05-05-2016, 21:53:03
De cualquier forma el no instanciar una variable generaría un Access Violation #000000... no un "A control cannot have itself as its parent"

Yo creo (no tengo compilador a la mano) que el problema está en la utilizacion del With (Ya nuestro amigo Al Gonzalez en algún hilo habló de su uso y abuso)

Asumo que al hacer el Create(nil); quieres asignarlo a tu btn... pues no funciona asi.

with TButton (btn) do
begin
Create(nil);
Caption := txtboton;
Width := 87;
Name := 'Button' + IntToStr(i);
BoundsRect:= Grid.CellRect(Columna, i);
ControlStyle := [csClickEvents];
onclick := evento;
Tag := i;
parent:= grid;
end;

La linea create dentro del with equivale a hacer:

TButton (btn).Create(nil);

instancia un objeto pero no lo asigna a la variable btn.

Lo que está ocurriendo es que dentro del with está asignando las variables a otro objeto, y segun parece, se está haciendo al StringGrid, de forma que en la linea parent:= grid, genera el error que te está enviando


Creo que deberias hacer algo como:


btn:= TButton.Create(nil);
with TButton (btn) do
begin
Caption := txtboton;
Width := 87;
Name := 'Button' + IntToStr(i);
BoundsRect:= Grid.CellRect(Columna, i);
ControlStyle := [csClickEvents];
onclick := evento;
Tag := i;
parent:= grid;
end;

Saludo,

AgustinOrtu
05-05-2016, 22:01:44
De cualquier forma el no instanciar una variable generaría un Access Violation #000000... no un "A control cannot have itself as its parent"

Esto tiene truco (http://www.clubdelphi.com/foros/showthread.php?t=89595), como descubri hace un tiempo

Es eso, o bien en esa ejecucion se presento esa oportunidad y btn podria apuntar a cualquier lado

ecfisa
06-05-2016, 02:12:45
Buenos dias, les comento... estoy tratando de crear objetos(botones, edit y demas cosas que se me ocurran) en una grilla...

...

Alguna idea de como puedo solucionarlo? saludos.
No miré a fondo tu código, pero en principio la forma de creación:

...
with TButton (btn) do
begin
Create(nil);
...

es incorrecta, usando with podrías hacer:

with TButton.Create(nil) do
...

Por otro lado usar como el tipo de parámetro a la clase TObject va a limitar las propiedades disponibles y la totalidad de los eventos.

Te pongo un ejemplo usando un parámetro con otro tipo de clase que te va a permitir crear muchos controles (no los que se te ocurran :)), pero sí unos cuantos descendientes ella:

...
procedure TForm1.FormCreate(Sender: TObject);
var
c : Integer;
sg: TStringGrid;
begin
sg := StringGrid1;
sg.ColCount := 7;
sg.FixedColor := clLime;
for c := 0 to sg.ColCount-1 do
sg.ColWidths[c] := 90;
end;

procedure TForm1.EventoClick(Sender: TObject);
begin
ShowMessage(Format('Click en %s',[TWinControl(Sender).Name]));
end;


type
TWinControlEx = class(TWinControl);

procedure TForm1.CrearWinControl(WcClass: TWinControlClass; Columna: Integer;
Evento: TNotifyEvent);
var
wc: TWinControl;
sg: TStringGrid;
r : Integer;
Rect: TRect;
begin
sg := StringGrid1;
for r := sg.FixedRows to sg.RowCount-1 do
begin
if Assigned(sg.Objects[Columna,r]) then Continue;
wc := WcClass.Create(nil);
wc.Name := Format('%s%d',[Copy(WcClass.ClassName, 2, MaxInt), r]);
Rect := sg.CellRect(Columna, r);
InflateRect(Rect, -2, -2);
wc.BoundsRect := Rect;
wc.ControlStyle := [csClickEvents];
TWinControlEx(wc).OnClick := Evento;
TWinControlEx(wc).Caption := wc.Name;
wc.Tag := r;
wc.Parent := sg;
sg.Objects[Columna, r] := wc;
end;
end;

procedure TForm1.btnCreateClick(Sender: TObject);
begin
CrearWinControl(TButton , 1, EventoClick);
CrearWinControl(TEdit , 2, EventoClick);
CrearWinControl(TMemo , 3, EventoClick);
CrearWinControl(TPanel , 4, EventoClick);
CrearWinControl(TCheckBox , 5, EventoClick);
CrearWinControl(TRadioButton, 6, EventoClick);
end;

procedure TForm1.btnFreeClick(Sender: TObject);
var
sg : TStringGrid;
c, r: Integer;
begin
sg := StringGrid1;
for c := sg.FixedCols to sg.ColCount - 1 do
for r := sg.FixedRows to sg.RowCount - 1 do
if Assigned(sg.Objects[c, r]) then
begin
sg.Objects[c,r].Free;
sg.Objects[c,r] := nil;
end;
end;


Salida:
http://s32.postimg.org/gf7xttdj9/leg128.gif

Saludos :)

leg128
06-05-2016, 02:45:11
Muchas gracias muchachos, tengo ganas de llorar de la emoción! :D :D El ejemplo de ecfisa y la correccion de [gatosoft] funcionaron de 10...Gracias
Saludos