PDA

Ver la Versión Completa : Pasar un parametro en la llamada a un form


apicito
08-08-2003, 14:23:30
Desde un formulario MDIChild llamo a un formulario FsNormal

procedure TDecretos.NuevoClick(Sender: TObject);
var EditDecretos:TEditDecretos;
Begin
EditDecretos:=TEditDecretos.Create(Self);
EditDecretos.Modo:='A';
EditDecretos.Show;
end;

en donde tengo definida una variable
Unit UEditDecretos;
public
Modo:Char;

Sin embargo el segundo formulario no recibe el valor que le asigno en el formulario llamador.
Alguien puede explicarme porque.

delphi.com.ar
08-08-2003, 16:05:13
No queda muy claro tu código, pero parece que Modo es una variable/campo de la clase TEditDecretos. Si es así, te garantizo que la clase TEditDecretos va a "recibir" el valor que le pases, solo tienes que tener cuidado en el momento que vas a utilizar este valor, ten en cuenta que no puede ser en el OnCreate, porque aún no se lo has pasado.

Saludos!

apicito
11-08-2003, 09:20:08
Efectivamente, la variable modo pertenece al public de Edit Decretos, pero si en OnShow de EditDecretos hago un:
if Modo='A' then ....
no me reconoce el valor de Modo.
Ya he probado a ponerlo tambien en el onActivate pero tampoco. Supongo que el orden de ejecucion del formulario llamado sea:
OnCreate
OnShow
OnActivate.

delphi.com.ar
11-08-2003, 17:09:39
La verdad que no puedo creer lo que tu dices, a mi parecer debes estar cometiendo algún error porque esta práctica es mas que habitual en la POO y funciona bien.
¿Te animas a postear tu código para que lo podamos evaluar?

Saludos!

apicito
12-08-2003, 08:44:25
En el fomulario que llama que es de tipo MDIChild

procedure TDecretos.NovoClick(Sender: TObject);
var EditDecretos:TEditDecretos;
Begin
EditDecretos:=TEditDecretos.Create(self);
with EditDecretos do
begin
Modo:='A';
Show;
end;
Grid.SetFocus;
end;

y en el formulario llamado que es de tipo fsNormal y donde tengo declarada como publica la variable Modo

public
Modo:Char;
Procedure CargaOrd;
Procedure CargaDecTip;
end;

hago en el on show

procedure TEditDecretos.FormShow(Sender: TObject);
begin
if Modo='A' then
begin
LabelModo.Caption:='NUEVO';
SurceDecr.AutoEdit:=True;
SurceDecr.AutoInsert:=True;
QueryDecr.Open;
QueryDecr.Append;
QueryDecr.FieldByName('DECR_FECHA').AsDate:=now();
QueryDecr.FieldByName('DECR_A_USUARIO').AsString:=
Datos.QueryUsu.FieldByName('USU_USUARIO').AsString;
CargaOrd;
QueryDecr.FieldByName('DECR_ORD').AsString:=
QueryOrd.FieldByName('USU_USUARIO').AsString;
CargaDecTip;
QueryDecr.FieldByName('DECR_TIPO').AsInteger:=
QueryDecTip.fieldByname('DECTIP_CODIGO').AsInteger;
Texto.text:=QueryDecr.fieldbyName('DECR_TEXTO').AsString;
end;
E_Fecha.SetFocus;
end;

Y con esto, el formulario se visuliza un segundo y se cierra. Sin embargo, si hago la llamada como show modal, se visualiza bien.

__cadetill
12-08-2003, 10:08:22
Solo unas aclaraciones

Sabes la diferencia entre show y showmodal? Con Show se muestra el formulario deseado, pero la ejecucion del form "padre" continua. Con ShowModal, se visualiza el formulario y la ejecucion del form "padre" se para hasta cerrar la ventana. Bien, vista esta aclaracion vamos a ver porque con Show funciona mal y ShowModal bien.

Si te fijas, tienes una variable local, EditDecretos. Recordemos el ambito de las variables locales: estas SOLO estan "vivas" DENTRO del procedimiento o funcion donde son declaradas. Como hemos visto que con Show el form "padre" sigue la ejecucion de la aplicación.... pues llega a salir del procedimiento, por eso el form creado se destruye, porque se destruye la variable con la que lo creaste. Se ha entendido? :confused:

Para crear un formulario no hace falta que declares esa variable. Puedes poner simplemente


procedure TDecretos.NovoClick(Sender: TObject);
Begin
EditDecretos:=TEditDecretos.Create(self);
with EditDecretos do
begin
Modo:='A';
Show; // o ShowModal, como quieras o prefieras
end;
Grid.SetFocus;
end;


Pero... me sigue quedando la duda si el form creado recibe o no el parametro (que en teoria deberia de recibir)

Bueno, espero te sirva y quede algo mas claro el tema de las variables locales

apicito
12-08-2003, 11:58:42
Gracias Cadetil, si, entiendo ahora lo de las variables locales. Si, al motraslo como modal ya veo que la variable modo recibe el valor que se le asigna. Ahora te explico lo que, en mi ignorancia, pretendía hacer:

Pretendía poder abrir varias versiones de formulario llamado (EditDecretos) y pensaba que si declaraba una variable y hacía varios create de ella podría tener en pantalla varias versiones de este formulario, cosa que no puedo hacer con ShowModal.

marto
12-08-2003, 12:01:45
Buenas,

Cadetill, me parece que te has colado. Es cierto que la visibilidad de la variable es local al procedimiento, pero no el objeto. Haciendolo tal y como postea apicito debería funcionar, el único problema es que pirde la referencia al form, pero éste no se detruye hasta que se llama explícitamente a free o se destruye su owner.
Por otro lado estoy completamente deacuerdo con deplhi.com.ar, este método FUNCIONA y funciona siempre, estoy cansado de hacer cosas así. Estoy convencido que apicito esta cometiendo algún error en otra parte del código, pero no acierto a verlo.

andres1569
12-08-2003, 12:15:35
Hola:

Efectivamente, como comenta Marto, aunque se pierda la referencia a la variable local, el formulario sigue "vivo". Al haber sido creado pasándole como Owner el formulario actual (Self), se destruirá cuando éste se destruya, o bien en el OnClose de TEditDecretos ponemos lo de Action := caFree, y nos aseguramos de liberarlo.

No veo por donde pueda venir el error, pero sería bueno que la variable EditDecretos : TEditDecretos definida localmente dentro del Button1Click que lanza el formulario, tuviera otro nombre, por ejemplo ED : TEditDecretos. Digo esto porque seguramente ya existe una variable con el nombre EditDecretos en la unit donde se declara este formulario. No sé si de ahí vendrá la confusión, pero pudiera ser que ese formulario, EditDecretos, perteneciera a los AutoCreate forms, y ya existiera, de modo que la asignación Modo := 'A' se realizara sobre el formulario ya creado, y no sobre el que estamos creando en ese momento. Esto es sólo una suposición, no estoy seguro del todo, porque Delphi debería dar prioridad a la variable local, pero podrías probar de hacer ese cambio que te comento.

Saludos

apicito
12-08-2003, 12:27:56
[i]
sería bueno que la variable EditDecretos : TEditDecretos definida localmente dentro del Button1Click que lanza el formulario, tuviera otro nombre, por ejemplo ED : TEditDecretos.

He hecho esto y se visualiza y desaparece., y el formulario EditDecretos no esta entre los formularios AutoCreate.

andres1569
12-08-2003, 12:36:22
Hola de nuevo:

Es extraño lo que te ocurre. ¿metes algún código que cause que se cierre el formulario nada más visualizarse?. No sé si estará relacionado con que lo lances desde un form MDIChild (aquí otros que han usado MDI seguramente lo podrán aclarar).

Quizás sería bueno ver más parte del código (tranquilo que al menos por mi parte no lo distribuiré por ahí :) :) ). Otra cosa, acuérdate de meter el código entre las marcas code y /code, así aparecerá identado y más fácil de leer.

Saludos

apicito
12-08-2003, 12:48:21
Ya sé que nadie me va a copiar. Quizás cuando lleve 20 años con delphi se me ocurrirá algo original.


unit UDecretos;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, IB_Components, Grids, IB_Grid, Buttons, ExtCtrls,
StdCtrls;

type
TDecretos = class(TForm)
Panel1: TPanel;
Novo: TButton;
Image1: TImage;
Image2: TImage;
QueryDecr: TIB_Query;
SurceDecr: TIB_DataSource;
Transa: TIB_Transaction;
Edita: TButton;
B_Tipos: TButton;
Grid: TIB_Grid;
procedure NovoClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure GridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure FormCreate(Sender: TObject);
procedure B_TiposClick(Sender: TObject);
procedure EditaClick(Sender: TObject);
private
{ Private declarations }
public

end;

var
Decretos: TDecretos;

implementation

uses UDatos, UEditDecretos, UDecTip;

{$R *.dfm}

procedure TDecretos.FormCreate(Sender: TObject);
begin
QueryDecr.Open;
end;

procedure TDecretos.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if Transa.InTransaction then
Transa.Rollback;
Action:=caFree;
end;

procedure TDecretos.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if (ACol=4) and (Grid.BuffFields[3].AsInteger > 0) then
Grid.Canvas.Draw(Rect.Left,Rect.Top,image2.Picture.Graphic);
if (ACol=3) and (Grid.BuffFields[2].AsInteger > 0) then
Grid.Canvas.Draw(Rect.Left,Rect.Top,image2.Picture.Graphic);
end;

// ************************* MENU **********************************************
procedure TDecretos.NovoClick(Sender: TObject);
var Ed:TEditDecretos;
begin
Ed:=TEditDecretos.Create(self);
with Ed do
begin
Modo:='A';
LabelModo.Caption:='NUEVO';
SurceDecr.AutoEdit:=True;
SurceDecr.AutoInsert:=True;
QueryDecr.Open;
QueryDecr.Insert;
QueryDecr.FieldByName('DECR_FECHA').AsDate:=now();
QueryDecr.FieldByName('DECR_A_USUARIO').AsString:=
Datos.QueryUsu.FieldByName('USU_USUARIO').AsString;
CargaOrd;
QueryDecr.FieldByName('DECR_ORD').AsString:=
QueryOrd.FieldByName('USU_USUARIO').AsString;
CargaDecTip;
QueryDecr.FieldByName('DECR_TIPO').AsInteger:=
QueryDecTip.fieldByname('DECTIP_CODIGO').AsInteger;
Texto.text:=QueryDecr.fieldbyName('DECR_TEXTO').AsString;
ShowModal;
end;
Actualiza;
Grid.SetFocus;
end;

procedure TDecretos.EditaClick(Sender: TObject);
var Ed:TEditDecretos;
begin
Ed:=TEditDecretos.Create(self);
Ed.QueryDecr.SQL.Text:='select * from DECR where DECR_CODIGO = '
+#39+trim(QueryDecr.fieldbyName('DECR_CODIGO').asstring)+#39;
with Ed do
begin
Modo:='M';
LabelModo.Caption:='EDITANDO';
SurceDecr.AutoEdit:=True;
QueryDecr.Open;
CargaOrd;
CargaDecTip;
QueryDecr.Edit;
ShowModal;
end;
Grid.SetFocus;
end;

procedure TDecretos.B_TiposClick(Sender: TObject);
var DecTip:TDectip;
begin
DecTip:=TDecTip.Create(Self);
DecTip.ShowModal;
DecTip.Free;
end;


y el otro


unit UEditDecretos;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IB_Components, Tx4oleLib_TLB, OleCtrls, DBOleCtl, ExtCtrls,
IB_Grid, IB_Controls, StdCtrls, Mask, Buttons, ComCtrls;

type
TEditDecretos = class(TForm)
B_Ok: TSpeedButton;
B_Cancelar: TSpeedButton;
LabelModo: TLabel;
Label3: TLabel;
Label1: TLabel;
Label2: TLabel;
Label4: TLabel;
E_Usuario: TIB_Edit;
E_Fecha: TIB_Date;
E_OrdCargo: TIB_Edit;
E_OrdNome: TIB_LookupCombo;
E_Tipo: TIB_LookupCombo;
E_Descrip: TIB_Edit;
E_Firma_Sec: TIB_Edit;
E_Firma_Ord: TIB_Edit;
Panel: TPanel;
Transa: TIB_Transaction;
QueryDecr: TIB_Query;
SurceDecr: TIB_DataSource;
SurceNum: TIB_DataSource;
QueryNum: TIB_Query;
SurceOrd: TIB_DataSource;
QueryOrd: TIB_Query;
QueryDecTip: TIB_Query;
SurceDecTip: TIB_DataSource;
Texto: TIB_RichEdit;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure B_OkClick(Sender: TObject);
procedure B_CancelarClick(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
Modo:Char;
Procedure CargaOrd;
Procedure CargaDecTip;
end;

var
EditDecretos: TEditDecretos;

implementation
Uses UDatos;
{$R *.dfm}

procedure TEditDecretos.FormShow(Sender: TObject);
begin
E_Fecha.SetFocus;
end;

procedure TEditDecretos.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if Transa.InTransaction then
Transa.Rollback;
SurceDecr.AutoEdit:=False;
SurceDecr.AutoInsert:=False;
Action:=caFree;
end;

procedure TEditDecretos.B_CancelarClick(Sender: TObject);
begin
Modo:='';
QueryDecr.Cancel;
Close;
end;

procedure TEditDecretos.B_OkClick(Sender: TObject);
begin
try
QueryNum.Open
except
Begin
showmessage('Error No Contador de Decretos');
// E_Nome.SetFocus;
Exit;
end;
end;
QueryDecr.FieldByName('DECR_CODIGO').AsInteger:=
QueryNum.Fields[0].AsInteger;
Try
QueryDecr.post
except
begin
Showmessage('Non se poido grabar o rexistro');
Exit
end;
end;
Transa.CommitRetaining;
Close;
end;

procedure TEditDecretos.CargaOrd;
begin
with QueryOrd do
begin
close;
SQL.text:='Select USU_USUARIO,USU_NOME,USU_CARGO from USU '+
'where USU_ORDENA='#39+'1'+#39;
KeyLinks.Text:='USU.USU_USUARIO=DECR.DECR_ORD';
KeySource:=SurceDecr;
Open;
end;
end;

procedure TEditDecretos.CargaDecTip;
begin
with QueryDecTip do
begin
close;
SQL.text:='Select * from DECTIP';
KeyLinks.Text:='DECTIP.DECTIP_CODIGO=DECR.DECR_TIPO';
KeySource:=SurceDecr;
Open;
end;
end;


end.

delphi.com.ar
12-08-2003, 16:23:31
No veo donde consultas la variable modo... ¿No era en el OnShow?

__cadetill
12-08-2003, 21:05:47
Posteado originalmente por marto
Cadetill, me parece que te has colado.

Toda la razon del mundo :o
Eso me pasa por no leer me la respuesta antes de publicarla :p
Tendre que leerme de nuevo la guia de estilo :D

apicito
13-08-2003, 08:54:00
No veo donde consultas la variable modo... ¿No era en el OnShow?
Es que la versión del formulario que postee ha cambiado a lo largo de estos dos días. En la original las asignaciones que ahora se hacen en el formulario llamador en los eventos onclick de Novo y Edita antes las hacía en el formulario llamado mediante un if: if Modo='A' then o if Modo='E' then....
Por lo que se refiere a la persistencia en pantalla del formulario llamado no acabo de entender como se puede conseguir sin utilizar el onshow, aunque mirando tu web en el ejemplo de formularios nietos he encontrado una solución, si no la que buscaba una que puede servir, que es asignarle al formulario EditDecretos como parent un panel del formulario Decretos, con lo que se visualiza dentro de él y no desaparece. Esto impide que las versiones que abro de EditDecretos se muevan por toda la pantalla pero es una solución, a falta de otra mejor.

andres1569
13-08-2003, 09:48:22
Hola:

Por lo que leo de tu mensaje último, el problema que tienes ahora es el de la persistencia en pantalla del formulario EditDecretos. ¿Has probado de pasarle el Parent del formulario Decretos?. Al ser éste del tipo MDIChild, quizás eso tenga algo que ver. Me estoy refiriendo a que le pases en el Create de EditDecretos el Form principal, el que hace de MDIParent, como parámetro.

Y respecto al problema original, el de que reconozca la variable Modo, aunque lo hayas solucionado llamándola desde botones diferentes, ¿has hecho alguna prueba desde el OnShow de EditDecretos? Es para sacarnos de dudas, no quiero darte más trabajo, pero creo que a todos nos quedó la intriga de por qué eso no funcionaba.

Saludos

__cadetill
13-08-2003, 11:00:57
Otro parent que podrias pasarle es Application

apicito
13-08-2003, 12:30:45
Posteado originalmente por andres1569

Y respecto al problema original, el de que reconozca la variable Modo, aunque lo hayas solucionado llamándola desde botones diferentes, ¿has hecho alguna prueba desde el OnShow de EditDecretos? Es para sacarnos de dudas, no quiero darte más trabajo, pero creo que a todos nos quedó la intriga de por qué eso no funcionaba.
Saludos
Si que funciona correctamente, como ya os dije antes me había engañado el hecho de que la centana desapareciese. Ahora todos los valores que le asigno a la variable Modo (y a todas las demás) las recibe el otro formulario sin problemas.

He probado poniendole como sender Application

Ed:=TEditDecretos.Create(Application);

y se mantine en pantalla, pero si pinchas en otro formulario o en propio padre desaparece.
Lo que son las cosas, ahora que he probado a ponerle como parent un panel del llamador me gusta como funciona. Me permite abrir varias versiones del formulario llamado, puedo cambiarme de uno a otro... osea lo que necesitaba.
Lo digo para que no os molesteis más por mi problema. En todo caso, si quereis probar algo más, yo estoy dispuesto a aprender y a probar lo que me sugirais.
Gracias a todos.