PDA

Ver la Versión Completa : variables entre forms


fedelphi
05-06-2007, 04:25:42
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

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

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

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
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?

...
...

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:


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
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:


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:


FCantidad := StrToInt(ECantidad.Text);


El otro formulario abriría el modal así:


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
Que grande roman, funciono perfectamente, muchisimas gracias por la ayuda:D:D:D

Le hice esto en el onclick
procedure TFAvierteBorraCirculante.BSiClick(Sender: TObject);
begin
BSi.Tag:=1;
Close;
end;
y asi en el onclosequery
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:


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