Creacin de Componentes con Delphi
Fernando Adrin Gmez
Introduccin
Qu es un componente?
Es un objeto con representacin visual que se puede manipular en fase de diseo.
Un componente, en su definicin ms simple no es ms que un objeto descendiente del tipo TComponent. TComponent proporciona las caractersticas bsicas que todo componente debe tener: capacidad de ser mostrado en la paleta de componentes as como de operar a nivel de diseo de formulario Todos los componentes forman parte de la jerarqua 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 algn otro ms especializado) y se aade a la VCL.
2
Pregunta:
Por qu Delphi es mejor que Visual Basic?
3
Jerarqua de Clases
VCL Visual Component Library
4
TObject
Es la clase base de todos los objetos Delphi.Provee: -La posibilidad de crear, mantener y destruir una instancia de un objeto. -Informacin acerca del tipo de clase y la instancia de un determinado objeto. -Soporte para manejo de mensajes Es recomendable usar tobject como clase base cuando se declaran objetos simples que no son componentes. Si no se especifica una clase base cuando se declara un nuevo tipo de objeto, delphi automticamente use tobject como clase base. Tobject no es tcnicamente una clase abstracta, pero generalmente no se crean instancias de esta clase. Metodos:Informacin sobre la clase,create,destroy. Clases Derivadas:Exception,TStream,TPersistent.
TPersistent
-Proporciona una forma de asignar valores a las propiedades -Proporciona la forma de asignar el contenido de un objeto a otro. No se crean instancias de tpersistent. Se usa como clase base cuando se declaran objetos que no son componentes, pero que necesitan tener la capacidad de asignacin de valores a propiedades. Mtodos:assign. Clases Derivadas:TClipboard,TCanvas,TPicture,TComponent
6
TComponent
Es el antecesor comn de todos los componentes delphi. -Proporciona la posibilidad de que un objeto aparezca en la paleta de componentes y pueda ser manipulado en fase de diseo No se crean instancias de tcomponent. Se usa tcomponent como clase base cuando se declaran componentes no visuales que pueden aparecer en la paleta de componentes y pueden ser manipulados en fase de diseo. Mtodos:getchildren,hasparent Propiedades:count,index,name,tag Clases Derivadas:TcommonDialog,TTimer,Tcontrol
7
TControl
Es el tipo de componente abstracto que sirve como base de todos los controles delphi. Un control es un componente visual, que permite al usuario poder ver y manipular el componente en tiempo de ejecucin. Todos los controles tienen propiedades, mtodos y eventos en comn que son especficos del aspecto visual de los controles. Propiedades:color,caption,hint,height,width,left,top,name,parent,text,visi ble,enabled EVENTOS:click,dblclick,drag & drop,mouse Clases Derivadas:TWinControl,TGraphicControl
TGraphicControl
Es un control abstracto que se usa para derivar los controles personalizados no-windows (controles grficos ) Proporciona una propiedad tcanvas ( superficie de dibujo ) y un mtodo paint. -No pueden recibir foco. -No pueden contener otros controles -No necesitan de una ventana -El dibujar un graphic control es mas rpido que un twincontrol ( no necesita HANDLER WINDOW) Clases Derivadas:TLabel,TImage,TSpeedButton
9
TWinControl
Es la clase abstracta base de todos los controles windows. -Pueden recibir el foco cuando la aplicacin esta en ejecucin -Se puede usar el teclado para interactuar con el control -Puede contener otros controles -Tiene un WINDOW HANDLE Eventos: teclado Clases Derivadas:TButtonControl,TCustomEdit,TTreeView,TListView.
10
Ventajas de los componentes
Podemos aprovechar todo el cdigo heredado de la jerarqua de clases Una vez creado podr ser utilizado en cualquier aplicacin No es necesario que sea distribuido conjuntamente con el programa pues el cdigo est incluido en el ejecutable que los utiliza. Se pueden conseguir muchos componentes gratuitos ( por ejemplo en internet )
11
Como crear un componente
Seleccionar el men Component, New component y aparecer un cuadro de dialogo con las siguientes entradas:
Antcesor Type: Se debe seleccionar la clase base ( de la cual se derivara el componente ) Class Name: Nombre de la clase que se va a crear Palette Page: Se selecciona la paleta desde la cual se podr acceder al componente Unit File Name: Es el nombre de la unidad en la cual se desarrollara el cdigo del componente. Search Path: Directorio de Bsqueda Add to Package: Permite agregar el componente a un paquete creado previamente. Automticamente se generara un cdigo asociado al componente y un procedimiento que se encarga de registrarlo.
12
Como instalar un componente
Elegir la opcin Options|Install Components desde el men de Delphi. Pulsar sobre el botn Add para seleccionar la unidad que contiene el cdigo fuente del componente. Una vez seleccionada la unidad, hacer clic sobre OK. Delphi compilar la unidad y reconstruir el archivo COMPLIB.DCL. Si se encuentran errores al compilar, se nos informar de ello. Basta con corregir el error, salvar la unidad y repetir el proceso anterior. Si la compilacin tiene xito, nuestro componente entrar a formar parte de la paleta de componentes.
13
El punto de partida
Criterios para elegir la clase base: TComponent - El punto de partida para los componentes no visuales. TWinControl - El punto de partida si es necesario que el componente disponga de handles. TGraphicControl - Un buen punto de partida para componentes visuales que no sea necesario que dispongan de handles, es decir, que no reciban el foco. Esta clase dispone del mtodo Paint y de Canvas.
14
Componentes
Propiedades Eventos Mtodos
15
Donde declararlas
Private Protected Public Published
16
Private: La caja negra
Declarando una parte de un componente (bien sea un campo, propiedad o mtodo) privado (private) provoca que esa parte del objeto sea invisible al cdigo externo a la unidad en la cul se declara el objeto. Dentro de la unidad que contiene la declaracin, el cdigo puede acceder a esa parte del objeto como si fuera pblico. Permiten ocultar los detalles de implementacin 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 implementacin interna del objeto sin afectar al cdigo que haya escrito el usuario
17
Protected: Interfaz del programador
La diferencia principal entre declarar una parte de un objeto protegida o hacerla privada es que los descendientes del componente podrn hacer referencia a esa parte. Este comportamiento es especialmente til para la cracin de componentes que vayan a descender de aquel que hemos creado.
18
Public: Interfaz en tiempo de ejecucin
Todo las partes de un objeto que declaremos pblicas (public) podrn ser referenciadas por cualquier cdigo ya sea interno o externo a la propia unidad. En este sentido, la parte pblica identifica la interfase en tiempo de ejecucin de nuestro componente. Los mtodos que el usuario del componente debe llamar deben ser declarados pblicos, as como tambin las propiedades de slo lectura, al ser slo vlidas en tiempo de ejecucin. Las propiedades declaradas pblicas no aparecern en el inspector de objetos. Esta seccin es tal vez la ms importante a considerar al disear un componente. Cuando se disean componentes, se debe considerar cuidadosamente que mtodos y propiedades deben ser pblicas. Si el diseo es correcto, este permitira retocar las estructuras de datos y mtodos internos del componente sin tener que tocar la interface pblica, que seguir siendo la misma para el usuario del componente
19
Published: Interfaz en tiempo de diseo
Las propiedades declaradas publicadas aparecen en el inspector de objetos en tiempo de diseo. Y ya que slo las partes publicadas aparecen en el inspector de objetos, estas partes definen la interfase en tiempo de diseo de nuestro componente. En general slo se deben declarar publicadas propiedades y no funciones o procedimientos (ya que lo nico que logramos con ello es declararlas pblicas).
20
Propiedades
Proporcionan al usuario del componente un fcil acceso al mismo Permite al programador del componente "esconder" la estructura de datos subyacente Estn disponibles en tiempo de diseo. Se puede inicializar los valores de las propiedades sin necesidad de escribir una sla lnea de cdigo Permiten la validacin de los datos al mismo tiempo de ser introducidas. As se pueden prevenir errores causados por valores invlidos Nos aseguran que desde el primer momento nuestras propiedades tendrn un valor vlido, evitando el error comn de hacer referencia a una variable que no ha sido convenientemente inicializada.
21
Declaracin de propiedades
Cuando se accede a una propiedad, en realidad se est accediendo a una variable privada del componente, en la que se almacena el valor de la propiedad. Esta variable interna se asocia a la propiedad en la declaracin de sta (por supuesto ambas deben ser del mismo tipo). La declaracin de una propiedad se realiza anteponiendo a su nombre la palabra reservada "Property", y tras el nombre se especifica el tipo al que pertenece. Formato:
Property nombrepropiedad:tipopropiedad read f write g;
22
Tipos de propiedades
SOLO LECTURA : En este caso solo se debe poner la clusula READ en la declaracin. Las propiedades de solo lectura no aparecen en fase de diseo. SOLO ESCRITURA : Es un tipo de propiedad muy poco usado, pero esta permitido por Delphi LECTURA-ESCRITURA: En la declaracin deben figurar tanto la clusula READ como la WRITE
23
Como se utilizan READ y WRITE ?
READ: Luego de la clusula read debe especificarse de donde se leera el valor de la propiedad. Para tal fin se puede especificar una variable del mismo tipo de la propiedad o una funcin que devuelve un valor del mismo tipo y no toma ningn parmetro. El valor obtenido es el que se puede visualizar en fase de diseo para cualquier propiedad. WRITE: Luego de la clusula WRITE debe especificarse hacia donde se escribir el valor modificado de la propiedad. Es posible utilizar variables del mismo tipo de la propiedad o bien un procedimiento que reciba un parmetro del mismo tipo de la propiedad. El uso de un procedimiento puede ser til para tener un mayor control de los valores asignados a la propiedad. 24
Convenciones de nombres
Los tipos que definamos comenzarn con la letra T (de tipo). P.e. Ttipo Los campos que almacenan los valores de propiedades comienzan con la letra F seguida del nombre de la propiedad que almacenan. As el campo Fnombre queda claro que almacena el valor de la propiedad nombre. Los nombres de los mtodos de lectura y escritura de los valores de una propiedad se denominarn mediente el prefijo Get (para lectura) o Set (para escritura) seguidos del nombre de la propiedad. P.e. el mtodo Getnombre
25
Eventos
Un evento no es ms que un procedimiento que se dispara automticamente, o por acciones efectuadas por el usuario (onClick, onMouseMove...), o directamente por el sistema (onPaint, onCalcFields...). Para el programador un evento no es otra cosa que una propiedad, aunque con algunas caractersticas particulares. Al cdigo que se ejecuta cuando se produce un determinado evento se le denomina manejador de eventos (event handler) y normalmente es el propio usuario del componente quin lo escribe Los eventos ms comunes ya forman parte de los propios componentes de Delphi (acciones del ratn, pulsaciones de teclado...), pero es tambin posible definir nuevos eventos.
26
Definicion de eventos
Primero debe declararse la variable que almacenar la direccin del mtodo. Esta variable debe ser del mismo tipo que el evento, y entre todas los tipos de eventos, el ms genrico es TNotifyEvent. En otras palabras, TNotifyEvent, es el manejador que crea el tpico esqueleto donde nosotros vamos a introducir el cdigo. Es el ms sencillo por lo que no proporcionar ms parmetros que el imprescindible (Sender: Tobject). Formato: El nombre de todo evento empieza con On
Property Onevento:Tnotifyevent read fevento write fevento;
27
Disparar eventos
Slo debe dispararse el evento si el programador codific cdigo para l; es decir si est asignado. El componente debe estar activado Al disparar el evento se le pasa el parmetro (Self), lo que cargar correctamente el objeto Sender.
Ej: if assigned(fevento) then fevento(self)
28
Mtodos
Son los procedimientos y/o funciones que forman parte del componente El usuario del componente los utiliza para realizar una determinada accin o para obtener un valor determinado al que no se puede acceder por medio de una propiedad Ya que requieren ejecucin de cdigo, los mtodos slo estn disponibles en tiempo de ejecucin
29
Ejemplos
Tarchivos ( derivado de Tcomponent ) Twincontrol1 ( derivado de Twincontrol ) Tdibujo ( derivado de Tgrapchicontrol )
30
Tarchivos
Propiedad nombrearchivo: admite un nombre de archivo existente, si no existe el archivo tiene un valor predeterminado para indicarlo Evento Onnombreincorrecto: se dispara cuando se trata de ingresar el nombre de un archivo que no existe en la propiedad nombrearchivo Propiedades Directorio_Windows y Directorio_Sistema: son de solo lectura. Indican el directorio de windows y el del sistema
31
Tarchivos
property nombrearchivo:string read fnombre write ponernombre; property OnNombreIncorrecto : TNombreIncorrecto read Fni write Fni; property Directorio_Windows:string read obtenerwindir; property Directorio_Sistema:string read obtenersysdir;
32
Propiedad nombrearchivo
procedure tarchivos.ponernombre(n:string); begin if existe(n) then fnombre:=n else begin fnombre:='nono'; if assigned(fni) then fni(self,n); end; end;
33
Evento Onnombreicorrecto
type TNombreIncorrecto=procedure(Sender: TObject; nombre:string) of object;
Tarchivos = class(TComponent).............. Fni : TNombreIncorrecto;
34
Propiedad directorio_windows
function tarchivos.obtenerwindir:string; {devuelve el directorio de windows} var nombre:pchar; begin getmem(nombre,250); getwindowsdirectory(nombre,MAX_PATH); obtenerwindir:=string(nombre); freemem(nombre,250); end;
35
Twincontrol1
El nuevo control va a contener un richedit y un botn que se crean dinmicamente y forman parte del nuevo componente. Propiedad Titulo_boton: permite asignarle un texto al boton Propiedades Largo_boton y Alto_boton : Permiten asignar largo y alto del botn Se hacen visibles muchas otras propiedades heredadas.
36
Twincontrol1
public constructor create(aowner:tcomponent);override; destructor destroy;override; published property Visible;.......................... property Titulo_boton:string read va write ponervalor; property Largo_boton:integer read largo write ponerlargo; property Alto_boton:integer read alto write poneralto;
37
Constructor
constructor twincontrol1.create(aowner:tcomponent); begin inherited create(aowner); a:=trichedit.create(self); a.parent:=self as twincontrol; a.top:=30; a.left:=30; c:=tbitbtn.create(self); c.parent:=self as twincontrol; c.top:=10; c.left:=10; largo:=c.width; alto:=c.height; End;
38
Destructor
destructor twincontrol1.destroy; begin a.destroy; c.destroy; inherited destroy;
end;
39
Propiedades
procedure twincontrol1.ponerlargo(b:integer); begin c.width:=b;{cambio en el aspecto} largo:=b;{cambio en el valor de la propiedad} end;
procedure twincontrol1.poneralto(b:integer); begin c.height:=b; alto:=b; end;
40
Tgraphiccontrol1
Es solo una superficie rectangular que se pinta de un color determinado Propiedad Color: permite elegir el color del que se pinta la superficie Propiedad MenuAsociado: permite asignar un men popup al componente. Se abre el men al apretar el botn izquierdo del mouse Adems al hacer doble click sobre el componente se abre un cuadro de dialogo que permite elegir el color de fondo
41
Tgraphiccontrol1
protected procedure paint;override; public constructor create(aowner:tcomponent);override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override; procedure dblclick;override; published property Color:tcolor read fcolor write ponercolor; property MenuAsociado:tpopupmenu read fmenuasociado write ponermenu;
42
El metodo paint
Se dispara cada vez que es necesario dibujar el control.
procedure dibujo.paint; var x,y:integer; begin for x:=self.left -left to self.width do begin for y:=self.top-top to self.height do begin canvas.pixels[x,y]:=fcolor; end;end;end;
43
Constructor
constructor dibujo.create(aowner:tcomponent); begin inherited create(aowner); fcolor:=clblack; fmenuasociado:=nil; colordialog:=tcolordialog.create(self); End;
44
Propiedad color
procedure dibujo.ponercolor(a:tcolor); var x,y:integer; begin for x:=self.left -left to self.width do begin for y:=self.top-top to self.height do begin canvas.pixels[x,y]:=a; end; end; fcolor:=a; end;
45
Propiedad MenuAsociado
procedure dibujo.ponermenu(a:tpopupmenu); begin fmenuasociado:=a; end; procedure dibujo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if button=mbright then begin if fmenuasociado<>nil then fmenuasociado.popup(left+x+self.left,self.top+ top+y); end; inherited mousedown(button,shift,x,y); end;
46
Eleccin del color
Al hacer doble click sobre el componente se abrir un cuadro de dialogo que permita elegir el color procedure dibujo.dblclick; begin if colordialog.execute then ponercolor(colordialog.color); inherited dblclick; end;
47
Bibliografa
Programacion con Delphi 4 Francisco Charte Pag. 755801 El Gran Libro de Delphi Burda Pag 211-265, 315-354 Delphi 4 Osier Pag 539-553 http://personal.redestb.es/revueltaroche http://www.clubdelphi.com/articulo/jmr/Chorradas.htm http://personales.mundivia.es/oscar/compo.htm http://www.hispan.com/eltaller/ControlDelphi.html
48
E-Mail
[email protected]
49
THE END
Posibilidades
50