Ver Mensaje Individual
  #5  
Antiguo 08-04-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Reputación: 29
Lepe Va por buen camino
Sender es un poquito especial precisamente está derivando de TObject porque al hacer la VCL realmente no se sabe quien puede ir en ese parámetro, así que se manda como TObject que es la clase Base. Digamos que puede ser cualquier componente gráfico que tiene eventos definidos.

Tú tienes 100 botones que hacen lo mismo, en lugar de crear 100 eventos distintos, creas uno solo, seleccionas los 100 botones en el IDE y despues le asignas el mismo evento.

Cuando se hace clic en ejecución, El Sender será el objeto que desencadena el evento, es decir el propio boton.

Como tú eres el que estas programando, sabes que el sender puede ser uno de esos 100 botones, en este caso particular no habría que preguntar el tipo de ese sender, es decir:

Código Delphi [-]
procedure TForm1.Button1Click(Sender:TObject);
begin
// recuerda, este evento está asignado a los 100 botones.

if (Sender is TButton) then   // <<<<<< esto no hace falta, porque tú
// has enlazado el evento SOLO CON BOTONES TBUTTON.

// Directamente escribimos:
TButton(Sender).blablabla
end;
Es decir, sabemos de antemano que es un TButton el que desencadena el evento.

Imagina que ahora tienes 99 botones (TButton) y un TBitBtn y tambien compartes el mismo evento para todos, ahora si es necesario preguntar quien desencadena el evento, porque son clases distintas:

Código Delphi [-]
procedure TForm1.Button1Click(Sender:TObject);
begin
// recuerda, este evento está asignado a los 100 botones.

if (Sender is TButton) then  // hacer lo que sea con el TButton
  TButton(Sender).blabla
else if (Sender is TBitBtn) 
  TBitBtn(Sender).blabla
end;
Primero preguntamos si es un TButton, si lo es, lo tratamos como tal.
TButton(Sender) es lo que se llama un moldeo de tipos, viene a decir: "usa el Sender como si fuera un Tbutton", y así tenemos acceso a todas las propiedades y métodos de ese TButton.

En tu caso particular, ese botón no está en la misma ventana, y además dices que las creas dinamicamente, pues supon este escenario:

- el form2 no está creado todavia.
- Abres el form3 y mandas a crear el Form1 desde alli:
  • Se crea el form1 y entra en el Form1Create
  • Pregunta si Form2.Button1..... espera, espera, delphi intenta acceder a Button1.... pero si todavía no está creado el Form2, tampoco lo estará Button1 ==> Access Violation.

Ahora si lo ves lógico ¿verdad?, Bueno y como se controla, pues tenemos que tener todas las precauciones posibles.

Assigned(Form2) es identico a preguntar if Form2 <> nil then

pero ¿y cómo sé yo que Form2 tiene nil dentro o cualquier otra cosa? Aqui es donde se empieza a elegir un criterio.

Si no necesitamos hacer cosas como:
Código Delphi [-]
  with TForm2.Create do
  try
....
   finally 
     Free
   end;
Tendremos que asegurarnos de que la variable Form2 solo tenga dentro un valor cuando se cree la ventana, y despues de liberarla de memoria, le ponemos un nil dentro:
Código Delphi [-]
procedure Tform3.Boton1Click(...);
begin
  Form2 := Tform2.Create(nil); // nadie la destruye porque la destruyo despues yo.

procedure TForm2.Form2Close(Sender: TObject; var Action: TCloseAction);
begin
  Action := cafree; // lo mandamos a liberar
  Form2 := nil ; le metemos a la variable el nil.
end;
Este truco de roman (si no me equivoco.. ) nos asegura que cuando se cierre la ventana, la variable tiene nil dentro, y por tanto:
- Si Form2 = nil significa que no se ha creado el Form2
- Si Form2 <>nil significa que la ventana se está mostrando o está oculta... pero fijo que está creada.

De ahí que use if Assigned(Form2) then para preguntar si está creada o no en mi mensaje anterior.

SAludos y espero se entienda.
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita