¿Cómo se crea un componente?
Volver al índice

boton.gif - .325 K¿Qué son componentes? La librería visual de componentes (VCL).

Los componentes son las piedra angular de la programación en Delphi. Aunque la mayoría de los componentes representan partes visibles de la interfaz de usuario, existen también componentes no visuales, como por el ejemplo los objetos Timer y Database.

Un componente, en su definición más simple no es más que un objeto descendiente del tipo TComponent. Todos los componentes descienden en su forma más primitiva de TComponent, ya que TComponent proporciona las características básicas que todo componente debe tener: capacidad de ser mostrado en la paleta de componentes así como de operar a nivel de diseño de formulario.

Los componentes hacen fácil la programación en Delphi. En vez de tener que operar a nivel de unidades, el usuario de un componente simplemente tiene que pinchar en él y situarlo en la posición deseada de su form. Eso es todo: Delphi se encarga de lo demás.

Todos los componentes forman parte de la jerarquía de objetos denominada Visual Component Library (VCL). Cuando se crea un nuevo componente, este se deriva a partir de un componente existente (bien sea TComponent o algún otro más especializado) y se añade a la VCL.


boton.gif - .325 KAnatomía de un componente. Propiedades, métodos y eventos.

Como ya se ha mencionado un componente es un objeto, y como tal, consta de código y datos. Pero al referirnos a estos no utilizaremos estos terminos, sino que hablaremos de propiedades y métodos, así como de eventos. A lo largo de este curso iremos estudiando en profundidad todos estos aspectos, pero hagamos ahora una primera aproximación:


boton.gif - .325 KControl de acceso a un componente. Declaraciones privadas, protegidas, públicas y publicadas.

Object Pacal dispone de cuatro niveles de control de acceso para los campos, propiedades y métodos de un componente. Este control de acceso permite especificar al programador de componentes que parte de código puede acceder a que partes del objeto. De este modo se define el interface del componente. Es importante planear bien este interface, ya que así nuestros componentes serán facilmente programables y reutilizables.

A menos que se especifique lo contrario, los campos, propiedades y métodos que se añaden a un objeto son de tipo publicados (published). Todos los niveles de control de acceso operan a nivel de unidades, es decir, si una parte de un objeto es accesible (o inaccesible) en una parte de una unidad, es también accesible (o inaccesible) en cualquier otra parte de la unidad.

A continuación se detallan los tipos de controles de acceso:
botonr.gif - .326 KPrivado: ocultando los detalles de implementación.

Declarando una parte de un componente (bien sea un campo, propiedad o método) privado (private) provoca que esa parte del objeto sea invisible al código externo a la unidad en la cuál se declara el objeto. Dentro de la unidad que contiene la declaración, el código puede acceder a esa parte del objeto como si fuera público.

La principal utilidad de las declaraciones privadas es que permiten ocultar los detalles de implementación del componente al usuario final del mismo, ya que estos no pueden acceder a la parte privada de un objeto. De este modo se puede cambiar la implementación interna del objeto sin afectar al código que haya escrito el usuario.

boton.gif - .325 KProtegido: definiendo el interface del programador.

Declarar una parte de un componente como protegido (protected) provoca, al igual que ocurría al declararlo privado, que el código externo a la unidad no pueda acceder a dicha parte (se hace oculta al código externo a la unidad). La diferencia principal entre declarar una parte de un objeto protegida o hacerla privada es que los descendientes del componente podrán hacer referencia a esa parte.

Este comportamiento es especialmente útil para la cración de componentes que vayan a descender de aquel que hemos creado.

boton.gif - .325 KPúblico: definiendo el interface en tiempo de ejecución.

Todo las partes de un objeto que declaremos públicas (public) podrán ser referenciadas por cualquier código ya sea interno o externo a la propia unidad. En este sentido, la parte pública identifica el interface en tiempo de ejecución de nuestro componente. Los métodos que el usuario del componente debe llamar deben ser declarados publicos, así como también las propiedades de sólo lectura, al ser sólo válidas en tiempo de ejecución.

Las propiedades declaradas públicas no aparecerán en el inspector de objetos.

Esta sección es tal vez la más importante a considerar al diseñar un componente. Cuando se diseñan componentes, se debe considerar cuidadosamente que métodos y propiedades deben ser públicas. Si el diseño es correcto, este permitira retocar las estructuras de datos y métodos internos del componente sin tener que tocar el interface público, que seguirá siendo el mismo para el usuario del componente.

boton.gif - .325 KPublicado: definiendo el interface en tiempo de diseño.

Al declarar parte de un objeto publicado (published) provoca que la parte sea pública y además genera información en tiempo de ejecución para dicha parte.

Las propiedades declaradas publicadas aparecen en el inspector de objetos en tiempo de diseño. Y ya que sólo las partes publicadas aparecen en el inspector de objetos, estas partes definen el interface en tiempo de diseño de nuestro componente. En general sólo se deben declarar publicadas propiedades y no funciones o procedimientos (ya que lo único que logramos con ello es declararlas públicas).

boton.gif - .325 KPasos necesarios para crear un componente. El experto de componentes.

A grandes rasgos, los pasos necesarios para crear un nuevo componente son los siguientes:
  1. Crear una unidad para el nuevo componente.
  2. Derivar el nuevo componente a partir de otro existente, el cuál servirá de base para añadir las nuevas características deseadas.
  3. Añadir las propiedades, eventos y métodos necesarios al nuevo componente.
  4. Registrar el componente, incluyendo los bitmaps adicionales, ficheros de ayuda, etc.
  5. Instalar el nuevo componente en la paleta de componentes.

De todos los pasos citados, hay uno que es especialmente importente: la elección del ascendiente a partir del cuál derivar el nuevo componente. Este paso es crucial, ya que una buena elección del ascendiente puede hacernos la tarea de añadir nuevas propiedades y métodos realmente fácil, mientras que una mala elección puede hacernos imposible llegar al objetivo propuesto.

Como base para la elección del ascendiente, conviene hacer notar las siguientes normas:

Bien, ya sabemos como determinar el punto de partida. Veamos ahora como crear la unidad que albergará el componente. Hay dos opciones, crear la unidad manualmente o dejar que Delphi haga el trabajo "sucio" utilizando el experto de componentes. Si optamos por la primera solución, basta con hacer clic en new unit y ponernos manos a la obra, pero de este modo tendremos que hacer todo a mano: derivar el nuevo componente, registrarlo, etc. Por ello es más recomendable la segunda opción: utilizar el experto de componentes.

Para abrir el experto de componentes basta con elegir File|New Component.

Nos aparecerá un cuadro de diálogo en el que debemos cumplimentar los siguientes campos:

Una vez introducidos estos campos, al pulsar sobre OK se nos desplegará el código de nuestra unidad. Si por ejemplo hemos introducido los siguientes datos en el experto de componentes:

Class Name: TMiComponente
Ancestor Type: TComponent
Palette Page: Curso

Al hacer clic en aceptar, Delphi nos generaría la siguiente unidad, lista para introducir las propiedades y métodos de nuestro componente:


unit Unit1;



interface



uses

  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

  Forms, Dialogs;



type

  TMiComponente = class(TComponent)

  private

    { Private declarations }

  protected

    { Protected declarations }

  public

    { Public declarations }

  published

    { Published declarations }

  end;



procedure Register;



implementation



procedure Register;

begin

  RegisterComponents('Curso', [TMiComponente]);

end;



end.

 

A partir de aquí todo consiste en introducir las propiedades y métodos necesarios para el funcionamiento de nuestro componente. Pero antes de nada conviene hacer notar algunos aspectos:

En la clausula uses, Delphi añade por defecto las unidades estandard. Si nuestro componente no usa alguna de ellas podemos eliminarla de dicha clausula. Del mismo modo, si utilizamos algún procedimiento o función situado en otra unidad, debemos añadir dicha unidad a la clausula uses. Vamos, como siempre ¿no? ;)

Las declaraciones de las propiedades, campos y métodos que vayamos definiendo, las situaremos en la sección apropiada de interfaz según corresponda, es decir las declararemos privadas, protegidas, pública o publicadas.

Delphi declara y define automaticamente el procedimiento register para registrar el componente en la paleta.