PDA

Ver la Versión Completa : Pasar parametros a una ventana


lucasarts_18
28-10-2006, 23:43:24
Hola a todos:

Mi Duda es la siguiente, en delphi siempre (no he visto otra forma) se pasan variables de un formulario a otro de la siguiente manera.


procedure TFrm_DetalleBuscaFacturaCambio.FormActivate(Sender: TObject);
begin
edt_numero.Text:=Frm_FacturaCambio.Edt_facturaentrada.Text;
SetReadOnlyTxt(edt_numero,true);
end;





Es decir en el evento FormActivate estamos leyendos variables de otra parte, que para mí está malísimo ya que las ventanas deben ser independientes unas de otros o sino se pierde en gran medida la reutilización de objetos.

Mi pregunta es, ¿existe una forma mas elegante de hacer esto?. En otros lenguajes puedes pasar variables u estructuras completas entre una ventana y otra ya que la opción de abrir un ventana permite pasar parámetros, en delphi no he visto hasta el momento nada de esto :(

Hasta Luego -

lucasarts_18
28-10-2006, 23:45:52
Hola:

Pido disculpa, no me he dado cuenta y posteé este mensaje en este apartado, pido por favor a un moderador que lo mueva a su sitio corresponiente, gracias :)

droguerman
29-10-2006, 00:18:25
Código Delphi [-] (http://www.clubdelphi.com/foros/#)//defines: constructor create(aOwner : TComponent; const prm : string); reintroduce;


//implementas
Código Delphi [-] (http://www.clubdelphi.com/foros/#)constructor TMiForma.create(aOwner : TComponent; const prm : string); begin inherited create(aOwner); fPrm := ''; end;

//y llamas

Código Delphi [-] (http://www.clubdelphi.com/foros/#)x := TMiForma.create(application.mainForm, 'hola');

lucasarts_18
29-10-2006, 01:15:19
Hola:

Gracias, está buena la idea, solo tengo una duda con el siguiente código


constructor TMiForma.create(aOwner : TComponent; const prm : string); begin
inherited create(aOwner);
fPrm := ''; //Esto no lo entiendo, donde está definido fPrm
end;



Si es fPrm el parametro prm, no deja asignarle absolutamente nada ya que es una constante






Hasta luego -

Epachsoft
29-10-2006, 03:35:49
Hola,

Lo que usualmente yo hago es lo siguiente.

En toda ventana nueva que estoy creando, agrego un metodo publico llamado execute(parametro1,parametro2,parametro3);

El execute contiene realmente el control ventana, ejemplo


function execute(param1:string):boolean;
begin
Result:=False;
If (PARAM1='CORRA') then
Resul:=showmodal=MrOk
else
Begin
// nada paso aqui.
Result:=False; // reiterativo, pero es una tradicion.
End;
End;


De esta manera se evita la MALA costumbre de poner codigo en el OnShow, en el OnActivate. Inclusive se puede controlar lo que pasa en el OnCreate.


Luego desde cualquier otra ventana yo ejecuto


Begin
With TNewWindow.Create(Self) do
Begin
Try
If Execute('CORRA') then DoSomething else Dosomethingelse;
Finally
Free; // Si se usa una variable temporal, lo mejor es usar FreeandNil.
End;
End;
End;


Espero que sirva. :)

lucasarts_18
30-10-2006, 00:35:27
Gracias a ambos, he resuelto el problema...:)

Lepe
30-10-2006, 10:45:54
Yo propongo otra cosa, de la misma índole, pero en otro sentido:


TForm1 = class (tForm)

private
Fparam1:string;
Fparam2:integer;

procedure Setparam2(value:integer);
function Getparam2:integer;
public
constructor Create(Aowner:TObject);override;

property Parametro1:string read Fparam1 write Fparam1;
property Parametro1:integer read Getparam2 write Setparam2;
procedure Execute;
end;

constructor TForm1.Create(Aowner:TObject);
begin
inherited Create(Aowner);
Fparam1 := EmptyStr;
Fparam2 := -1;
end;

procedure TForm1.SetParam2(value:integer);
begin
{ Value es el valor que se le va a asignar desde fuera de la clase
justo cuando alguien hace Form1.param2 := 33
}
if Value <> Fparam2 then
begin
// podemos comprobar que el antiguo Fparam2 es distinto al
// valor que se le quiere asignar, y no repetir acciones.
// Además podemos saber el valor que tenía y ahora el valor que tendrá,
// en algunas situaciones es muy util, porque podemos inicializar variables
// liberar objetos, etc.
end;
end;

function TForm1.GetParam2:integer;
begin
result := Fparam2;
// devolvemos la variable privada, igual hay que hacer cálculos u otras cosas
end;

procedure TForm1.Execute;
begin
if Fparam1 = EmptyStr then
raise Exception.Create('dale un valor a Parametro1');

if Fparam2 = -1 then
raise exception.Create ('dale un valor a Parametro2');


Ventajas:
- Si ahora necesitamos añadir otro parámetro más, no hay necesidad de modificar la declaración del procedimiento Execute, es decir modificar los parámetros de entrada que necesita, simplemente se añade una propiedad más, modificas internamente el método Execute y listo. Normalmente no tienes que modificar el programa que hace uso de la clase.

- Podemos saber los valores antiguos y nuevos de cada parámetro, como ya dije, para inicializar o liberar recursos.

- Su uso es más parecido a la VCL, por tanto en un futuro será intuitivo su uso. ¿el TQuery lleva parámetros en su método Open(sql: string)?, o por ejemplo, ¿el TOpenDialog en su método Execute?, pues por eso mismo.

Saludos

Lepe
30-10-2006, 10:49:07
Respondo en otro mensaje para no mezclar conceptos.

En realidad lo único que tienes que escribir en delphi es esto:

Form1 = class (tForm)

public
constructor Create(Aowner:TObject);override;

property Parametro1:string read Fparam1 write Fparam1;
property Parametro1:integer read Getparam2 write Setparam2;
procedure Execute;
end;

y ahora pulsar CTRL + SHIFT + C (Class completion de delphi), delphi te propondrá el esqueleto del mensaje anterior.

Saludos de nuevo.

lucasarts_18
31-10-2006, 04:28:35
Lepe:

Gracias por tu aporte, pero después de unas copitas de vino no creo que pueda analizar bien tú código, prometo mañana echarle un vistazo :)

Nos vemos...

Lepe
31-10-2006, 10:52:43
Reconozco que al verlo por primera vez impresiona un poquito, veamos el concepto, y así de camino sirve para otros foristas:
property Param1:string read Fparam1 write Fparam1;

¿Qué es FParam1?
Simplemente una variable privada del mismo tipo de datos que Param1. Se podría decir que es una "Copia de seguridad" de la propiedad.

¿Por qué se llama FParam1?, es un estándar, a todos los campos (Fields) que son privados de una clase, se le añade la letra "F" al principio.

¿Por qué no hacerlo así:

public
Param1:string;
Porque si tenemos que modificar la clase por otros detalles, estamos utilizando la variable pública Param1, y puede incluso que necesitemos cambiar el tipo de datos, esto supone que los programas que usan esa clase también necesitan modificarse. Esto es una onda expansiva, igual que tirar una piedra en el lago, las modificaciones se van propagando y al final necesitas rehacer todo el programa.

Al usar una variable pública y otra privada, se pueden hacer cambios en el interior de la clase y no modificar la variable pública. No hay onda expansiva ;).

// desde fuera de la clase, hacemos uso de ella:
ShowMessage(Form1.Param1)
Con esa linea estamos leyendo (read) el valor de Param1, en realidad delphi, lee el valor de la variable FParam1.

// desde fuera de la clase, hacemos uso de ella:
Form1.Param1 := 'hola mundo';
En este caso estamos escribiendo (write) en la variable, por tanto delphi asignará a FParam1, el valor 'hola mundo'.

La otra variante que lleva dos procedimientos, es exactamente igual, solo que ahora en lugar de leer de una variable privada, se ejecuta una función (GetParam1) que devuelve un string. También al tiempo de asignar una variable, se usa un procedimiento (SetParam).

"Get" y "Set" también es un estándar, son prefijos que siempre se añaden para hacer más legible el código.


Saludos

roman
31-10-2006, 17:55:35
Porque si tenemos que modificar la clase por otros detalles, estamos utilizando la variable pública Param1, y puede incluso que necesitemos cambiar el tipo de datos, esto supone que los programas que usan esa clase también necesitan modificarse. Esto es una onda expansiva, igual que tirar una piedra en el lago, las modificaciones se van propagando y al final necesitas rehacer todo el programa.


La onda expansiva no se detendrá si cambias el tipo de datos. Por lo demás estoy completamente de acuerdo con lo que expones y en mi opinión es el camino más adecuado.

El uso de un método para paso de parámetros puede ser útil en ciertas circunstancias pero muchas veces terminamos teniendo métodos con una lista interminable de parámetros. Uno sigue teniendo pleno control del formulario al momento de crearlo, aunque, de hecho, no entiendo esto:

De esta manera se evita la MALA costumbre de poner codigo en el OnShow, en el OnActivate

¿Por qué es mala costumbre?

// Saludos

Epachsoft
31-10-2006, 21:13:54
Yo en lo personal me iria mas por hacer un "overload" o "override" del metodo execute, tal como se hace con el "creator" o el "destructor", dependiendo de la necesidad. Modificando los parametros de entrada si eso es lo que se busca.


Mis problemas con OnActivate
- Se activa cada momento en que la ventana obtiene "focus", si usted trabaja con multiples ventanas, este evento y el codigo dentro del mismo se ejecutara multiples veces al hacer switch, no una ves, a como es usualmente deseado en un metodo de ejecucion tipo "execute".

Esto se puede eliminar agregando variables internas para controlar la primera vez que se logra la activacion y asi en adelante no re-ejecutar las instrucciones en este evento, pero en fin, mas codigo.

No hay nada de malo con Onshow, pero en lo personal, para valores de inicializacion y de ejecucion de nuevos dialogos, OnShow es un evento que ocurre ya muy tarde en el ciclo de ejecucion de una nueva ventana. No permite inicializar variables visuales y no visuales que se necesitan previo al despliegue de una ventana. En fin, es el gusto de cada cual, en lo personal para un metodo de ejecucion de una ventana o dialogo, muy raramente usted vera codigo creado alrededor del evento OnShow.

El VCL muestra muchos ejemplos de esto, raramente OnShow es utilizado internamente.

roman
31-10-2006, 21:43:40
Mis problemas con OnActivate
- Se activa cada momento en que la ventana obtiene "focus", si usted trabaja con multiples ventanas, este evento y el codigo dentro del mismo se ejecutara multiples veces al hacer switch, no una ves, a como es usualmente deseado en un metodo de ejecucion tipo "execute".


No entiendo por qué eso es lo deseado; estamos hablando de OnActivate, y tal es el comportamiento documentado. Si no es eso lo que se quiere entonces se usa otra cosa, pero eso no quiere decir que el evento no sea adecuado o que sea mala práctica poner código ahí.


No hay nada de malo con Onshow, pero en lo personal, para valores de inicializacion y de ejecucion de nuevos dialogos, OnShow es un evento que ocurre ya muy tarde en el ciclo de ejecucion de una nueva ventana. No permite inicializar variables visuales y no visuales que se necesitan previo al despliegue de una ventana.


Como bien dices, es una cuestión personal. Yo uso sin ningún problema este evento para inicializar (no construir, que para eso está OnCreate) cuestiones visuales como etiquetas, por ejemplo. Es cierto que hay cosas que conviene hacer antes de mostrar (Show/ShowModal) el formulario, pero eso sólo indica que para ciertas cosas, dicho evento no es el adecuado, de ninguna manera significa que sea mala práctica per sé.


El VCL muestra muchos ejemplos de esto, raramente OnShow es utilizado internamente.


Es que, de hecho, difícilmente verás ningún evento utilizado internamente, no es exclusivo de estos eventos, simplemente porque éstos, los eventos en general, están pensados para el programador final, la VCL sólo los pone disponibles.

// Saludos

Epachsoft
31-10-2006, 22:39:28
"Es que, de hecho, difícilmente verás ningún evento utilizado internamente, no es exclusivo de estos eventos, simplemente porque éstos, los eventos en general, están pensados para el programador final, la VCL sólo los pone disponibles."

Incorrecto, en gran parte de la VCL se usa por herencia los metodos OnCreate, OnChange, OnKeyDown, etc, seria mas bien extrano decir que se puso ese evento unicamente para el usuario final.

El VCL no es simplemente una cosa bonita que Borland puso ahi, es un claro ejemplo de la forma correcta de desarrollar codigo usando Object Pascal, desde su sintaxis, best "coding practices", comentarios y estandarizacion de presentacion de codigo.

Es un ejemplo en vivo de como implementar todo tipo de soluciones, e.g. una caja de dialogo donde se despliega un mensaje (MessageDlg), un wrapper de Activex, etc, codigo que usaremos muchas veces en situaciones de nuestra vida diaria. Solo examinen la implementacion de los DBAware components y noten como gracias a toda esa base de clases, metodos y con gran uso de herencia y polimorfismo logran implementar esos increibles componentes.

Danny Thorpe, antiguo chief scientist de Borland y la persona a cargo del compilador de Delphi escribio el maximo manual (http://www.amazon.com/Delphi-Component-Design-Danny-Thorpe/dp/0201461366) de como escribir componentes, dialogs, etc en Delphi, utilizando como ejemplo el mismo VCL y la mayoria de sus metodos. Es una gran lectura, y un libro considerado como clasico.

----

Ahora bien por el otro lado, repito, no utilicen el OnShow event para inicializar variables. Si estan haciendo aplicaciones pequenas para la casita, con par de formas y que solo ustedes van a hacer perfecto, pero si es para aplicaciones serias donde se utiliza mucha herencia, formas MDI y Frames, poner eventos en el OnShow o en el OnActivate SOLO les va a traer problemas y dolores de cabeza. Inicializacion !!NO!! en ese evento. Usen Oncreate, o pongan un metodo execute. (Noten como la mayoria de Dialogos en Delphi (revisen tambien los componentes JEDI) tienen un metodo Execute y pocas veces codigo en OnShow.

Muchas gracias. :)

roman
31-10-2006, 22:48:56
Incorrecto, en gran parte de la VCL se usa por herencia los metodos OnCreate, OnChange, OnKeyDown, etc, seria mas bien extrano decir que se puso ese evento unicamente para el usuario final.


Incorrecto, lo que se usa son los métodos virtuales correspondientes como Show.


El VCL no es simplemente una cosa bonita que Borland puso ahi, es un claro ejemplo de la forma correcta de desarrollar codigo usando Object Pascal, desde su sintaxis, best "coding practices", comentarios y estandarizacion de presentacion de codigo.


Y ¿quién ha dicho lo contrario?


Si estan haciendo aplicaciones pequenas para la casita, con par de formas y que solo ustedes van a hacer perfecto,


¡Vaya arrogancia la tuya! Con esto cierras cualquier posibilidad de diálogo.

// Saludos

Epachsoft
31-10-2006, 23:16:56
Don Roman,

No hubo arrogancia de por medio, es mas si nota, el comentario no fue dirigido a ninguna persona en especial. Estoy simplemente exteriorizando mi experiencia personal, yo en casa, no me preocupo tanto por crear las ventanas en el momento en que se necesitan (al fin y al cabo en casa programo por R&D), dejo que delphi las cree por si solas al inicializar el proyecto (ideal si se tienen hasta 10 ventanitas), yo en la casa no me preocupo mucho por vicios de programacion porque solo yo usare y entendere ese codigo.

El problema surge cuando ese codigo es usado por muchos, en equipos de 6+ miembros donde existe rotacion de codigo, son vicios de desarrollo como los anteriores los que atrasan el desarrollo si son generalizados.

Insisto, un foro es un lugar para la discusion y la opinion personl, y me preocupa y alarma que mi comentario genere una reaccion contraria en cualquiera.

Un claro ejemplo son los newsgroups publicos de borland delphi. Ahi cualquier res se destaza en segundos, y los moderadores tienen que lidear con situaciones realmente agobiantes y tambien con gente realmente inteligente, pero con actitudes realmente encontradas.


Saludos.


Pst.

Codigo del VCL donde se implementa un Override al DBLookUpList OnKeyDown event.


procedure TDBLookupList.KeyDown(var Key: Word; Shift: TShiftState);
begin
try
FInCellSelect := True;
inherited KeyDown (Key, Shift);
finally
FInCellSelect := False;
end;
if (Key in [VK_UP, VK_DOWN, VK_NEXT, VK_PRIOR, VK_HOME, VK_END]) and
CanEdit then ListClick;
end;


Es mas gran parte de la libreria dbLookUp.pas de Delphi utiliza los eventos OnKeyPress, OnKeyDown, OnMouseMove y otros.

Por ejemplo, tiene gran sentido el tomar el dbgrid basico y override alguno de sus eventos con el fin de extenderlo y volverlo a publicar como un componente extendido. Gran parte del JVCL se basa en este principio.

Lepe
01-11-2006, 01:37:39
La onda expansiva no se detendrá si cambias el tipo de datos.

Ese punto no lo expliqué como quería.

Si tenemos el método Get (ya hablando con propiedad), podemos tener la propiedad pública de tipo String, pero usar un campo privado de tipo entero. En el métodos Get se hacen las conversiones oportunas para devolver un string.

De esta forma se mantiene el tipo de datos de la propiedad pública, pero se ha cambiado el tipo de datos del campo privado.

¿para qué hacer algo así?, bueno, quizás haya que devolver "331 Pepe Martínez", donde el 331 es el código de cliente y después el nombre, quizás interese guardar como entero el 331 para uso interno. (solo es un ejemplo ;)).

Saludos

roman
01-11-2006, 02:11:47
De esta forma se mantiene el tipo de datos de la propiedad pública, pero se ha cambiado el tipo de datos del campo privado.

Ya veo. Entonces estoy 110% de acuerdo con tu método. :)

// Saludos

jachguate
01-11-2006, 02:26:01
Codigo del VCL donde se implementa un Override al DBLookUpList OnKeyDown event.
Difiero de tu opinión. Este código demuestra justamente lo expresado por roman:

Incorrecto, lo que se usa son los métodos virtuales correspondientes como Show.
Solo que este método, en lugar de ser virtual, es dinámico.

Hasta luego.

;)