Aula Macedonia


Curso de Programación Visual en Delphi


Artículo realizado por
José Antonio Suárez.





Capítulo 5.
Desarrollo de un componente


En este capítulo vamos a centrarnos en un aspecto muy importante, comercialmente hablando, de la programación en Delphi. Me refiero al desarrollo de componentes.

La creación de componentes para Delphi y para otros muchos lenguajes que permiten añadir funcionalidades extras a sus entornos de programación son un lucrativo negocio dentro del mundo de Internet.

Actualmente, cuando se quiere hacer algo particularmente tedioso, o difícil, o simplemente cuando no se tiene tiempo, lo primero que hace uno es conectarse a Internet y buscar en los servidores de componentes si existe uno que cumpla nuestras necesidades, pudiendo encontrarse con que ya hay hecho exactamente lo que se quiere, o que por "desgracia" tendrá que hacerlo por sí mismo.

Componentes hay de todos los tipos, tamaños y funcionalidades, que van desde simples "apaños" a los componentes que incorpora Delphi, hasta ejemplos magistrales de lo que es programar bien.

En el código que se incluye al final de este capítulo, se encuentra la implementación de un componente, el cual, y a través de los comentarios pertinentes, vamos a ir conociendo poco a poco. Veremos de qué se trata eso de hacernos nuestros propio Objeto (componente) para poder usarlo posteriormente en nuestros programas.

¿Qué hay que hacer?

El componente que he creado a continuación es muy simple.

Supongo que ya conoceréis el TShape que viene con Delphi (paleta Additional), y si no es el caso, es el momento de ejecutar Delphi y probarlo.

Lo que se pretende conseguir es que cuando el cursor entre en una zona determinada del formulario, nuestro programa sea capaz de darse cuenta de que ha entrado y podamos hacer algo en ese momento (y lo mismo cuando salga).

Se puede hacer un apaño de compromiso mediante el evento OnMouseMove del formulario, el cual nos dá la coordenada X e Y del cursor del ratón, pero esto va a provocar que cada vez que mueva el ratón, se ejecute la comprobación de si está en las coordenadas que me interesan, cosa que hay que evitar para no sobrecargar el procesador.

Así que lo que se busca en realidad es una forma de crearnos nuestros propios eventos OnMouseEnter y OnMouseExit o OnRatonEntra y OnRatonSale, como prefiráis, de forma que tan solo se generen estos eventos una vez, y no cada vez que movemos el ratón con la pertinente comprobación de coordenadas.

Para realizar esto tenemos que decirle a Delphi que vamos a "crear" un nuevo evento, que va a ser provocado por el mensaje pertinente del propio Windows, cada vez que entre el ratón (CM_MOUSEENTER), y que salga (CM_MOUSELEAVE).

No pretendo que sea fácil de entender en este punto del tutorial sobre Delphi, ya que no es fácil debido a que maneja muchos conceptos avanzados de Windows, pero con saber someramente de qué va la cosa, es suficiente. Basta con especificar exactamente qué es lo que hay que decirle a Delphi para que nos cree unos nuevos eventos como los que ya tiene por defecto:

procedure CMMouseEnter(var msg:TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var msg: TMessage); message CM_MOUSELEAVE;

Estos 2 procedimientos se van a incluir en nuestro componente que va a ser un "hijo" de TShape.

He elegido TShape porque puede hacerse completamente invisible a nuestros ojos con tan solo poner:

shape.Brush.Style:=bsClear;
shape.Pen.Style:=psClear;

y de esta forma aunque el control esté sobre el formulario, no tendrá ni bordes ni nada, aunque no deje de estar ahí… y si encima hacemos que nos permita saber cuándo entra el ratón en él, y cuándo sale… pues es lo que buscamos.

Una aplicación para nuestro TShape "Plus" es por ejemplo, cambiar un gráfico de la pantalla cuando el cursor esté en un sitio determinado. Este sitio (rectangular) va a ser el que ocupa el control TShape que no se ve pero que sí está.

Imaginemos que tenemos un gráfico en pantalla que queremos que se "encienda" cuando el cursor entre en él, y que se "apague" cuando el cursor salga.

¡Pues usamos nuestro componente y pan comido (o bit devorado)!

Sigamos.

Va a ser necesario conocer al menos lo que es la programación orientada a objetos, ya que lo que vamos a hacer en realidad es hacer una herencia del objeto TShape, añadirle dos procedimientos más y redefinir los métodos de creación y destrucción. Pero no es nada difícil, ya que gracias a Borland, la sintaxis no se parece para nada a la de C.

¡Y por fín, el Código!

Pasemos ya al código y a los comentarios "en línea"

// EL nombre del fichero .pas en el que se guardará el componente será ShapeAvanzado.pas
unit ShapeAvanzado;

interface

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

type

//  Al componente lo llamaremos TShapeAvanzado, hijo de la clase TShape
  TShapeAvanzado = class(TShape)		

  //Ahora se define lo nuevo que se va a incorporar el antiguo TShape

  private
// "private" quiere indicar que lo que se defina en esta parte no va a ser visto desde fuera, es 
// decir, no vamos a poder poner ShapeAvanzado.FOnEnter. Tan solo será "visible" desde
// dentro del propio componente y por los hijos que declaremos sobre él igual que hemos 
// hecho con TShape. Un ejemplo sería:  TShapeMasAvanzado = class (TShapeAvanzado);

// Con lo siguiente decimos que en estas variables vamos a "almacenar" los mensajes 
// que Windows nos envíe cuando el cursor entre y salga.
FOnEnter, FOnExit: TNotifyEvent;

  protected
// "protected" es prácticamente igual que "private", con la excepción de que lo que en esta 
// parte se ponga no será visible para los hijos de nuestro componente. Además, es el lugar
// donde se tienen que declar los manejadores de eventos de los controles (los On…)
    	procedure CMMouseEnter(var msg:TMessage); message CM_MOUSEENTER;
    	procedure CMMouseLeave(var msg:TMessage); message CM_MOUSELEAVE;

  public
// "public" es para la redefinición de los métodos del padre de nuestro componente, o sea que,
// como lo que hacen "Create" y "Destroy" de TShape se nos queda corto, los vamos a 
// modificar. Más concretamente le vamos a añadir al código que tengan, lo que nos hace falta.
// Esto se dice con "override", es decir, que mantenga lo que tenía y que añada (sobrecarge) 
// lo nuevo que le vamos a definir.
    	constructor Create(AOwner:TComponent);override;
    	destructor Destroy;override;

  published
// "published" es lo que vamos a ver desde fuera del componente, o sea, cuando ya lo estemos 
// usando como uno más. Así, cuando ya lo tengamos, en el Inspector de Objetos de Delphi, en
// la pestaña de "Events" aparecerán nuestros 2 nuevos eventos: OnEnter y OnExit.
	property OnEnter: TNotifyEvent read FOnEnter write FOnEnter;
	property OnExit: TNotifyEvent read FOnExit write FOnExit;

  end;

procedure Register;

implementation

procedure Register;
begin
// El componente, cuando se añada a la paleta de Delphi, se hará en una nueva pestaña 
// llamada "Macedonia"
	RegisterComponents('Macedonia', [TShapeAvanzado]);
end;

procedure TShapeAvanzado.CMMouseEnter(var msg:TMessage);
begin
// Lo que hay que hacer cuando se reciba un mensaje de Windows, es almacenarlo en las 
// variables que hemos definido
    	if Assigned(FOnEnter) then
    	FOnEnter(Self);
end;

procedure TShapeAvanzado.CMMouseLeave(var msg: TMessage);
begin
// Lo que hay que hacer cuando se reciba un mensaje de Windows, es almacenarlo en las 
// variables que hemos definido
    	if Assigned(FOnExit) then
     	FOnExit(Self);
end;

constructor TShapeAvanzado.Create(AOwner:TComponent);
begin
	// Heredamos el código del padre…
     	inherited Create(AOwner);
	// … y le añadimos el nuestro
	Brush.Style:=bsClear;
	Pen.Style:=psClear;
end;

destructor TShapeAvanzado.Destroy;
begin
	// La redeclaración del método Destroy podríamos habernosla ahorrado, pero por convención
	// la redeclaramos y la dejamos tal cual… en vistas a en un futuro añadir más funcionalidad a
	// nuestro componente.
	inherited Destroy;
end;

end.

 

El Final

Y por fin nuestro nuevo y flamante componente TShapeAvanzado está listo para ser codificado, guardado, compilado, e instalado en Delphi.

Pero antes, una cosa:

¿Donde se escribe todo esto?

Pues hacemos los siguiente en Delphi 3:

"Menú Component"

"New Component"

Elegimos el "Ancestor Type" (o sea, el TShape)…

… y rellenamos el resto.

Botón "Create Unit"

Y yá estamos en la ventana de edición, así que a rellenar lo que le falta.

 

¡Feliz Programación!… o como dicen lo anglosajones: Happy Codding!





AULA MACEDONIA
a
MACEDONIA Magazine