Ahora es cuando vamos a empezar a personalizar nuestro componente. Lo primero que tenemos que hacer es definir las propiedades que el usuario podrá manipular. Como antes hemos visto, nos valdrá con definir un valor a convertir, un valor convertido y los tipos de monedas de ambos valores.
Estos tipos de moneda tendrán que ser un valor concreto dentro de un conjunto de valores soportados, así que nos aprovechamos del tipo de dato enumerado de Pascal. Declararemos el tipo de dato TTipoMoneda, que define todas las monedas soportadas.
TTipoMonedas = (tmEuro, tmDolar, tmYen, tmPeseta);
Una vez que tenemos esto, podemos definir los atributos que almacenarán estos valores dentro del componente. A continuación mostramos sólo la definición del componente:
TConversorMonedas = class(TComponent)
private
FValorConvertir: float;
FValorConvertido: float;
FMonedaConvertir: TTipoMoneda;
FMonedaConvertido: TTipoMoneda;
end;
El componente ya es capaz de almacenar unos valores, aunque como lo hemos definido dentro de la sección private, nadie podrá modificar ni consultar estos valores. Para ello debemos definir unas propiedades, dentro de la sección published, para poder ser modificadas desde el entorno de Delphi.
La sección published contiene todas aquellas propiedades y eventos que serán mostrados en el Inspector de Objetos de Delphi. Además, se puede acceder a ellos tal y como si fuesen públicos:
TConversorMonedas = class(TComponent)
private
FValorConvertir: float;
FValorConvertido: float;
FMonedaConvertir: TTipoMoneda;
FMonedaConvertido: TTipoMoneda;
published
property ValorConvertir: float
read FValorConvertir
write FValorConvertir;
property ValorConvertido: float
read FValorConvertido;
property MonedaConvertir: TTipoMoneda
read FMonedaConvertir
write FMonedaConvertir;
property MonedaConvertido: TTipoMoneda
read FMonedaConvertido
write FMonedaConvertido;
end;
Vamos a fijarnos en las líneas dentro de la sección published. Se trata de definiciones de propiedades, utilizando la palabra reservada property. Con esto definimos una serie de datos que serán leídos y escritos de forma indirecta. En nuestro caso, decimos que cada vez que se lea el valor de la propiedad ValorConvertir, se accederá al atributo privado FValorConvertir, y cada vez que se escriba, se almacenará en dicho atributo. Lo mismo ocurre con las propiedades MonedaConvertir y MonedaConvertido. Sin embargo, la propiedad ValorConvertido tiene algo especial: si prestamos un poco de atención a su declaración, veremos que tienen una cláusula read pero no tiene la correspondiente cláusula write. Esto es debido a que sobre esta propiedad se puede leer pero no se puede escribir, es decir: que es de solo lectura.
Si compilamos y volvemos a instalar el componente, podremos ver cómo las nuevas propiedades aparecerán en el Inspector de objetos. Además, en las propiedades de tipo TTipoMoneda, solo se podrá seleccionar entre aquellos valores que permite el tipo enumerado.
Por cierto, si alguno de vosotros no puede ver la propiedad ValorConvertido, que no cunda el pánico. El Inspector de objetos de Delphi, por defecto no muestra las propiedades de sólo lectura. Si utilizáis la versión 6 (o posterior), basta con acceder a la opción Tools - Environment Options - Object Inspector, y marcar la opción Show read only properties. En las versiones anteriores no podremos ver este tipo de propiedades.
Y por último, lo que tenemos que hacer es asegurarnos de que los atributos tienen los valores adecuados. Esta operación vamos a hacerla a través de un método público, llamado Convertir, desde el que se harán todos los cálculos necesarios para hacer la conversión de ValorConvertir a ValorConvertido.
La definición del método es la siguiente:
public
procedure Convertir;
Nos debemos asegurar de que, cada vez que se cambie el valor origen (ValorConvertir), se cambie el valor destino (ValorConvertido), así como al cambiar los tipos de divisa.
Esto lo podemos hacer asignando métodos a las operaciones de escritura de las propiedades. De este modo, conseguimos ejecutar un código cada vez que alguien intente almacenar un valor en una propiedad. Para ello, debemos cambiar la definición de las propiedades y añadir los tres métodos que vemos a continuación:
protected
procedure SetValorConvertir(value: float);
procedure SetMonedaConvertir(value: TTipoMoneda);
procedure SetMonedaConvertido(value: TTipoMoneda);
published
property ValorConvertir: float
read FValorConvertir
write SetValorConvertir;
property ValorConvertido: float
read FValorConvertido;
property MonedaConvertir: TTipoMoneda
read FMonedaConvertir
write SetMonedaConvertir;
property MonedaConvertido: TTipoMoneda
read FMonedaConvertido
write SetMonedaConvertido;
Y en la codificación de los métodos "Set" lo que debemos hacer es volver a hacer la conversión cada vez que se modifique algo, como vemos a continuación:
procedure TConversorMonedas.SetValorConvertir(value: float);
begin
if value <> FValorConvertir then
begin
FValorConvertir = value;
Convertir;
end;
end;
procedure TConversorMonedas.SetMonedaConvertir(value: TTipoMoneda);
begin
if value <> FMonedaConvertir then
begin
FMonedaConvertir = value;
Convertir;
end;
end;
procedure TConversorMonedas.SetMonedaConvertido(value: TTipoMoneda);
begin
if value <> FMonedaConvertido then
begin
FMonedaConvertido = value;
Convertir;
end;
end;
Ahora lo único que nos queda es compilar e instalar de nuevo el componente, y jugar con él. Podremos ver cómo, en el Inspector de objetos, se cambiará el contenido de la propiedad ValorConvertido cada vez que cambiemos alguna de las demás propiedades. En ejecución podremos utilizar el componente igual que cualquier otro, leyendo o escribiendo sobre sus propiedades.