Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Ayuda sobre gestion de ventanas modales y no modales (https://www.clubdelphi.com/foros/showthread.php?t=38285)

Delphius 10-12-2006 01:07:01

Ayuda sobre gestion de ventanas modales y no modales
 
Buenos dias foristas,

Estaba viendo algunas recomendaciones que hace Ian Marteens en su libro La Cara Oculta de Delphi 4. Para ser exacto el método de clase que declara para crear ventanas modales o no modales, en la página 274.

Entiendo bien lo que hacen dichos algoritmos... y me gustaría llevarlo a la práctica... emplearlos en forma genérica (supuestamente esa es la ventaja de implementar como un método de clase) y al querer hacerlo me sale la duda: ¿Tengo que diseñar una clase TVentanaModal y TVentanaNoModal que derive de TForm? o de TCustomForm? A mi entender eso pretende...:confused:

¿Si declaro esas clases... como hago para que pueda hacer uso de las mismas?.... Generalmente uno hace File -> New -> Form. Y como es de esperar... este deriva de TForm. Ahora,.. la pregunta del millón: ¿Como hago para que al diseñar una nueva aplicación pueda usar dichas "formas" y no un TForm?:confused:

Por otro lado estaba pensando en que tengo que hacer herencia visual de un TForm y allí le meto el método de clase ¿?:confused:... pero la verdad es que nunca llevé a la práctica este tipo de herencia...
Tengo entendido que uno puede guardar una forma (para una aplicación)... y luego puede hacer File -> New -> Other -> Proyect, seleciona la forma deseada y tildando en Inherit hace herencia visual. Claro, todo dentro del aplicativo en cuestión. ¿Y si yo quiero tener algo genérico.... como los TAboutForm... pero que sea TVentanaModal y TVentanaNoModal como implementa Ian Marteens? De seguro que existe solución para lo que necesito.:D

Yo para combatir algunos de estos malestares de gestiones de ventanas me había declarado una unit (en mis primeros meses de programacion en Delphi) con funciones y procedimientos que realizan operaciones sobre las formas que se le pasen como parámetros. Algo como::rolleyes:

Código Delphi [-]
unit WindowsUses;

interface

uses Windows, SysUtils, Forms, Messages, Classes;

procedure Mostrar(Forma: TForm;Value:Boolean;PosX,PosY:integer);
procedure ExpandirForma(Forma:TForm;Ancho,Largo:integer);
function FormaCreada(Nombre: String): boolean;
procedure DestruirForma(Forma: TForm);
procedure MinimizarForma(Forma: TForm);
procedure MaximizarForma(Forma: TForm);
procedure RestaurarForma(Forma: TForm);
procedure MinimizarAplicacion;
procedure FinalizarAplicacion;

implementation

procedure Mostrar(Forma: TForm;Value:Boolean;PosX,PosY:integer);
var Ban: Boolean;
begin
Ban := FormaCreada(Forma.Name);
if Ban
   then begin
        with Forma do
          begin
          Left := PosX;
          Top := PosY;
          Visible := Value;
          end;
        end;
end;

procedure ExpandirForma(Forma:TForm;Ancho,Largo:integer);
var Ban: boolean;
begin
ban := FormaCreada(Forma.Name);
if Ban then begin
            with Forma do
              begin
              Height:= Largo;
              Width:= Ancho;
              end;
            end;
end;

function FormaCreada(Nombre: string): boolean;
var Ban: boolean;
    i: integer;
begin
Ban := False;
i := 0;
while (Ban = False) and (i<= Screen.FormCount-1) do
  begin
  if Screen.Forms[i].Name = Nombre
    then ban := True
    else Inc(i,1);
  end;
Result := Ban;
end;

procedure DestruirForma(Forma: TForm);
var Ban: boolean;
begin
Ban := FormaCreada(Forma.Name);
if Ban
   then Forma.Destroy;
end;

procedure MinimizarForma(Forma: TForm);
var Ban: boolean;
begin
Ban := FormaCreada(Forma.Name);
if Ban then begin
            with Forma do
            WindowState := wsMinimized;
            end;
end;

procedure MaximizarForma(Forma: TForm);
var Ban: boolean;
begin
Ban := FormaCreada(Forma.Name);
if Ban then begin
            with Forma do
            WindowState := wsMaximized;
            end;
end;

procedure RestaurarForma(Forma: TForm);
var Ban: boolean;
begin
Ban := FormaCreada(Forma.Name);
if Ban then begin
            with Forma do
            WindowState := wsNormal;
            end;
end;

procedure MinimizarAplicacion;
begin
Application.Minimize;
end;

procedure FinalizarAplicacion;
begin
Application.Terminate;
end;

end.

Disculpen que ponga todo el código, pero armar un zip con un solo pas y para que sólo contenga esto... me parece un desperdicio de recurso.:cool:

Las funciones sirven... pero me empezó a gustar la alternativa de Ian... es más, me justificaba dicendo: "Se entiene mejor FrmProveedores.Mostrar() que tener Mostrar(FrmProveedores,True,0,0).
Entonces... si puedo declarar tantos metodos de clase como para satisfacer las mismas ( o màs) funciones descriptas en la unidad expuesta anteriormente me evitaría que hacer uso de dicha unidad. ¡Ya quedraría todo encapsulado en la clase!

Como alternativa (me gusta buscar opciones, no es que quiera complicarme la vida)... e inspirandome en parte por Ian se me estaba ocurriendo diseñar un componente no visual que encapsule varias funciones e intercepte posibles mensajes que se le dirijan a la forma que lo contiene y realize las modificaciones y/o operaciones necesarias... pero claro... estaría reinventando el TApplicartionEvents ¿o me equivoco?

Bueno, despuès de tanto lío... espero que alguien me haya entendido... sino bueno... seguiré viendo a ver si se me ocurre algo, me siento bajo un manzano y espero a ver si una manzana me ayuda a darle explicaciòn... jaja.

Escucho alternativas... y si alguien ha logrado captar mi idea... y logra explicarme un poco del tema se lo agradecería.

Muchas gracias a todos que hayan dedicado tiempo en leer este hilo.
Saludos,

Delphius 11-12-2006 05:16:42

Bueno... la verdad es que por ahora... me estoy inclinando en usar y mejorar mi unidad. Sigo tratando de entender eso del metodo de clase y TVentana.... ya veré si encuentro la luz a todo este asunto.

Saludos,

PD: Disculpen que en el post anterior haya soltado semejante texto... quería tratar de exponer con claridad mi idea y lo que podía llegar a entender.

AzidRain 11-12-2006 06:29:08

No se si no entendí bien o me parece que estamos reinventando la rueda...

El que una ventana sea o no modal no radica en alguna de sus propiedades, es decir no es que haya ventanas que son modales o no modales "per se" . Mas bien se trata de un comportamiento de la ventana al momento de mostrarse. De ahi que una ventana puede mostrarse en forma modal con ShowModal o amodal con Show.

Asi tenemos que quien decidirá si una ventana se muestra o no en forma modal eres tu mismo y esto solo se lo indicas a la ventana.

Delphius 11-12-2006 06:52:40

Cita:

Empezado por AzidRain
No se si no entendí bien o me parece que estamos reinventando la rueda...

El que una ventana sea o no modal no radica en alguna de sus propiedades, es decir no es que haya ventanas que son modales o no modales "per se" . Mas bien se trata de un comportamiento de la ventana al momento de mostrarse. De ahi que una ventana puede mostrarse en forma modal con ShowModal o amodal con Show.

Asi tenemos que quien decidirá si una ventana se muestra o no en forma modal eres tu mismo y esto solo se lo indicas a la ventana.

Gracias por responder AzidRain. Tengo bien en claro que no radica en propiedades... y que es a gusto de uno como se visualiza. No me expliqué bien...

Lo que pretendo es implementar es funciones, procedimientos que brinden mayor funcionalidad y manejo para el tratamiento de ventanas tanto ya sea como modales o no. Por ejemplo: Si tienes varias ventanas... digamos unas 50 entre modales y no modales lo más natural es que busques implementar código reutilizable para ver como se muestran... que debe realizar.. etc... etc... lo que ofrece Ian en su ejemplo es un método de clase que crea ventanas y guarda ciertos valores (en Tag) para que luego... por poner un ejemplo: dependiendo de lo que almacene hablitar controles. Es una tarea comùn... y muy habitual. Ian, a mi entender, propone que estos métodos genéricos (para ambos usos) queden encapsulados en la clase... y evitarias tener que emplear unidades extras para lograr lo que bastaría ahora con un:

Ventana.HazAlgo(bla, bla)...



Mi intención es ampliar las ideas de Ian... y darle mayor métodos de clase y facilitarme el uso de varias unidades. Métodos genéricos... después... una vez ya declarados... es cuestión de usarlos cuando sean necesarios y los necearios para un aplicativo en particular.

Mi problema es que Ian no termina de explicar, a mi entender, donde... y cómo implementar sus ejemplos. Se que un método de clase es:

Código Delphi [-]
class Function LaClase.NombreFuncion(parámetros): TipoResultado

Me marea el hecho es que que el pone: TVentanaModal.Mostrar y en ninguna parte me dice si TVenatanaModal es que... derivado de TForm... ¿Y si declaro la clase.... como la instancio? si.. con create pero ... y que además se "vea la forma" y pueda incorporarle botones... grids... en sintesis controles... es mi dilema...

A ver si ahora si se me entiende mejor...
Saludos,

AzidRain 11-12-2006 08:51:04

Lo que anotas en tu código me suena como a un gestor de ventanas, pero mre resulta ocioso porque la propia ventana ya contiene código para hacer todo lo que mencionas.. Por otro lado creo que bastaría con extender la clase TForm e ir añadiendo la funcionalidad que requieras según el tipo de ventana o según lo que quieras hacer con cada ventana.

Seria de mas ayuda que empezaras por un diagrama estático UML para modelar lo que quieres hacer antes de empezar con código, te clarificaría mas el concepto ya que estamos hablando de cosas abstractas...

Lepe 11-12-2006 17:19:34

Yo lo de usar el .Tag me horroriza.

Cuando usé el .Tag en 3 componentes de un mismo form tenía un cacao mental que ni te cuento. Que si el tag se guardaba esto, en aquel componente significa lo otro...

Si tienes un Form y quieres guardar el estado de la ventana, por poner un ejemplo, aplico el archiconocido KISS (Keep It Simple Stupid ;))

Código Delphi [-]
type TEstado = (eModal, eNormal);

TForm1 = class(Tform);

public
   property Estado:TEstado read Festado write FEstado;
end;
Ni constantes, ni tags, ni números. Queda claro nada más ver el código, solo hay dos posibilidades "Estado Normal" y "Estado Modal"

Las funciones de clase no las uso mucho, ya que de hecho, cuando se ejecutan aún no existe el objeto en memoria (no se ha creado aún), así que hay que tener cuidado al usarlo.

La herencia visual desde cero. Creas una ventana llamada BaseForm: (file -> New -> Form)
Código Delphi [-]
{-----------------------------------------------------------------------------
 Unit Name: BaseForm
 Purpose:
    - Heredan de TBaseForm todas las ventanas con IDentificador de cada tabla.
    - No usan las variables globales de cada Form.

 History:
-----------------------------------------------------------------------------}

unit UBaseForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TBaseForm = class(TForm)
  protected
    function GetId:integer; virtual; abstract; 
    procedure SetId(const Value: integer);virtual; abstract;
  public
    { public declarations }
    property Id:integer read GetId write SetId;
  end;

implementation

{$R *.dfm}

end.
Ahora como bien dices, vas a File -> new -> other -> forms -> heredar de (tbaseForm)

La nueva ventana aparece así:
Código Delphi [-]

type
  TfrmCliente = class(TBaseForm)

    function GetId: integer; override;
    procedure SetId(const Value: integer);override;
  public
      { Public declarations }
    property Id;
  end;

Solo queda implementar los métodos en la ventana que toque:
Código Delphi [-]
procedure TfrmCliente.SetId(const Value: integer);
begin
  dscliente.Locate('IDCLIENTE',Value,[]);
end;

function TfrmCliente.Getid: integer;
begin
    Result:= dsclienteIDCLIENTE.AsInteger;
end;

Si tienes 10 ventanas (clientes, proveedores, factura, albaran, productos, ...)
todas heredan de TBaseForm, por tanto ya tiene su propiedad Id.

A lo que voy, crear cualquier ventana e ir a un registro, se simplifica:
Código Delphi [-]
var Forma :TBaseForm
begin
  Forma := TFrmcliente / TFrmFactura / TfrmProductos .Create(Self);
  Forma.ID := 32 // el cliente 32, la factura 32, el producto 32, etc.
  Forma.Show;
end;

Da igual si usas ADO, BDE, MDOLIB, etc

La Forma Base puede tener controles en su interior, pero eso si, no podrás quitarlos en una ventana heredada, por tanto, hay que pensar bien qué llevará un TBaseForm, por ejemplo un Toolbar y el botón "Buscar", el resto de botones del toolbar se pueden añadir después a TfrmCliente.

Saludos

Lepe 11-12-2006 19:17:42

Reholas.

Estuve pensando casi 1 hora como responder el mensaje anterior, sin mucho éxito, verás:

El problema que intentan solucionar todas las rutinas es encontrar si la ventana está creada o no y después interactuar con ellas. Usando otra filosofía nos quitamos ese problema de encima:

Código Delphi [-]
procedure TForm1.FormClose(... Action:TCloseAction);
begin
  Action := cafree;
  Form1 := nil
end;
Ya no tenemos que buscar en todas las ventanas de TScreen para saber si está creada o no, basta con:
Código Delphi [-]
if Assigned(Form1) then // equivale a if Form1 <> nil then
  // está creada
else
  // no lo está
end;

DestruirForma se consigue accediendo a Form1.Close

ExpandirForma se puede sustituir por el método SetBounds del TForm, que ya permite modificar sus cuatro propiedades top, left, width, height y es una sola llamada. Sí le vería sentido a ExpandirForma si al agrandar el ancho no cupieses en pantalla y entonces modificara su Left para que tuviese el ancho especificado por parámetro.

Las rutinas MinimizarAplicacion y FinalizarAplicacion son más del tipo "Sistema GH" de Al González, en ese aspecto no entro, ya que le tengo bastante respeto a Al, y a sus conocimientos ;); yo al menos no usaría un procedimiento que solo tenga una línea de código.

Si ya estan diseñadas las funciones y las estas utilizando, no cambies el código, pero no te aconsejaría que creases mil y una función, (mira sistema GH antes ;))

Saludos

Delphius 12-12-2006 05:55:12

Gracias Lepe
 
Lepe gracias por responder... la verdad es que a tu código lo voy entiendo y tiene sentido. Eso si, hay algo que no me cierra:

Cita:

Empezado por Lepe
La herencia visual desde cero. Creas una ventana llamada BaseForm: (file -> New -> Form)
(....)
Ahora como bien dices, vas a File -> new -> other -> forms -> heredar de (tbaseForm)

Entiendo como se hace la herencia visual... pero, a mi entender, en esta forma de crear la ventana BaseForm al momento de "guardarla" lo hace dentro de un proyecto específico (puede que esté equivocado) por poner un ejemplo: Project1.dpr
Por tanto... cuando uno realiza File -> New -> other -> forms toma las formas presentes en el proyecto... en este caso Project1.dpr:confused:

Mi intenciòn es tener una clase genérica, y no que quede guardada en un proyecto en particular.

Si me puedes aclarar esa duda... a lo mejor pueda apreciar mejor las alternativas.

El código que había puesto en un anterior post era como una práctica... en los primeros días en que me senté frente a Delphi. Si es cierto que tiene funciones que son inútiles mantenerlas:D:p Ahora lo se... le saqué el polvo al disco duro... y apareció. La verdad es que la usaba cuando hacia mis prácticas para la facu y aplicaciones chicas.

Lo que pasa es que ando viendo como mejorar esto del tratamiento de ventanas para que se me facilite la vida:D:rolleyes:.... tengo que empezar a meter código para mi tesis... y después de unos análisis me di cuenta de que va tener bastantes pantallas:o... y tener una libreria como esa... por dios.... ¡necesito algo mejor!:eek:

Gydba 12-12-2006 12:59:55

Buenas y santas,

Pare ser completamente honesto no entendí del todo cuál es el hilo de la cuestión. Si ahora hablamos de crear clases pues bueno, tranquilamente podrías en una unit definir una clase heredada de un TCustomForm o TForm con las propiedades, métodos y funciones que quieras. Luego al añadir un formulario nuevo no hace falta hacer mucho más que añadir la unit de tu TCustomFormX generado a las uses y reemplazar la definición TForm por TCustomFormX. Evidentemente olvidate de que en el diseñador de objetos dentro del Delphi veas tus nuevas definiciones, pero de ésta manera no necesitás añadirla al IDE, sino en donde lo vayas a utilizar como un unit más. (mepa que hasta yo me perdí, sino se entendió me avisan :))

Código Delphi [-]
type TCustomFormX = class(TForm)
private
   strPropiedad1 : String;
   ...
   strPropiedadN : String;
published
   property Propiedad1 : String read strPropiedad1 write strPropiedad1;
   ...
   property PropiedadN : String read strPropiedad1 write strPropiedadN;
end;
No hay ciencia en eso, aunque si tienes rutinas para instanciar tus ventanas y heredás aun más tu clase TCustomFormX podrías crear rutinas del tipo:
Código Delphi [-]
type TFrmTest = class(TCustomFormX)
   ...
end;
...

var
   varFormX  : TFrmTest;
   varClassX : TFormClass;
begin
   varClassX := TFormClass(FindClass(NombreClase));
   varFormX  := (varClassX.Create(MainForm/Application) as TFrmTest);
   with varFormX do begin
      Propiedad1    := 1;
      ...
      PropiedadN    := N;
      Show/ShowModal;
   end;
end;


Ya también si deseas puedes realizar procesos sobre todas las ventanas que tengas abiertas recorriendo el objeto Screen.Forms y consultando por el tipo de clase podrías filtrar ciertos valores.

Si dije cualquier bolazo solo háganmelo saber porque como dije no entendí bien que es lo que se busca.

PD: Existía unos componentes que bien no recuerdo el nombre (APE, MDIModal o algo así) que permitían un manejo muy precioso de las ventanas modales. Buscar en torry puesto que no recuerdo.

Lepe 12-12-2006 14:44:56

Te respondo con otra pregunta: La unidad Sysutils.pas ¿a qué proyecto corresponde? No me salgas con que es una unidad inherente a Delphi... tú puedes hacer lo mismo ¿no?

Aunque un Form normalmente está dentro de un proyecto, se puede tener en una carpeta llamada "Forms utiles" convenientemente añadida al library Path de delphi. Puedes usar ese Form en varios proyectos simultáneamente.

Normalmente "todo lo que inventamos" ya ha sido pensado por alguien y tiene una versión mejor :D, por eso he aprendido a no complicarme la vida. Los requerimientos que tienes hoy, sin duda, variarán mañana; como no somos genios tendremos que modificar las cosas una y otra vez.

Ahora estas pensando en formularios de una sola instancia, usando la variable global que propone delphi (FrmClientes, FrmFacturas); debido a que continuamente estamos aprendiendo, mañana necesitarás varias instancias de una misma ventana y no podrás usar esas variables, por tanto todas las rutinas que tienes hechas no sirven, tendrás que modificarlas :(

Posiblemente haya una forma de trabajar para lo que pides (que conceptualmente se me escape), al menos para ventanas modales yo no sé como tratarlas de forma genérica, ya que además de cerrarse y obtener el típico mrOk/mrCancel necesitamos información adicional y para ello necesitamos acceder a la propia ventana o incluir algún evento personalizado.

Saludos

Delphius 12-12-2006 16:18:33

Muchas Gracias
 
Gydba y Lepe muchas gracias por tratar de entenderme:rolleyes::D

Cita:

Empezado por Lepe
Aunque un Form normalmente está dentro de un proyecto, se puede tener en una carpeta llamada "Forms utiles" convenientemente añadida al library Path de delphi. Puedes usar ese Form en varios proyectos simultáneamente.

Pues,... sin comentarios.... se me paso ese detalle:p... hay que ·$%& que soy. La verdad es que no la pensé así.

Cita:

Empezado por Lepe
Posiblemente haya una forma de trabajar para lo que pides (que conceptualmente se me escape), al menos para ventanas modales yo no sé como tratarlas de forma genérica, ya que además de cerrarse y obtener el típico mrOk/mrCancel necesitamos información adicional y para ello necesitamos acceder a la propia ventana o incluir algún evento personalizado.

Es verdad que en ocasiones para determinar el "comportamiento" de una ventana se va a requerir mayor información... alguna variable global o propia de la unidad...
Mi misión es tener métodos genéricos. Esas cosas ya para mi son particularidades de cada aplicativo. Ya veré como darle la "especialidad".

Cita:

Empezado por Gydba
Pare ser completamente honesto no entendí del todo cuál es el hilo de la cuestión

El hilo de la cuestión era (o es:D) tener definido métodos, funciones, o procedimientos genéricos (y en lo posible reutilizable) que trabajan sobre formas modales y no modales. El dilema es: ¿Cómo hacerlo? ¿Cuales son las alternativas?

Lo que pasa es que preferiría escuchar alternativas antes que cerrarme por una sola opción.

Cita:

Empezado por Lepe
por eso he aprendido a no complicarme la vida

Yo me la complico... es para mi una fuente de inspiración y autosuperación. Pero bueno... gustos... Y además, me permite aprender más.

Cita:

Empezado por Lepe
Normalmente "todo lo que inventamos" ya ha sido pensado por alguien y tiene una versión mejor :D

Si.... me vivió pasando. Recuerdo bien mi primer caso (este me motivó estudiar informática): Yo tengo una pequeña obseción por la historia bélica antigua... y tengo cierto gusto en particular por la cultura egipcia. Siendo pequeño, mientras jugaba al AOE I, con los egipcios... me salió la idea de hacer un juego de estrategia que sólo tratase la vida egipcia... como no sabía programar mi idea estaba en mi mente... o al menos eso creía. A unos cuantos días prendo la tele y allí estaba: mi idea.... en vivo y directo. Nivel X, un programa de juegos, estaba mostrando lo que yo me había imaginado... Pero bueno.

Saludos,

Gydba 12-12-2006 16:57:38

Quizás es demasiado general lo que dices, puesto que hay que ver que tipo de rutinas buscas. Cuanto más te metas en lo que son las ventanas modales te darás cuenta que en última instancia tienen serias limitaciones puesto que el propio SO se encarga de todo en último plano. Con limitaciones me refiero al hecho de desarrollar rutinas para controlar el comportamiento tanto de éstas como de las ventanas no modales.

Para terminar te puedo sugerir que te fijes en éstos componentes que desarrollaron para entornos MDI, quizás te nutran más de cualquier cosa que pueda decir:
http://www.torry.net/quicksearchd.ph...ngine&Title=No

OFF TOPIC:
En mi opinión está bárbaro que uno invierta cierto tiempo en aprender cosas que generalmente parecen ordinarias o una perdida de tiempo. Por lo menos a mi la satisfacción de pasarme una semana viendo como las VCL dibujan un botón, una grilla o un label para luego generar nuevos componentes me gratifica más que cualquier paga por trabajo. Así que ánimos!

OFF TOPIC ^ 2:
No estarás hablando del juego "Faraón" de Sierra, verdad?

Lepe 12-12-2006 18:40:45

Cita:

Empezado por Gydba
En mi opinión está bárbaro que uno invierta cierto tiempo en aprender cosas que generalmente parecen ordinarias o una perdida de tiempo. Por lo menos a mi la satisfacción de pasarme una semana viendo como las VCL dibujan un botón, una grilla o un label para luego generar nuevos componentes me gratifica más que cualquier paga por trabajo. Así que ánimos!

Estoy totalmente de acuerdo, de hecho la VCL contiene no pocos trucos, cada vez que se mira se aprende algo nuevo.

Yo también dispongo de "esas funciones" en mis archivos, no creo que vuelva a usarlas pero, lo que aprendí diseñándolas y buscándoles errores, eso, eso nadie me lo quita ;).

Que conste que alguna de esas funciones si las he usado posteriormente, de hecho, recuerdo antes mis propias funciones que las homónimas de delphi (funciones que no encontraba en la ayuda y que yo mismo creé).

Saludos

Delphius 13-12-2006 05:10:25

Cita:

Empezado por Gydba
No estarás hablando del juego "Faraón" de Sierra, verdad?

Pues, si.... por algo no queria nombrarlo.... con sólo acordarme el nombre me da rabia:D

Me voy a poner a ver el componente que hay en el enlace.
Gracias

Saludos,


La franja horaria es GMT +2. Ahora son las 13:24:03.

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