Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-04-2006
dape dape is offline
Miembro
 
Registrado: ene 2004
Ubicación: Tacna - Perú
Posts: 138
Poder: 21
dape Va por buen camino
¿Quién llamó mi form?

hola amigos, estoy tratando de averiguar con que botón se ha llamado a una form, para eso utilizo el siguiente código:

Código Delphi [-]
procedure form1.create(sender: tobject)
begin
    if sender = form2.boton1 then
       {ejecutar código 1}
    if sender = form3.boton2 then
      {ejecutar código 2}
    {realiza el resto}
end;

como lo habrán notado al form1 puedo llamarlo desde el form2 o el form3, para esto realizo una evaluación en el oncreate del form1 para saber quién lo ha llamado para poder ejecutar un pequeño código específico para cada botón, el caso es que al ejecutar el programa me sale un error de violación de acceso si no recuerdo mal, ejecuta el programa paso a paso y el error salta al hacer el llamado del form1 y evaluar el primer if, al aceptar el error el programa continua pero no evalúa los if, ¡se los pasa de largo olímpicamente como si no hubiera presionado ningún botón para llamar al form1!.

¿Es correcta mi forma de utilizar el sender? ¿existe alguna otra manera de saber quién llamó al form1?.

Desde ya gracias por la ayuda que puedan brindarme.

Saludos desde Tacna - Perú

David
Responder Con Cita
  #2  
Antiguo 07-04-2006
Edgtho Edgtho is offline
Miembro
 
Registrado: abr 2006
Posts: 47
Poder: 0
Edgtho Va por buen camino
Te da una violacion de memoria porque estas comparando un tobject con un tbutton sin ningun parseo de clase. Es decir, aparte que hay maneras alternativas mucho mejores. Yo por ejemplo utilizaria el nombre del boton, la propiedad tag o la propiedad hint para identificar el boton origen.


Código:
If (Sender as Tcontrol).name = 'button1' then
 ....
Tomando tag=1 para form1 y tag=2 para form2
Código:
If (Sender as Tcontrol).tag = '1' then
 ....
O mejor aun, pensando que puedes llamarlo desde distintos botones utilizar la propiedad parent

Código:
If (Sender as TWincontrol).Parent.name = 'form1' then
 ....
If (Sender as TWincontrol).Parent.name = 'form2' then
  ....
__________________
Dios es real a menos que sea declarado entero
Responder Con Cita
  #3  
Antiguo 07-04-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
dape Usando ese código estas suponiendo que Form2 y Form3 se crean desde el principio de la aplicación, y además se crean antes que el Form1. ¿es correcto todo esto?

Este tipo de acciones son muy propensas a fallos, por lo que se suele controlar bien:
Código Delphi [-]
procedure form1.create(sender: tobject)
var Encontrado : Boolean;
begin
  Encontrado := false;
  if Sender is TButton then
  begin
    if Assigned(Form2) then // si está creado el Form2
    if Tbutton(sender) = form2.boton1 then
    begin
       {ejecutar código 1}
      Encontrado := true;
    end;

    if not(Encontrado) and Assigned(Form3) then
    if Tbutton(Sender) = form3.boton2 then
    begin
      {ejecutar código 2}
      Encontrado := true;
    end;
  end;
  
  If not Encontrado then
    {hacer lo que sea}

    {realiza el resto}
end;

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #4  
Antiguo 08-04-2006
dape dape is offline
Miembro
 
Registrado: ene 2004
Ubicación: Tacna - Perú
Posts: 138
Poder: 21
dape Va por buen camino
Hola, gracias por las respuestas.

Edgtho, voy a probar tus recomendaciones y después cuento como me fue.

Lepe, los form los creo a "pedido", es decir no no se crean al ejecutar la aplicación, solo cuando los necesito, no sé si eso influye en algo.

Lo que ocurre es que nunca he hecho algo así, siempre evité usar el sender porque no lo entendía bien y cuando necesitaba usar más de una ves un form, pues, lo volvía a rehacer pero me cansé de eso, no me parece nada práctico así que decidí investigar algo sobre el uso del sender y, bueno, lo usé a como lo entendí y según parece no lo entendí bien.

De nuevo gracias por las respuesas y seguiré sus consejos.

saludos desde Tacna - Perú

David
Responder Con Cita
  #5  
Antiguo 08-04-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 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
  #6  
Antiguo 11-04-2006
dape dape is offline
Miembro
 
Registrado: ene 2004
Ubicación: Tacna - Perú
Posts: 138
Poder: 21
dape Va por buen camino
hola, después de tanto pelear con el fatidioso sender, el código me quedo así:

Código Delphi [-]
procedure form1.create(sender: tobject)
var Encontrado : Boolean;
begin 
    Encontrado := false; 
    if Sender is TButton then 
    begin 
        if Assigned(Form2) then // si está creado el Form2 
           if not (Tbutton(sender) = form2.boton1) then //¿acaso fue <> en lugar de =? 
        begin 
            {ejecutar código 1} 
            Encontrado := true; 
        end; 
        if not(Encontrado) and Assigned(Form3) then 
          if not (Tbutton(Sender) = form3.boton2) then 
          begin 
               {ejecutar código 2} 
               Encontrado := true; 
          end; 
    end; 
    If not Encontrado then 
      {hacer lo que sea} 
      {realiza el resto}
end;

Bueno, no sé si será así com debe quedar el código, pero funcionó; talvez se pregunten porqué están negados los if, la respuesta es que si no lo niego no me los evaluava, no me pregunten porque ya que no tengo ni la más mínima idea y me gustaría mucho tenerla.

Gracias por la ayuda prestada.

saludos desde Tacna - Perú

David
Responder Con Cita
  #7  
Antiguo 11-04-2006
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Delphi no se salta un if así por las buenas .

Bien tienes desactivada "complete evaluation" en las opciones del compilador, y entonces si la primera condición de un if es falsa y están unidos con operador "and" entonces no sigue evaluándolas. Yo tambien la tengo desactivada.

Tambien puede ocurrir que por optimizaciones del debugger de delphi, no pueda darte un valor concreto usando F7 y F8.

Ese código debe funcionar en todas las situaciones mientras se llame desde un botón.

Si directamente se hace:
Código Delphi [-]
 Application.CreateForm(TForm1, Form1);
No se encontrará y ejecutará el "If not Encontrado then" que debe controlar precisamente ese posible error.

Lo que haya en "realiza el resto" no debe hacer llamadas ni a Form2 ni al Form3. De esa forma, jamás dará errores extraños.
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #8  
Antiguo 13-04-2006
amadis amadis is offline
Miembro
 
Registrado: may 2005
Ubicación: San José, Colón, Entre Ríos, Argentina
Posts: 315
Poder: 20
amadis Va por buen camino
Thumbs up Atadura con Alambre

Yo hace tiempo intentaba saber lo mismo!

Al final me las arreglé con un poco de astucia y ate con alambre.

Lo que hice fue crear en cada form una propiedad llamada LLAMADOR del tipo Tform.
Código Delphi [-]
llamador : Tform;

cada vez que voy a crear un form ya sea de un boton o menu luego de crearlo le paso el valor a llamador que será el Form Actual.

Por ejemplo si tienes un Form 1 que puede llamar a demas forms y quieres saber a quien devolver el foco.

Cuando desde form 1 creo al Form3 le paso en la propiedad LLAMADOR el valor FORM1.
Luefo desde form 3 preguntas si LLAMADOS = FORM1 y haces lo que quieras.
O si quieres al cerrar Form3 preguntas si llamador = Form1 le devuelves el foco o haces lo que quiera.

Yo directamente lo que hacia al cerrar era maximizar llamador ya que es una variable Tform encontes solo le decia LLAMADOR.WINDOWSSTATE := MAXIMIZED; y listo.

Espero que te sirva mi ayuda aunque no se que era lo que buscabas
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Imposible hacer visible un form desde otro form SMTZ .NET 13 16-01-2006 21:41:08
Error cuando llamo a un programa esxterno desde mi aplicacion quake2420 Varios 2 12-08-2005 19:30:44
Como llamo desde delphi un Applet maravert JAVA 1 08-09-2004 03:24:12
como llamo al shellexecute sarga API de Windows 2 14-04-2004 15:18:49
¿Como llamo a esta variable¿ chele Varios 5 18-03-2004 16:12:02


La franja horaria es GMT +2. Ahora son las 22:50:11.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi