Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   variables entre forms (https://www.clubdelphi.com/foros/showthread.php?t=44375)

fedelphi 05-06-2007 04:25:42

variables entre forms
 
Mi problema es el siguiente, tengo un form principal que se crea con el proyecto al ejecutarse, bien, desde este form creo en tiempo de ejecucion todos los otros forms de la forma
Código Delphi [-]

procedure TFPrincipal.Consultacirc1Click(Sender: TObject);
var
  cons:TFConsultaCirc;
begin
  cons:=TFConsultaCirc.Create(self);
  cons.Show;
end;
cuando cierro el form en el onclose hago la action:=caFree.
Bueno, el problema viene aqui, en este form que creo en tiempo de ejecucion tengo una variable publica para accederla desde otro form que lo muestro como showmodal, de esta forma
Código Delphi [-]
type
  TFConsultaCirc = class(TForm)
    DBGrid1: TDBGrid;
    BEliminar: TButton;
.
.
.

public
    env_devs:integer;
  end;
.
.
.
procedure TFConsultaCirc.BEliminarClick(Sender: TObject);
var
  adv:TFAdvierteBorraCirculante;
begin
adv:=TFAdvierteBorraCirculante.create(self);
if adv.showmodal=mrYES then
      begin
.
.
.
end;

y este es el codigo del form que llamo con showmodal
Código Delphi [-]
 if ECantidad.Text<>''then //este codigo es dentro del form.showmodal
  begin
    FConsultaCirc.env_devs:=strtoint(ECantidad.Text);
    ModalResult:=mrOK;
  end
  else
    showmessage('Ingrese la cantidad de envases');
pero al llegar a la asignacion me da el error 'Access violation ...', ahora mi pregunta; como hago referencia a esta variable del otro form? se que mi problema es por crearlo en tiempo de ejecucion ya que si lo creo cuando se ejecuta la aplicacion hago referencia a ella y listo, pero quiero saber como trabajar con los forms creados de esta manera. Espero haber sido claro, disculpen cualquier error ya estoy un poco perdido y cansado con este rollo.
Gracias
Fede

cHackAll 05-06-2007 06:03:05

Mmmm...
 
No me queda muy claro el código, para mi el problema es que estas usando una variable dentro de un objeto... cuando liberas el objeto, todo lo que éste contanga también sera liberado (en memoria), asi que por que no intentas poner la variable justamente donde defines al objeto formulario?

Código Delphi [-]
...
...
 
var
 FConsultaCirc: TFConsultaCirc;
  env_devs:integer;

implementation
 
...
...

de esta forma solucionaras tu problema!

suerte!

roman 05-06-2007 08:13:34

Creo que no va por ahí el problema: el formulario aún no se destruye puesto que desde él se llamó modalmente al otro.

Sin poder decir nada en definitivo, a mi me parece que la variable FConsultaCirc a la que se hacer referencia en el código, no es la que nuestro amigo piensa que es. Hay dos variables llamadas así: la que fedelphi declara en el método Consultacirc1Click del formulario principal, y la que el IDE de Delphi pone en automático al agregar el formulario:

Código Delphi [-]
type
  TFConsultaCirc = class(TForm)
    ...
   end;

var
  FConsultaCirc: TFConsultaCirc = class(TForm);

Como no parece que al formulario modal se le pase una referencia al formulario que lo abrió, todo parece indicar que la variable que entra en juego es la que el IDE coloca, que seguramente nunca se ha creado, y de ahí el "Access Violation".

// Saludos

fedelphi 05-06-2007 15:13:10

Gracias por responder, pero creo que roman me entendio mejor, como hago para pasarle una referencia del formulario que llama al formulario modal? :confused:, no se hace al crearla con self en el create?
Fede

roman 05-06-2007 18:08:34

Cita:

Empezado por fedelphi
como hago para pasarle una referencia del formulario que llama al formulario modal?

La pregunta más bien es: ¿para qué quieres eso?

Según alcanzo a ver de tu código, el formulario modal está para preguntar al usuario un dato que requiere el otro formulario, y ese dato intentas asignarlo directamente desde el modal, pero esa no es tarea de éste formulario.

Piénsalo así: en general, un formulario modal se usa para preguntar valores, pero qué se hace con esos valores es responsabilidad de quien llama al formulario.

Por ejemplo, un cuadro de diálogo como OpenFileDialog tiene como finalidad preguntar al usuario por un nombre de archivo. El cuadro jamás va a colocar el nombre seleccionado en ninguna parte ajena a él, únicamente "devolverá" el archivo seleccionado en su propiedad FileName.

En tu caso yo haría algo similar. Al formulario modal le anexas una propiead al caso:

Código Delphi [-]
type
TFAdvierteBorraCirculante = class(TForm)
  ...
private
  FCantidad: Integer;

public
  property Cantidad: Integer read FCantidad write FCantidad;
end;

En el evento OnCloseQuery de este formulario verificas si el usuario oprimió OK. De se asi, asignas el dato en ECantidad.Text a FCantidad:

Código Delphi [-]
FCantidad := StrToInt(ECantidad.Text);

El otro formulario abriría el modal así:

Código Delphi [-]
procedure TFConsultaCirc.BEliminarClick(Sender: TObject);
var
  adv: TFAdvierteBorraCirculante;
begin
  adv := TFAdvierteBorraCirculante.create(self);

  try
    if adv.showmodal=mrYES then
    begin
      env_devs := adv.Cantidad;
    end;
  finally
    adv.Free;
  end;
end;

Observa el uso del try-finally para destruir al formulario modal. No dejes que éste se "autodestruya" poniendo Action := caFree en el evento OnClose. Lo necesitas "vivo" para cuando se cierre y tomes el vaor de su propiedad Cantidad.

// Saludos

fedelphi 05-06-2007 21:26:46

Buenisimo!!!
 
Que grande roman, funciono perfectamente, muchisimas gracias por la ayuda:D:D:D

Le hice esto en el onclick
Código Delphi [-]
procedure TFAvierteBorraCirculante.BSiClick(Sender: TObject);
begin
  BSi.Tag:=1;
  Close;
end;
y asi en el onclosequery
Código Delphi [-]
procedure TFAvierteBorraCirculante.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  if Bsi.tag=1then
  begin
    if ECantidad.Text<>''then
    begin
      CanClose:=True;
      ModalResult:=mrOK;
      FCantidad := StrToInt(ECantidad.Text);
    end
    else
    begin
      showmessage('Ingrese la cantidad de envases');
      CanClose:=False;
    end;
  end;

end;
y creo que asi queda completo
Fede

roman 05-06-2007 21:46:58

Eso del BSi.tag está un poco feito :p

Lo normal es que a tu botón Aceptar le pongas su propiedad ModalResult en mrOk, para que automáticamente, al momento de oprimir el botón, se asigne mrOk al formulario. Y éso es lo que usas en CloseQuery para determinar si se oprimió Aceptar:

Código Delphi [-]
procedure TFAvierteBorraCirculante.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  //if Bsi.tag=1then
  if MOdalResult = mrOk then
  begin
    if ECantidad.Text<>''then
    begin
      CanClose:=True;
      //ModalResult:=mrOK;
      FCantidad := StrToInt(ECantidad.Text);
    end
    else
    begin
      showmessage('Ingrese la cantidad de envases');
      CanClose:=False;
    end;
  end;
end;

y ya no usas el evento OnClick del botón.

// Saludos

fedelphi 05-06-2007 22:22:23

OK, gracias de nuevo.
Fede


La franja horaria es GMT +2. Ahora son las 15:27:20.

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