Nunca he programado un componente, pero hacía mucho tiempo que este tema me intrigaba así que me he puesto manos a la obra y he sacado esto. Muchas cosas son literales de la documentación que he buscado pero he procurado dejarlas mas claras y explicando los ejemplos para la mejor comprensión. Alguno de esos textos está en ingles y eso a mucha gente no le ayuda xDDDDD.
Veamos:
Tu creas una clase nueva.
Si te basas en una clase ya existente pones el inherits
Luego añades la claúsula export.
Luego tienes que definir la constante _properties que es obligatoria. Esta constante proporciona información al IDE de como debe operar con esa propiedad.
También tienes que definir un icono para ese control en la caja de herramientas.
Y por último te tienes que poner a escribir código para esas propiedades y métodos.
la constante _properties
Luego pones la variable _properties que tiene el siguiente formato:
PUBLIC CONST _properties="*, propiedad1, propiedad2, ..., etc"
cada propiedad en la línea anterior lleva la siguiente información:
[-] Name [ { Kind [ Arguments ] } ] = Default
El signo menos: Si una de las propiedades la declaras con un signo - significa que las quitas. Eso ocurre si usas un * para heredar todas las propiedades del padre, pero alguna de ellas no la quieres. Entonces la declaras como una mas pero con un signo menos.
La clase puede valer lo siguiente:
Color ---> un entero que representa a un color. Al verlo el IDE sacará un colorchooser para elegir el color
Font ---> Una fuente. El IDE sacará un fontchooser para elegir una fuente.
Path ---> Un path. El IDE sacará un filechooser para elegir un path
Picture ---> Una imagen o un icono de stock. El IDE sacará un picturechooser para elegirla.
Range ---> Una propiedad con valor entero y un valor mínimo y máximo. El IDE sacará un spinbox para elegirlo.
Clase ---> En vez de los casos anteriores puedes poner el nombre de una clase que contenga una lista de constantes.
Si no especificas clase entonces se utiliza el tipo de dato de la propiedad (string, ..., etc).
Ejemplo
PUBLIC CONST _properties="Enabled=True,Font{Font},Background{Color}=-1,Foreground{Color}=-1," &
"mode{select.*}=Single,Handle,Tag"
Esto declara las siguientes propiedades:
Una propiedad TAG que no tiene ningún valor inicial. Al no especificarle nada el IDE asumirá su valor datatype especificado posteriormente.
Una propiedad HANDLE que no tienen ningún valor inicial. Al no especificarle nada el IDE asumirá su valor datatype especificado posteriormente y que como veremos es integer.
Una propiedad ENABLED que inicialmente valdrá TRUE
Una propiedad FONT. No tiene un valor inicial y para seleccionar una fuente el IDE mostrará el fontchooser.
Una propiedad BACKGROUND que tiene valor inicial -1 (no se que color es ese) y para elegirla el IDE usará el colorchooser.
Una propiedad FOREGROUND que funciona igual que la anterior.
Una propiedad MODE cuyos valores posibles están definidos como constantes en una clase llamada 'select'. Tiene por valor por defecto 'single' que es el nombre de una de esas constantes de esa clase.
Con ello habrás definido el nombre de las diversas propiedades que tendrás. el * se utiliza para heredar todas las propiedades de la clase padre si estás basando tu nueva clase en una ha existente que tendrás que heredar de la siguiente forma:
Si una de las propiedades la declaras con un signo - significa que las quitas. Eso ocurre si usas un * para heredar todas las propiedades del padre, pero alguna de ellas no la quieres. Entonces la declaras como una mas pero con un signo menos.
La constante DefaultEvent
Si pones esto (no es obligatorio) entonces al estar en el IDE y hacer doble click para acceder al código te saldrá el evento click para escribir código.
La constante DefaultSize
Es el tamaño del control cuando lo pones en un formulario del IDE. En este caso es 36x36.
La constante _DrawWith
Cuando pongas un control de esta clase en el formulario del IDE pintará un textbox.
La constante _Arrangement
Es el arrange que tendrán sus hijos si se trata de un contenedor. En el caso propuesto es 2. Los valores posibles son los de la clase arrange.class
Solo se usa si el control es un container.
El icono del componente
En la caja de herramientas debe aparecer un icono del control para poder seleccionarlo. Para definirlo hacemos lo siguiente:
En la raíz del directorio del proyecto creamos una carpeta llamada
control que contendrá los iconos (deben ser png) y el nombre del icono debe ser el nombre de la clase.
Implementación de las propiedades
Anteriormente se explicó como declararlas para el IDE. Esto es el icono que tendrá en la caja de herramientas o la manera en que el IDE debe ofrecernos dar valores a las propiedades o el valor por defecto que tendrán.
Pero llega el momento en que hay que escribir código de lo que esas propiedades hacen. Una propiedad será de tipo string o integer o lo que sea.
En este caso implementamos la propiedad ENABLED que es de tipo boolean.
y también definimos una propiedad handle que es de tipo entero y de solo lectura
Recuerdo que en _properties se escribió una propiedad enabled=true osea que el ide pondrá el valor true a una propiedad enabled que ahora definimos como boolean.
Como la propiedad ENABLED es de lectura escritura esta será la función para el caso de lectura (nota el _Read)
Y esta será la función de escritura para ENABLED (nota el _write)
SUB Enabled_Write(bEnabled AS Boolean)
$bEnabled = bEnabled
UpdateEverything
END
La variable $bEnabled es una variable privada y UpdateEverything es un método privado de esta clase.
La función handle es de solo lectura así que solo tiene función _read
Tras la codificación de las propiedades vendrían los métodos uno de los cuales será un método privado llamado UpdateEverything
Y otros serán públicos y devolverán valores
Así que en definitiva un componente nuevo que se base en un textbox y que admita la propiedad locked que sea boolean y por defecto false sería así:
Además crearemos un icono para la caja de herramientas, lo dejaremos en la carpeta controls, será de tipo png y tendrá por nombre el de la clase "miclase.png"
Con esto habremos conseguido un nuevo textbox que se llame como sea y que además de las propiedades del textbox tenga una propiedad nueva llamada locked que puede valer true o false y que hace lo que corresponda según locked_read al leer o locked_write al escribirla.(por ejemplo en este caso anular el keypress) cuando sea true
Todo esto lo he sacado de aquí
Programar Componentes en Gambas
Declaración de propiedades
Declaración de métodos