Você está na página 1de 295

Comunidad WWW.GAMBAS-ES.

ORG
GAMBAS
Gambas Almost Means Basic
Comunidad WWW.GAMBAS-ES.ORG
INFORMACIÓN
Tienes en tus manos el libro COMPLETO de “GAMBAS programación visual con
Software Libre” escrito por Daniel Campos y José Luis Redrejo bajo licencia libre.
Al libro electrónico original le faltan las páginas 34, 35, 58, 59, 104, 105, 166, 167, 190,
191, 216, 260 y 261.
Hemos escaneado e insertado estas páginas faltantes en este nuevo libro electrónico, creando
así el libro electrónico completo que todo “gambero” debería leer.
Hemos modificado el libro original, añadido las páginas faltantes, unificado todos los
capítulos en un único fichero y lo volvemos a hacer público conservando la misma licencia
libre.
Comunidad WWW.GAMBAS-ES.ORG
06/01/2010
Autores:
DANIEL CAMPOS
JOSE LUIS REDREjO
Responsable editorial:
SORAYA MUl'JOZ
Responsable de Marketing y Comunicación:
ALVARO GARClA
Edición:
MIRlAM MONTERO
Diseño de portada:
PICTOGRAMA
MaquetaciÓn:
ANGEL ESTRADA
ISBN: 978-84-934371-2-3
Depósito Legal:
Edita:
CEDlT UN EDlTORIAL,S.L., 2005
Avda. Portugal, 85- local
28011 Madrid (España)
Tel.: 91 577 03 55
Fax:: 91 577 0618
www.tibrosdelinux.com
info@LibrosdeLinux.com
LICENCIA
Se permite la copia y distribución de la totalidad o parle de esta obra sin ánimo dc lucro. Toda copia tOlal O
parcial deberá citar expresamente el nombre del autor, nombre de la editorial e incluir esta misma licencia,
añadiendo. si es copia literal. la mención "copia literal':
Se autoriza la modificación ytraducción de la obra sin ánimo de lucro siempre que se haga conslar en la obra
resultante de la modificación el nombre de la obra originaria, el autor de la obra originaria yel nombre de la
editorial. La obra resullante también será libremente reproducida. distribuida, colllunicada al público ytrans-
formada en términos similares a los expresados en esta licencia.
Impreso en España (Printed in Spain)
-Este libro ha sido realizado con Soft"''an- Ubre, concretamente con: OpenOffice.org, Evolulion. Mozilla, GIMP.
PRÓLOGO
La escena se desarrolla en algún lugar en el campo. en verano...
- ¡Abuelo. no te duermas! o has acabado de contarme la historia del ordenador...
~ ¿Eh? .. ah... sí... bueno, bueno...
El abuelo bostezó y pensó en lo que iba a decir. Ya había anochecido ysólo se oia el
canto de los griUos y el rechinar de la butaca.
"Cuando mi hermano compró su primer ordenador personal, estaba compuesto de
un lector de cintas. de algunos KB de memoria -no recuerdo exactamente cuántos-
y de un teclado mecánico, cosa poco frecuente en aquella época. Pero, sobre todo,
disponía de un lenguaje BA5IC completo y de un manual que intentaba enseñar la
programación paso a paso.
Algunos afIas más tarde fui yo el que me compré un ordenador. Los modelos eran
más potentes, pero volví a encontrar el lenguaje BASIC y la posibilidad de sacar el
máximo rendimiento.
En aquella época, las revistas hablaban de programación, la gente programaba e inter-
cambiaba programas. Algunos copiaban programas que no habían creado y se les
llamaba piratas... No, no, todos no tenían un parche negro en un ojo y un garfio en
lugar de una mano.
Prólooo


o a.rorT'ocit"''l VIS JOI r')n 5('"1.&. ~ r e 1 ibre
Después llegó la época del IBM pe y poco a poco las cosas empezaron a cambiar.
Al principio era una enorme caja gris, fea y ruidosa. Pero aumentó en potencia y
mientras más potencia adquiría. menos posibilidad había de sacarle el máximo
rendimiento.
Gracias a un puñado de futuros millonarios teníamos pantallas más grandes, más
colores, más sonido, más memoria. más capacidad de almacenamiento. Pero, al mismo
tiempo, se chapuceaban los sistemas operativos, se despreciaban los principios ele-
mentales de seguridad) se frenaban las aplicaciones, se bloqueaban los formatos de
datos, se ocultaba y se mentía sobre el funcionamjento interno del conjunto.
El usuario se convertía en un consumidor como cualquier otro. Campai'ias de publi-
cidad gigantescas le conducían a comprar una especie de caja negra de la que segui-
damente babía que controlar al máximo la utilización. A pesar de todo. la gente con-
tinuaba intercanlbiando y los piratas pirateando.
En cuanto a los que realmente eran capaces de sacar el má:x;mo rendimiento a los
ordenadores, tenían que comprarlos y después encerrarlos tras las puertas de un
campus o de una cláusula de no divulgación. Si no hacían esto. tenían que dejar de
programar.
Afortunadamente, las cosas no sucedieron exactamente como estaba previsto y gra-
cias al nacimiento de Internet, y a la mezcla de talentos de numerosos programado-
res, a menudo voluntarios. idealistas y pragmáticos al mismo tiempo. se impuso un
movimjento de liberación y nació, entre otros, el sistema operativo GNU/Linux.
Pero esto es otra historia, te la contaré mañana.....
La idea de desarrollar Gambas sobre Linux en casa vino principaJmente como reac-
ción a la obligación de utilizar Visual Basic sobre Windows en el trabajo.
Cualquier usuario con un poco de idea, cualquier empresa. cualquier administra-
ción, necesitan sacar el mayor rendimiento posible a su ordenador, es decir, hacer de
él lo que quieran hacer sin tener las competencias necesarias requeridas por los len-
guajes de programación, ni el tiempo para adquirirlas.
Con un lenguaje incoherente, incompleto y repleto de fallos, Visual Basic ha res-
pondido, a pesar de todo, a estas necesidades. Pero sus creadores, encerrados en su
torre de marfil, lo han ido poco a poco abandonando. ¿Había quizás desprecio hacia
esos usuarios que tenían la pretensión de sacar, como a ellos les pareciera, el máxi-
mo rendimiento de su herramienta de trabajo?
A pesar de que forma parte de la gran familia BASIC y que la interfaz de los progra-
mas se dibuja con el ratón, Gambas no tiene ningún otro punto en común con Visual
Basic y es totalmente incompatible con él. Sin embargo, mi prioridad es que pueda
satisfacer la misma necesidad: conseguir de la manera más simple posible sacar el
máximo rendimiento de todas las funciones del sistema operativo subyacente,
GNU/Linux en este caso preciso.
Gambas se inspira, sobre todo, en Java: se trata de un lenguaje orientado a objetos,
procedural e interpretado. Pero su intérprete es mucho más rudimentario: no hay
compilación just-itl-time, no hay garbage collector. Sin embargo, he cuidado mucho
su simplicidad, su coherencia, su fiabilidad y sus facultades de internacionalización.
Gambas es extensible. Es posible escribir componentes que aüaden al lenguaje cla-
ses suplementarias. Estos componentes ofrecen, en general, el acceso a librerías espe-
cíficas: QT, GTK+, SDL, OpenGL, y así sucesivamente...
Gambas ofrece un entorno de desarrollo integrado, moderno, que está, él mismo,
escrito en Gambas. Es ése principalmente el que me permite probar el lenguaje :-).
Además, es totalmente posible prescindir de él.
Finalmente, y nunca insistiré lo suficiente, Gambas no es un lenguaje creado por
programadores profesionales para programadores no profesionales. Yo soy su pri-
mer usuario yotra de las razones que me ha llevado a crearlo es que todavía no deseo
aprender en serio Perlo Python :-)


Programación visual con Software Libre
La primera versión estable de Gambas salió el 1 de enero de 2005, pero las cosas se
pondrán realmente interesantes con la segunda versión. En el momento en el que
escribo estas líneas, la versión de desarroUo ofrece la posibilidad de escribir compo-
nentes directamente en Gambas, sin necesidad de dominar C O C++. Más tarde, esta
posibilidad permitirá al entorno de desarroUo diseñar algo más que formularios grá-
ficos: tablas, hojas HTML, etc.
Es difícil prever de manera precisa cuándo saldrá esta segunda versión, e incluso,
más en general, cómo evolucionará Gambas en el futuro. El trabajo que queda por
hacer es todavía enorme y las cosas dependen mucho de los usuarios.
En cualquier caso, espero que tendréis tanto gusto en utilizarlo como yo lo he teni-
do en crearlo y que participaréis en su evolución. Y si, como para otros, Gambas es
el factor que os lleva a utilizar por fin eJ Sofhvare Libre, espero que sentiréis como
yo el respiro que produce esta libertad.
Martes. 16 de agosto de 2005.
- BENOiT.
íNDice
CAPiTULO" ¿OUÉ es GAMBAS? 17
IJ IJ e o [] 1. I El lenguaje BASre: su historia .........•.......... 18 •
[J lJ [] e a 1. 2 Un entorno libre . . . . . . ..•.... .21
III El [] e IJ 1. 3 Elementos de Gambas . . . . . . . . . . . . . . . . . 23
I!II!l1IJ [] IJ l. 4 Cómo obtenerlo . 24
mo IJ D o l. 5 Compilación y dependencias . . . •. . . . 26
1:1 11 ti o 1:1 l. 6 FamiliarizarsE con el lOE . 27
o o o o o El primer EJemplo. . . . . . . . . . . . . . . . . •. . . 29
o o o o o Mejor con un ejemplo grafico . . . •.......... 32
aooao Un poco de magia . •.......... 35
OIJ IJ o [J 1. 7 Sistema de componentes . 36
CAPiTULO 2, PROGRAMACiÓN BÁSICA 41
o liI o IJ IJ 2. I Organizadón de un proyecto de Gambas 42
o o o o o Declaración de variablES. . . . . . . . . . . . . . . . 42
a a a a o SubrutInas y funcIones. . . . . . . . . . . . . . . . . 45
fndice
PrOQftlmoción viwol ton Software Lbre


••



2.2 Tipos de datos ............•.....•.....•.......... 49
ConY8'SlOn dE tipos .....................•.......... 50
MatricES 52
2. 3 OperacionEs matematicas .............•.......... 54
OpEradonEs logIcas 56
2. 4 Manejo de cadenas ....................•.......... 56
2.5 Control de flujo ..................•......•......... 60
lF_ TtiEN.... ElSE ...........•.....•......•......... 60
SelEct .....................•............•.......... 62
FOR ...................................•........... 63
~ Y REPEAT ........................•......... 64
0EpI.rad0n En El DE dE Gambas 66
2. 6 Entrada Y salida de ficheros ..........•......... 6S
2. 7 Control de EM"OI"ES ......•..•..••...•..•.•••••••.• 72
2. 8 ~ CM k:i ItarJa a objetos
con GaJT1bas 73
2. 9 PropiedadES. Métodos y Eventos 79
CAPiTuLO 3: LA INTERFAZ GRÁFICA 81
• 3. I Concepto 81
PartIEndo de la COI'lSCMa •••••.•••••••.••••••••.••••. 84
8 ti.tuI no dE dEsatToIIo SS
• • • • 3. 2 Manejo baslco de los controles _•......... 87
Posidon Y tarnai'Io _ 87
Vlsiblldad 89
r o [ Textos l'EIadonados ..........•......•......•....... 89
o o o o o Colores ......................•......•......•....... 90
ODDDCl Ratón 92
DOOOD TEcJado 95
• • • •• 3. 3 Galería de controlES 96
o o o o ControlEs baslcos _ 96
DDDD
'00
onDO
Otros controle; básicos misceláneos ......•........ 99
Listas de datos 100
Otros controlEs avanzados 101
••••• 3.4 Diálogos ................................•......... 101
o o (J o o La ciasE Message .................•................ 101
o [J o o o la clase Dialog ....................•.....•......... 104
o o o o o Oiálogos pErsonalizados ................•.......... 106
••••• 3.5 Menús .................................•........... 111
••••• 3.6 Alineación de los controlEs 114
o o o o o Propiedades de la alinEación 114
o o o o o Cont/'Oles con allneaclon predefinida 117
o o o o o Diseño de una aplicación que aprovecha
o o o o o este recurso 117
••••• 3.7 Introducción al dibujo de primitivas 120
CAPíTULO 4: GESTiÓN DE PROCESOS 125 •
••••• 4. I La ayuda ofrecida por otros programas 125
••••• 4.2 Gestión potentE dE procesos 126
••••• 4.3 EXEC 127
o o o o o Palabra clave WArT 128
o o o o o El descriptor del procESO .......•......•............ 130
OOOot: Redire:cion con ro 133
o o o [1 o Matar un proceso ..........................•....... 134
o o o o o RedJrección de la salida estandar
de errol"Es .................................•....... 136
o o o [O Redirección dE: la salida estándar ...........•....... 139
[) 1 O o O Evento Kill() y la propiedad Value 142
[J O o O a Redirecclón de la entrada estándar.
el uso de C1.05E 146
o o o o o Notas finales sobl"E el objeto Process 148
••••• 4.4 SHELL 148
[ndice
DOC
D D'
11
CAPITuLO 5: GESTiÓN DE BASES DE DATOS 151
•• 5. 1 Slstanas de baSES de datos 151
• • • • 5.2 Bases de datos y Gambas .........•............ 153
••• • S. 3 Gambas-database-tnanager.
el gestor gratico 154
o o o CrEar' una baSE ..........................•......... t54
000 CJNEaruna ~ ....................•.....••........ I ~
o GEstionar datos dE lX\OI tab&a 164
SOL ...........................•........•.......... IGS
• • 5.4 Programadón _ 167
o o ModElo dE baSES dE datos .......•......•.......... 167
ConectandoSE por codlgo ................•......... 168
Consulta dE datos .................•......•......... 171
Borrar ~ b os 174
AfIacIr rEgistros ..................•......•......... 176
r..4ocIificar /"EQI5tros .................•......•....... 180
5.5 Otras caracterisUcas ....................•....... 190
[ Estructura dE las tablas ...................•....... 190
o Mas ut:iIldadEs del GEstOl" de Bases
de Datos .............•....................•....... 192
CAPITULO 6; RED 195
6. I CoocEptos 195
• 6.2 Creando un SEl"vidoI" TCP .........•............. 198
• 6. 3 Un diente TCP 20S
• 6.4 Clientes y servidOl"E5 localES ......••............ 211
• 6.5UDP ................................•............. 213
• 6.6 RESOlución de nombrES 216
• 6. 7 Protocolo HTTP 220
• 6. 8 Protocolo FTP 22S
CAPíTuLo 7: XMl 227
••••• 7. I Escritura con XmlWrlter .............•.......... 230
• •••• 7.2 Lectura con XmlReader .........•.....•.......... 238
o ~ s d E ~ r a ...............•.....•.......... ~
o PtantEatnientoinictal ..............•......•......... ~
Un ~ de lEctura ...............•.....•........ 240
••• • 7.3 X5LT .......................•.....•............... 252
¿Que ES X5LT? 252
o o o o Una plantilla de ejemplo 252
o o o Transformando El docUmEnto con Gambas 2S4
• 7.4 Acerca dE XMl-RPC 255
CAPITULO B: HERENCIA 257
• •• 8. I Lenguajes orientados a objetos y herencia 257 11
•• 8.2 Conceptos nEcesarios 258
la ciasE padrE 258
la cIasE hija. Palabra davE ~ r r s 262
u ExtmdiEndo fundonaIIdades.
Palabra davE SUPER 264
ModifICando funcionalidades 265
ReempiaziIDdo mÉtodos eSPEciales:
_New y 1rEe 269
UlTlttacionEs 272
• B. 3 CrEar un nuEVO control con Gambas 273
PlantEando El codigo 273
lrnpIementacion basica 274
• 8.4 NUEVOS componentes con Gambas 279
Preparacion dEl código. Palabra ciavE EXPORT 280
Archivos necesarios, ubicaciones 280
Probando El nUEVO componarte 282
11
Progromocion viwoJ roo ~ I !:t.-
CAPiTULO 9, ACCESO A LA API .................•.......... 287
•••• 9. I Declarar una función Externa .........•......... 288
o I Cómo denominar la libreria ...............•......... 289
El uso de los alias .......................•......... 290
Tlpos de datos ...................•......•......... 291
••••• 9.2 Fundones auxiliares 291
••••• 9.3 Un ejemplo con Iibaspell 293
••••• 9.4 ObtEnEJ" Información acerca dE la l i b r e r ~ 297
••••• 9.5 Resumen 300
APENDICE: Marcas registradas .......•......•................ 301
.
• o Es obvio que para los que hablamos
el idioma espaflOl, la palabra gambas nos sugie-
re algunas cosas, pero todas ellas bastante alejadas del
mundo de los ordenadores en general y del entorno de la pro-
gramación en particular. El autor original de Gambas, Benoh Minisini,
no habla una palabra de nuestro idioma y su inocente ignorancia le condujo a
nominar su obra con el acrónimo GAMBAS: Gambas almosr meam BAS/C, es
decir, 'Gambas casi quiere decir BASIC'. No es la primera vez: que un nombre o
una marca bautizados en otros idiomas produce estos extraños cambalaches, recor-
demos que Coca Cola,n.o'tuvo que cambiar su pronunciación en China porque la
primera versión de su nombre significaba ml/cule el re,wCllajo de cera, o algunos
todavía recordamos nuestra cara de asombro al ver los anuncios de un coche al
que Suz:uki dio en llamar Pajero. Tampoco está mal recordar que ya había antece-
dentes de otros lenguajes de programación con nombre de animal, como Carnel

j

Progromación viwol coo Softwore libre
o Python, aunque en esos casos el nombre estaba en inglés y en español no resul-
taba tan chocante.
En fin, como Benolt, que tiene los derechos de autor, no desea cambiar el nombre,
nos tendremos que ir acostumbrando a que Gambas empiece a sonarnos a algo más
que a buen marisco. De hecho, Gambas abre el entorno de la programación visual
en Linux a todo el mundo, como 10 hizo en su dla Visual Basic
mo
en Windows. Pero
como el tiempo no pasa en vano, Gambas intenta no reproducir los errores que se
cometieron entonces. la ampliación del lenguaje BASIC alcanza con Gambas amplias
cotas de potencia, profesionalidad y modernidad, sin abandonar nunca la sencillez
y claridad de este lenguaje de programación de alto nivel. Ya nunca más se podrá
decir que construir aplicaciones visuales para Línux es un proceso largo y comple-
jo que lleva años de trabajo a gurús y maniáticos de la informática.
Gambas no el un lenguoie de prOSroma<:ión, es tombién un entorno de progro·
mod6n v;suol poro desarrollar aplicaciones gróficos o de consola. Hoce posible el
desarrollo de oplicociones complicados muy rópidomente. El programador diseño los
ventonos de formo gráfico, arrostro objetos desde lo Cojo de HelTClmiento$ y
be código en BA51C poro codo obieto. Gambas est6 orjenlodo o lo que sigo
nifico que Ilomo automáticamente o 101 procedimientos <:\IOndo el u5\lorio de lo opli.
coción elige un menú, hoce die con 81 rotón, mU8ve obj8toS en lo pontollo, etc.
••••• l. I El lenguaje BA5IC: su historia
El nombre BASIC corresponde a las siglas Begimler's Al/ Pllrposc Symbolic Instrucrion
Code (Código para principiantes de instrucciones simbólicas con cualquier pro-
pósito J. El lenguaje fue desarrollado en 1964 en el Dartmouth College por los
matemáticos lohn George Kemeny y Tom Kurtzas. Intentaban construir un
guaje de programación fácil de aprender para sus estudiantes de licenciatura. Debia
ser un paso intermedio antes de aprender otros más potentes de aquella
época, como FORTRAN o ALGOL Este último era ellengua;e mis utilizado en
aplicaciones de proce505 de datos, mientnl$ que FORTRAN era empleado en las
aplicaciones científicas. Sin embargo, ambos eran dillciles de aprender, tenfan
gran cantidad de reglas en las estructuras de los programas y su sintaxis. El pri-
mer programa hecho en BASIC se ejecutó a las 4 de la madrugada del 1 de mayo
de 1964. Debido a su sencillez, BASIC se hizo inmediatamente muy popular y se
empezó a usar tanto en aplicaciones cientificas como comerciales. Tuvo el mismo
impacto en los lenguajes de programación que la aparición del Pe sobre los gran-
des ordenadores.
Cuando se desarrolló BASIC eran los tiempos en los que la informática estaba
reduida en uniV<'rsidades y grandes empresas, con ordenadores del lamano de una
habitación. Pero pronto las cosas empezaron a cambiar. En 1971 lntel fabricaba el
primer microprocesador. En 1975, la empresa MITS lanzó al mercado un kit de
ordenador llamado Altair 8800 a un precio de )97 dólares. Era un ordenador bara-
to. pero no para gente inexperta, había que saber electrónica para montarlo. Además
tenía sólo 256 bytes (no es una errata, solo bytes, nada de Kbytes, megas o gigas) I
y se programaba en código máquina a base de Oy 1, moviendo unos interrupto.
res que tenIa en el frontal. I>o$ joV<'ncitos vieron un modelo en una revista de elec-
trónica y decidieron montarlo. Le ofrecieron al dueño de MITS, ademas, hacer un
intérprete de BASIC para los nuevos modelos de Altair. Eran William Gates y f'auJ
Allen, y aquel BASIC, con un tamaño de 4 Kbytes, fue
_....-
I\'Mllo1' EIl't1nlIlIcS
WariIIo flJIol." S lUl
.... 1 ................
.-
Figura 1. lonJ:omiento
del A1loir 8800.
el primer producto que entregó una nueva empreSa
llamada Microsoft. Fue sólo el principio. A finales de
los 70, AlIen y Gales hablan portado BASIC ya a un
buen número de plafaformas: Atari, Apple. Commo-
dore... Yen 1981, ctundo desarrollaron OOS para IBM
y su nuevo Pe, añadieron también su propio intér-
prete de BASIC al sislema. En posteriores años siguie-
ron Otras versiones hechas por OlraS compañías como
Borland, pero el declive de BASIC habia empezado.
Uis inlerfaces gráficas de ventan:1S que Apple popula-
rizó y Microsoft adoptó con sucesivas versiones de
11
Windows{T>O', st convinieron en un cSlándar y BASIC no era un lenguaje prepara-
do para eslos entornos.
Sin embargo. en marro de 1988, un dts<irrollador de softwart" llamado Ajan Cooper
l
intenlaba vender una aplicación que permitía personalizar fácilmente el enlomo
de ventanas usando el nlÓn. El progr.ama M" lIamabll Tripod y en aquellas fechas
consiguió que lo viera y le encargara el desarrollo de una nueva ver-
sión a la que llamaron Ruby, y a la que añadieron un pequeño lenguaje de pro-
gramación. Microsoft reemplazó ese lenguaje por su propia versión de BASIC,
Quickbasic y el 20 de marzo de 1991 se lanzó al mercado con el nombre de Visual
Basie. Al principio fue un verdadero fracaso de venias, pero la V('Tsión 3 publica-
da en ti otoi'Jo de 1996 fue un bito lotal, tanto que aclu¡¡lmenle es el lenguaje de
progr.amadón más usado. Visual Buic siguió hasta 10I versión 6.0.
En 2002 fue en la plataforma .NET de desarrol1o. en lo que para muchos
de los Stguidores ha supuesto el abandono de Microsoft, ya que ha cambiado buena
parte de la sintaxis añadil!ndole complejidad en contradicción con el esplritu y el
nombre del lenguaje. En cualquier caso, a dla de hoy se calcula que entre el 70% Y
80% de todas las aplicaciones desarrolladas en \I,Ilndows se han hecho con alguna
de las vtrsiones de Visual Basic.
Las causas del txjto de Visual Basic son numerosas, pero entre otras se pun:!e sel'la-
lar como obvia el uso del lenguaje BASle que fue pensado para un aprendizaje acil.
Otro de los motivos es disponer de un entorno de desarrollo cómodo, que hace un
juego de niños el disel'lo de la interfaz gráfica de cualquier aplicación, apartando al
programador de perder tiempo en escribir el código necesario para crear vtTItanas,
botones, etc.., y dqfndole centrarse (¡nicamente en 10I solución al problema qllt cual·
quin programa intenta resolver. Con la popularización de operatÍVQS libres
como GNU/Linux. éstas y otras razones hacían prever que la aparición de un entor-
no equivalente libre seria un l!xito yconlribuirla a la presentación de muchos nue·
vos desarrollos que lo utilizarlan. Ha habido varios intentos que no han cuajado,
bien por la lentitud de su evolución, bien por su dificultad de uso o por no ser total-
mente libres y no haber arrastrado a una comunidad de usuarios detrás. Finalmente,
&noit Minisini. un programador con experiencia en la escritura de compiladores
-
que estaba harto de luchar contra los hilos de diseno de Visual 8asic, y dese¡ab¡a
poder usar un enlomo de GNU/Linux Cácil en su dislribución, comenzó a desa-
rrollar su propio entorno para Linux basado en BASIC. El 28 de febrero de 2002
puso en Inlernet la primera versión pública de Gamb¡as: gambas 0.20. 8enoít eli-
minó del diseno del lenguaje bastantes dr los problemas que Visual Basic tenfa,
como la gestión de errores, y le añadió caracUrislicas comunes en los lenguajes
actuales más modernos, como la orientación a objetos y la propia estructura de 105
programas
1
. Como prueba de fuego, el propio entorno de desarrollo fue progra-
mado en Gambas desde la primera versión, sirviendo a un tiempo de demostración
de la polencia del lenguaje y de delección de necesidades y corrección de errores
que se fueron incorporando a las dislinlas versiones.
En enero de 2ooS,&noit publicó la versión 1.0, en]¡a que ya se incorporaba un
pui\¡ado de componenles desarrollados por otros programadores que colaboraron
con 8: Daniel Campos. Nigel Gerrard, LauTnlI Carlier, ROO Kudla y Ahmad KahmaJ.
Esta versión se consideró suficientemente establr y cerró un cido. A partir de esa
frclla empezó la programación de la versión 2.0. t.sta ya induye algunas mejoras en
e1lenguaje, muchos más componentes y un nuevo modelo de objetos que permi-
tirán usar Gambas en un futuro para el desarrollo de aplicaciones web con la misma
mosofia y facilidad que actualmente se: usa para aplicaciones de escritorio.
L 2 Un entorno libre
Gambas es un entorno de desarrollo que se distribuye con la licencia GPL GNU
(General Pub/ic LicmaJ). Esto significa que se distribuye siempre con el código fuen-
te y respeta las cualro libenades que define la Free Software Foundalion:
, La libertad de usar el programa con cualquier propósito (libertad O) .
• La libertad dr estudiar cómo funciona el programa y adaptarlo a las propias
nrcrsidades (libertad 1). El acceso al código Cuente es una condición previa
para esto.
11
11
con Se twore li
• La libertad de distribuir copias, con las que se puede ayudar al vecino (liber-
tad 2).
· La libertad de mejorar el programa y h¡ctr públicas las mejoras a los demás.
de modo que toda la comunidad se beneficie (libertad 3). El acceso al código
fuente es un requisito previo para esto.
Una de los engiu\os más comunes en el uso de Software Libre es la crenlcia de que
este moddo de desarrollo obliga a que el trabajo se publique gratis. lo que es del todo
incierto. Estas cuatro libertadts permiten que, quien lo deset, venda copias de Gambas
(entregando siempre el código fuente y respetando esas cuatro libertades) y. por
supuesto. de eualquier aplicación dNarroUada con este progralTJil. Las aplicaciom:s
desarrolladas con Gambas put'Ckn Ono acognose a la licencia GPL
También cualquier programador es libre de alterar el propio lenguaje y modificarlo
a su gustO, siempre y cuando entregue ti código correspondiente a esas modifica-
dones y los derechos de autor de los originales.
Aparte de estas libertades propias de la naturaleza de un proyecto de Software Ubre
sobre GNU/Linux, Gambas añade más facilidades para el programador:
• Una ayuda muy completa del lenguaje y cada uno de los componentes, algo
que es muy de agrad«tt para los qut nnpiezan a programar en Gambas, y que
no es habitual en los proyectos de Software Libre. La ayuda que se publica está
cn inglés, pero existe un grupo dc personas trabajando en la \r;¡ducción a espa-
ñol
4
• Si todos nos animamos a colaborar! en la traducción, pronto estari com-
pleta y disponible para el resto de usuarios.
, Una API (Interfaz para programar la aplicación) sencilla y bien documenta-
da, lo que facilita a los programadores crear nuevos componentes para Galllbas.
La API no es de utilidad inmediata para quien desarrolle con este lenguaje,
pero pennite a los programadores avanzados que 10 deseen añadir funciona-
Ildades al mtorno de desarrollo ycrear nuevas herramientas para Gambas.
El lenguaje está preparado para ser independiente del gestor de ventanas que use. Esto
significa que, sin cambiar una sola linea de código. una aplicación puede ser compi.
lada para ser ejecutada en un escritorio Cnome o KDE, usando las librcrias propias
de ese escrilorio y siendo una aplicación nativa de ese entomo. En el futuro se pue-
den desarrollar componentes para Windows...... Fluxbox y otl"05 gestores de venta-
nas, y los programas no tendtin que modificar su código para que sean aplicaciones
nativas de esos entornos. Marcando. antes de compilar, una opción en el entorno de
desarrollo para elegir el componente a usar (actualmente se puede elegir entre gtk y
ql. para Gnome o KDE), se generan distintas aplicaciones para distintos entornos con
el mismo código fuente. Esta característica no se encuenlra disponible en ningún airo
lenguaje aistente.lo que convierte a Gambas en un entorno único.
1. 3 Elementos de Gambas
Para poder desarroUar y ejecutar programas hechos con Gambas. son necesarios dis-
linios elementos:
• Un compilador. que se enc:argati de transformar lodo el código fuenle yarchi-
vos que formen parte de un proyeclO hecho en Gambas, en un programa eje-
cutable.
• Un intlrprete capat de hacer que los programas hechos en Gambas sean eje-
cutados por el sistema operatil'O.
- Un entorno de desarroUo que facilite la programación y disct\o de las interfa-
ces gráficas de los programas.
• Componentes que al\aden funcionalidades al lenguaje. La palabra (omponen-
le en Gambas tiene un significado especifico. ya que no alude a partes
cas, sino a Iibrcriil5 espccfficas que le dotan de más posibilidades. En la actua-
lidad existen componentes para usar xml, rooaiones de red. oprngl. sdl. ODBC,
dinintu bases de datos, aprcsioncs regulares, escrilorios basados en qt. en gtk.
1. lavé es
11
11
etc. Estos componentes son desarrollados por distintos programadores, siguien-
do las directrices de la AP¡ de Gambas y la documentación publicada al efec-
to por Belloi' Minisini.
1. 4 Cómo obtenerlo
Las nuevas versiones de Gambas se publican a través de la página web oficial del pro-
ye<to: http://gambas.sourceforge.net.Enlaactualidadexistendos ramas de Gambas:
la rama estable o 1.0 y la rama de desarrollo o 1.9 que desembocará en la versión 2.0.
De la rama estable s610 se publican nuevas versiones cuando es para corregir algún
fallo que se haya descubierto.
En el momento de escribir estas lineas, la versión estaole era la 1.0.11 y no se prevé
que haya cambios en el fulurO. La versión de desarrollo está en continuo cambio,
mejora y adición de nuevos componentes. Esto la hace muy atractiva, debido a la
existencia de importantes funcionalidades que no están en la versión f'stablf' (como
los componentes gtk yODBC). Sin embargo, al ser una rama en desarrollo, es muy
probable que lenga fallos no descubkrtos y es seguro que sufrirá cambios en un futu·
ro próximo. En este texto trataremos todas las novedades que la versión de desarro·
110 contiene para que sea el usuario el que escoja con qué rama trabajar. Buena parte
de las diferencias se encuentran en los nuevos componentes. Algunos de estos serán
tratados en este texto, por lo que si el lector quiere trabajar con ellos deberá usar la
rama de desarrollo.
Las nuevas versiones se publican siempre en forma de cMigo fuente, para que los
usuarios que lo deseen compilen el código y obtengan todas las parles que Gambas
tiene. Los autores de algunos de los componentes que se han hecho para Gambas,
publican de forma separada en distintos sitios web las versiones nuevas de estos, pero
todas se env!an a Beno)t Minisini y paS<ln a formar parte de la publicación comple-
ta de este lenguaje de programación en la siguiente versión. De este modo, se put'dt'
decir que cuando 13enolt hace pública una nueva, el paquete del código fuente con·
tiene las últimas versiones de todo el conjunto en ese momento.
Como In compilación de Gambas y todos los componentes asociados puede ser una
tarea dificil para usuarios no expertos, es común quc se crttn paquetes binarios con
la compilación ya hecha y listos para scr instalados cn distintas diSlribucioncs dc
gnu/Linux. En la misma página ",di dondc sc pucde bajar d código rumte sc mcut"fl-
tran los cnlaccs para la dcscarga dc los paquetcs compilados para cslas distribucio-
nes, Existen actualmetlle paqueles disponibles para Debian, Fedora, Mandriva, Gentoo,
Slackwarc, QiUnux ySuSoe. En algunos casos, como para Fedora y Dcbian, eslán dis-
poniblcs tanto los paquctes de la vcrsión establc como la de desarrollo.
En d caso dc Dcbian, los paquctcs son realizados en gnuLinEx y, posteriormentc,
subidos a Debian para que eslén disponibles y usables en esla distribución y en lodas
sus derivadas. como Knoppix, Guadalinex, Progeny, Xandros, Unspire, Skolelinux,
ele. Por este motivo, las últimas VttSiones están sicmpre disponibles antes en los rqJO-
silorios dc gnuLinEx hasla que 50n subidos y aprobados cn Ikbian. Las lineas del
archivo /tfelaptlsourr:tj.Ii5t de un sisltma Dcbian para instalar La vcrsión más actua-
lizada de los paquetes de Gambas son:
Para la vcrsión estable:
I
deb
Para la vcrsión dc desarrollo':
gambasl
deb hUp://_.linez.orglsources/linez/debilD/ el gl......s
Acontinuación, en cualquiera de los dos casos, para instalar todos los paquetcs de
Gambas, hay que ejecutar como usuario rool:
apt.-qet update
apt-get install gambas
Aunque el código fuente dc Gambas Soe dislribuye en un único archivo comprimido.
la instalación desde paquctes compilados Soe hacc con un bucn puñado de archivos.

Programación viwal ton Software libre
La razón es que no todos son necesarios para eiecutar aplicaciones hechas en Gambas.
En las distribuciones de Linux se ha seguido d criterio de separar en distintos paque-
tes el entorno de desarrollo (paquete gmuba>-ide), el intérprete (paquete gambas-rwl-
time), y se ha hecho un paquete separado para cada uno de los componentes. Si se
quiere programar en Gambas son necesarios la mayoría de ellos, al menos los que el
entorno de desarrollo necesita. Si se quiere ejecutar un programa hecho con este len-
guaje, sólo es necesario gnmbns-rrmtime y un paquete por cada uno de los compo-
nentes que el programa use. Por ejemplo, si es un programa que está hecho para el
escritorio Gnome y no usa ningún otro componente, sólo sería necesario instalar en
el sistema los paquetes gnmbas-rrmtime ygambas-gb-grk.
•• l. 5 Compilación y dependencias
Si en lugar de instalar paquetes ya compilados para la distribución de gnu/Linux
deseamos compilar Gambas desde el código fuente, deberemos seguir los pasos habi-
tuales en Jos sistemas GNU. Es decir, descomprimir el archivo con las fuentes y, desde
el directorio que se crea al descomprimir y usando un terminal, ejecutar las siguien-
tes instrucciones:
./eonfiqu.re
~ k .
lllake install
La última de ellas debemos hacerla como rool, si queremos que el programa esté dis-
ponible para todos los usuarios del ordenador. Si estamos habituados a compilar
aplicaciones en sistemas GNU, disponemos ya de un compilador instalado y de bas-
tantes librerías de desarrollo. Las instrucciones anteriores tratarán de compilar e ins-
talar lodos los componentes de Gambas, que son muchos. Si no tenemos las libre-
das correspondientes a alguno de ellos, simplemente no se compilarán y la instrucción
./configure nos informará de ello. Es importante saber que d entorno de desarrollo
está hecho sobre las librerías gráficas qt, por tanto, para poder usar d entorno nece-
sitaremos tener instalado, al menos, estas librerlas de desarrollo con una versión igual
o superior a la 3.2. la versión dt:! compilador ga: ha de ser lambitn tsla, como míni-
mo. Cada uno de los compontntes titnt dependencias dI.' sus propias librerías y
dependerá de la distribución de Linux que usemos, para saber el nombre del paque-
te que deberemos instalar anles de poder realizar la compilación.
L 6 Familiarizarse con el lOE
Aunque un programa en Gambas se podría hacer perfcctamente usando un editor
de texto plano cualquiera, seria un desperdicio no aprovcchar uno de los mayores
atractivos que el lenguaje tiene: su lOE o entorno de desarrollo. EliDE de Gambas
ahorra al programador buena parte del trabajo más tedioso, le proporciona herra-
mientas que hacen mucho más f.:Icil su larea, con utilidades de ayuda, de diseño de
interfaces, aUlOcompletado de instrucciones, traducción de programas, ttc. En la
imagen siguiente podemos ver algunas de las ventanas más importantes dt'l t'ntor-
no, que se usan durante el desarrollo de una aplicación:

11
-,- ..
-
-
••
••
••
••
,.
'.
_..........
,
-
-••
.,
-
-
_.
-

-
-
.. -
0 .- _
• __.r _
--_.
___.. .rr_
- - ... -
-
-
- ,-
-"'.""--.."'''''
.,-
--.'-'-" •••
........-..
-_.. -
--,
..... -
.. - .
_ .. _.._.-
-" "-""'"
.....- ..
.,_ .
"oo, r"..
o" _
-
-
figwo 2. Enlomo de desarrollo de Gambas.
• _ •• p"
---- '''l3' ;¡o.j;.e. 0-:T' Q.
. -. "
- 1"0""',-.,'''''"O" .•".'-'........,:
c:
Progromocióro viwoJ con Software libt'e
Cuando arranca Gambas, lo primero que: nos aparttc: es la VC\lana <k bienvenida.
Proyecto. rec:lenus
Pro"eelos .."",nI es
J DalabaH
... GbWhois
,.. usuarioKentros
¡,J monilOfllrore
.... erypt

Figuro 3. Venlono cJ. bienvenida.
Aquí se nos la opción de comenzar un nuevo proyecto o aplicación, abrir un
proyecto del que tengamos sus archivos disponibks, abrir uno usado recienternm-
le o uno de los numerosos ejemplos que estan incluidos en la ayuda de' Gambas.
Antes ck cualquiera de estas opciones es nn:esario que lodos los códi-
gos fuc:nte de una apliOld6n h«ha en Gambas es lo que se denomina proy«to. El
proyecto está (ormado por una serie de archivos que en Gambas estan SIEMPRE
situados dentro de un único dir«torio. En ti puede haber, a gusto del desarrollador,
dislintos subdirectorios yorganizar todo como se desee, pero cualquier gráfico, tato
ycódigo que (orme parte de la aplicación estará dentro de él. Por dio, si elegimos en
o:ta ventana la opción Nuevo proyecto... , el asistente siempre creará un nuevo
torio con el nombre del proyecto y ah! irá introduciendo todos los archivos necesa-
rios para el desarrollo de la aplicación. Asl, para enviar a alguien el código fuente de
una aplicación hecha en Gambas o cambiarla de ordenador o disco, só[o hay que
transportar el directorio con el nombre del proyecto, sin tener que prwcuparse de
otros archivos. Del mismo modo, si desde el entorno de desarrollo escogemos un
archiyo o un glifico para integrarlo en nuestro trabajo, el archivo sc:1i copiado auto-
máticamente al directorio del proyecto.
o e e primer Ejempk)
Una de las formas mas habituales de empezar a trabajar con un lenguaje de progra-
mación es haciendo un pequeno programa que: muestre el mensaje Hom MUlldo.
Por tanto, empezaremos a conocer el entorno de desarrollo yel lenguaje de progra-
mación con este tlpico ejemplo. Comenzaremos haciendo un !rola mundo que sea
puro BASIC, es d&ir, que sea igual al que hubieran hecho los autores de BASIC allá
por el ano 1964.
En aquellos tiempos las interfaces gráficas no existlan, por 10 que este primer pro-
grama sc:ri un programa feo, de lerminal. En el BASICoriginal, hacer que aparaca
un mens¡je en el terminal es tan simple como escribir la línea:
ntNT "Hola Mundo"
No tl necesario ningún encabez.ado previo, la instrucción PRINT sirve para mos-
trar cualquier cadena de texto en ellerminal, que en BASIC se presentan entre comi-
llas dobles. IX ah! qUl;' el programa sea tan simple como ese. Vamos a ver cómo hacer-
lo con el entorno de desarrollo de GAM RAS:

_.. _...-
....
-"--.--
-
. ~ - - -
J.--
Figuro 4. Mi$lenle de Gomb<.n.
1. Escogemos la opción Nuevo proyerto...
en la venlana anterior (Figura 3).
Aparecer.í un asislentt, ro el que pulsa-
mos Siguiente. Surgiri una nueva venla-
na para elegir el lipo de aplicación.
Escogemos la tercera opción: Crear un
proyecto de texto'.
2. Le damos un nombre al proyeclO, por
ejemplo holmmmdo y un titulo. Pulsamos
el botón Siguiente (Figura 4).
-

_.
_... _... -
..
-
'"'---
---
_.._----.-
e.- __...........
---_..__.


-----_....-
E1iegimos el directorio del disco en
el que queremos crearlo; pulsamos
de nuevo el botón Siguiente y apa-
rccm un l'tSumen oon los lbtos dd
proyecto (Figura 5).
3. A continuación pulsamos el botón
OK. Se abrirá el entorno de desarro-
llo de Gambas listo para empezar a
programar. Al ser una aplicación de
terminal, que no lleva interfaz gnUi-
ca, de momento, sólo ne«:sit Irnos fijamos m la
ventalla de la izquierda. qut en nuc:slro caso
dri como título: Proytao-ltaIamundo (F'¡gun. 6).
11
En TC'alidad es, probablemente. la ventana más
importante para el manejo del entorno de desarrollo.
Asimple viSla se puede ver el menu superior, que con-
tiene las entradas necesarias para guardar y cargar pro-
yectos, aClivar las distintas ventanas del [DE, manejar
la ejecución de los programas, personalizar el enlomo
(en Herramientas I IOtros I Mostnr mas-
cota, po(kmos ocultar la animadón la gamba,
nos (Stá mirando al abrir ti proyecto),

fis- 6. Proyecto-
"""""""".
De nos fijamos sólo ti árbol direaorios que: \'er
la ralzdel árbol es el nombre del proyecto: holamundo, y de tres
ramas: Clases y Módulos, que son para distintos tipos de archivos código fuen·
re; y Datos, cuyo nombre: indica su finalidad, almacenar ahi los archivos de datos
que la aplicación
principio. Gambas nos da dos formas de realizar Jos programas, incluso si
son tan simples como el hemos hecho. dtgir entre una programación
orientada a objetos, paradigma ((pico de los lenguajes de programación más poten-
tes o una programación estructurada simple. Según ello, e! archivo que contenga el
código de nuestro programa será una Clase o un Módulo. Por simplicidad, de momen-
to vamos a usar un Módlllo. Haciendo dic con e! botón derecho de! ratón sobre el
árbol de carpetas aparecerá un menú contextua!. Elegimos las opciones Nuevo I
Módulo. Surgirá una ventana en la que escribimos el nombre del módulo, por ejem-
plo miprogramil, y pulsamos el botón OK, con lo que aparecerá nuestra primera v e n ~
tana, con el título miprograma.modllle, donde poder escríbir código.
Pt.ellC so.e "".!I
fllml,. •....1• ....<lo.
I
, ~
Por fin podemos escribir nuestro código
en BASIC. Lo haremos justo antes de la
línea donde pone END, tal y como queda
reflejado en la figura de la izquierda.
Figura 7. Venia"" doode escribir el
código.
Cuando después de escribir el código que
ya sablamos, pulsamos la tecla INTRO,
vemos que el entorno colorea e!texlo de
una forma particular. Podemos pararnos
un instante a ver los distintos colores que se muestran (Figura 7):
• En gris aparece una línea que comienza por una comilla simple ('J. Esto indi-
ca que la línea es un comentario, es decir, no se trata de ningún código de pro-
gramación y el texto que sigue a la comilla no se ejecuta nunca, son comenta-
rios que el programador puede/debería poner para facilitar que otros (o él
mismo, pasado un tiempo) entiendan lo que el programa hace en ese punto.
, En azul podemos ver palabras clave del lenguaje BA$IC.
• En color rosado aparece la cadena de texto.
• A [a izquierda vemos un resalte amarillo al comienw de las líneas que han sido
modificadas. Esto apare.:;erá siempre en [as Uneas que contengan modificacio-
nes que no hayan sido compiladas.
11

L
Bien, ya esl:llislo el programa. Para comprobarlo se pulsa en el botón verde, con el
símbolo del Play, que está en la pantalla del proyecto. Al hacerlo apar«trá una nueva
\'entana llamada ConJOla en la que se \-erá la salida de nuestro programa. En este caso
strá el simple lexlO Holo Mlmdo. Este es lodo el código necesario, ya se puede com·
pilar el programa para generar un archivo e,iecutable que funciona sin necesidad del
entorno de desarrollo. Para ello, en el menú de la ventana del proyecto hay que esco-
ger: Proyecto ICrear ejecutable. Saldrl. un cuadro de diálogo para elegir el direc-
torio en ti que queremos (TUT ti ejecutable. Pulsando DI< 10 generará. Al cerrar
ahora el mioma de dc:sarroUo ck Gambas y abrir un IfiITlinal o p;¡.sar a una (onso-
la de Linux, podemos probar su funcionamiento. Para ello. tn el dimlorio donde
se haya creado el ejecutable, hacemos:
josefaOO-004:-$ OI! 9' bes/bol_'ndol
jose@aOO-004:-/gaabas/bol"'ndo$ ./bol··'ndo.gambas
Rola lIlUrIdo
Mejor con un EjEmplo gratlco
El (jemplo anl«ior moslraba una aplicación d( consola, qU( nos r«:u«(Ú, a los vi(-
jos tkmpos tk otros sist(mas oper.llivos o a la fonna d( trabajar d( los hackers infor-
máticos. En realidad, hacer es( tipo d( programas no demuestra (1 potencial de
Gambas, puesto que son realmente simples (igualm(nte fáciles de realizar en otros
como Python o cualquier vi(ja v(rsión d( BASIC.
Es m(jor hac(r el programa Hola MlIndo para ti (ntorno gráfico qU( inunda los
(scritorios d( los ordenadores actuales. Para ello empuaremos igual que antes,
arrancando Gambas y creando un Nuevo proyecto siguiendo exactamente los
mismos pasos, ac(pto qU( (n lugar d( (SCogu Cr(ar un proy«:to de tato, cuan-
do (1 asist(ntt nos pr(S(nt( las distintas opciones. Crear un proy«IO
grifico.
Para no repetir nombre, podemos d(nominar al proy«to ltolanlll/ldo2. Al acabar
ti proceso apar«:(!'á de nu(V() la ffntaru de proyecta. pero (n esta ocasión t(ndrá
una rama mú (n (1 árbol: Formularios. Un formulario es d dond( se diseña
la interfaz gráfica de la aplicación, es decir, donde se insertan objetos como boto-
nes, cuadros de texto, listas, casillas de venficación, etc. Los formularios se corres-
ponderán con las ventanas que la aplicación mostrará.
Haciendo die con el botón derecho del ratón sobre el árbol del proyecto, elegimos
ahora en el menú contextual que aparece: Nuevo I Formulario. Por simplieidad, en
este caso ni siquiera hace falta cambiar el nombre, sólo pulsando en el botón OK
aparecerá en pantalla la ventana del formulario y una ventana para escribir código
BASIC casi idéntica a la del ejemplo anterior, sin nada escrito. El resultado será algo
parecido a lo siguiente:
......... _ __, -o'
..'- ---
5"'"111 ,u;.. <> :fier
~ .

.......,,-'"
,.... .., ..... ~ .. "
'_'00 <:l<... ,_oo
.p -
'000
?


Figura 8. Pantolla dellormulario.
--
r-
.-
.-
--
..•
-
.•.
-
.-
--
.-
'-
.•.
""
-
Haciendo die sobre la palabra Form en la ventana de la derecha, correspondiente a
la Caja de Herramientas, aparecerán distintos objetos que podemos colocar en los
formularios. Entre estos está el icono del botón (se distingue rápidamente por tener
la palabra OK escrito dentro). Haciendo un dic de ratón en él, se puede dibujar en el
formulario un botón, tan sólo hay que arrastrarlo con el ratón y el botón izquierdo
pulsado, para dar la forma que queramos. Gambas escribe el texto Buttoll/ sobre el
ratón, pero como ese texto no es demasiado intuitivo 10 mejor es cambiarlo. Para ello
hay que pinchar en el botón y después, en la ventana de propiedades, hacer un die en
la línea donde pone Text. Ahora se puede escribir el nuevo texto, por ejemplo Púlsame.
l. ¿Qué es Gambos2
Programación visual con Software Libre
También, pulsando en la propiedad Name le cambiamos el nombre al objeto botón,
poniéndole, por ejemplo, btnMensaje. Siguiendo los mismos pasos dibujamos otro
botón sobre el formulario, escribimos el texto Salir y el nombre btnSalir. Una vez que
tenemos diseñada la intefaz gráfica con el formulario y los dos botones, pasamos a
escribir el código BASIC correspondiente. Para ello, haciendo un doble dic con el
ratón sobre el botón con el texto Púlsame, aparecerá la ventana de código con un texto
ya escrito, al que añadiremos algo de forma que el código de ese botón quede así:
PUBLIC SUB btnMensaje_Click()
Message.lnfo("Hola Mundo")
END
Haciendo doble dic sobre el botón Salir, escribimos el código que falta:

PUBLIC SUB btnSalir_Click()
QUIT
END
El resultado final debe ser algo como esto:
Figura 9. Resultado final de lo programación de los dos botones.
Propíedad.s
(Class;) BullO"
(Name) 1)tnMenuJe
(Group) 1 1
x 56
y
"
·0
o
!
Forml.cI... 14: 1 [Modificado) g Width 141
"O
Jtl€>rA..,,,
, ,
-, - .. -ti P
H;iQiit
" O PÚfseme
Visible True
Gambes C\eS5 file
Enabled
O O
Font
PUBLIC SUB btnHensoje_Click()
BótckQlGUnd
Foregfound

fU"
Mouse
EHIl room;
]

falseo
P\eltc sta btnSahr_CtJ.ckO fFa'se
-::J
5.",
Text jpulsame
llUIT
Picture
--
Border True
Defilult Fabe
Cancel False
Con esto ya está el programa terminado. Igual que antes, pulsando en el botón verde
de la ventana de proyecto el programa se ejecutará. Sin embargo, en este caso la eje-
cución presenta novedades importantes: es UH programa gráfico, tiene ya su venta-
na con la barra superior y los típicos botones de maximizar y minimizar. Además,
cuenta con dos botones y la aplicación está esperando a que el usuario haga dic en
alguno de ellos para actuar.
Hora de experimentar. Sería bueno, llegado este punto, que perdiéramos un poco de
tiempo tocando las distintas propiedades de cada uno de los tres objetos que el pro-
grama tiene: el formulario y los dos botones, parando el programa y volviendo a
arrancarlo para ver el resultado de las modificaciones tantas veces como queramos.
Aunque no es parte de este capítulo, hay un par de detalles que ya deberían empe-
zar a observarse:
• El código BASIC se escribe entre unas líneas que empiezan por PUBLlC SUB
y acaban en END.
• El texto que sigue a PUBLlC SUB lleva el nombre del objeto sobre el que se ha
hecho un doble dic, seguido de la palabra Click, eso significa que el código se
ejecutará cuando el usuario haga dic sobre el objeto.
• Para que aparezca Message.Info, se escribe Message y se pulsa sobre esta pala-
bra. Aparece un menú entre cuyas opciones se encuentra la palabra Info.
Moviéndonos con los cursores del teclado y pulsando la teda de espacio o
INTRO sobre esa palabra, quedaba escrito en la ventana de código. Ése es el
autocompletado, que nos ayuda a escribir el código evitando tener que memo-
rizar sentencias y mensajes extraños.
Un poco de magia
El entorno de desarrollo de Gambas está hecho con el componente qt, y de forma
predeterminada lo escoge para las aplicaciones gráficas. Por tanto, un programa
gráfico hecho en Gambas usa, en principio, estas librerías y se puede considerar

1. ¿Que es G.:::o:..;.m.:.::b.:.::o:.:.s
2
:..;.. _
Progromoción"¡woI con Software Libre
una aplicación nativa para el tseritorio KDE. Sin glk dis·
la versión desarrollo de Gambas, hacu programas
dos con las Gtk para realizar aplicaciones del tseritorio Gnome.
Si hemos instalado los paquetes de Gambas correspondientes a la rama de desarro-
llo, incluyendo el paquete gambas.gb.gtk, podemos recuperar la aplicación hola-
I11lmdo2 del ejemplo anterior, ir a la ventana de ProyeClo y hacer clic en el menú
ProyeClo I Propiedades, pestaña Componentes, y seleccionar gb.gtk. El resultado al
ejecutar la aplicación es que se trata de una nueva, pero antes de KDE y ahora de
Gnome. jY sin tocar una sola línea de código!
11
. ,
-
. --. .'
IJJ)--

I
Figuro 10. Aplicación holoml,lndo2
MKDE.
1"'-

_.
)--
I

I
-
I
I

Figura 11. Aplicación holomunda2
Hasta el dla de: hoy no existe ningún olro lenguaje: de programación con el que se
pueda hacer esto.
• L7 Sistema de componentes
A lo largo de: tos apartados anteriores han aparecido distintas referencias a los com-
ponentes de Gambas, incluyendo su descripción en el tercer apartado de este capítu-
lo. Estos permiten extender este lenguaje de programación. La interfaz desarrollada
por Benolt para su programación hace que hayan sido varios los programadores que
han colaborado con él, desarrollando nuevos componentes que se van añadiendo a las
distintas versiones de Gambas en cada nueva publicación. En la versión 1.0 estable de
Gambas sólo se podían desarrollar en e yC++, pero desdc la versión 1.9.4 de la rama
de desarrollo t a m b i ~ n se pueden escribir componentes en Gambas, lo que abre nume-
rosas posibilidades futuras ya que es mucho más sencillo hacerlo que en C.
El listado de componentes disponibles es amplio y se aumenla continuamente en la
versión de desarrollo. Para la rama estable están fijados [os siguicnles:
· gb.compress: para compresión de archivos con protocolos zip y IJZip2.
•gb.qr: para objelos visuales de las librerias gráficas q[.
•gb.qr.cxt: para objetos visuales de las librerías gráficas qt que no son estándar.
•gb.ql.editor: un edilor de lexto hecho usando las librerías gráficas qt.
•gb.q[.kde: objetos visuales propios del escritorio KDE.
•gb.qt.kfle./itm/: un navegador web d('1 escritorio KDE.
•gh.llet: objetos para conectar a servidores de red y a puertos serie de comuni-
caciones.
•gh.net.crlr/: objetos para construir servidores de red.
•gh.dh: objetos de conexión a bases de datos.
· gb.dh.mysq/: driver para conectar al servidor de bases de datos MySQL
•gb.db.postgresq/: driver para conectar al servidor de bases de datos PostgreSQL
•gb.dh.sq/ill': driver para usar bases de datos Sqlite 2.x.
•gb.xm/: objetos para parsear archivos XML
1. ¿Ové es Gamba,?
11
, '''H'''''' '..... 'VO ••,."... , "V" ....... " OOV'" ~ , ...'"
•gh. vh: colección de funciones para facilitar la migración desde Visual Basic.
•gh.sdl: objetos para reproducir, mezclar y grabar archivos de sonido.
•gb.pcre: objetos para usar expresiones regulares en el lenguaje.
En la rama de desarrollo existen estos componentes (algunos de los cuales han sido
muy mejorados y aumentados, como el gb.sdI) y otros más, con una lista en conti-
nuo crecimiento. En el momento de es<:ribir estas líneas podemos contar con:
•gb.crypt: objetos para encriptación DES y MDS.
•gbIorm: objetos gráficos para formularios independientes de las librerías grá-
ficas usadas.
• gb.gtk: objetos gráficos para formularios de las libreríasgtk. Tiene los mismos obje-
tos que el com¡xmentegh.q/, pero enlazan con esta otra librería de desarrollo.
•gb.db.odbc. driver para conectar a bases de datos a través de ODBC.
•gh.i'Jfo: objetos que proporcionan distinta información acerca de los compo-
nentes y el sistema donde la aplicación se ejecuta.
•gb.opellgl: objetos para dibujos tridimensionales con aceleración OpenGL.
•gb.xml.rpc: objetos para el uso del protocolo rpc-xml.
· gb.sdl.image: objetos para dibujos en dos dimensiones con aceleración gráfica.
•gb. v4/: objetos para capturar imágenes de cámaras de video en Linux.
•gb.gtk.pdf se utiliza para renderizar documentos pdf desde aplicaciones hechas
en Gambas.
Oo.
o',
El listado de componentes disponibles para el programador puede verse en la pesta-
ña Componentes, accesible a través del menú Proyecto I Propiedades. Cada uno de
los componentes se corresponde a un paquete compilado en la distribución, de forma
que si se anade al proyecto, por ejemplo, el
componente gb.SlIl, ha de instalarse el paque-
te gnmbas-gb-sdJ en los ordenadores donde
se quiera ejecutar la aplicación compilada.
Los controles son clases para crear objetos útiles en la programa-
ción. Los objetos creados pueden ser visuales (como pestañas, edi-
tores de texto, ete.) u objetos de código (como servidores de red o
conexiones a bases de datos). Si el componente tiene objetos visua-
les, estos se incorporan a alguna de las pestanas de la Caja de
Herramientas del entorno de desarrollo.
Figura 12. Componentes.

H«ramienlos COll
Figuras 13, 14 Y1S.
Cl:Jjo de
componentes COll
ob¡eIos

form

Al hacer dic sobre cada uno de los compo-
nentes aparece una pequeña descripción de
su función, el nombre del autor o autores
del componente, y un listado de los con-
troles que están disponibles para el desa-
rrollador si selecciona ese componente
(Figura 12).
Sp,,,,,
,,-
Co""'.'
== C"JO , _ [j "
_.. .. _-
--.
....,-_......-
..... _ .. o'
._... .. __.
..-....
0-
....,.
o'
0'-
<-oo,..
""'."-'-'-
-"-.-_.........- ...... _...
p,
:ion UIJI (O l •
En las imágenes anluiores podemos ver algunos de los objetos gráficos que están
disponibles al stlrcdonar los dislimus cumponente..
Cada componente tkne su propiiJ doc;:ulIl('ntación que se encutntra incluida en la
ayuda de Gambas. En la n.nu. estable esta documentación está available; en
la rama de desarrollo sólo está disponible si ha sido seleccionado para su U50 en ti
proy«lo.
Todas las cosas que se pueden hacer con Gambas, y no son parte del propio lengua-
je BASIC, se programan mediante el U50 de componentes. [sto significa que, por
ejemplo. para hacer una aplicación de bases de datos es necesario seleccionar ti com-
¡>onente gb.db o no estarán disponibles los objetos de conexión a bases de datos. Lo
mismo ocurre con las conexiones de red, caplura de video, ctc. Estos objetos nO son
parte del lenguaje BASIC.
I NOTAS
1http://_.coope...com/olan/hrtf>.,._of_vb.hhn/
2 o.fe"'WI(IO) y Visuo/ BoK
http://wiki.gnulinex.org/gambaJ/210
J http://_.fd.org/lic:enJing/lic:enHJ/gpl.htmIHoy ung IJoducción lno
ohaoII 01 .... http://gugJ.Jindominio.net/licenc:ioJ/
• DocumenIoción de Gamba) tri tipOñoI, http://wiki.gnulinex.org/gombaJ/
Inl.lnJccio...) poro coIobolor en lo documentoelÓn en e)p<lñol
http://wiki.gnulinu.org/gombaJ/6
/l Si lo insloloc:ión $O hoc. desde un ill.lemo gnuLn&. no necelOOO oñodir eua linee
pt>e)!o que lo versión de dewrrollo de Gambas es porre del repos.torlo of,dol de
gnulinEx.
7 Debido o lo mayor extensión de lo cooena Creor un proyecto de ...to en espa-
ñol que en o/ros idiomos. es que e$O menwje aparezco cortado y no ¡.e veo
completo. No lIay que preQ(uporse por etlo. no aleda poro nodo o ellKción y
suponemm que $Oró cOrf&gido en veniarlf!s del lOE.
• En el Capírulo I ~ vieron ya algu-
nos delalles acerca de la programación con
GamNs.
Ahora, estudiaremos, principalmente, la sinlaxis e instrucciones mas
importantes del lenguaje BASIC que US3 Gambas. Buena parte de estas instruc-
ciones existen en el BASIC estandar y algunas otras son extensiones propias de
Gambas.
Aunque sea más espartano, en este capItulo se usarán casi siempre ejemplos de códi-
go de consola, como vimos en el apartado El primer ejtmplo dd Capitulo J.
Haciéndolo de este modo evitaremos las intrrferencias que puede suponer la expli-
cación de conceptos relacionados con la programación gráfica y los componentes.
Estos conceptos se explicarán con extensión en capítulos posleriores.
11
ProgromOCton visual con Software l i ~ r _ ~
•• •• 2. I Organización de un proyecto de Gambas
Antes de comenzar con la programación básica hay que resumir algunos conceptos
previos:
• El código fuente de los programas hechos en Gambas está compuesto de uno
o más archivos que forman un proyecto. Este proyecto se archiva en un direc-
torio del mismo nombre.
• Los archivos de código pueden ser: M6dulos (contienen código en BASIC que
se ejecuta directamente), e/nses (contienen el código en BASIC que ejecuta un
objeto de esa clase) y Formularios (áreas donde se disena la interfaz gráfica de
la aplicación y que se corresponden con las ventanas del programa),
· los proyectos de texto sólo contienen MMu/os y/o e/mes. Las aplicaciones grá-
ficas contienen Formularios y Clases, pero también pueden contener Módulos.
• El proyecto puede contenrr otros archivos de datos, documentos, textos, ete.,
sin código BASIC para ser ejecutado por la aplicación.
Los archivos que contienen código en BASIC (Módulos y Clases) siempre están estruc-
turados de la siguiente manera:
• Declaración de variables.
• Subrutinas y Funciones.
o o o o o Declaración de variables
Los programas manejan datos continuamente. Estos datos pueden ser de muchos
tipos: números, letras, textos, etc., y cambiar a lo largo de la ejecución del programa
(en ese caso reciben el nombre de variables) o permanecer con un valor fijo duran-
te todo el tiempo (entonces se denominan com/allles). A los datos que usa un pro-
grama se les asigna un nombre identificador.
BASIC permitía usar variables y constantes sin haberlas dedarado antes, es decir,
sin haber expuesto al principio del programa un listado con las variables que se
iban a usar.
Eso produce programas ilegibles en cuanto empiezan a ser de tamaño medio y es
una fuente constante de errores. Para evitar esto, Gambas obliga a dedarar las cons-
tantes y las variables antes de utilizarlas.
Hay dos lugares donde se pueden declarar las variables, dependiendo del ámbito en
el que se vayan a usar. Si se declaran dentro de una subrutina o función (en el siguien-
te apartado se verá con detalle qué son las subrutinas y funciones), están disponi-
bles para ser usadas sólo dentro de esa subrutina o función. Si se declaran al princi-
pio del archivo de código (sea un M6dulo o ulla Case) están disponibles para todo
el código de ese archivo, en todas sus subrutinas.
Para dl'c1arar una variable en una subrutina o función se emplea la sintaxis:
El tipo_variable hace referencia al tipo de dato de la variable: número entero, cade-
na de texto, número decimal, etc. El nombre de la variable lo elige el programador
libremente. Siempre es recomendable que sea algo que indique para qué se va a usar
la variable. Es decir, se debl' huir de nombres como a, b, c, etc., y usar, por ejemplo,
edad, fecha_nacimiento, altura, etc.
Las variables que se declaren en una subrutina o función sólo se usarán dentro de
ellas. Cuando terminen se destruirán. Eso permite utilizar el mismo nombre de varia-
ble dentro de distintas subrutinas y su valor nunca se confundirá o mezclará.
Para declarar una variable al principio del M6dulo o e/lIse usamos la sintaxis:
ISTATIC] (POBLIC ! P R t v ~ ) nombre variable AS
tipo_variable
2. Progromación básico
11

nW'<,Irnoclon Y I ~ u o l con .xmwore llore
Si se define la variable como PRIVATE. estará disponible dentro de todo el fichero,
pero no será accesible desde otros ficheros del mismo proyecto. Si se la declara como
PUBl.IC, se podr.\ acceder a la variable desde un fichero del proyecto distinto a donde
se dedarÓ.
La palabra STATIC se usa en los archivos de Clase, no en los Módulos. Sirve para defi-
nir un comportamiento especial en todos los objetos de una misma clase. En pocas
palabras se podria explicar con un ejemplo: si tenemos una clase perro, tendremos
algunas variables como color, raza, peso, etc., y cada objeto perro tendrá su propio
valor en cada una de es.as variables.
Al mismo tiempo, podemos declarar una variable que sea mímrro_t/e-PtTtllS, de forma
que si cambiamos su valor dl." 4 a 3, lodos los objetos perros tendrán 3 patas y cada
uno seguirá con su propio peso, color, ete. En este caso, la variable mílllero_de....pnras
se declararía 5TATIC en el código BASIC del archivo de 1,1 dase perro. Se verá todo
este comportamiento más adelante en este mismo capitulo.
Las constantes se definen sólo al principio de un archivo de Módrlio o Clase, no se
pueden definir dentro de las subrutinas y funciones. La sintaxis es:
( POBLIC I PRIVATE ) CONST nombre_constante AS
tipo_constante - valor
Por tanto, al igual que las variables, pueden ser privadas o públicas.
Veamos un ejemplo de todo esto:
Gambas module file
Archivo de Módulo con el nombre: ejemploVariables
PRIVATE edad AS Oate
PRIVATE altura AS Single
PRIVATE OONST Pi _ 3.141592
~ c calidad AS Integer
PUBLIC SUB Subrutinal ()
DIM num AS Integer
DrM nombre AS String
edad-3D
num _ 54
PUBLIC SUB subrutina2()
DIM nwn AS Integer
DIM apellido AS String
edad-J2
nlUll - 4
En este ejemplo vemos que las variables e<lad y altura se pueden usar en todo el archi-
vo. Por tanto, después de ejecutar la Subrutina 1, edad valdrá 30 y, después de eje-
cutar la Subrutina2 valdrá 32. Vemos también cómo la variable num está definida
en las dos subrutinas. El valor de nuro desaparece al acabar cada una de las subru-
tinas y, por tanto, durante Subrutina I valdrá 54 ydurante Subrutina2 valdrá 4, pero
después de que se ejecute el END de cada una de esas dos subrutinas, simplemente
no existirá y si se hace referencia a nWIl en cualquier otro punto dd programa se
producirá un error.
Finalmente, vemos que la variable calidad está definida como pública. Esto signifi-
ca que desde cualquier otro archivo del programa se puede hacer referencia a ella
mediante el nombre ejemploVariables.CIllidad, donde ejemploVariables es el nom·
bre que se le ha dado al fichero donde se ha declarado calidad.
o U o o o Subrutinas y funciones
Es impensable escribir todo el código de un programa sin una mínima organiza-
ción. En BASle el código se organiza dividiéndolo en procedimientos. Existen dos
tipos de procedimientos: subrutinas y funciones. Una subrutina es un procedi-
miento que ejecuta algo, pero no devuelve ningún valor. Ejemplos de subrutinas

2. Programoción bósic,o'- _

Programación Vi5Uol.'_OI!.-::.ottwore Libre
serían procedimientos para dibujar algo en la pantalla, tocar un sonido, etc. Sin
embargo, una función es un procedimiento que devuelve siempre un valor al ter-
minar su ejecución. Ejemplos de función serían el cálculo de una operación mate-
mática que devuelve un resultado, el proceso para pedir datos al usuario de la apli-
cación, etc.
Ya hemos visto en el capítulo anterior la sintaxis para declarar las subrutinas, pues·
lo que se mostró cómo el entorno de desarrollo escribe automáticamente la subru-
tina que el programa ejecuta al hacer un die del ralón sobre un botón. La sintaxis
completa es:
(PUBLIC I PRIVATE) SUB n<XDbre_de_la_subrut.ina (pl As
Tipo_de_Variable,p2 As Tipo_da_Variable, •.. )
código que ejecut.a la subrutina
Las palabras PUBLle y PRIVATE significan exactamente lo mismo que cuando se
definen variables: determinan si la subrutina puede ser llamada sólo desde el archi-
vo donde se ha codificado (PR/VATE) o desde cualquier archivo de la misma apli-
caciÓn (PUBLle).
Las variables pi, p2, ete., permiten pasarle parámetros a la subrutina, que se com-
portarán dentro de ella como variables declaradas dentro de la propia subrutina. Es
decir, desaparecerán al ejecutar el END final. Se pueden pasar tantos parámetros
como se desee a una subrutina, declarándolos todos, por supuesto.
Existen algunas subrutinas con nombres especiales en Gambas, por lo que el pro-
gramador no debe US<lr esos nombres. tstas son las siguientes:
• Mai1l: existe en todas las aplicaciones de Gambas que sean de texto, no en las
gráficas. Es el punto por el que empieza a ejecutarse el programa. Si no h u b i e ~
ra subrutina Mai'l, Gambas daría un mensaje de error al intentar arrancar,
puesto que no sabría por dónde comenzar.
• _New y -ftee. se ejecutan, respectivamente. al crearse ydestruirst un objeto.
Sólo se encuentran en los archivos de clase.
• Objeto_El't'ntcr. se ejecutan automáticamente cuando al Objeto le ocurre el
Evenlo. Ya hemos visto algun ejemplo en el capítulo anterior, como
btnSD/ir_Qid:O, que se ejecuta cuando d usuario de la aplicación hace dic con
el ratón sobre el botón btnSa/ir. En las aplicaciones gráficas, el n'Cnto Opcn del
formulario con el que se inicia la aplicación es la primtr.l subrutina que el pro-
grama ejecutará. En el último apartado de este capítulo se tratarán espcc:ifica-
mente los su significado y utilidad.
Veamos un programa de ejemplo (para probarlo, debemos crear un nuevo programa
de texto siguiendo los pasos explicados en el CtlpítuJo J, apartado El primer ejemplo:
PUDLIC SUB Main ()

END
PUBLIC SUB pinta_.e4ia(valorl AS Integer, valor2 as
Integer)
PRIN'l' (valad + valor2)/2
END
Aunque éste es un programa poco útil, sirve par.! apresa.- con simplicidad la forma
de funcionar de las subrutinas. Comienza ejecutando la subrutina Main, en ella sólo
hay una llamada a ejecUlar la subrutina pinta_media pasándole los númel'O$ ente-
1'0$ 4 Y8 como parámetro. la subrutina pinta_media muestra en la consola el
tado de hacer la media entre los dos que han sido pasados como parámetros.
La sintaxis para declarar una función es la siguiente:
(PUBLIC I PRIVATE) FUNCTIOH nombre_de_la_función
(pI As Tipo_ds_Variable,p2 As Tipo_de_Variable ..• )
As Tipo_de_Dato
2_ Programación


••• código que ejeeuu la fu.nei6n
RE"1'URN la fu.nei6n
".,
La declaración es casi idfutica a la de: la subrutina, añadiendo dos cosas más: d tipo
de: dalo que la función devuelve en la primera linea y la n«esidad de usar la sen-
tencia RETURN dI" BASIC para indicar el valor a devolver.
Veamos otro ejemplo que produce el mismo resultado que el anterior, pero usando
una función:
PUBLIC SUB Main()
DIM final AS Single
final - calcula_Media(4,8)
PRINT !iDal
".,
PUBLlC f'UNCTION ealeu.la_SUlllll33(valorl AS Integer,
valor2 as Integer) AS Single
RETURN + valor2)/2
".,
En esta ocasión es la subrutina Main la que: se encarga de pintar m la consola d
lado de la openu:ión. Es muy imponanle destacar la difen:ncia entrt la forma en que
se llama a una subrutina y se llama a una función. En el ejtmplo anterior vimos que
para llamar a la subrutina sólo se escribía su nomhn: con Sus parámetros entrr parén-
tesis. Sin embargo, ahora vemos que al llamar a la función se usa una asignación,
final'" calcula_Media(4,8). Esto debe hacerse siempre al llamar a una función: la
asignación sirve para recoger el valor que se devuelve. Por motivos obvios, la varia-
ble que recoge el valor que la función retorna debe declararse del mismo tipo de dato
que el que devuelve la función. En el ejemplo anterior la funciÓn devuelve un dato
tipo Single (un número real con decimales) y la variable final se ha declarado, por
tanto, de tipo Single.
2. 2 Tipos de datos
Ya hemos visto a 10 largo de los textos anteriores el uso de variables y cómo se
declaran.
Hasta el momento, sólo conocemos algunos tipos de datos. Revisemos ahora todos
los que soporta Gambas:
• Bao/can: es un tipo de dato que suele ser el resultado de una comparación. Sólo
acrpta dos valores: Fa/se y Trile (Falso y Verdadero en español).
• Byte: representa un número entero positivo entre Oy 255.
• 5/rort: representa un número entero con valores posibles entre -32.768 y +32.767.
• Tllleger: representa un número cnlero con valores posibles entre ·2.147.483.648
y +2.147.483.647.
• Long: representa un número enlero con valores posibles entre
-9.223.372.036.854.775.808 Y+9.223.372.036.854.775.807.
• Single: representa un número real, con decimales, con valores posibles enlre
-1,7014118+38 y +1,7014118E+38.
• FIOrH: representa un número real, con decimales, con valores posibles entre
-8,98846567431105E+307 y +8,988465674311 05E+307.
• DrHe: sirve para almacrnar un valor de fecha y hora. lnlernamentr, la fecha y
hora se almacena en formato UTe, al devolver el dato se representa en el for-
mato local, según la configuración del ordenador.
• Strillg: se usa para almacenar una cadrna de texto. En BA51C las cadenas dr
trxto se asignan mediante dobles comillas.
11
I
• Vllrianr: significa eualquiD" tipo de data, es decir, puede almacenar un Irrtt¡a,
Singlt, String, tIC. Se dtbe tvilar su uso porque ocupa mis memoria que los
ameriores ylos cálculos con Variant son mucho más lentos.
• Objecl: representa cualquier objeto creado en Gambas.
Sen' el programador el que elija el tipo de dato con el que debe ser declarada una
variable. Siempre se ha de tender a USólr los tipos de datos más pequmos, puesto que
ocupan mtnos memoria y el microprocesador los maneja con mis velocidad. Sin
embargo, eso puede limitar las opciones de la aplicación, por lo que a menudo se
opla por tipos mayores para no cerrar posibilidades.
Por ejemplo, si se va a usar una variable para definir la edad dt una persona, 10 lógi-
co es utilizar un dato de tipo bytt (el valor máximo es 255). Sin embargo, si la edad
a guardar es la de un árbol, es conveniente usar un tipo Shorl, ya que puede haber
árboles con más de 255 anos. ptto no se conocen con más de 32.767.
ConVErSiOn de tipos
Gambas IXrmite distintas conversiones entre tipos de dalos. La forma de hactr la
conversión puede ser implicita o explicita. Son oonvtrsiones implícitas cuando el
propio intérprete de Gambas se tnCarga de gestionarlas. Por ejemplo:
DDK a. Single
DDK operudol Q SiDCJle
DDK operando2 a. IDteger
operandol- l.5
operando2-2
- operandol • operando2
En este caso, para poder realizar la multiplicación, el intérprete convierte, de forma
transparente para el programador, el operando2 a un valor Single. Son conversio-
nes explicitas las que debe hacer el programador al esuibir el código para poder
realizar 0lXraciones. mezclar datos de diSlintos tipos. ete.
Estas conversiones se hacen mediante unas funciones que están incluidas en el
BASIC de Gambas. Evidentemente, la conversión se hará siempre que sea posi.
ble, si no lo es, producirá un error. toste ¡;S el listado de funciones de conversión
existente:
• CBool(expresióll): convierte la expresión a un valor booleano, verdadero o falso.
El resultado será falso si la expresión es falsa, el número 0, una cadena de texto
vada o un valor nulo. Será verdadero en los demás casos. Por ejemplo:
- Devuelven Fa/se las siguientes operaciones: Cboo/(""), Cboo/(O),
Cboo/(NULL).
- Devuelven Trile las operaciones: Cboo/(1), Cboo/("Gambil5").
• CByte(expresiólI): convierte la expresión en un valor tipo Byte. Primero se con-
vierte la expresión a un número binario de 4 bytes. Si este número es mayor
de 255, se corta r("Cogiendo los 8 bits de menor peso. Por ejemplo, Cbyte("l r)
devuelve 17, pero Cbyte( 100000) devuelve 160. El valor 160 es debido a que el
número 100.000 en binario es 11000011010100000, sus 8 últimos bits son
10100000, que pasado de binario a decimal da lugar a 160. Si no sal>emos ope-
rar con números binarios lo mejor que se puede hacer es evitar este tipo de
conversiones que resultan en valores tan "sorprendentes".
• CSllort(expresión), Clm(expresióII) o C/meger(expresióll), y CLo/lg(expresión):
convierten, respectivamente, la expresión en un número de tipo SlIoTl, /meger
y Long. En el caso de CShort la conversión se realiza igual que para CByte,
pudiendo producirse resultados extraños igualmente si la expresión resulta en
un número mayor de 32.767.
• CDme(cxpresióll): convierte la expresión en una fecha, pero hay que tener cui-
dado porque no admite el formato de fecha local, sólo el formato inglés
mesldía/aiio llOfils:minlllOs:segundos. Es decir, CDme("09/0ó/1972 01 :45: 12")
es el día 6 de septiembre de 1972.
2. Programación básica
11

nogramoclon V,WC!I con ;)()lfWOre u ~ e
• CS¡,¡gle(expresión) o CSng(e.xpresiÓ'I) y CFQ(lt(expresión) o Cjlt(expresión): con-
vierten, respectivamente, la expresión en un número del tipo Sirlgle yFlom. La
c);presi6n debe usar el punto (.) y no la coma (,) como separador decimaL
• CStr(expresión): convierte la expresión en una cadena de texto sin tener en
cuenta la configuración local. Por tanto, Cslr(1.58) devuelve la cadena de texto
1.58, independientemente de si la configuración local indica que el separador
decimal es el punto Ola coma, OCSlr(CDale("09/06I1972 0/:45: 12:)) devuel-
ve "09/06/1972 O/ :45: Ir.
• 5trS(expresiófl): convierte la expresión en una cadena de texto, teniendo en
cuenta la configuración local. Por tanto, Str$( /.58) devuelve la cadena de texto
1,58, si la configuración local está en espal'iol. Del mismo modo,
Str$(CDllIe("09/06/1972 01 :45: 12")) devuelve "06/09/1972 01:45: 12" si la con-
figuración local está en español, puesto que en este idioma la costumbre es
escribir las fechas en la forma día/mes/año.
• Vill(expresión): convierte una cadena de texto en un tipo Boolean, DllIe o algu-
no de los tipos numéricos, dependiendo del contenido de la expresión. Val
es la función opuesla de Str$ y. por tanto, también tiene en cuenta la confi-
guración local del ordenador en el que se ejecuta. Intenta convertir la expre-
sión en un tipo Dnu, si no puede en un número con dKimales, si tampoco
puede en un número enlero y si, finalmente, tampoco puede la convierte en
un tipo Boo/eall.
a o a a o MatriCES
En numerosas ocasiones, cuando se intenta resolver un problema mediante la pro-
gramación> surge la necesidad de contar con la posibilidad de almacenar distintos
datos en una misma variable. La solución más simple para este problema son las
Matrices o Arm)'5. Se pueden definir matrices que contengan cualquier tipo de datos>
pero con la condiciÓn de que lodos los elementos de la matriz sean del miSmo tipo.
No hay más límite en la dimensión de la matriz que la memoria del ordt'nador y la
capacidad del programador de operar con matrices de dimensiones grandes.
La sintaxis para trabajar con matrices es la misma que para las variables, añadiendo
entre ;;or;;hetes las dimensiones de la matriz:. Algunos ejemplos:
DIM Notasl2, JI AS Single
DIM Edades[40) AS Integer
PRIVATE Esto_no_hay_quien_lo_maneje[4, J, 2, S, 6, 2]
AS St.ring
Para acceder al valor de ;;ada una de las celdas de la matriz, hay que referirse siem-
pre a Sil índice. En una matriz: de dos dimensiones lo podemos identificar fá;;ilmente
por filas y columnas.
Hay que tener en cuenta que el índice ;;omienz:a a contar en el 0, no en el l. Es dcrir,
en la matriz: Listndo!3! existirán los valores correspondientes a Lislado!O], Lis/mio!11
y Listado!2]. Si se intenta acceder a Listado{J] dará un error Out ofBOlmds, fuera del
límite. Por ejemplo:
Dim Alumnos[4,lO¡ AS String
Dim columna AS Integer
Dim fila AS lnteger
Columna" 2
Fila- 6
Alumno[Columna, FilaJ-NHanolo Pérez Rodriguez"
Hemos visto que hay que declarar estas matrices con las dimensiones máximas que
van a tener. Eso supone que el intérprete de Gambas reserva la memor13 necesa-
ria para ellas al comenzar el uso del programa. Sin embargo, hay ve<::es en que, por
las cara;;terísticas de la aplicación, se desconoce la dimensión que hará falta para
la matriz:. Para solventar esta posibilidad Gambas tiene predefinidas matrices uni-
dimensionales dinámicas de todos los tipos de datos, excepto Boolean. Con estas
matrices se trabaja de forma distinta a las anteriores, ya que hacen falta funciones
para añadir nuevos elementos a la matriz, borrarlos o saber el número de elementos
que tiene ésta.


Progromoción con Software libre
Con este ejemplo veremos el uso y funciones más usuales al trabajar con matrices
dinámicas:
DIM nombres AS String(]
, La siguiente instrucción inicializa nombres para
poder usarlo.
, Es un paso previo obligado:
nombres - NEW Stringll
, Asi podemos añadir valores a la matriz:
nombres .Md(

nombres.Add(uAntonio
W
)
'Count devuelve el número de elementos de la matriz.
'La siguiente instrucción pintará 3 en la consola
PRINT nombres.COunt
'La siguiente instrucción borrará la fila de "Juan":
nombres.Remove(l)
PRlNT nombres.Count 'pintará 2
PRINT nombres(ll 'pintará "Antonio"
'La siguiente instrucción vaciará nombres:
nombres.Clear
PRINT nombres.COunt 'pintará O
••••• 2. 3 Operaciones matemáticas
Cuando se trata de trabajar con números, Gambas tiene las operaClones habituales
en casi todos los lenguajes de programación:
. +, -, . y usan, respectivamente, para la suma, resta, multiplicación y divi-
sión.
• f\ es el operador de potencia, por ejemplo, 4 f\ J = 64.
o Para la división hay dos operadores adidonales, \ o DIVy MOD, que devuel-
ven, respectivamente, la parte entera del resultado de la división y el resto. Es
decir, 9 D/V 2 = 4, 9 \ 2= 4 Y9 MOD 4=/P.
Aparte de estos operadores existen [as siguientes funciones matemáticas para reali-
zar cálculos más complejos:
• Abs(mímero): devuelve el valor absoluto de un número.
o Dec(mímero): decrementa un número.
o Frac(mímero): devuelve la parte decimal de un número.
• rrlc(mímero): incrementa un número.
oll1/(llIímf'ro): devuelve la parte entera de un número.
• Mllx(7lIímf'roJ, ruímero2, ...): devuelve el número mayor.
· Mill(mímero/, mímero2, ...): devuelve el número menor.
• ROlmd(lllÍmero,decimllles): redondea un número con los decimales desea-
dos.
o Sgrl(mímero): devuelve el signo de un número.
o Rud([mÍlrimo/,{máximo)): devuelve un número aleatorio comprendido entre
minimo y máximo. Si no se expresa ningún valor para mínimo y máximo, el
número estará comprendido entre Oy l. Si sólo se expresa un valor, el núme-
ro eslará comprendido entre el Oy ese valor. Muy importante: antes de usar
Rlld es necesario ejecUlar la instrucción Rarrdomiu que inicializa el generador
de números aleatorios. Si no se hace, se obtendrá el mismo número en sucesi-
vas ejecuciones de Rud.
2. Programación básico


p
OperacionEs Ioglcas
Para realizar operaciones variables de tipo Booleat/ o expresiones cuyo resul-
tado sea BooIean. existen algunas instrucciones similares a las que podemos ,"n- en
casi lodos los lenguajes de programación. Se trata ÁND. OR, NOT YXOR. Si lene-
mos conocimientos de lógica y numeros binarios. no nos rcsultar.i dificil identifi-
carlas y sabc.-r su comportamiento allralarse de las operaciont:S binarias más bási-
cas. En caso conlrario, scr.l fácil usarlas y entender $U funcionamiento con una simple
lraducción al español de las tres primeras: Y, O, NO. Es decir, sirven para unir con-
diciones del tipo: color ('$ verde y no es marrón, que se escribirla:
El caso de XOR es más dilleí] de entender puesto que es una operación algo espe<:ial
llamada OR exclusil'o. El resultado de una operación XOR es \'erdadcro cuando los
dos operandos son distintos y, falso, cuando los dos operandos son iguales. En la
práctica, esta operación se utiliza en cálculos con números binarios, en cuyo caso
seguro que conocemos perfectamente su funcionamiento.
2 4 Manejo de cadenas
Una de las tareas más habituales en los programas informáticos es el uso de cadenas
de texto, tanto si se trata de aplicaciones de bases de datos.como para la simple salida
de mensajes en pantalla. En Gamb.»se han implementado todas las funciones de cade-
nas de te:<to del BASIC e'ltándar más las que están presentes en Visual Bask. Antes de
proceder a su listado, destacar que existe un ·operador" de cadenas de texto que per-
mite concatenarlas directamente, se trata del simbolo &. Veamos un ejemplo de su uso:
Dim Nombre AS String
Dim Apellidos AS String
Nombre -
Apellidos • G6mez H
PRINT Apellidos , M ,\; Nombre
La salida en consola será:
Álvarez G6mez, Manuel
Veamos ahora el listado de las funciones disponibles para manejar cadenas de
texto:
• Asc(Cadella,¡Posició'lj): devuelve el código ASClll del carácter que está en la
posición indicada en la cadena dada. Si no se da la posición, devuelve el c&h-
go del primer carácter.
• Chr$: devuelve un carácter a partir de su código ASCII. Esta función es útil
para añadir caracteres especiales a una cadena de texto, por ejemplo:
PRINT "Manuel
ff
& Chr$(lO) & "Ant.onio"
insertará una tabulación entre los dos nombres, ya que en la tabla ASCII el
código 10 corresponde a un avance de línea (Une Feed).
• hlSrr (Cadena, SlIbcadena (, Inicio J): busca la subcadena dentro de la cade-
na y devuelve un número con la posición donde la encontró. Si se da el valor
1uicio, la búsqueda empezará en esa posición. Por ejemplo:
PRINT Inst.r("Gambas es basic", "bas", S)
devuelve un J1, mientras que:
PRINT Inst.r("Gambas es basic
ff
, "bas")
devuelve un 4.
• RinStr (Cadena, SlIbcadena [ , Inicio J): funciona igual que /nStr, sólo que
empieza a bUSC3T de derecha a izquierda en la cadena.
2_ Programación bósico


Programaclor v l ~ u a l con Software Libre
• Lcase$(Cadena): convierte una cadena a minúsculas.
• Ucase$(cadena): convierte una cadena a mayúsculas.
p. Left$(cadena,n): devuelve los primeros n caracteres de Llna cadena.
• Right$(cadena,n): devuelve los últimos n caracteres de una cadena.
• Mid$(Cadena, posición (,nJ): devuelve una cadena que empieza en posición y
mide n caracteres. Si no se especifica n, la cadena devuelta contendrá todos los
caracteres a partir de posición.
• Replace$(Cadena, patrón, reemplazo): reemplaza, dentro de Cadena, cada vez
que encuentra el texto patrón por el texto reemplazo. Por ejemplo:
PRINT Replace$(ULinEx es una distribución de Linux
u
,
IILin", I'gnu/Lin")
pinta el texto:
Ugnu/LinEx es una distribución de gnu/LinuxU
• Subst$(Patrón, reemplazo] (, reemplazo2, ... ]): sustituye en la cadena patrón los
símbolos &], &2... por las cadenas reemplazo], reemplazo2... Por ejemplo:
PRINT Subst$(UEl alumno &1 tiene &2 añosu,uManuelU,U8
U
)
da como salida la cadena:
UE1 alumno Manuel tiene 8 años
u
.
Evidentemente, el potencial de esta instrucción se muestra cuando las cadenas de
reemplazo son variables de tipo String.
• Len(cadena): devuelve la longitud de una cadena.
• Ltrim$(cadena): elimina los espacios en blanco de la parte inicial de una
cadena.
• Rtrim$(cadena): elimina los espacios en blanco de la parte final de una cadena.
• Trim$(cadena): elimina todos los espacios en blanco de una cadena.
• Space$(n): devuelve una cadena que contiene n espacios en blanco.
• String$(n, patrón): devuelve una cadena que contiene el patrón concatenado n
veces.
• Split( Cadena r, Separadores, Escape, Ignorar_nulos}): devuelve una matriz
de cadenas de texto. Las partes de esta matriz se obtienen al trocear la Cadena
cada vez que se encuentra uno de los Separadores. Si no se especifica ninguno,
el separador se considera la coma (,). Si en algún caso se quiere incluir el
Separador en alguna de las cadenas separadas, habría que colocar el Escape mar-
cand el principio y final de la parte en la que debe ignorarse el separador.
• Ignorar_nulos es un valor True o False, e indica si se deben ignorar o no las
cadenas que resulten vacías como consecuencia del troceado. Veamos un ejem-
plo que explique mejor el funcionamiento:
DIM texto as String[]
DIM texto2 as String[]
texto = Split(UHabía una vez un circo
u
, u U)
texto2 = Split(UHabía una vez iun circoi
u
, u u Ui")

& texto[2] & PRINT texto[O] & U," & texto[l] & U,"
& texto[3]
PRINT texto2[O] & u,u & texto2[1] &
& U," & texto2[3]
11 "
,
11 "

&
2 Programo Ion bO I o
11
Programación visual con Softwore libre
devuelve:
Habia,una,vez,un
H8bia,una,vez,un circo
En el segundo caso se puede ver cómo, aunque el separ.ldor es el espacio en blan-
co, no se ha separado el texto un circo al estar rodeado del carácter de escape.
••• •• 2. 5 Control de tlujo
Son muchas las ocasiones en que el flujo en que se ejecutan las instrucciones en un
programa no es adecuado para resolver problemas.
Todo el código BASIC que hemos visto hasta ahoro ejecuta sus instrucciones de arri-
ba abajo, según se las va encontrondo. Sin embargo, con frecuencia, habrá que vol-
ver atrás, repetir cosas, tomar decisiones, etc. Este tipo de acciones se denomina con-
troj de flujo y el BASle de Gambas proporciona un buen juego de sentencias para
manejarlo.
o '1 IF ... THEN ... ELSE
Es la sentencia más común paro tomar una decisión: si se cumple una condición,enton-
ces se ejecuta algo, en caso controrio, se ejecuta otro cosa.
Su forma más básica es:
IF Ell'presi6n THEN
""'''
osi lo que se ejecuta es una sola instrucción:
IF Expresión TREN sentencia a ejecutar
La sintaxis completa de la instrucción es:
IP Ezpresi6cl I { AMO IP I OR Ir } Ezpred6cl .•. 1 TBEN
BLSE IP ExpresiÓII. 1 ( ANO IP I OR IP } Expresión •.• 1
..".
J
Algunos ejemplos de uso:
DIM Edad AS Int.eger
Ir Edad > 20 TBEN
PlUJfT -Adult.o-
END"
IP Edad > 20 'ftlEH PIU1fr "Adulto-
IP Edad < 2 AMO Bd.ad >O 'l"HEN
!:LSE IF Edad < 12 THEN
PRIN'l' "Ni.ño-
ELSE IP Edad < 1B 'l'HEN
PRIN'l' "Joven-
Dependiendo del valor que tuviera la variable Edad al llegar al primer IF, se impri-
mirá un resultado distinto.
11
XIOfl l;IOSICQ
11
Programoción viwol .011 Softwore ülxe
En el caso anterior vimos que en ocasiones el flujo dd programa necesita revisar
varias condiciones sobre una misma variable, produdtndo un lfd("f¡tro de otro (IF
anidados). Esa estructura no es cómoda de lef:r ni produce un código limpio. Pan.
estos casos aisle la sentencia SELEcr. que es mucho mas apropiada. Su sintaxis es.:
SELEC'1' ( CASI: I EXpresión
r CASE E;qlresi6a ( 1'0 &xpresión f2 ) ( • ... 1
••• J
1 CASE I 1'0 Expresi6n 12 1 [ , ••• 1
I { CASE ELSE I DEl'AULT }
Veamos cómo se aplica al mismo ejemplo anterior de las edades:
DIM Edad AS ll1t.eger
SELEC'1' CASE edad.
CASE O ro :2
PRlNT ya puedes votar"
CASE 13 1'0 11
PRINT
CASE ELSE
PRINT "Adulto"
"'" SELECT
Se trata de un código mucho mis fácil de leer que el anterior.
FOR
Cuando se hace necesario contar o realizar una acción un número drterminado de
veces, la sentencia fQR es la solución:
FOR variable - Expresión. '1'0 EIpresión [ STEP Expresión J
El bucle incrrnlenta la Variable de uno en uno. a no ser quC' se especifique un valor
a STEP. Se pueden espedficar valores negativos, de (orma que se convertirla en una
cuenta atrás. Por ejemplo:
DDK D AS I D ~ e g e r
POR D - 10 Te 1 STEP -1
Si se quiere interrumpir un bucle en algún punto, se puede usar la sentencia BREAK:
DIM n AS Integer
POR Il - 10 ro 1 STEP _1
PRlNT n
NEXT
FJ bucle aeobaria <;U:I.noo n valí"", 3Yno se escribirlan los últimos 3 numeros. Tambitll
se dispone dI" la sentencia CONTINUE, que permite saltarse pasos en d bucle:
DIM D AS Integer
FORn-1Ta4
IF n-2 TREN CONTlNUE
PRINT n
11

Se saltaria el 2 al escribir los valores de n. Existe una vilri,lnlC del bucle fOR que
5t usa al rt<:orur dementas de una colección. como una matriL La sintaxis en este
caso es.:
POR UCB Variable 1M Expresión
Pongamos un ejemplo u$3ndo las matrices dinámicas que ya hemos visto en este
capillllo:
DrM Matriz AS StringlJ
DIM Elemento AS String
Matriz - NEW Strinq[l
Matriz.AddC-Aaul-)
Matriz·A6dC-Rojo-)
Natriz·A6dC-Verde·)
POR EACII B l ~ t o XIf Natris
PRIft El_nto;
Escribirla como salim: AzulRojoVrrde.
WHIl..E y REPEAT
Cuando se quien: repetir la ejecución de una porción de código en varias ocasio-
nes dependiendo de una condición, tenemos dos instrucciones distintas: WHILE y
REPEAT.
Su oomponamiemo es casi idéntico. la diferencia estriba en que si la condición nece-
safia para que se ejecute el código es falsa desde el principio, con REPEAT se ejecu-
tara una va y con WHILE no se ejecUl3rá nunca. La sintaxis de ambas es:
HIIILE COndición
instrucciones
y
.•. instrucciones
UNTIL COndición
En el caso del bucle WHILE existe una variante de la sintaxis consistente en susti-
tuir WHILE por DO WHILE y WEND por LOOP. Es exactamente lo mismo; depen-
de del programador elegir un formato u otro. Veamos un ejemplo:
DIM a AS Integer
.. ,
HIIILE a <- 10
PRINT NHola Mundo N i a
,,'" .
.. ,
PRINT NHola Hundo N i a
,,'" .
UNTIL a > 10
Este ejemplo producirá el mismo resultado en la ejIXución del bucle WHILE que en
el del REPEAT, en ambos casos escribirá diez veces "Hola Mundo" junto al valor de
la variable a que se irá incrementando de 1a 10. El uso de estas estructuras puede
ser peligroso. Si durante la ejecución del bucle no hay forma de que la condición
pase de ser verdadera a falsa, estaríamos ante un bucle infinito y el programa entra-
ría en situación de bloqueo.

p
oepul'acion En €I DE de Gambas
Una VC'Z escrito parte del código de un programa, lo usual es comprobar si funcio-
na, pero lo habitual es que la mayor parte de las veces no lo haga m el primer inten-
to. Tanto si se es un programador aperimentado como si no, los fallos son parte de
la rutina. Saber encontrarlos y corrtgirlos 1:5 lo que S(' denomina depuración, y es
una de las tareas más importantes a reliizar. Cuando son fallos de sintaxis, el entor-
no de desarroUo suele darnos mensajes indicativos del problema, parando la ejecu-
ción en la linea ni que M: produce.
otll ;1)elO AS ....\1
Otll .Fo.. AS
figurg 1.1'un1o de interrupción en lo linea
de código.
r ••tl
1'(8.j( sta 1ot __(hc1C 1
..
Cuando se adquiere una cierta soltura con el lenguaje, los fallos de sintaxis son cada
vez menos comunes, pero los fallos en la lógica de la ejcwción del programa se pro-
ducirán siempre. Cuando esa lógica pasa, además, por instrucciones de control de
flujo como las que hemos ViSIO en este capítulo, la dificultad en encontrar los erro-
res es mayor, puesto que la aplicación transcurre en distintas ocasiones por la misma
porción de código y es posible que el falJo no se produzca la primera vez que se eje-
cUle ese código.
Para facilitar esta tarea, eliDE de Gambas dispone de distintas herramientas de dqm-
ración. La primera de ellas es la posibilidad de fijar puntos de interrupción. Es decir,
señalar sitios nl los que el programa se
parará para permitir vtr d estado de las
variables y en punto de la ejecución
se enCUnltra.
Para fijar un punto de interrupción en
una linea de código, tan sólo hay que
colocar el cursor del ratÓn en esa Unea
y pulsar la teda F9 o el botón con el
slmbolo de la mano levantada, que está
en la parte superior de la ventana de
código. Las Uneas en las que se fija un
punto de interrupción tienen el fondo
en rojo.

La misrrna opm¡ción que: crea el punto la eli-
mina, es decir, pulsando F9 de nue'iO d fondo
rojo La ejecución del progra-
ma, como se explicó en el capitulo anterior,
se arranca pulsando en el simbolo verde de
Play de la ventana de Proyecto (o pulsando
la tecla de función F5). Junto al botón verde
CIlt se encuentra un botón de Pausa, que permi-
figura 2. Ejecución del programa te parar la ejecución, y otro más de Stop que
desde la veolallll Proyecto. permite detenerla en cualquier momento.
Si se quiere correr la aplicación ejecutando una a una las instrucciones para ir obser-
vando por dónde transcurre el flujo del programa, se puede pulsar la tecla de fun-
ción F8 o cualquiera de los dos botones que se encuenttan a la derecha del símbolo
de Stop. Hadendo esto, d entomo de desarrollo saltará a la primer'a linea que se deba
correr e irá ej«utando Unea a !inta cada V(l. que pulsemos F8, o el icono que mues-
tra la flecha entrando entre las Uaves, mencionado anteriormente. El botón que está
justo a la derecha del Stop y que muestra una flecha saltando por encima de las Ila·
ves, parece producir el mismo efecto (su tecla rápida es Mayúsculas + F8), pero no
es asl: el comportamiento cambia cuando el programa llegue a una llamada, aUlla
subrutina o a una fundón. En este caso, este icono ejecutará la llamada y todo lo que
tenga que hacer la función o subrutina en un solo paso, sin que veamos el flujo del
programa por el procedimiento. Si pulsado F8 habrfamos entrado en
la subrutina y visto también paso a paso eómo se ejecutan las instrucciones. Por
tanlo, con estos dos botones podemos elegir cuando lleguemos a la llamada a un
pJ'lXffiimienlo, si quttmlO$ depurar ese procedimiento Osimplemente
cutarlo y pasar a la siguiente línta de código.
Finalmente, cuando pausamos la ejecución del programa, aparecen tres nuevas pes-
tañas en la parte inferior de la ventana de proyecto. En la pestaña Local se ven todas
[as variables del procedimiento que se está ejecutando y el valor que tienen en ese
momenlo. En la pestaña Pila se ve el listado de llamadas enlre procedimientos que se
han producido hasta llegar a ese punto del programa. Así, podemos saber a través de
11
""
.. F'9UfV 3. Ptitoñas loco!, .... Y
de lo __lona Proyedo.
ProwamociÓl1 SoHwore ubre
qué pasos se ha llegado a esa instruc-
ción. Finalmente, en la pestai'la
V3r podemos introducir cualquier
expresión en BASle, incluyendo ope-
racionn con las variables que el pro-
grama tmga declaradas para ver cuál es
el resullado o el valor que lienen en el
momenlOde la pausa.

-
- -
"
11
2. 6 Entrada y salida: ficheros
En este aparlado veremos la forma más común de trabajar con ficheros en Gambas.
Gambas trata los ficheros como un flujo de datos (la palabra exacta para esto es
Stremn), lo que tiene una implicación muy cómoda: todos los flujos de datos se tra-
lan de igual manera, con lo que el código para manejar un fichero es igual al códi-
go para manejar una conexión de red o un puerto de comunicaciones, puesto que
todos son de tipo Strtam. Las operaciones tradicionales con un fichero $On
abrirlo, crearlo, escribir y Ittr datos. Veamos cómo se usan:
Archivo - OPElf lk:ab", de Archivo FOR REAl) I IRPUr 1
( MRtftl 1otn'PUT I ( CREA'1'E I APPEHD [lfM"CH I
Abrimos un archivo con dislinlas finalidades:
• REAO o INPUT: para leer datos, en el primer caso no se usa buffer de datos,
con INPlIT 51 que hay un buffer intermedio.
• WRITE o OUTPUT: para eS<:ribir datos, con WRITE no hay buffer de datos,
con OUTPUT s( se usa.
• CREATE: si el fichero no existe se crea. Si no se usa esta palahra, el fichero debe
existir antes de abrirlo o dará un error.
• APPEND: los datos se afladen al final del fichero.
• WATCH: si se especifica esta palabra, Gambas lanzará los eventos (que vere-
mos más adelante) File_Rf'<ld y File_lVrite en caso de que se pueda If'('r y escri-
bir en el archivo.
Ahora. cerremos un Archivo que ha sido abierto con la sentencia OPEN.
CLOSE [ , 1 Archivo
Escribimos. convirtiendo en cadena de texto, la Expresión en el Archi\'o abierto anle-
riormente.
PRINT [ 'Archivo , J Expresión J
Si no se especifica ningún archivo, tecleamos la expresión en la consola, como se ha
visto en distintos ejemplos a lo largo de todo este capítulo. la instrucción PRINT
admite un cierto conlrol de cómo se colocan las expresiones, dependiendo de algu-
nos signos de puntuación que se pueden colocar al final de la sentf'ncia:
• Sí no hay nada desputs de la ExpresióIJ, se añade una nueva línea al final. Por
tanto, la salida de la siguiente instrucción PRINT será en una linea nueva.
• Si hay un punto y coma detrás de la ExprcsiólI, la siguiente instrucciÓn PRTNT
se escribirá justo detrás de la salida anterior, sin espacios, lineas o tabulacio-
nes intermedias.
• Si hay un punto y coma doble, se añade un espacio entre las expresiones, lo
q u ~ permite concatenar expresiones en una misma línea usando distintas sen-
tencias PRINT.
,Si se utiliza una coma en lugar de un punto y coma, se añade un;! tabulación.
con lo que tambitn se pueden concatenar expresiones en una misma línea.
2 Programación básico
11
11
Prograrr :ión VIS Jol con 50ft vare libre
- ---
Seguidamente, escribimos, sin convertir en cadena de texto, la Expresión en el Archivo
abierto anteriormente. Es una instrucción que suele usarse en lugar de PRJNTcuan-
do los datos a escribir no son cadenas de texto, como en el caso de archivos binarios.
NRlTE [ 'Archivo , J Expresión [ , Longitud 1
En cualquier caso, también puede usarse con cadenas de texto y permite indicar, con
el parámetro longitud, el numero de caracteres que se desean sacar en cada opera-
ción de escritura. Al contrario que con PRINT, no se pueden usar signos de pun-
tuación para controlar la posición de la escritura.
INPUT I 'Archivo , J Vadablel r , Variable2 ... J
Leemos, desde un Archivo, un dalo y asignamos su valor a Variablel, Variable2, etc.
Los datos deben estar separados en el archivo por comas o en distintas líneas. Si no
se especifica el Archivo, leemos los datos desde la consola, esperando que el usuario
de la aplicación los introduzca.
READ ( 'Archivo, J Variable I , Longitud)
Se puede decir que es la instrucción opuesta a WRlTE. Leemos del Archivo datos
binarios y les asignamos su valor a la Variable. Sí ésta es una cadena de texlO, se puede
fijar la Longitud de la cadena a leer.
LINE INPUT r 'Archivo , J Variable
En una línea de lexto enlera del Archivo, le asignamos a la Variable. No se debe usar
para leer de flujos binarios.
Eaf ( Archivo )
Devuelve True (verdadero) cuando se llega al final del Archivo y Fa/se (falso) en caso
contrario.
Lof ( Flujo )
Si el Flujo de datos o un archivo, devuelVe' su tamaño. Si en lugar de un archivo o
un Socker de una co0ai6n de red o un objelo Proass. devuelVe' el número de byto
que puedt:n 1«rsC' de una sola vez. Una Ve'Z vislas las SC'nlencias más comuno para
el manejo de flujos de dalos, veamos algunos ejemplos de uso:
Leer dato. de un puerto .eI;"1e,
(Requiere seleccionar el componente
proyecto)
DIM Archivo AS File
gb. net en el ...:J
, El evento File_Read .e produce cuando baya dat.oli ...:J
que
PUBLIC SUB File Read()
DDt iByt.e AS Byte
READ 'Archivo, i8yt.e
PRIHT un byte, i8yt.e
"'"
'Lee el contenido del fichero Iet.c/pasawd J lo
....est.r. en l. consol.,
DIM Archivo AS File
DIM Line. AS Std.ng
Archho • OPEM P'OR. lNPU'l'
WHILE MOr Eof(Archivo)
LIME INPUT 'Archivo, Line.
PRIHT Linea
.....
CLOSE Archivo

11
11
2. 7 Control de EI'"J"Or-es
Es seguro que, tn alglln momento, en la mayor parte de los programas, bien por
acdones dd uSUólrio del prognama, bien por el propio nujo de la ejecución. se pro-
ducen errores, como intentar borrar un fichero que no existe, hacer una división
por cero, conectar a un servidor web que no responde, etc. En lodos estos casos,
Gambas muestra un mensaje: en pantalla y, a continuación, el programa se
y deja de funcionar. Es evidente que ése es un comportamiento que d desarro-
llador no desea y debe poner las medidas oportunas para evitarlo. La forma de
hacerlo es implcmell1ando un control de errores para que la aplicación sepa lo
que debe hacer en esos casos. Gambas implementa las instrucciones necesarias
para caplurar los errores y procesarlos según los deseos del programador. Las ins-
trucciones para ello son:
• TRY Se"rlllóll: ejecuta la sentencia sin lanzar el error aunque se produzca, el
programa continúa por la instrucción que haya desputs del TRY, tanto si hay
error como si no. Se puede saber si existe error funsultando La sentencia ERROR
que valdroi verdadero °falso. Por ejemplo:
Borrar el archivo aunque PO e.iat.
TU 1tn.L
, Cc::q:lrobar ai ha tenido é.ito
IP ERROR '1"SEIf PRIIft' .Me> fue posible el1.l"",r el archivo·
• FlNAUY: se coloca al final de un procedimiento. Las instrucciones que sigucn
a continuación se ejecutan siempre, tanto si ha habido un error en el procrdi-
miento como si no lo ha habido.
'CATCH: se coloca al final de un procedimiento. Las instrucciones que siguen
a continuación se ejecutan sólo si se ha producido un error ellla ejecución del
procedintiento (incluyendo si el error se ha producido en subrutinas o fun-
cioncs llamadas desde el miSntO procedimiento). Si existe una instrucción
F1NALLY, ha de colocarse delante de CATCH.
Veamos un ejemplo de FINALLY y CATCH:
, Mostrar un archivo en la consola
SUB PrintFile(Nombre_Archivo AS String)
DIM Archivo AS File
DIN Linea AS String
OPEN Nombre Archivo FOR READ AS 'Archivo
WHILE NOT EOF(Archivo)
LINE INPtrI' 'Archivo, Linea
PRINT Linea
FINALLY Siempre se ejecuta, incluso .. hay error
CLOSE I Archivo

CATe"
.
s• ejecuta s6lo .i hay error
PRINT "Imposible mostrar el archivo
..
Nombre Archivo

EHD

2. a Programación orientada a objetos
con Gambas
BA$IC es un lenguaje de programación estructurada. Esto significa que los progra-
mas tienen eIlIujo que hemos visto hasta ahora: empiezan en un punto de una subru-
tina y van ejecutando las instrucciones de arriba a abajo, con los saltos correspon-
dientes a las llamadas a procedimientos y distintas funciones de control del flujo
como bucles, condiciones, etc.
Este IÍ¡xJ de programación permite re;olver la mayor parte de los problemas y, de hecho.
se ha estado usando durante muchos anos. A día de hoy, se siguen desarrollando
11
aplicaciones con lenguajes. como BA51C o e, de programación estructurada. Sin
embargo, desde finales de Jos años 70 se ha venido trabajando también en otro para-
digma de programación: la programación orientada a objetos. Los lenguajes que
adoptan este paradigma, como Smalhalk, Java o C++, intentan modelar la realidad.
La ejecución de estos programas se basa en la interacción de los distintos objetos que
definen el problema, lal y como ocurre en la vida normal, en la que los objetos, per-
sonas y animales nos movemos, enviamos mensajes unos a otros y ej('{;utamos accio-
nes. La programación orientada a objetos se usa cada Jia con más frecuencia por-
que permite una mejor división de las tareas que un programa debe hacer, facilita la
depuración y la colaboración entre distintos programadores en los proyectos que
son de gran tamaño y, en muchos aspectos, tiene un potencial mucho mayor que la
programación estructurada.
Por todas estas razones, es común que se aiiadan características de programación
orientada a objetos a lenguajes que, como BASIC, en un principio no la tenían.
Gambas permite hacer programas estructurados a la vieja usanza, escribiendo el
código t'n Módl¡/OS, como hemos visto. Ytambién posibilita la programación o r i e n ~
lada a objetos mediante el uso de Clases. Es más, para la programación gráfica y el
uso de la mayor parle de los componentes que se añaden al lenguaje, no hay más
alternativa que el uso de objetos.
Podemos ver cómo funciona todo esto en Gambas pensando en el caso de que tuvié-
ramos que escribir un programa que simulara el comportamienlo de un coche.
Us.1ndo la programación orit'ntada a objt'los, dt'finiríamos cada una de las partes del
coche mediante un archivo de clase en el que escribirfamos el código BASIC n e c e ~
sario para definir las características de esa parle y la interfaz con la que se comuni-
ca con el mundo real. Por ejemplo, definiríamos cómo es un volanle, cómo es una
rueda, cómo es un asiento, un acelerador, un motor, etc. Después, y basándonos en
eS;1 definición, crearíamos cada uno de los objetos para crear el coche: un volante,
cuatro ruedas, varios asientos, un motor, un acelerador, etc. Cada uno de esos obje-
tos respondería a cierlos mensajes. Por ejemplo, el volante respondería a un giro
actuando sobre el eje de las ruedas, el motor respondería incrementando sus revo-
luciones si recibe una presión del acelerador, ete.
Cada vez que crealnos un objeto basándonos en el archivo de clase que lo ha defini-
do, decimos que el objeto ha sido instanciada. Se pueden instanciar tantos objetos
como se desee a partir de una clase y una vez creados tienen vida propia, son inde-
pendientes unos de otros con sus propias variables internas y respondiendo a las dis-
tintas acciones según hayan sido definidos todos en la clase.
Otra de las caracterlsticas de la programación orientada a objetos es la Herencill.
Cuando un objeto hereda de otro objeto significa que es del mismo tipo, pero que
puede tener caracterlsticas añadidas. Por ejemplo, supongamos que definimos la clase
cuadro_de_texto con ciertas caraeterfsticas como tamaiío de texto, longitud, etc. A
continuación, podemos crear objetos de esa clase y son clIadros_dejexto. O:m Gambas
podemos, además, crear una nueva clase, por ejemplo: cuadro_de_texto_mllltilíltea
que herede de cuadro_dejexto. Eso significaría que un cuadra_de_texto_multilílJea
es un Cfwdra_de_texto al que se le añaden más cosas. Todo el comportamiento y pro-
piedades del cumlra_de_texto ya están codificados y no hay que volver a hacerlo.
Veamos un ejemplo sencillo que aclare algunos conceptos, para lo que vamos a crear
en el entorno de desarrollo un nuevo proyecto de programa de texto. A continua-
ción, le añadimos un Módillo con un nombre cualquiera y dos archivos de clase, a
uno lo llamamos SerVivo y a otro Hombre.
tste es el código que debemos escribir en el archivo de clase SerVivo.c1s:
, Gambas class file
PRIVATE patas AS Inteqer
PRlVATE nacimiento AS Inteqer
PUBLIC SUB nacido(fecha AS Date)
nacimiento· Year(fecha)
END
PUBLIC SUB PonePatas(numero AS Inteqer)
Patas • numero
END
2 Programacion bó.ico
11

Progromación vi§uol con SoHwore ubfe
PUBLIC FUNCTION edad () AS Inteqer
RETURN Year(Now) - nacimiento
"'"
PUBLIC FUNCTION dicePatas() AS Inteqer
RETURN patas
"'"
!:.sIl' es el código a escribir en el archivo de clase Hombre.e/s:
• Gambas clas5 tile
INHERlTS SOrVivo
PRlVATE Nombre AS String
PRlVATE Apellido AS String
PUBLIC SUB PoneNombre(cadena AS String)
Nombre - cadena
PUBLIC SUB PoneApellido(cadena AS String)
Apellido - cadena
"'"
PUBLIC FUNCTION Nanbrecaopleto() AS String
RETURN Nombre & H H " Apellido
"'"
y éSle el código a escribir en el Módulo que hayamos creado:
• Gambas ~ u l e file
PUBLIC SUB MainO
DIM mono AS SerVivo
DIM tipejo AS Hombre
mono" NEW SerVivo

mono. PonePatas(3)
PRINT mono.edadO
PRINT mono.dicePatas()
tipejo .. NEW hombre



PRINT Upejo.edad()
PRINT tipejo.NombreCompleto()
"'"
Veamos los tres archivos, empezando con el dt' clase SerVivo.e/s. Tiene un código
muy simple: declara un par de variables, un par de subrutinas con las que se puede
asignar el valor a esas variables y dos funciones con las que devuelve valores de algu-
nos cálculos realizados sobre las variables y la fecha actual.
El archivo Hombre.e/s es muy similar, pero con una sentencia nueva: al inicio dd
fichero se ha colocado la instrucción INHERITS $erVivo. Al haber hecho eso esta-
mos diciendo que todos los objetos que se instancien de la clase Hombre serán obje-
tos SerVivo y, por tanto, tendrán tambi"'n las mismas funciones que un SerVivo y
podrán realizar las mismas operaciones.
Si hubieran sido necesarias algunas labores de inicialización de los objetos al ser
creados, se harían añadiendo al archivo de dase una subrutina con la sintaxis:
PUBLlC SUB _New(). Todo el código que se escriba ahí se ejecutará cada vez que
se cree un objeto.
Y, finalmente, el módulo y su procedimiento Maill. Ahi se declaran dos variables:
mono y tipejo, pero en lugar de declararlos como uno de los tipos de datos que
vimos en los primeros apartados de este capítulo, se dedaran como objetos de la
2. Programación básica

11
PiQ9romociC!'!.-,:isuol con Software ubre
clase SerVivo y Hombre. Por tanto, hablando con propiedad, mono y tipejo no son
variables, sino objetos. Las clases corresponden a los nombres de los dos archivos
de dase que hemos definido. Además, vemos que para crear un objeto de una clase
es necesario usar siempre la palabra NEW', lo que provocará además que se e j e c u ~
le el código de la subrutina _New del archivo de clase, si esta subrutina existiera.
Una vez que el objeto ha sido creado, podemos acceder a sus subrutinas y funcio-
nes escribiendo el nombre de un objeto y el procedimiento separados por un punto.
Sólo podemos acceder a los procedimientos que hayan sido declarados en el archi·
va de clase como PUBLle.
Aparte del ahorro de código obvio qu!.' supone para la clase Hombre no tener que
escribir las funciones que hace un SerVivo, hay algunas consecuencias más impor-
tantes que se deducen de este ejemplo. Tal y como está escrito, se podría alterar el
código de la clase SerVívo, modificando y cambiando variables, y el programa segui-
ría funcionando igual, sin tener que tocar en absoluto la clase Hombre.
Es decir, se puede, por ejemplo, mejorar el método para cakular la edad, teniendo
en cuenta el día de nacimiento dentro del ano. También se puede cambiar el nom-
bre de las variables y no afecta a la clase Hombre y al resto del programa. Otra de las
posibilidades que existe es el uso de los archivos de clase tal y como están en otro
proyecto donde, del mismo modo, se necesiten seres vivos, reutilizando de forma
sencilla el código ya escrito.
Se han elaborado multitud de libros y artículos sobre la programación orientada a
objetos. La pretensión de este apartado es únicamente servir de mera introducción
general y e:-:plicar la sintaxis necesaria para su uso con Gambas. L1 mejor forma de
aprender, disfrutar de ella y obtener todo su potencial es probando y viendo ejem-
plos que la usen extensivamente.
El código fuente del entorno de desarrollo de Gambas han· un uso muy amplio de
clases yobjetos, con lo que es una fuente completa de ejemplos. Está disponible den-
tro del directorio apps/src/gambas2 del fichero comprimido que contiene los fuen-
tes de Gambas.
2. 9 Propiedades. Metados y Eventos
Los componentes que cxlimden las posibilidades de Gambas son dt distintos tipos,
pero lodos dios COnllenm clases que definen distintos objetos. En d ClSO de los com-
ponentes que sirven para crtar interfaces gráfICas, estos objetos incorporan un icono
a la Ca;a de Herramientas del entomo de desarrollo. No hay que crear este tipo de obje-
tos escribiendo tl código correspondiente yla palabra NEW, sino sólo dibujándolos
sobre un formulario despub de haber pulsado el botón con el icono respectivo. Es el
entorno de desarrollo ti que SI' encarga de escribir el código necesario para crearlos.
Cw1quiera de los objetos que SI' auna panir de los componentes lienen ya un com-
ponamiento definido en su clase. Este componamimto la interfaz con la que
los objetos se van a comunicar unos con OITOS en el programa, y lo nt'Ctsario para
que ti programador pueda definirlos y haenlos actuar a su conveniencia. Para faci-
litar esas lareu, estos objetos disponen de Propiulodes, Mirados y El't'PI'OS. La:; pro-
piedades permiten cambiar parámetros del objeto. En u:alidad. al darle un valor l
una propitdad no estamos sino asignando valores a algunas variables del objeto que I
bte interpreta internamente para producir un efecto. Por ejemplo, podemm asig-
narle a un formul3rio un valor numérico a la propiedad B(lckgrolllu/, y con ello le
cambiaremos el color del fondo. Para modificar las propiedades disponemos de la
ventana de Propiedades en elIDE (visible al pulsar F4 o desde el menú de la ven-
tana de Proyecto: Vista I Propiedades). que nos permite hacerlo con una interfaz
gráfKlll sencilla. También podemos cambiar una propiedad mtdiante código hacien-
do referencia al nombre del objeto y a la propiedad. separados por un punto. Por
ejnnplo: dejaria el fondo del formulario Fonrrl en color negro.
Los mhodm son las funciont'$ que el objeto puede realizar. Sólo pueden asignarse
mediante código y cada objeto tiene su propia cole<:ción de métodos. Por ejemplo:
brn5/llir.Hide harla que el botón btllSalir se ocultara. Finalmente, los eve¡¡/os son
subrutinas que se ejecutan para indicar algo que le ha ocurrido al objeto. Un ejem-
plo que ya vimos en el capitulo anterior es el evento Click del botón que se ejecuta
cuando hacemos dic con el ratón. Los eventos son, en las aplicaciones gráficas, los
que marcan el flujo del programa. De he<:ho, oon frecuencia se dice que Gambas es
un lenguaje de programación orientado a eventos. Es el usuario de la aplicación al
interaccionar, el qm: obliga al programa a ejecutar código respondiendo a sus accio-
nes. Los objel:os en Gambas avisan con los ~ t o s cada. va que: se produce una acción
s o b ~ dios. Es el programador el encargado de escribir en las subrutinas que tratan
los eventos el código neccurio para responder a eUas..
El entorno de desarrollo proporciona varias formas de conocer los métodos, even-
tos y propiedades que un objeto puede entender. la primera y mis obvia es usando
la ayuda, donde se puede encontrar el listado de todas las clases de objetos disponi-
bles, con todas las explicaciones yel listado completo de las propiedades. El editor
de código también suministra información, puesto que al escribir el nombre de un
objeto y pulsar un punto, aparece un menú contextual con d listado de las propie-
dades (en color violeta) y métodos (en color verde) que el objeto tiene disponibles.
Para los objetos gráficos hay algunas ayudas
• , 4 ~

más. El listado de propiedades disponibk se


1


-
,,(l..., I
puede ver en la ventana de Propiedades.
~ .....-
-
_.
_._-
--
- Para los eventos podemos hacer c1ic con el
. ~ ~ ..
"
.-
- - botón derecho sobre un objeto grifico en su

"
-'-
-
-
fonnu1ario. Apa.recná un menú donde, e n t ~
-
-
-
otras, vemos la opción ~ ~ t o . Podemos de-
-
-
_.
-- gir el evento que queramos y, automática-
_.
-

-
mente, el entorno ya escribini el código
-
-
correspondiente al principio y al final del
-
procedimiento. Figura 4. Ev.nlo Oick.
NOTAS
I Los ordenadores s4Io enhenden de número., no de letras Para poder usa, camcle-
res se aplican tablas de conversión que asignan un número a código o cada carác·
ter. la tobla de cooveni6n usada normalmente se llama ASCII
En h"p://e.,wikipec!ia.org/wiki/Auii se pvede ve' lo toblo completa
3. I Concepto
Si bien Gambas, como cualquier aIro lenguaje de pro-
gramación bien diseilado, puede trabajar perfe1:lamentc desliga-
do de toda libreria gráfica, creando programas de consola, uno de sus pun-
{OS fuerles es la sencillez para crear interfaces gráficas de usuario.
En d mundo GNUfLinux ha aíslido, a Jo Largo de la historia, divns,u librmas que
facilitan la (nadón de dichas inlerfaces. Al nivd más bajo, d tradicional siSlemól
X· Window tan sólo proporciona una API para mostrar vrntanas, dibujar lineas,
copiar mapas de bits y poco más. Sobre dicho sistema, una de las primeras libre-
rías de aporo que proporcionaba controles completos, tales como botones o eli-
qurtas. fue la MotiP", tradicional de sistemas UNIX"". Su don libre, Lesslif, pro-
bahlemenle l1eg6 demasiado larde al escenario para lener un papel relC'vanle.
---

11
lrc 1
Las interfaces creadas con estas dos librerías han tenido siempre fama, además, de
ser bastante feas o incómodas, especialrnrnle a ojos de los usuarios de Windows.... ,
y no hay que olvidar que de este sistema propietario proviene buena parte de los
actuales usuarios de escritorio GNU/Linux.
La compañía TrollTechn" por su parte, creo las librerías QT, para el desarrollo dl."
aplicaciones gráficas con C++. Estas librerías, en principio, se distribu[an bajo una
Ikencia, la OPL, no totalmente compatible con el proyecto de la Free Software
Foundation. Su inclusión wmo hase del proyecto de escritorio KDE generó un gran
revuelo, y el rechazo de un sector de la comunidad hacia ambos proyectos (QT y
KDE). En la actualidad, [as líbredas QT en su roidón no comercial, se distribuyen
bajo licencia GPL, lo cual implica que los programas desarrollados y compilados con
QT como base, han de ser también Software Libre compatible con la GPL. Un pro-
grama que no cumpla esta norma, habría de ser compilado sobre la versión comer-
cial de QT, que la compañia ames citada vende y soporta.
En parte como rechazo al tándem QT/KDE, y en parte para crear una alternativa al
popular escritorio KDE, surgió el proyecto GNQME, que está basado en las libre-
rías GTK+.
GTK+ se desarrolló al principio como una libreria gráfica escrita únicamente para el
popular programa de dibujo The Gimp (de hecho, GTK significa Gimp Tool Kit). Pero
más tarde se escindió de este proyecto para convertirse en una librería de propósito
general, especialmente diseñada para desarrollos en lenguaje C. Hoy en dia, lodo el
proyecto GTK+ está dividido en varios bloques y niveles: Glib, utilidades de carácter
general sin relación con la interfaz gráfica: Gobject para dotar, de cierta orientación
a objetos al lenguaje C; Atk, que es un kit de accesibilidad; Fango, para la gestión de
fuentes; Gdk, para el dibujo de bajo nivel; y, finalmente, GTK, que proporciona los
elementos de la interfaz gráfica habitulll. Lllicencia de GTK+ es LGPL, por lo que ha
sido utilizada, además de en muchos proyectos de Software Libre, en programas grá-
ficos privativos que no desean contar con el soporte de la versión comercial de QT
porque la han visto como una alternativa más cómoda en sus desarrollos, o han deci-
dido reducir los costes al no tener que pagar por la librería gráficll.
Al margen de estos pesos pesados, hay nombres como FOX, FLTK o WxWidgets, que
también resuenan como alternativas para el desarrollo de programas gráficos.
Por tanto, hay muchas alternativas (toolkits) para desarrollar interfaces, y al menos
dos de ellas (QT y GTK+) sirven como base para los dos escritorios más comunes
(KDE y GNOME), que a su vez aportan un aspecto y funcionalidades diferentes. No
obstante, una aplicación KDE puede funcionar en un entorno GNOME y v i c e v e r ~
sa, a costa, quizá, de perder homogeneidad en el entorno.
Gambas ha decidido ser neutral al respecto. Aporta una interfaz de alto nivd, senci-
lla para el diseño y programación habituales, que no está ligada a los conceptos de
QT, GTK+, ni a ninguna otra Iibreda gráfica subyacente.
No obstante, a la hora de implementar dicha interfaz sí que es necesario emplear
alguna librería de sustento por debajo, escrita en C o C++. Por tanto, existen dos
componentes gráficos que proporcionan al programador libertad de elección: gll./11
y gb.gtk. Como se puede suponer por sus nombres, el primero utiliza código c o m ~
pilado con QT y el segundo código compilado con GTK+.
La particularidad de Gambas es que el código escrito para gb.t¡1 funcionará exacta-
mente igual si reemplazamos este componente por gb.gtk y viceversa. Por lo talllo,
el programador en cada momento puede elegir el que más se adapte a sus necesida-
des por diversos motivos, por ejemplo:
• Integración con KDE, GNOME o XrCE (este último, un escritorio ligero basa-
do en GTK+).
• Aspecto final. Algunos programadores y usuarios se sienten más a gusto con
una aplicación QT, Otros con GTK+.
• Cuestiones de rendimiento, uso de recursos.
• Licencia, costes en software comercial.
3. lo intedoz gráfico
11
Progromoc;Ó!l viwol con Softwore ü ~
• Nece5idades especiales. GTK+ se pufiie compilar sobre DireclFB, un sistema
gráfico alternativo a X-Window, ligero y apIo para sistemas empotrados. Tal
vugb.ql se pueda compilólr en el futuro sobre Qtopia, la libreria de TroUTech'"
generalmente empleada en POAs.
a o [J o PartiEndo de la consola
Vamos a empaar por el camino dificil para comprender cómo la interfaz gráfica
no es más que otro accesorio de Gambas. que al igual que el resto de componen-
les, aporta clases a partir de las cuales crearemos objetos. en este caso Controles o
Widgets.
Crearemos un proyecto de consola, (si, de consola), llamado Ventana. Afladiremos
un módulo modMain y una referencia al componente gb.qt.

----,
o ... a- ..... 'lIJ Q
.."'1'1 •
1
";;.
0-
."-
-
11'> ·, ,," .. P
-_.-,!.
-... ...._.
-
. ,
------
Escribiremos ahora el siguiente código:
PUBLIC SUB Main()
DIM hlfin AS Kindow
hNin - NEN Nindow
hWin.Show()
AJ ejecutarlo, aparece una ventana solitaria en la pantalla, que desaparecerá cuando
pulsemos el botón Cerrar del gestor de ventanas.
Las ventanas son contenedores de primer niveL Un COllfcni'dor es un control que per-
mite situar otros en su interior (botones, cuadros de tcxto, cte.). Y el adjetivo de pri-
mcr nivel se refiere a que no tiene un padre, es decir, que no cuelga de otro control
de nuestra aplicación, sino directamente del escntoría.
En este progf3111a podemos ver varios efectos, a primera vista, extraños. El primero
es que hemos declarado hWin como una variable local, asf pues, parece que al fina-
lizar la función Main el objeto debería destruirse. Esto no asf ya que la ventana, al
ser un control, mantiene una referencia interna (los objetos Gambas sólo se destru-
yen si no existe una referencia en toJo el programa). Dicha referencia paJemos decir
que se corresponde con la ventana que está dibujada en el servidor gráfico, con la
intermediación de la librería gráfica (en este caso QT). Por otra parte, el programa
debería haber finalizado al terminar la función MainO y no ha sido así.
El segundo efecto se debe a que tanto el componente gb.qt como el componente
gb.gtk son llamados automáticamente tras el método MainO del programa, y queda
en el lazo principal de la librería gráfica, esperando a que se produzcan eventos grá.
ficos (por ejemplo, una pulsación del ratón sobre un control).
En la práctica, para crear un programa gráfico indicaremos directamente en el asis-
tente que deseamos crear un proyecto gráfico, de modo que el entorno de desarro-
llo incluye ya, por defecto, el componente qb.qt, y nos permite crear un form¡jlario
de inicio. Un formulario de inicio es un;) clase de inicio que hrreda las característi-
cas de 1;) c1;)se Form, que no necesit;) de un método Main en el programa porque el
intérprete llama directamente;)l formul;)rio P;)ra mostrarlo, y entra en ellaw de ges-
tión de eventos.
o o o o o El entorno de desarrollo
Para crear un nuevo formulario nos situaremos en la ventana principal del lOE y,
tras pulsar el botón derecho, elegiremos Nuevo I Formulario.
3. la interfoz gróRco

rrogramrn;IOl'l VISUal con uore
@ ...
S Im.. ...
\;!J ARluvo de texto".
el ¡;..rpM.....
Figuro 2. PO$OS poro crear un nuevo formulario_
Figuro 3. Cootroles disponibles en
k. Coja de herramientas.
'U.E
r.;; ""l!-
,_o
Ahora paSólremos a situar los
diferentes controles, para lo
euallos seleccionaremos de
la Caja de herramientas y
los posicionaremos sobre 105
formularios manteniendo el
botón izquierdo pulsado,
mientras le damos el tamaño
deseado. El código se irá
escribiendo en función de los
eventos que generen los con-
troles, por ejemplo, el ev<"oto
Click de los botont"s o los eventos de ralón y tedado de cada control.
11
Al pulsar con doble die sobre un control, se genera, automáticamente, el encabeza-
do del código correspondiente al evento por defecto (el más característico) del con-
trol seleccionado.
, ,
Además, pulsando con el botón
derecho se puede seleccionar la
lista de eventos disponibles para
un control.
Figura 4. Eventos del coolrol Bu1tol11.
3. 2 Manejo basico de los controles
A pesar de que cada control ha sido diseñado para cumplir una función específica,
comparten buena parte de su interfaz de programación, de modo que aprender a
manejar un nuevo control sea tarea sencilla para un programador que ya ha traba-
jado con otros controles.
Los controles heredan métodos, propiedades y eventos de la clase Contral, por lo que
todas las caracter[sticas heredadas son aplicables a todos ellos.
En cuanto a los contenedores, proceden de la clase Contlliner (que a su vez procede
de Control) e igualmente tienen muchas características comunes.
Posición y tamaño
Todos los controles disponen de una serie de propiedades que permiten conocer y
modificar su posición y tamaño dentro de su contenedor, o del escritorio en el caso
de las ventanas:

FM.I... lo,,,, IModlRc.dol
,
1
)'0
o o
1
" ~ ,
t o
figuro S. Propiedades Xe Y~ control.
• Propiedades X e Y: son de lectura
y escritura, y determinan la posi-
ción del control, es decir, su punto
superior izquierdo. En los contro·
les comunes, la posición índicada
es relativa a su contenedor, y en el
caso de las ventanas es relativa a la
esquina superior izquierda del
escritorio. Los controles disponen de otras dos propiedades, Left y Top, que
son sinónimas de X e Y, respectivamente. Usar una u otra se deja a la elec-
ción del programador.
. Propiedades W y H: son de lectura y escritura, y determinan el ancho yalto
del control, respectivamente. Dispone de dos propiedades sinÓnimas. Width y
Height con el mismo significado.
3. la interfaz gráfico
rr<><: 1m n IJC con:">l'

• Propiedades ScreenX y ScreenY: son de sólo lectura, y permiten conocer la
posición de cualquier control relativa al escritorio, en lugar de a su contene-
dor padre.
Los contenedores disponen, además, de las propiedades CJieIllX, C/ieI1lY, ClientWidth
y ClientHeiglu, que determinan, respectivamente, el inicio y la dimensión del área útil
para contener controles ¡lijo. Por ejemplo, el control TabStrip, que dispone de unas
pestañas en la parte superior, sitúa a sus hijos por debajo de ellas; y ScroI/Vil.'W, que
puede mostrar barras de S<:roll, ve su área útil reducida por dichas barras.
Existen también una serie de métodos para modificar los controles:
• Método Resize(W,H): con él podemos cambiar el tamaño de un control modi-
ficando su alto y ancho de una sola vez., en lugar de hacerlo en dos pasos modifi·
cando las propiedades Wy H, lo que mejora el efecto gráfico de la redimen-
sión ante el usuario.
• Método Move(X,Y}: mueve de una sola vez el control a la posición indicada,
en lugar de hacerlo en dos pasos. También dispone de dos parámetros adicio-
nales, Move(X, Y,W,H), con los cuales además de mover el control se puede redi-
mensionar, todo ello en un solo paso, generando una transición más suave ante
el usuario, que si modificáramos las propiedades una por una.
• Métodos MoveRe!ative y ResizeRe!ative: son similares a Move y Resize, res-
pectivamente, pero en este caso las unidades no son pixeles, sino unidades rela-
tivas altamarlO de la fuente por defecto del escritorio. Con esta capacidad, el
aspecto del formulario será similar para usuarios que utilicen distintas confi-
guraciones de fuentes (por ejemplo, grandes en un escritorio a J024x768 o más
pequeñas en un escritorio a 800x600).
Las vent,mas (controles Wjmlow y Form) disponen, por su parte, de varios cventos
relacionados con la posición y tamaño. El evento Resize se genera cada vez que cl
usuario redimensiona una ventana, y MOI'e cuando se mueve.
Visibilidad
Todo control puede encontrarse: en uno de estos dos estados en un momento dado:
que significa que aparc:ce rc:presc:fllado ante ti usuario; c: INvisibk, que man-
tkne lodas sus propiedadc:s, pero no apar«e de cara al usuario.
La propiedad Visible: sir\'e para conocer 1'1 estado de visibilidad, en todo momento.
Por ejemplo, los métodos SIJOw() y Hide() muestran y ocultan, respectivamente, el
control.
Con lo que respecta a las ventanas, disponen de dos ("Ventos, Sllow y Hide, que se dis-
paran cuando se muestran o dejan de estar visibles.
Además., la apertura por primera vez de un formulario Oventana genera ti c:venlo
Op<'.
Crear eFecto> de blinLI'lQ, controles toles como eliquekl1 que oparecen y desopo<ecen
poro IIomar lo otención delltSUOrio, puede ser Util en algono ocasión especial, si se recla-
ma olención par olgún motivo críti<:o, Pero, en general, abusor de esto lé<:nieo mole.to
o los uSllOrios y se considera poca aprcpioda en uno inl""¡oz COffee:tomenle diser.odo.
Textos l"E1adonados
Todos los controles puedc:n diversu cadenas de texto, que muestran de una u
Olra forma.
Para lodos dios, la propiedad ToolTip se encarga de mantener un lexlo que apare-
cerá como una pequeña ventana flotante, cuando el usuario sinie el ratón por enci-
ma del área ocupada con el control.
De esta forma, se pueden dar pc<¡uclias informaciones de guia para que el usuario
conozca la función de dicho control dentro del programa,

11
con Software libre
Muchos controles disponen de un texto que muestran en su espacio principal, como
es el caso de las etiquetas, las cajas de texto o los bolones. Para todos estos c o n t r o ~
les, la propiedad Texr es la que determina la cadena a mostrar.
Puesto que Gambas trabaja con coditkación UTF-S para la interfaz gráfica, puede
que sea necesario utilizar la función COl'lv$ para convertir desde otras codifi¡;:acio-
nes, a la hora de representar texto procedente, por ejemplo, de Ulla base de datos o
de un proceso en ejecución en segundo plano.
Estos controles, por comodidad para programadores de otros enlornos, tienen un
sinónimo para esta propiedad, denominado Caption, salvo en el caso de las venta-
nas cuyo sinónimo es Title.
ColOrES
Para cada conlrolse definen dos colores: ForeGrolmd, que es el color de primer plano
en el que normalmente se mostrará el texto del controlo parte de sus líneas y dibu-
jos; y Background, que es el color de fondo.
Por herencia de otros lenguajes de programación, disponen de dos sinónimos:
BackCalor y ForeColor.
Los colores en Gambas son valores numéricos enteros, desde el Oal hexadecimal
FFFFFF, de forma que cada componente de color viene determinado por sus com-
ponentes de rojo, verde y azul.
La intensidad de cada uno de estos colores básicos varía entre el O(mínimo) yel 255
(máximo).
La gestión del color se realiza en Gambas a través de la clase Color, que dispone de
varios métodos estáticos, as! como de una serie de constantes.
Las constantes de la clase Calor determinan una serie de colores básicos, en su codi-
ficación numérica;
COLOR TONALIDAD NORMAL
Negre Color.Block
Blonco CoIol.Wnite
"".1
Color.Blon
Cion Color.Cyon
Magento color.Magento
Noronjo color.Oronge
Roso color.Pink
Rojo color. Red
Violeto cotor.Violet
Amarillo colOl.Yellow
Gris Color.Grey
Verde Color.Green
Gris Cloro Color.LigntGroy
TONAUDAD OSCURA
Color.DorkBlue
Color,DorkCyon
Color.DorkMogento
Color.DorkRed
Color,DorkYellow
Color,DorkGreen
El método RGB recibe tres parámetros, las componentes de rojo, verde y azul, en este
orden, con valores entre Oy 255 para c3d3 uno, y devuelve un número represent3n-
do al color.
El método HSV recibe tres parámetros, las componentes de tonalidad (0-360), satu-
ración (0-255) ybrillo (0-255), en este orden, ylo devuelve traducido a un color con
su codificación numérica habitual.
Existen también unas propiedades que determinan los colores del sistema.
Por ejemplo, y dependiendo del tema que haya seleccionado el usuario, los cua-
dros de texto pueden aparecer de color blanco con letra negra, o los formularios
de color gris.
Estas propiedades permiten conocer los colores actuales para los elementos de la
interfaz gráfica:
3, La ''1twfoz grafica
11
Programación visual COl1 Sottware libre
Color de Fondo general
Color de landa de k>s bolones
Color de primer piona de lo. bolones
Color de primer plano general
Color de fondo de un elemento ,eleccionodo
Color de primer plano de un elemento .eleccionodo
Color del texto en coios de texto
Color de landa en coias de texto
Color.Background
Color, BuHonBoáground
Color.ButtonFoleground
Colol.Foregrovnd
Colo<.SelectedBockgrouod
Color.SelectedForegrouod
Color.TextBoáground
Color. Textforeground
11
Es poco recomendable cambiar los colore. de lo interfaz por caprkho O cuestiones de
e.tético particulares del programador. Codo u'uario elige el temo que mós se adopto
o sus gustos o necesidad..s visuales, y puede sentirse incómodo .i le forzamos O USOr
otros colores. Por otro parle, algunos temas pueden interlerir su. colore, con los que
hemos definido en nuestro aplicación, resultando lo combinación dificil de ver, mole!'
to o desagradable. Sólo se cambiarón colores de los controles, cuando seo expresa-
mente nece,ario por algún motivo de diseño (por ejemplo, resoltor de formo claro un
texto en uno etiqUf!to).
[J O O O Ratón
El ratón es la interfaz por excelencia de cualquier escritorio actual. Hemos de dis-
tinguir aquí dos apartados.
En primer lugar se encuentra la representación de éste en el escritorio, el puntero,
que habitualmente aparece como una flecha, blanca o negra. Al respecto, cada con-
trol dispone de una propiedad Mome, la cual puede tomar como valores las cons-
tantes de la clase MOl/se para cambiar su aspecto.
Se consideran constantes para que el ratón adopte diversos aspectos, como puede
ser un reloj (espera), un cursor de texto, flechas en diversas orientaciones, cte.
los constantes de lo clase Mouse son los mismos para gb,ql y gb.glk, no obstanle,
sus "olores numéricos son distintos. Por tonJo, un código bien escrito y escalable,
no debe usor volares numéricos para indicar un tipo de puntero, sino los conslan-
tes de esto clase.
Cada control dispone, además, de una propiedad Crlrsor, que aCl'pta una imagl'n y
permite dibujar un puntero totalml."nte personalizado (a partir de un archivo .pus o
.xpm, por ejemplo) para cada control. Depl'ndiendo del servidor gráfico utilizado
en el sistl'ma, es posible qUl' d cursor pUl'da tener también varios colores, no sólo
en blanco y negro como los tradicionales.
La clase estática ApplicllIioll, aporta una propiedad BIISY, que es un número entero.
Si su valor es mayor que cero, todos los controles y ventanas de la aplicación mos-
trarán d puntero con un reloj (indicando al usuario que ha de esperar), indepen-
dientemente del cursor empleado para cada control en concreto. Si el valor pasa a
cero, se retorna a los cursores habituales.
Por otra parle, cada control recibe eVl'ntos dd ratón, que podemos manejar desde
el programa. Los l'Vl'ntos MOlIseDowrt, MOIIseUp, MouseWlrcel y MOIISeMOVC, dl'ter-
minan, respt'<.:tivamentl', si el usuario pulsó un botón, lo levantó, movió la rueda del
ratÓn o movió el ratón de posición.
Dentro de estos evemos, y sólo demro de ellos, se puede emplear la clase Mouse, para
determinar qué botón se pulsó (izquierdo, derecho o central) mediante las propieda-
des MOII5e.Left, Mouse.Right o MOII5e.Middle, que toman el valor tme si el botón (orres-
pondiente ha sido pulsado o levantado; la posición del ratón dl'ntTO dd (ontrol (MOI'5e.X
y Mou5e. Y); la posición dd ratón respecto al e:saitorio (Mollse.SaeenX y Mouse.Sa-eertY);
asi como el movimiento sobre la rueda dd ratÓn (Mouse.Delta y MOlIse.Orierttiltion).
En la mayor parte de controles, el evento MOIl5eMove, se prodm:e sólo si hay, al menos,
un botón pulsado del ratón por parte del usuario.
3. Lo Interfaz grófico
11

Este pequcflO ejemplo permite movcr un bolón de posición dmtro de un formula-
rio, cuando el usuario lo arrastl'll mientns mantinlt pulsado el 001611 izquierdo.
Creamos un formulario Forml, con un botón Bullon1, que incluye este código:
PRIVA'l'E pJ: AS Integer
PRIVA'I'E pI' AS Integer
Ir NDuse.Left '1'IlEN
, posiciones inicial.s
pI - M:IUM.I
pY - Mouse.Y
''''".
Ir Mause.Left TREN
DesplazlllllOlll el bot.6a de acuerdo
con la variaciÓD de X e Y
••••••••••••••••••••••••••••••••••••••
Buttonl.Move(Buttonl.X - • House.X, Buttonl.Y _
py + House.Y)
END "
A diferencio de 01r05 enlorn05 de de50rroHo, donde el evento recibe V<lri05 porómelr05
indicando el botón, po.icíón, ele., en Gamba. todo ello UI conoce o partir de lo infor·
moción almacenado en lo do"fl Mou.e, que sólo esló di.pooible en e.to. evento•.
El evento MOIlSeDow71 es cancelable, lo que significa que empleando la instrucción
S1DP EVENT dentro de su código, se evita que se propague y, por tanto, que el con-
trol actúe en consecuencia, según su funcionamiento interno habitual (por ejemplo,
un balón no lanzaria el evento Click si se cancela MOllseDown).
Otros eventos comunes en los controles son DblClick (doble pulsación del ratón),
Merm (pulsación del bolón derecho) o Click (pulsación del bolón izquierdo), Algunos
controles pueden no disponer del evento C1ick.
Teclado
De forma similar al ratón, el teclado se controla con los eventos KqPres5 y KeyRelease.
Estos no lienen parámetros.
La clase estática Key proporciona la información necesaria para controlar el teclado
dentro de estos eventos, de igual modo que la clase Mome dentro de los eventos de
ratón.
El evento KeyPress es cancelable con la instrucción STOP EVENT, de modo que se
pue<le impedir, por ejemplo, que en una caja de texto se impriman determinados
caracteres.
En el siguiente ejemplo, se bloquea un TextBox, de forma que sólo permita la entra-
da de números, la pulsación de las teclas Supr (borrado) y BackSpace (borrado hacia
atrás) y ellabulador para pasar el foco a otro contro1.
Para ello llama a STOP EVENT cuando el código de la teda pulsada no es ninguno
de los deseados:
e f ~ r 1 C

Progromoc,ón viYJOI con Software
PUBLIC SUB Text80xl_KeyPress()
SELECT CASE Key. Coda
CASE t8 ro 57 ' Códigos ASCII de los números
CASE Key.BackSpace • Retcoceso
CASE Rey.Delate ' Borrado
CASE Key.Tab ' Tabulador
CASE ELSE
STOP EVENT
"'" SELECT

3. 3 Galeria de controles
Controles basicos
Tantu gb.qt como gb.gtk aportan una serie de con-
troles básicos para desarrollar una interfaz gráfica.
A continuación se detallan estos controles y sus
características principales.
.._......,-...__...
,...... - , _-
__ ,_.
".-
FigurCl 6. de gb.qt
y gb.glk.
• __ J
'...- .. ... -:'¡
9J:,,]01-'-
.__...

.--
--
.-
• Labcl: es una etiqueta simple que contiene
una línea de texto de poca longitud. Su única
función es moslrar un texto en una posición
dentro de un formulario. La propiedad Ten
es la que determina el texto a mostrar en cada
momento. Al margen de este uso básico, se
puede modifiGH tanto su color de fondo
(Backgrollnd), como el color de primer plano
(ForeGrolwd). Como el resto de controles,
responde a los eventos de ratón, por 10 que en un momento dado, ayudado de
MOll5ePrrn y MOllseRr/eau, pueden servir para implementar un botón perso-
nali7..ado.
• TextLabel: es muy similar al control Úlbe/, pero tiene la particularidad de que
es capaz de mostrar texto formateado en HTML. De esta forma, indicando una
cadena con etiquetas HTML en la propiedad Texr, podremos tener texto que
combine negrita. itálica, subrayado yotras caracterfsticas de texto enriquecido.
con HTML</b><br>Dentro de una
<i>etiql1eta."
El componente de menos etiquetas HTMl, en las versio-
octuoles_ Por porte. gb.qr permite kJ inclusión de toblos e imógenes desde un
orchillO. Un programo de$Orrol!ooo poro ser independiente del toolkit, no debería obu-
>or de eMo. Pero un programa expresamente diseñado poro troba¡or con gb.qt puede,
por el contrario, socor provecho de sus características extra.
• TextBox; es una caja de textO, de una soja línea, en la cual el usuario puede modi-
ficar, copiar, cortar o borrar texlO. El texto introducido se recibe Omodifica por
código mediante la propiedad Texl. Además, el ml'todo Se/ect permite seleccio-
nar o resaltar por código una parte del texto, y Se/ectjo/l dola de algunas pro-
piedades para conocer el texto que el usuario ha seleccionado.
Gambos emplea codificación UTF·8 en la grófico, por lo que un cor6cter
puede suponer 1, 2 o 3 byles de longitud. Asi, eKribir Len(Text/loJ< 1. Text) poro cono-
cer lo longitud en caracteres de un texlo, no siempre doró el resultado En
lugar, se debe emplear ,,1 mé10d0 TexrBox.tengrh, que do lo longitud en
del texto.
3 lo mlcrfoz: .9.rofico

11
VI!>Ual con Software Libre
- ..
· TextArea: se trata de una caja de texto que es capaz contener múltiples Ilneas.
Se permite también los retornos de carro. Como en el caso del TexlBox, el méto-
do Se/ta;en y la propiedad Se/eer determinan el texto selecdonado. Además,
este control dispone de los métodos Undo y Redo que equivalen a [as órdenes
Deshacer y Rehacer de cualquier editor de textos. Es decir, eliminan los últimos
cambios del usuario o los vuelven a situar en el texto.
• Botones: Gambas tiene tres tipos de botones. El primero, Burton, es un botón
normal, dispone de una propiedad Text que indica el texto a mostrar, asl como
una propiedad Picture para mostrar un icono identificativo. Este control dispo-
ne del evento C/ick que se dispara cuando se pulsa con el botón izquierdo (o dere-
cho si está configurado para zurdos). Otro tipo de botón es el ToggleButton, que
mantiene su estado tras una pulsación, es decir, cuando se pulsa una vez, queda
presionado, y al pulsarlo otra vez, sale de ese estado. La propiedad Value sirve para
conocer o variar su estado: FALSE significa 'no presionado' yTRUE'presionado'.
El siguiente botón, TOO/BlIttOIl, es similar, pero sólo muestra un pequeño icono,
sin texto. Está diseñado para insertarse en barras de herramientas, habituales en
la parte superior de las interfaces, como acceso rápido a ciertas funciones comu-
nes. Puede actuar como un botón normal, si su propiedad Toggle vale FALSE, o
como un interruptor (como un ToggleBI<tfon), si Toggle vale TRUE. Así mismo
dispone de una propiedad Border que de valer FALSE dará apariencia plana al
botón, y de valer TRVE lo mostrará con relieve, como un botón normal.
loo botone5 Toggle pueden ler confu505 con algunol temal de KDE o GNOME. 5ien-
do difícil para el U5uorio determino, si $e encuentro pul$Odo O no. Cuando 5eO po$j·
ble se empleara un CheckBox en lugar de un Togg/eBulton. O bien 5e 'esoltara 5U elta-
do de olgun modo. por ejemplo, cambiando el colo< de fardo o el ícooo que loe mue5lra.
bto evitora problemas con los futuros U$lKIrios de lo oplicoci60.
• CheckBox: muestra un texto determinado por la propiedad Text, junto con
una caja donde el usuario puede pulsar para marcar o desmarcar la opción.
La propiedad VaJue indica si el usuario ha marcado o no el CheckBox, yel even-
to Cliange informa de cada cambio. Se suele emplear para opciones de confi-
guración que sólo disponen de dos posibles valores: 'Activado o Desactivado',
'510 No', 'Verdadero o Falso',
• RadioButton: es similar a CheckBox, pero tiene la particularidad de que todos
los RadioBllfton existentes, hijos de un mismo contenedor, están internamen-
te agrupados, y en cada momento sólo puede haber uno activado. Cuando el
usuario activa uno de ellos, e! resto se desactiva, por lo que se emplea para
seleccionar una opción que excluye a otras dentro de un menú de opciones.
• PietureBox: este control tiene la función de mostrar una imagen. Responde a
eventos de ralón, por lo que se puede empicar como bolón personalizado. Su
propiedad Stretch permite adaptar la imagen al tamaño de! Picll¡reBox en cada
momento, la propiedad Border determina su apariencia plana o con relieve y
la propiedad Pictllre representa la imagen a mostrar.
Otros controles basicos miscelaneos
Otros controles que pueden ayudar a diseñar una
interfaz y tienen un propósito mucho más concre-
to son los que se presentan en la imagen de la
izquierda.

,
'1
Figuro 7, Otro tipo de

• ProgressBar: barra de progreso que muestra un
porcentaje de forma gráfica. Sirve para dar idea del
avance de un proceso que dura mucho tiempo, de
forma que e! usuario no sienta que la aplicación
está colgada mientras trabaja en segundo plano.
• Slider: es similar a ProgressBar en el sentido de que muestra un porcentaje,
pero en este caso el usuario es quien varla su valor. Un buen ejemplo es su uso
para subir o bajar e! volumen en una aplicación que reproduzca audio. I..os
valores de volumen se definen entre un rango máximo y mínimo, y e! usuario

_ Vi5U!!Lcon libre
lo cambia a su gusto. El evento C/Jange señala un cambio por parte del usua-
rio en el valor de la escala.
• MovieBox: a pesar de su sugerente nombre, no se trata de un reproductor mul-
timedia, sino algo más humilde. Muestra una animación en formato GIF o
MNG, sin que el programador deba preocuparse de la sucesión de (fames del
archivo que se muestra. La propiedad Path determina el archivo a reproducir,
y Playing permite el control de la reproducción, con los valores TRUE (repro-
ducir) o FALSE (detenido).
• ScrollBar: se trata de una barra de scroll para desplazar aIro control, habi-
tualmente, de forma que sea el usuario quien determine [a posición de éste. La
propiooad Va/lIe indica el valor elegido por el usuario, r el evento Clrange seña-
la cada cambio.
A diferencio de otras interfaces gróficas, donde existen voriontes horizontales y verti-
cales poro determinados contfoles, en Gambas los contfoles Slider y ScrollBor deter·
minon Sil orientación automóticamente: si son mós anchos que altos serón horizonta·
les, y verticales en coso contforio.
listas dE datos
Existen tres controles diseñados para mostrar listas de diferentes modos:
1. ListBox: es una lista simple. Se añaden o eliminan elementos que se repre-
sentan como una línea de texto cada uno. El usuario tiene capacidad para
seleccionarlos o deseleccionarlos. La propiedad Made determina si el usuario
no puede seleccionar ninguno, s6lo uno o varios.
2. ListView: similar a LiS18ox, dispone de capacidades adicionales. Puede repre-
sentar un icono junto con cada elemento de la lista, y cada uno de ellos está
identificado por una clave única de texto, que nos permite hacer búsquedas
de los elementos por su clave. AsI mismo dispone de un cursor interno que
puede moverse hacia adelante y hacia atrás, lo que lo hace apropiado para
interactuar con una aplicación de bases de datos, donde puede representar
un campo de una ta.bla.
3. ComboBox: n una lista desplegable. El usua.rio sólo '"e el elemento seleccio-
nado en C1da momentO y puede desplegar la lista. para sdeccion.ar uno u airo.
otros controks avanzados
Acontinuación mostramos otros controles más avanzados:
, TreeView: sirve para representar elementos en un árbol, de forma que cada
nodo puede tener aIras nodos hijos.
• ColumnView: es similar al anlerior, pero cada nodo puede disponer de varias
columnas.
. GridView: sirve como representación de parrilla, de forma que disponemos
de registros agrupados en filas y columnas. Es empleado, habitualmente, para
interactuar con bases de datos.
3. 4 Dialogos
Gambas aporta una serie de diálogos auxiliares para mostrar o recabar información,
interactuando con el usuario.
La clase Message
La c1a,s.e Message se encarga de mostrar una ventana modal al usuario, en la cual pode-
mos definir un texto, que será una información o una pregunla, y una serie de boto-
nes para elegir una opción. La clase MesslIgees eslática, y dispone de una serie de
métodos para mostrar distintos tipos de mensajes, que serán reconocibles para el
usuario gracias al icono que acampana a la ventana yque da una idea del caráCler del
lo "

Programación con Software Ubre
mensaje. En estos métodos se situará siempre, como primer parámetro, el texto a mos-
trar y, a continuación, elteno de los botones, hasta un máximo de tres. Si no se indi-
ca el texto de los botones, aparecerá sólo un botón indicando üK para que el usua-
rio acepte la lectura del mensaje.
• Arbol [El
• Messagc.lnfo (Texto, BOlOnl): se utili7.a para mos-
trar un mensaje meramente informativo. Sólo per-
mite definir un botón, que normalmente tendrá un
texto tal como üK o Aceptar. Figura 8. Mensaje
informoli"O.
11
Lo clase Messoge también puede S&f llamado como uno función, de modo qoo el código:
Es equivalente o:
• Message.Delete (Texto, Botan1, Bo-
ton2, Boton3): se utiliza para indicar
que se va a proceder a eliminar algo
(archivo, registro de una tabla... ), y
se solicita al usuario su confirmación.
• "'bol
'ii""""'l" do confinnoc'ón do
proc...... 11

Figura 9. o'i.ensaje de eliminación.
,., Acbol
• Message.Error (Texto, Boton 1, Bo-
ton2, Boton3); se emplea para indi-
car un mensaje de error.
Q M.n.eje de Erro,
i Contlnuor I ¡I Oepu,o'
Figura 10. Mensaje de error.
......bol
Figura 11. Men""ie
pora preguntor.
• Message.Question (Texto, I5otonl, Boton2, Boton3): es
una pregunta al usuario, generalmente para confirmar
una acciÓn o una opción de configuración.
" .....bOI
Figura 12. .Meo",,¡e de
advertencia.
• Message.\Varning (Texto, Botonl, 60ton2,
Boton3): advierte al usuario de que la acción que
va a realizar supone un cierto peligro, por ejem-
plo, pérdidas de datos de una tabla que podrian
ser útiles aún.
Los métodos de la clase MeSS(lge devuelven un número entero que denota el botón que
el usuario pulsó. El primer botón comienla en el número l. Los mensajes son moda-
les, lo que quiere deár que la interacción de la interfaz de usuario con el programa, as!
como el flujo de éste, quedan bloqueados hasta que se pulse uno de los botones.
01M hReli AS INTEGER
el disco
"Si", "No")
11
Figura 13. Coodro de
di61ogo COf1 botón de cerror.
Dependiendo del gestor de ventanas del sistema, es
posible que los cuadros de diálogo tengan un botón
de cerrar. Si el usuario cierra el mensaje de este
modo, se devolverá el número del botón existente
más alto (en el ejemplo anterior el 2), por tanto la
opción menos peligrosa, o que se estima a ejecutar
por defecto, se habrá de indicar en el botón más alto.
Pr09.ramaClon visual con Software
Los mensajes se han de emplear con prudencia. Una aplicación que continuamente blo-
quea la interfaz y desvía el foco de atención del usuario, puede llegar a ser realmente
molesta. Las interfaces de otros sistemas propietarios se han llegado a hacer famosas en
los chistes de las oficinas por las continuas preguntas del estilo' ¿Está seguro de que... ?'.
La clase Dialog
Esta clase aporta ciertos diálogos comunes, que ahorrarán mucho tiempo de trabajo
mecánico al programador de una aplicación gráfica. Dependiendo del componente,
lógicamente, tendrán un aspecto similar al resto de aplicaciones GTK+ o QT. Los
métodos de esta clase no toman ningún parámetro, y devuelven siempre un valor
Bolean, de modo que TRUE significa que el usuario ha pulsado el botón Cancelar, y
FAL5E significa que aceptó el valor seleccionado. Las posibilidades que nos ofrecen
son las siguientes:
H",
H",
,"""""
H",
211OCJOS
I9i08lOS
2l108JOS
19/08105
19/08105
19f08lOS
... IMQtkfN:lldo Il.:
19/08/05 ·1
......,
.,cdrom
...-
...
.........
o-O
,.hb
..,Ion... lound
MmiKlio
_FJ..;Imnt
Op••
"'"
\JEsaltonO
""'''CIO

. ""
.. Figura 14. Apertura de archivo.
• Dialog.OpenFileO: sirve para
que el usuario seleccione un
archivo para su apertura. La
propiedad Path de la clase se
utiliza para situar la ruta inicial
en el sistema de archivos. Tras
ser mostrado y seleccionado por
el usuario, contiene la ruta ele-
gida por éste.

Figura 15. Ventana pora guardar un archivo.
- - - .)
....
• Dialog.SaveFüeO: es similar al
anterior, pero el diálogo está
orientado a guardar un archivo,
de forma que permite elegir uno
que no existe. Como en el caso
de OpenFile(), la propiedad Path
sirve para situar la ruta inicial y para recabar la ruta seleccionada por el usuario.
,.,1....00
• Dialog.SelectDirectoryO: en este
caso, el valor de Path no será un
archivo, sino una carpeta. El diálogo
permite seleccionar sólo carpetas, no
archivos. :J
_""'M
... w.otJ'cI
_Iob

__o
J"""
_ l ..n.........
.
\$hcrltono
._=--....,._..,1',;'"1"11""11'•••••••• 1'..... .....,I:¡:.
..
... boDl 19108105
...(orom Hoy
'*"'ftv Hoy
"""'''''
""
lUOC/'O!l
.......,
2)108,105
• 0III1l5
._..
'9IOIII1l5
H.,
I¡ +-, Ji
111 Figura 16. Apertura de carpeta5.
Select Color
¡
M-"'. 270 :
S-lIturb(IÓn. O •
62 1:
riombre del (olor: ¡¡t9D909D
Ixs:.lII'\(elor 1
Figura 17. Selección del color.
BaJo: 157 :
157 :
Azul: 151 :
• Dialog.SelectColorO: permite al
usuario seleccionar un color perso-
nalizado. La propiedad Color se
emplea de modo similar a la propie-
dad Path de los casos anteriores, es
decir, sirve tanto para fijar el color
inicial como para determinar el ele-
gido por el usuario.

S.fec;t Font
ix!:oI'InCel(l"! [aAcept(lr1
abcdefllh'Jk ABCDEFGHIJK
• Dialog.SelectFontO: con él se elige
una fuente personalizada. Se trabaja
sobre la propiedad Font de la clase
Dialog.
Jpmel'\o'
__.• ' 12.0
10
11
13
14
I
\o-
Stlllodard l F;
:'r''''' f _ ... _- -rrt'l.:.
yista prellmlner:
, ""... EstIlo'
Nlmbus Sl.lns L rItbhc
OpeoSymbol
-i.II§11•••19 Bold
60ld Illllhc

111 Figura 18. Elección de la fuente.
Ademó5 de la propiedad Path exi5te una propiedad Paths para obtener 105 valore5 de los
archiv05 5eleccionad05, cuando 5e nece5ite elegir mós de uno a la vez. Para activarla, el
método Dialog.OpenFi/e admite un parómetro opcional que habró de tener valor TRUE.
3 La interfaz gráfica
,-
Figuro 19. Formularios FMain y
FDiologo.
11
• Dialog.Filter: permite indicar filtros para los archivos a mostrar. Se trala de
una matriz de cadenas en la que podemos situar, por ejemplo, las extensiones
de los archlvos a elegir, usando comodines si 10 deseamos.
• O¡alog.Tille: permite establecer un título para la ventana, que por defecto
corresponderá a la acción a realizar (Se/eCl Foru, Se/eel Color, etc.).
Dialog.Title .. "seleccione imágenes a procesar"
Dialog.Filt.er· ["*.png", ".jpg"]
IF Dialog.OpenFile(TRUE) TBEN
Message.lnfo(NAcci6n cancelada
H
)
ELSE
Process_lmageneS(Dialog.Paths)
END "
Diálogos personalizados
Al margen de los diálogos ya mencionados, el programador puede crear otros per-
sonalizados. Cuando un formulario se muestra de forma Modal, es decir, con los
métodos SlzowModa/() o 5howDi/lIQg(), puede devolver un valor entero, que sirve
como indicación de la opción elegida por el usuario. Veamos un pequeño ejemplo.
Creamos un programa gráfico, con un formulario principal de inicio llamado FMain
Yotro formulario Hamado FDialogo. Creamos también tres pequeños iconos en for·
mato pl/g o los copiamos de la carpeta
/r4sr/s/ulrelpixlIlapS del sistema, y los renom-
bramos como /l.pl/g, b.pllg YC.pllg, de forma que
los tengamos disponibles en la carpeta del pro-
grama. El formulario principal FMain tendrá
un PictllreBox llamado plmagc, y un botón
denominado bfl/Select con el texto Icono. El for-
mulario FDialogo dispondrá de tres controles
PidllreBox, cada uno de ellos conteniendo uno de los iconos pllg que habíamos situa-
do en el proyecto, Ylos llamados piel, pie2 Ypido
Con el código del formulario FDialogo lo que constguiremos es que cada vn que
el usuario pulse uno de los controles PiftllreBox, el formulario, que se moslrali de
forma modal, devuelva un valor enttrO que identifquea d ieono pulsado.
KE.Close(l)
ME.Close(2)
PUBLIC SUB piel MousetloNn()
KE.Close(3)
END
11

------
• w· En cuanto al formulario FMain, la pulsación del botón
conducirá a mostrar el formulario FDialogo de forma
modal y, en función del valor devuelto, silUali una ima-
gen u otra en el PicwreBax llamado plmage:
FigUfg 20.lmógerles que hemrn
situado en el Pidure&x.
11
Programación v ¡ ~ u a l con Software libre
PUBLIC SUB BtnSelect_Click()
SELECT CASE FDialogo.ShOWOialog()
CAS' 1
pImage.picture - Picture["a.png"l
CAS"
pImage.Picture - Picture["b.png"]
CAS"
pImage.picture - Picture¡"c.png")
END SELECT
Tras ejecutarlo, podremos comprobar el resultado. Si el usuario cierra el formula-
rio modal pulsando el aspa del gestor de ventanas, se devolverá el valor por defec-
to, es decir, cero, lo que equivale a cancelar la selección. Puede plantearse otro pro-
blema más complejo: la necesidad de devolver otro tipo de valores, tales como
cadenas o referencias a objetos. En este caso, la solución del enlero no es válida. Si
tratamos de mantener una cadena en una variable del formulario, ésta se liberará
tras cerrar el formulario, lo cual no nos sirve. Por ejemplo, modificando el código
anterior, de la siguiente manera, para que el formulario FDialogo mantenga una
cadena ron el valor elegido:
PUSLIC valor AS String
Valor. Na.pngN
ME.Close()
PUBLIC SUB pic2_MouseDown()
Valor _ Nb.pngN
ME.Closen
Valor. NC.png"
ME.Close()
y modificando el formulario principal para que tome el valor de la cadena:
PUBLIC SUB BtnSelect_Click()
FDialogo.ShowDialog()
IF FDialogo.Valor <> NN TREN
plmaga.Picture - Picture(FDialogo.Valor)
END "
No conseguiremos que funcione, ya que la secuencia es la siguiente:
1. La llamada a FDialogo.5howDialogO crea una instancia de la clase FDja/ogo.
2. Tras la pulsación del usuario, se destruye esa instancia y con ella el valor alma-
cenado en la variable pública Valar.
3. La interfm: gróhco
11
Software übre
3. Al llamar a FDialogo.Valor, se crea otra instancia de FDialogo, que liene la
variable Va/ar con su valor por defecto (cadena Vacía).
Podemos solventar este problema por dos caminos:
\. 8 primero consiste en declarar la variable Valor como estática. Así la varia-
ble no depende dr cada instancia, si no de la clase, de forma que no se crea ni
se destruye en cada llamada a FDialogo.S/lOwModa/().
Figur<I 21. Propiedod Persisten' con
valor TRUE.


False
Icon
Picture

Persistent
Borde.
2. El segundo consiste en aprovechar
la propiedad Persistent de los for-
mularios. Poniendo su valor a TRUE,
un formulario no se destruye cuan-
do el usuario lo cierra pulsando el
aspa del gestor de ventanas, ni se-
llama al método e/oseO, si no que
simplemente se oculta. Y si estaba en pantalla de forma modal, el programa
abandona esle modo y continua su ejecución normaL
11
Así pues, en tiempo de diseño siluarcmosla propiedad Persjstent del formulario
FDialago a TRUE, y modificaremos el código del formulario FMain para que des-
truya el formulario de forma expHcila tras haber leído el valor que interesaba.
PUBLIC SUB BtnSelect_Click()
FDialogo.ShoWDialog()
IF FDialogo.Valor <> NH TREN
pImage.Picture - Picture[FDialogo.Valor]
END "
FDialogo.Delete()
3.5 Menús

..-
....." ... _ C t r I + ~




figtJfQ 22. l.ocolizociÓll del
Editor de menú.
La creación de menús es realmente scnólla ya que un
asistente dellDE permite disei'¡arlos. Tan sólo hay
que situarse sobre un formulario, pulsar el botón
derecho, y seleccionar la opción Editor de meou...
Los menús se crean como árboles, es dedr, cada menú
de primer nivel, por ejemplo los típicos menús de la
barra superior de muchos programas como Archivo,
Editar, Ver, Ayuda, ete., tendrán menús hijos que se
sitúan un nivel más profundo que éste y, a su vez, si
estos tienen hijos, se situarán un nivel más profundo.
Todo ello se controla con los botones con forma de
flecha, las verticales permiten cambiar el orden de aparición de los menús, y con las
horiwntales modificamos [a profundidad de estos.
11
En la Figura 23 podemos ver un ejemplo con
un menú principal que tiene tres opciones,
y sus correspondientes submenús.
Si el nombre de un menú se deja en blanco,
éste se muestra como una barra separadora
en lugar de una entrada de menú normal.
-
-
-
_ r
_ úcno. "'--. w .... ' ._, .¡ ....
- r 8c<!J I
.,_._.. -
r=.:·
-
'-
:-
Las propiedades más importantes son el Nombre, que es el nombre del objeto menú
y que corresponderá con su gestor de eventos, el Tftll/O, que es el texto que aparece-
rá en la pantalla, un icono a elegir si lo desea-
mos, y un posihle atajo de te<:lado para acce-
der sin necesidad del ratón.
Figura 23. Eiempkl de menús coo
submenús.
3. La interfaz grófico
Figura 2•. fMoin.
El formulario tendr.i el aspecto de: la Figu-
n. 24. Si en tiempo de diseño pulsamos
sobre UIlO de los menús que no tienen hijos,
elIDE nos llenrá dirttlamentc: al evento
C/idr: del menú, que es donde: podemos
crear el código que se c:j«utari cuando el
usuario pulse el menú.
---
-
--
s
-1
END
- .........-.......
- ,!J!!.
...
F9- 25. Mroú lfIlI-.nos al el
boa)" dtoedo de un bn-ohio.
-
-
--
-
- -
--
-
...... " .....
Si lo que deseamos es crear un menú de los
que se muestran cuando el usuario pulsa,
porejemplo,d bot6n derechosobTe un for-
mulario u otro oontrol, tendremos que crear
un menú de primer nil'd ron su propiedad
visible a fALSE, y sus correspondientes
hijos. Después, al lanzarse el C'\'eIlto del (0.--
mulario o control que nos interesa, por
C'jemplo, la pulsación del botón derecho
sobre un formulario, que se detecta median-
Il' la gestión dd nTIlto Me/m, indicaremos
a nuestro menú invisible que debe mos-
trarse como un menú contextual:
11
PUBLtC SUB ()
mnuEditer.Popup()
END
-
Figo.ru 26. Rewhodo
del me..u rontextuol.
mIMen..
I,,",Clones
Env r
Eh "",
Al ejeclllar el código, el resultado al pulsar el
botón derecho sobrt ti formulario.
En euamo a la naturaleza de los menús, no son más que
objl"tos, aunque en eSle caso no provienen de la clase
Control, si bien disponen de algunas propiedades comu-
nes como Texlo PicWrc.
Ala hora de crear un menú, habrá de indicarse su objeto
plldre. que podrá ser una ventana o formulario para los
menús de primer nivd, u otro menú paro los Irijos del pri-
mm). Los menússt putden crear o <kstruir direc-
tamnltl" por código:
DIM hl AS Menu
DIM h2 AS Menu
OIM hJ AS Men..
hl - NEW Menu(HE)
h2 - NEW Menu(bl) AS "h2."
h2. 'l'ell:t - "enviar"
h3 - NEW Menu(hl) AS "hJ"


3. 6 Alineación de 105 controles
Propiedades de alineación
Algunos contene<lores disponen de una propiedad Arrangement que permite d e t e r ~
minar cómo se alinean los controles dentro de un contenedor. Por defeclo, el valor
de la propiedad es None, lo que significa que las posiciones de los controles son libres,
como es típico en las interfaces para Windows'''' o en algunas libredas como QT.
Sin embargo, en olTas librerías gráficas como GTK+, o en las definiciones del len-
guaje XUL diseñado por el proyecto Maúlla para aplicaciones web, lo habitual es
encontrar contenedores que definen dónde se situará cada hijo, de forma que el pro-
gramador !iÓlo ha de indicar el modo general de alineamiento y los controles se adap-
tarán en todo momento a dicha alineación.
En principio, diseñar interfaces de esta manera puc<le ser algo complicado para gente
sin experiencia, no obstante, una vez que se toma algo de pericia, aporta grandes ven-
tajas. La principal es que el diseño de ventanas rc<limensionables con controles varia-
dos en su interior es trivial.
Cada usuario puede agrandar o hacer más pequeña la ventana, o variar su relación
alto/ancho, y la aplicación seguirá manteniendo un aspecto coherente en cada momen-
to, dentro de unos limites razonables de tamaño.
Gambas define varia. posibllidades de alineamiento para los controles:
• None: alineamiento libre, el contenedor no decide nada acerca de la posición
de sus hijos.
• Horiwntal: todos lo. controles se alinean de izquierda a derecha, ocupando
todo e! espacio en vertical dentro de! contenedor.
• Vertical: todos los controles se alinean de arriba a abajo, ocupando todo el
espacio en horizontal dentro del contenedor.
• LeftRigth: los controles tratan de alinearse de izquierda a derecha, y si falta
espacio, de arriba a abajo.
, TopBottom: los controles tratan de alinearse de arriba a abajo, y si falta espa-
cio, de izquierda a derecha.
Además de la propiedad general Arrangemenl, se aporta la propiedad Padding, que
es un espacio que queda libre en el borde del contenedor, y una propiedad Spachtg,
que determina un espacio de separación entre control y control.
Cada control, por su parte, dispone de la propiedad Expand. Si el control se sitúa
sobre un contenedor cuya propiedad Arrangemenr es distinta de Norte, el valor
Expand determina si éste, junto con el resto de controles del contenedor que ten-
gan la propiedad Expmrd a TRUf, tratarán de ocupar el espacio libre que quede
dentro del contenedor.
.. miMenu 11:
ACCIones
Enviar
Ehmlnar
.. Figura 28. Proyedo
Alineación.
Para comprobar el efecto de todas estas propiedades, crea-
mos un nurvo proyecto gráfico llamado Alineacion, con
un sólo formulario dr inicio FMaill, en cuyo interior situa-
remos dos botones y un RariioBllttOtl. Tras ejrcutarlo vere-
mos el resultado habitual: un formulario con tres con-
troles algo desordenados.

RDdo08ut1onl
Cambiamos el valor de la propiedad
Arrmrgement a Horizontal y ejecuta-
rnos el programa.
Ahora los controles se han situado ali-
neados en horizontal, ocupando todo
el espacio vertical del contrnedor
(Figura 29).
Figuro 29. Controles alineados en horizontal.
3. Lo interfaz gróflco
111
Progromoción visuol con Softwore übre
Ponemos la propiedad Border del formulario a Resizable, de modo que podamos
variar su lamano. Hacemos varias pruebas de ejecución cambiando su relación altu-
ra/anchura.
-
-
_.
-
_.
- -
_.
.. Figuro 30. Variación del formulario úo altura/anchuro_
Como podemos observar, los controles siguen ocupando todo el ancho del contene-
dor, mientras que el ancho extra queda libre. Situamos ahora la propiedad Expalld del
control Bul\on2 a TRUE, yvolvemos a ejecutarlo. Con esta nueva configuración, todo
el espacio del contenedor es aprovechado, modificando el ancho del control Bunon2.
Figura 31. Aprovechamiento del e$f>OCio del conter.edor.
Si situamos la propiedad Expand de Bullon 1 también a TRUE, el espacio extra será
compartido por ambos controles.
Figura 32. Espacio COl lopOitido entre los controlocbes Ilutlon1Y8utton2.
Para dejar espacio visible por el borde del contenedor, podemos dar un valor a la
propiedad Padding, y para separar un poco cada control utilizaremos la propiedad
5pacirlg. Los valores indicóldos son píxeles de separación.
El efecto de lo propiedod Arrangemenr no 5e oprecio en liempa de di5eiío, de e5te
modo 5i par error se cambio o un valor no de5f!Ooo, podremos revertirk> 5in perder lo.
pa.icione5 de codo control dentro del contenedor.
a a o o o Controles con alineación predefinida
Los controles Form (Window), Panel, TabSrrip y ScrollView permiten definir las pro-
piedades de alineación, sin embargo, otros controles tienen esta propiedad implíci-
ta y no es modificólble. Estos son los siguientes:
• Hbox: es un panel que siempre tiene alineación horizontal.
• Vbox: es un panel con alineación vertical.
• Hpanel: sigue el modelo RightToLefl.
• Vpanel: sigue el modelo Vpallel.
Además de estos, los controles Hsplit y Vsplit son contenedores con un modo de na·
bajo totalmeme distinto: cada control añadido se muestra sepólróldo por una barra
verticóll, en el caso de Hspljt, u horizontal, en el caso de Vsplit, que el usuario pue<le
mover para agrandar uno u otro control en detrimento del tamaño de su vecino.
o o [j o O Diseño de una aplicación que aprovecha este recurso
A la hora de diseñar una aphcación redimensionable, 10 mejor es plantear 3reas de
trabajo con distinta funcionalidad y agruparlas en distintos paneles horizontales y
verticales. Supongamos un clon de los exploradores de archivos habitual cs. Una
zona de trabajo estar3 formada los tlpicos botones de menú, que permiten realizar
3. lo interfaz grófica

Programación visual 'fl_1l.-Software Libre
[as tareas más comunes y que presentan un icono y un tooltip explicativo. aIra
zona dr trabajo puede ser la parte inferior, en la que se muestran datos de estado.
Por último, la zona central muestra los archivos y, a su vez, es una zona dI' trabajo
que comprende otras dos: un árbol con las ,aTpelas a la izquirrda, y una zona más
grande a la derecha con la vista en detalle de los archivos. No crearemos en este
ejemplo el código correspondiente, pero si seguiremos los pasos necesarios para crear
la interfaz de un modo adecuado, para conseguir que cada usuario pueda disponer
de sus vrnlanas como mejor lo desee.
En primer lugar, hay tres grandes grupos de trabajo, que van de arriba abajo. Por
tanto, lo mejor es definir un formulario con la propiedad Amlllgeme7lt situada a
Vertical.

........ ,_,.....,ft.....]
- ..,.....

..........


,_o
.. ,.T......
.,-
-
.-.
,..
,..
.....-
,..
,..
,..
,..
'..



figur(l 33. formulario con k. propiedad Arrongemento Ver'ico/.
Dentro de ésta, situaremos tres paneles con alineación horizontal, es decir, tres con·
tenedores Hbox. Deseamos que la parte superior con los botones y la inferior con la
barra de estado, tengan un ancho fijo, pero la parte central que contiene el cuerpo
de la información útil del programa, será redimensionable. Por tanto, la propiedad
Expmld del panel central habrá de tener el valor TRUE.
, _ - - - _.•.- _ - .--
¡ ¡
, .
9,-:.:-:.::.-.::."'::.:..:.:·.:.:·.:.:-....:0::·.::::.:.:·.::.::::.-:.::::.-:'
,
"".', H"",,' 1
,
i ¡
i i

.-
'-
'.
-
TOoIT",
-
,.-
..
'-.
Figura 34. Paneles Hbox con olineación horizontal.
La parte superior contendrá divt"TSOS botones tipo
ToolButum, que podemos TC'Saltar con distintos ko-
nos. La parle inferior dispondrá de dos etiqUe1:3.S
Label con borde Sunkl'n, una de las cualC"$, según
qué parle se quieI'l" hacer u\ensible, tendrá su pro-
piedad Expmrd a TRUE.
Figuro 35. D i ~ del
Iormulario fMoin.
Dentro del cuerpo SC' situará lIna caja vt"rtical ;¡ la
izquierda ( ~ ) con otros botones auxiliuC"$. Es
d mismo diSC'no que la zona de botones principal,
,1 pero alineada en vl"rtical.
"
l::"'-. .__.__
·r··--Tl--------j1
U: .•_••~ .._ _ ~
figura 36. Botones OIIl<iliores
dellormulorio.

--o
Figura 37. Introdvc::ción del
cor1trol Hsplit.
Tras esto, situaremos un contl"nedor Hsp/ir, de
modo que el usuario pueda disponer de una barra
para modificar d tamaño rdativo del :irbol Yla zona
principal de trabajo. Dentro de ~ l se colocará, a la
izquierda, el control TreeView para el árbol, asi
como el conlrol/collView para la zona principal.
El control Hsp/il debe tener la propiedad Expillld
a TRUE, para que aproveche todo el espacio libre
disponible dentro de su contenedor.
3. lo ,nlerfoz gról1co
p.
So re l e
Ya podemos ejecutar el programa para ver la interfaz, añadiendo, si 10 deseamos,
algo de código para rellenar el árbol y [a vista de iconos.
Podemos modificar el alto yancho de la aplicación, la cual
se encargará de mantener, en lodo momento, la relación
de los distintos controles, sin que sea necesario añadir nin-
gún código de cálculo de posiciones por nuestra parle.
11
figura 38. Modificación del alto y ancho de la aplicación Alineción.
3. 7 Introducción al dibujo de primitivas
Además de los controles ya diseñados, el programador puede necesitar dibujar gni-
ficos personalizados. La dase estática Draw se empIca para dibujar sobre un control,
que puede ser un formulario o el control DmwillgArea.
Dibujar directamente sobre un formulario no tiene demasiado sentido, ya que una
vez se refresque la interfaz, por ejemplo tras pasar otra ventana por encima o mini-
miwr y maximiwr, se pierde el dibujo realizado sin que tengamos control sobre la
situación.
Sin embargo, DmwillgArcll dispone de dos modos de trabajo: en el primero, como en
el caso del formulario, se pierde el dibujo una vez se refresca el control, pero el even-
to Refres/¡ nos informa para que redibujemos la parle eliminada; en el segundo, que
se activa poniendo la propiedad Úlc1lcd a TRUE, el control guarda una caché del dibu-
jo realizado y no genera eventos Refresh, sino que redibuja automáticamente la zona
clareada.
......- _.- =.
....
Figuro 39. Proyedo Dibujando.
Como ejemplo, crearemos un proyecto grá-
fico Dibujando. que contenga un formula-
rio FMain, y en su inlerior un conlTol
DrawillgAmlllamado Lien7.o y un botón Ila·
mado Dibujar.
La propiedad Quhed del control Dmwj¡rgArea
se pondrá II TRUf.
El código del botón Dibujar será el siguiente:
Drlnl. Begin(LieD.Zo)
Draw.Line(O, O, Lien,so.W, Lienzo.B)
Draw.Line(O, Lieozo.B, Lienzo.w, O)
Draw.EDd( )
11
l
-
1
Al ejecular el programa y pulsar el
bolÓn. apar«erá un aspa creada por
nueslro código.
Este código contiene, para cualquier dibujo, el mttodo de trabajo siguiente:
• En primer lugar, se ha de especificar a la clase Dmw qué control será el emplea-
do para dibujar los elementos que indiquemos. para 10 cual se emplea el méto-
do Draw.Begin(} pasando como parámetro el control deseado, en nuestro caso
el control Lit/IUJ.
ProgrOI V I ~ U Q I con Softwm
11
• Tras esto, pasamos a dibujar [as primitivas que deseamos. Aquí hemos emple-
ado el método Draw.LincO, el cual dibuja líneas cuando especificamos los pun-
tos de origen y destino.
• Finalmente, siempre hay que llamar al método Draw.End{) para que la caché
del control DrawingArea se dibuje en la pantalla, y se liberen los recursos aso-
ciados al proceso de dibujado del control.
La clase Draw permite dibujar distintos tipos de primitivas:
• Draw.Ellipse: elipses.
· Draw.üne: líneas.
· Draw.Point: puntos.
• Draw.Polyline: varias líneas enlazadas.
• Draw.Polygon: polígonos.
• Draw.Rect: rectángulos.
En todo momento podemos controlar distintos aspectos del dibujado, utilizando lo
siguiente:
• Draw.BackGround: color de fondo del pincel.
• Draw.ForeGround: color de primer plano del pincel.
• Draw.FillColor: color para relleno de elipses o rectángulos.
• Draw.FilISlyle: utiliza las constantes de la clase FiIl pan determinar el patrón
de dibujado (relleno, rayado en horizontal, líneas y puntos, ete.).
"-demás de las primitivas, podemos dibujar elementos complejos con:
• Draw.Text: dibuja un texto en una posición indicada y con la fuente seleccio-
nada por Draw.Font.
• Draw.lmage: dibuja un gráfico almacenado en un objeto lmage.
• Draw.Piclure: dibuja un gráfico almacenado en un objeto Picrure.
?or último, Draw.Clip permite seleccionar una área de Clippillg, es decir, reducir el
¡rea útil de dibujo a un rectángulo que espedfiquemos, de modo que todo trazo que
luede fuera de él se excluirá de ser realmente dibujado.
11
4.1 La ayuda
ofrecida por otros programas
Los sistemas GNU/Linux siguen la filosofia de UNIX. Parte de cUa
consiste en crear pequeños programas especializados en cada larea, en
lugar de generar grandes aplicaciones monolíticas. Como resultado, en GNU/Linux
disponemos de muchas pequeñas utilidades de consola capaces de desarrollar casi
cualquier tarca que necesitemos. Los programas con interfaz gráfica, habitualmen-
te, son simples [rolll-cllds para aplicaciones de línea de comandos. Podemos poner
como ejemplo el magnífico programa de grabación de CDs y OVOs KJB, una apli-
cación sencilla, bella e intuitiva que, sin embargo, es sólo la portada de aplicaciones
como cdrecord o mkisofs, potentes herramientas de consola. ReproduclOres de video
o audio como Toten! o Kmplayer, recubren también aplicaciones sin interfaz gráfi-
ca propia, como el gran Mplayer.
-
11

Progromoc.:ión visuol con Sof:!ware Libre
Para aquellos que provienen del entorno Win321VB, puede resultar cxlraño. acos-
tumbrados a trabajar sólo con los n'Cunos que: apona el propio entorno de progra-
mación o añadiendo llamadas ti Id APl, t'$IO es, trabajando con ¡murias dd sistema
cuando va se queda corto, pe:ro este: modelo de segmentación m pequeñas unida-
des ofuct pronto gn.ndes ventajas al programador.
GNU/Linux pennilt desarrollar sin reinventar b. rueda. La shdl bash, común en
estos sistemas, junto con las herramientas habituales de consola que acompañan
a cualquier dismbución, proporcionan todo lo necesario para grabar un CD, repro-
ducir video, gestionar servicios LOAP, transmitir ficheros con flp, hup, 5mb, scp
o nf5, enviar y recibir correos, administrar bases de dalos, convertir formatos de
ficheros gráficos o de texto y mu:has tareas más. No es ncasario, en la mayor
parle de nuestros desarrollos, entrar en las complejidades de las diversas librerlas
escritas en e, tratar de s.olucionar los problemas de conversión de tipos entre un
lenguaje de alto nivel y e, ni caer frecuentemente en violaciones de segmento por
un descuido en un puntero mal gestionado. Basta con consultar la documenta-
ciÓn de un comando y llamarlo tal y como harlamos manualmente desde la con·
s.ola del sistema.
lo depuración del P'ogrolnO Iombién f.who r n ó ~ -.cilio: bo5tO probor el comondo
diredomente desde un termIno! de 18my cornprobor Ion rewhodo,. Ontel de emb.
berlo en el código Gombo,.
4. 2 Gestlon potente de procesos
Adiferencia de VB, donde lo llnico que podíamos hacer sin ayuda de la API era lan·
zar un proceso y desentendernos de ~ l , Gambas permite sincronizar la ejecución de
los dos programas, comunicarse con él leyendo y escribiendo por la entrada y sali-
da estándar (,Idi,l y ,tJout), conocer el estado (en ejecución o finalizado) y recibir
sus mensajes dI' error por la salida estándar de errores (stdur).
4.3 EXEC
Existen dos comandos pan lanzar la ejecución de programas dtsde Gambas: éXEC
y SHElL Un program.to en ejecución se denomina pr0ce50 y a partir de ahora habla-
remos de procesos ro.is que de programas. La primera instrucción, EXEC, lanza e\
comando que indiquemos, acompañado de los parámetros que escribamos:
[Variable-) EXEC [C(llllll8ndll WAIT JI FOR
(1tEADIlfRI'l'EIREAD lfRI'I'E) [Te St.ringl
Para facilitar la escritul11 de.' [os parámetros, evitando los problemas que putden sur-
gir con caracteTd tsp«ialts tales como los espacios, la sintaxis de EXfC indica que
hemos de pól$3.T d comando y los par.lmetros como una matriz o arl1lY de: cadenas:
[O ... )
De esto formo, si Ienemos qlltl ejecutor, por ejemplo, el comondo col ton un nombre
de archivo lol como m; orchiVO,b<f. qVl'l tiene un e$pOCio en medio, desoporece lo (lmbi-
gíi&ckld y lo necelidod d. indicar mós <;a,oclertu especiales como \, c;oo .1 fin de eli·
mino' lo polibilidod ti. q.... el comando tome mi orchivo.bd como dos porómell'os e<1
Iugor de uno 5610.
Vamos a ir desgranando poco a poco las diferentes opciones. CommClIld es d único
p.ar.imetro obligatorio y reprcsmta el comando a ejecutar. En el modo dt trabajo más
liimplt dt EXEC, btt tjecula el comando qut lt indiqutmo! y 5t dt él
Ahora, vamos a crtar un proyteto dt consola con Gambas. Para ello, aftadimos un
módulo de inicio y, como único código. tscribimos:
PUBLIC st1B Main()
111


Al erecutor\o se Ionzo el ccmondo 15 con el porómelro -1, obteniendo un de
arch,vos de lo carpeta octuolen formolo Io.go. Ob_mos q..... nue$lfO molnz de
codellcu ¡ndoooclo d"eclOmente en el «IfTI(Indo; podriomos haber hecho también
el p<cgromo osi:
PUBLIC SUB MainO
0114 scad AS MEK String( J
EXEC .Cad
Pero el intérprete de Gombas es capaz de recOllOCe< VIlO morriz indicando !In codenos
enlre corchetes y, de eso Formo, roas hemos librado ele unos cuontos lineos de c6digo.
Hasta aquí todo lo que hace Gambas l'$ d nuevo proceso, los pará-
metros, y desentenderse de: él. Se c:¡«ula de: forma asincrona, t!i decir, c:I programa
Gambas sigue su curso sin esperar a que: el proceso hijo finalice. Esto puede: un
inconveniente: si lenemos que sincronizar, o esperar a que el proceso acabe, antes de
continuar con la siguiente instrucción. Podemos realizar esta tarea de las Ires mane-
ras que vemos a continuación.
Palabra davE WAIT
Si añadimos el flag WA/T a la instrucción EXEC, el programa principal se detendrá
hasla que el proceso haya finalizado de forma normal o debido a algún fallo.
Veamos de nuevo el primer ejemplo con pequeñas lllooificaciones. Vamos a hacer
un listado de la carpeta Idev, que contiene gran cantidad de archivos. Si los dos pro-
cesos se eje<utan de forma aslncrona, obtendremos resultados impredecibles:
PUBLIC SUB Main()
exec (Ulsu,u/devu,u_lffl
PRINT uHOlA DESDE GAMBAS
u
mm
A continuación, lo compilamos y ejecutamos varias veces desde un terminal.
Ohservaremos que, como en el listado de más abajo, la frase HOLA DESDE GAM-
BAS se introduce de forma caprichosa entre el listado generado por el comando Is:
~ ~ ~
, roo<
"'0'
5 jun 28 10:55 mouse -> psaux
crw-rw----
,
~ ,
roo< U, J2 jun 28 10:55 mouseO
drwxr_xr-J: 2
~ ,
roo< 60 jun 28 10:55 net
crw-rw-rw-
,
~ ,
roo<
"
3 jun 28 10:55 null
1rwxrwxrwx
,
~ ,
roo< 3 jun 28 10:55 parO -> 1pO
HOLA DESDE ........
crw-rw----
,
danie1 u>b 99, O jun 28 10:55 parportO
11
crw-rw----
,
roo< roo<
",
62 jun 28 10:55 pkt.cdvd
crw-r-----
,
~ ,
roo<
"
4 jun 28 10:55 port
crw-------
,
~ ,
roo< 108, O jun 28 10:55 ppp
Apliquemos ahora el flag WAIT:
PUBLIC SUB MainO
EXEC ["ls","/dev",U_1U] WAIT
PRINT HHOLA DESDE GAMBAS"
mm
Lo ejecutamos cuantas veces queramos: ya no existe el problema inidal, el progra-
ma Gambas espera a que termine de ejecutarse 15, y después pasa a la siguiente línea
de código. Hemos conseguido sincronizar la ejecución de dos procesos de forma sen-
cilla, simplificando nuestro código, ya que de otro modo tendríamos, por ejemplo,
4. Gestión de procesos
11
que haber volcado el listado en un fichero, esperar en un buck a que el tamaño del
fichero dejase de- crecer y, a continuación, leerlo y mostrarlo en pantalla.
El descriptor del proceso
Habremos observado que al principio de la sintaxis de EXEC, se indica un valor
opcional VARIABLE=, que recibe algo de retorno tras llamar a EXEC. Esta variable
es un objeto de la clase Proccss, y lo que se recibe es un descriptor del proceso que
hemos lanzado. Los objetos de la clase PfOceSS tienen una serie de propiedades que
nos permiten conocer el estado del proceso, así como actuar sobre éL
Lo que nos interesa ahora es la propiedad State, que refleja el estado de ejecución.
Cuando se lanza un proceso, el valor de State es Process.Running, es decir, proceso
en ejecución. Si el programa ya ha terminado, la variable Stilte podrá tomar dos valo-
res Process.5ropped, detenido, finalizado, o ProTess.Cmshed, si finalizó debido a un
error grave, habitualmente una violación de segmento.
Utilizando esta propiedad tendremos la capacidad de sincronizar los dos procesos
de un modo más potente: podremos realizar algunas tareas en nuestro programa
Gambas, mientras esperamos a que finalize el proceso au)[iliar. Tipkamente, lo que
haremos será dar algo de fredback o información al usuario dr que debe esperar.
Como ejemplo, vamos a descargar un fichero desde Internet cuando el usuario pulsa
un botón, y a indicarle que estamos trabajando, que no se ha colgado la aplicación,
si no que debe esperar con paciencia.
Vamos a trabajar con la aplicación auxiliar cud, que es un programa de línea de
comandos que permite precisamente lo que querernos: descargar un fichero desde
una URL. Si no tenemos cud ya instalado, aprovecharemos para hacerlo ahora, ya
que está disponible para todas las distribuciones GNU/Linux habituales, as! como
para FreeBSD. Para ello, consultamos desde Synaptic, Yast, RpmDrake o nuestro ges·
tor habitual de paquetes en otras distribuciones.
Lo que descargaremos es un programa en Gambas llamado RtldioGambas, cuyo códi-
go contiene un buen ejemplo de gestión de procesos y que tambit'n podemos estudiar.
Además, nos sirve para escuchar programas de radio emitidos por Internet, lo cual no
está mal. La VRL es h«vJlgambas..gnulinex.orglradiogambaslRadioGambas- I.O.l.tar.gz,
aunque podemos consultar en hupJ/gambas.gnulinex.orgiradiogambas la existencia
de versiones más recientes.
[
-
--
l
Ahora, vamos a crear un programa gráfico y, en
él, un formulario, con un botón llamado
BtnDescarga y una etiqueta llamada Lbllnfo.
.. Figura 1. Valar Inactiva de la
etiqueta y botón Descargar.
La etiqueta tendrá como propiedad Text el valor
Inactivo, y el botón tendrá el texto Descargar.
El código del formulario será el siguiente:
PUBLIC SUB Click()
DIM hPt'QC AS Pt'QCess
DIM SUrl AS STRING
sUrl-"http://qambas.qnulinex.org/radiogambasl
RadioGambas-l.O.l.tar.qz"
hProc - EXEC ["curl
w
• sUJtL, "-o", User.Home &
"/RadioGambas. tar .qz" I
DO WHILB hProc.State - Process.Runninq
SELECT CASE Lbllnfo.Text
CASE "1"
Lbllnfo.Text - "1"
CASE "1"
11
Programación visuol CO!1 Software libre
CASE w\\w
LblInfo.Text _
CASE &LSE
LblInfo.Text _ ulu
"'" SELECT
HAIT 0.1
"'"
LblInfo.Text _ uInactivo
u
finalizada
U
)
"'"
Ejecuramos el proceso con los parámetros ne<:esarios para que 10 descargue en nues·
tra carpeta personal con el nombre RadioGambu.tar.gz, y recibimos un descriptor
del proceso. Seguidamente, entramos en un bucle que se ejecuta mielllras el proceso
está vivo, es decir, mientras el estado del proceso es Process.Running. En dicho bucle
cambiamos el valor del textO de la etiqueta entre los valores ".", "1", "1" Y"\", de forma
que se genera la ilusión de un molinillo, con 10 que el usuario sabe que algo se está
cociendo por debajo. Con la instrucción WAlT refrescamos la interfaz. Al terminar,
informamos al usuario y ponemos la etiqueta con su valor original.
Probom01o modificar ,,1 programo eliminando el código del molinillo y ejecutando ,,1
programo de formo sincrono, como explicamos con el Aog WAIT:
hProc-EXEC[ sUJ;"l , U-o", System.Hane ,

Ellvneionom;"nlo es igual de efectivo: el progroma de$Corgo el fichero en ambos cosos,
pero ahora lo intedoz de usvorio quedo b1oqveodo duronte lo descmgo, lo qVll puede
hacer pensar que nuestro programo se ha colgado y generar alguna. 1I0modol
inútile. o nue.tro .ervicio de atención 01 cliente, en el peor de los cosos. E. impor-
Tonte, por ello, evoluor en qué coso. no. conviene uSOI WAIT y en cuóle. es mejor
informar, de alguno manero, 01 usuario poro que monlengo lo colmo y lo. monos
leja. del teléfono.
o O O O O Redil'ECc16n con ro
En los ejemplos anteriores con el comando /s, la salida aparecía directamente en
la consola, lo cual no es útil si queremos procesar la información procedente del
comando.
Podemos utiliZ<lr la palabra clave TQ para conseguir dos propósitos de forma sen-
cilla: esperar a que el proceso acabe antes de continuar el programa principal y reci-
bir en una cadena de texto la s;¡lida del programa:
PUBLIC SUB Main()
DIM scads AS NEW String[J
DIM Buf AS String
DIM Bucle AS Integer
sCuds • Split(Buf, ~ \ n ~ )
sCads.Remove(O)
sCads.Remove(scads.Count - 1)
FOR Bucle· O TO sCads.COunt _ 1
PRINT Left(scads[Buclel, 10)
"'''''
A Gestión de procesos
11

PrQgramociór visual con Software Libre
--- - -- -- -
La instrucción EXEC aguarda hasta que finalice el comando Is, almacenando en un
buffer la salida estándar del comando, que nos devuelve en la cadena Buf. A conti-
nuación, procesamos la cadena Buf separándola en lineas con Split, eliminamos la
primera y última (sin información úlil) y mostramos en pantalla sólo la parte del
listado correspondiente a los permisos.
Lo solido de los procesos con vario. líneas ... puede dividir fácilmente empleando lo
fund6n Spli¡, y utilizando COmO separador el retorno de corro \n.
Hasta aqul hemos visto cómo sincronizar los dos procesos, pero aún podemos tener
más control sobre él.
Matar un proceso
Además de [as propiedades cid objeto Process, éste ofrece un método de gran impor-
tancia: Kili, el cual prrmitr matar o acabar con el proceso en cualquier momento.
Supongamos que en nuestro programa anterior, la red es desesperadamente lenta y
el usuario decide no esperar e interrumpir la descarga. Gracias a KilJ podemos incluir
esa posibilidad en nuestro programa, vamos a ver cómo llevarlo a cabo.
Añadimos al programa anterior un botón llJ-
mado BtnCancelar, con texto Cancelar y con el
l1ag Enabled a FALSE, para que inicialmente esté
inactivo.
El nuevo código es el siguiente:
P R I V ~ hCancel AS BOOLEAN
PUBLIC SUB BtnCancelar_Click{)
hCancel-TRUE
END
--
Figura 2. 6tnConcelar
Inactivo.
PUBLIC SUB BtnDescarga_Cllck()
DIH hProc AS Process
DIM sUrl AS String
hCancel-PALSE
BtnCancelar.Enabled-TRUE


hProc • E1EC sUrl, User.Home &

DO WHILE hProc.State -
SELEeT CASE LbIInfo.Text
CASE
LblInfo.Text -
CASE
LblInfo.Text -
CASE
LbIInfo.Text -
CASE
LbIInfo.Text _ wln
CASE EUlE
LblInfo.Text __ 1_
END SEt.ECT
HAIT 0.1
IF hCll1>Qol-TR1JE 'I'HEN
hProc. Kill ( )
Message.Warnlng("Proceso cancelado
n
)
LbIInfo.Text _
BtnCancelar.Enabled-PALSE
RE'roRN
END IF
11

Progromoción vislIOl con Softwore ulve
LOOP
LblInfo.'feltt - "Inactivo"
Mesnge.Info("Desc:arga finalizada")
una global, hCancel, para saber si el usuario ha pulsado el
Dotón Cancelar. Al iniciar la descarga, esta a fALSE. Si el usua-
rio pulsa el botón 8InCancc!ar, dicha variable lOma el valor TRUE. En nuestro
bucle, comprobamos el valor de hCancel y, de ser TRUE, matamos el proceso con
Ki1IO, devolvemos la interfaz al estado in3ctivo, inform3mos al usuario y salimos
de la subrutina.
Aunque ya tenemos sincronización del proceso y podemos acabar con él a nuestro
antojo, el feedback que hasta aqul hemos proporcionado al usuario es algo pobre: el
molinillo no nos sirve para conocer cuál es el estado real de la descarga, ni hacernos
cuánlo más habremos de esperar.
Sin embargo, curl está emitiendo un por la salida estándar de cnOre:!i stderr
(o texto impreso por la consola, si no estamos familiarizados con ese tfrmino), que
podemos apfO\'C'Char.
Redil'ECdón dE la salida EStandar dE EJTOf'ES
Si estamos familiarizados con el lenguaje C, los se a la salida están-
dar con la función printf() y a la salida estándar de errores mediante perror(), ambas
incluidas en la librerla estándar de e (g/ibc en sistemas GNUfLinux).
lo. proce$Os pueden enviar le"to o lo consola por dos vía., lo primero e, utilizando
lo $Olido e,tándor y. lo lo ,olido estándar de errare•. lOJ dos cominos Jepo-
rodo••e utilizan po.o dilerencior qué tipo. de men.oje••e envíon. Por lo .olido
e..tóndor [sidoult se -'e em,tir ,nlorrnociOO Uril Como \/l!ferrM» en el sigUtenle opor·
rado, el ptogfOmo cwI em,te el hchero recibw:lo poi' la solido eslóndor salvo que indi-
quemos eKptesomenle el fichero dónde depoSlfOrlo Por lo solido e..tóndor de er'o-
res [stdenl se emiten mensojes de estodo, de advertencia o de error CurI optovecho
esto solido poro indicar ele.lado de lo descorgo o poro informar de un error en el
inten!o de
Centrándonos más en curl, si aplicamos el parámetro -ti, d programa va mostran-
do una barra de progreso formada por el s[ml>olo ti (almohadilla o sostenido) y un
indicador del tanto por ciento descargado.
Gambas permile recoger el contenido lanto de la salida eslándar como de la salida
esIándar de errores, si aplicamos el flag FOR READ a la hora de ejecutarlo.
Cuando el proceso hijo envla una cadena por la salida de ("rrores (llaman-
do a permrO, si está escrito en C), nuestro programa Gambas recibirá un evento
ErrorO procedente de la clase Process. La sintaxis de este evento es:
PUBLIC SUS Process_Error(IError As String)
En la cadena .JEITor r«ibircmos el mensaje d(" error, o informati\"O, procedeme del
proceso hijo. Vamos ("ntonces a modifi¡;ar el programa para. rn:ibir el porcenlaje de
descarga y represenlarlo en la eliqueta, en lugar del molinillo.
PRIVArE bCancel AS Boolelln
PUBLIC SUB BtnClncelllr_Click()
hClncel • TRUE

11
DIN 5Cad AS St.ringll
Err - Tru.(Err)
&Cad - Sp1it.(Err, " ")
lbUrato.Ten - &Cad[scad.Cow1t. - 11
2ND
PUBLIC SUB Bt.nDescarqa_C1ick()
DIH hProc AS Process
DIH sUr1 AS St.ring
h<:ance1 - FALSE
Bt.n<:anee1ar.Enab1ed • TRUE
sUr1."ht.t.p:llgambas.gnulinex.org/radiogambasl
RadioGambas-l.O.l.t.ar.gz
W
hProc • EXBC (-cur1-, , "-0-, User.BoDe •
•• t.ar.gz-. --''') POR READ
00 WHILE hProc:.SUlt.e • Process.R"nning
HU'r 0.1
Ir hCan<:e1 • TRUE TImN
hProc. Kill ()
Hessage.warning(-Proceso cancelado")
- "Inactivo-
Bt.nCancelar.Enab1ed • FALSE
RE'l'IIRN
2ND "
ux'"
En esta ocasión ejecutamos el programa cud con el parámetro adicional-#. Cada
vez que nuestro programa redbe un evento Error de Pnx:ess, éste se trata en nues-
tro código: tomamos la cadena, eliminamos con Trim{) los posibles espe-
ciales de conlrol que (uTl U$a para mantener d cursor en la misma linea, de
modo que dt la impresión que la barra de progreso avanz.a (se trala de los llamados
caracteres ANSI de conlrol), separamos la cadena en varias subcadenas tomando el
carácter de espacio como base y nos quedamos con la última subcadena, que es la
que contiene el dato del porcentaje, para representarla en la etiqueta.
Supongamos ahora que no deseamos gu.ardar un fichero, sino mostrar direclamen-
te su contenido en pantalla.. Por ejemplo, en la URL http'J',,"ww.gnu.OfW'licensr:oJgpltxt,
disponemos de un fichero que, en lexlO plano, contiC'ne la licencia GPL original
en inglés.
u REdlrecclón dE la salida e;tándar

La primera opción sería guardar el fichero y, una \"ez finaliz.ado el proceso, leerlo y
representarlo en pantalla, pero de este modo complicamos el código ya que tenemos
¡¡UC cre3r un fichero en alguna ubicación (por ejemplo, /fmp), leerlo y luego borrar-
lo par3 no dejar restos en el disco duro. Como indicamos en el anterior 3p3rtado, el
:onlC'nido de la salid3 estándar tambii'n puede ser lC'ido y cUTl rnvia el fi<:hero a la
;alida estándar salvo que, como en nuestros ejrmplos anlC'nores, esp«ifiqurmos un
llchC'ro dondC' drposilar los datos recibidos.. La sintaxis del eve:nto generado por la
-ecrpción de dalos procrdenles de la salida estándar del proceso, es algo diferenle dr
a de los erorres o informali\'os que vimos antes:
mm
11
Programoción visual con Software libre
En esle caso no hay ninguna cadena para recibir la información, por el contrario,
cada objeto Process se comporta como un flujo o strellm, lo que en olras palabras
significa que podemos trabajar con él del mismo modo que haríamos con ficheros
abiertos con OPEN, pudiendo utilizar, por tanlO, READ o UNE INPUT.
Hay que recordar también que Gambas provee una palabra clave, LAST, que dentro
del evento representa de formó! genérica al objeto que lo generó. Podemos, enton-
ces, leer el contenido de];-I salida estándar del proceso utilizando LAST como pará-
metro de las instrucciones relacionadas con lectura y escritura de procesos. Por ejem-
plo, para leer una Irnca completa, haríamos:
PUBLIC SUB Process_Read()
DIH sCad AS STRING
LINE INPUT 'LAST,sCad
PRINT sCad
Para nuestro programa, añadiremos una caja
de texto (TextArea), llamándola TxtLicencia,
con su texto inicial en blanco y en ella pondre-
mos el contenido del fichero gpl.txl, conforme
lo recibimos.
--
El código es el siguiente:
PRIVAtt hCancel AS Boolean
PUBLIC SUB BtnCancelar_Click()
hCancel • TRUE
END
"".......
Figurg 3. Caja de texto
btlicencio.
DIH sCad AS String
LINE INPUT tIAST, sCad
TXTLicencia.Text _ TxTLicencia.Text & sCad & "\n
w
PUBLIC SUB Process_Error(Err AS String)
DIH sCad AS String[ 1
Err • Trim(Err)
sCad _ Split(Err, " ")
LblInfo.Text - sCad(sCad.Count - 1]
PUBLIC SUB BtnDescarga_Click()
DIH hProc AS Process
TxtLicencia.Text _ ""
bCancel - FALSE
BtnCancelar.Enabled TRUE
bProc - EXEC (Ucurl", Ubttp://www.gnu.org/licenses/
gp1.txt", "_t"1 FOR READ
DO WHILE hProc.State - Process.Running
WAIT 0.1
IF hCance1 - TRUF; TllEN
hProc.Kill()
4. G e ~ t i ó n de procesos
11
Programación vi5ual con Software libre
Message.Warning("Proceso cancelado
N
)
LblInfo.Tert _ "Inactivo"
Btncancelar.Enabled - FALSE
""'"""
END "
lOOP
LblInfo.Tert _ "Inactivo
N
Hessage.Info(NDescarga finali:l¡ada")
En el evento ReadO leemos una línea y la afiadimos al contenido previo de TxtLiccncia,
más un retorno de carro para separar cada línea.
o Evento KlIIO y la propiedad Value
Además del método KiII(), la clase PrOCe5j emite un evento KillO cuando un proce-
so ha finalizado, sea de forma normal o por un error. La sintaxis de dicho evento es:
PUBLIC SUB Kill()
Hasta ahora, en nuestro gestor de descarga hemos esperado en un bucle a que el pro-
ceso acabe, pero podemos crear una estructura más elegante, más adaptada a la pro-
gramación orientada a objetos, valiéndonos de dicho evento: en lugar de esperar en
un bucle, aguardaremos tranquilamente y sin hacer absolutamente nada en nuestro
programa principal hasta recibir el evento Kill(), bien sea porque la descarga ha fina-
lizado, bien sea porque el usuario ha decidido cancelar el proceso:
PRIVAXE bCancel AS Boolean
PRIVAXE bProc AS Process
bcancel - TRlJE
bProc . KilI ( )
PUBLIC SUB AS String)
OIM scad AS String[]
Err _ 'l'rim(Err)
sCad _ Split(Err, u
LblInfo.Text - acad(ICad.Count - 1]
END
PUBLIC SUB process_Kill()
IF bcancel - TRUE TBEN
Messlge.Warning{Uproceso cancelado
U
)
ELS'
MesS8ge.lnfo(MDescarga
END "
LblInfo.Tell:t -
8tnCancelar.Enabled - FALSE
PUBLIC SUB BtnDescargs_Click()
DIM sCad AS String
4. Ge f 1'I:1e
111

Programoción viwol con Softwore übre
TxtLicencia.1'e:.;t - ....
bCancel '"' f'ALSB
8tnCancelar. Enabled. '"' 'l'RlIE
hProe '"' E%EC ["curl", ''http://www.gnu.org/llcenses/
9 P l . t ~ ....._, .. ] POR READ
"'"
Hemos cambiado la declaración de hProc de la función BtnDescarga_Clkk() al ini-
cio de nuestro formulario, para que sea accesible también desde el evento
BlnCancdar_OickO. Ahora [anlamos el proceso y ya no esperamos en un bucle. Si
el usuario decide cancelar la descarga, matamos el proceso en el mismo evrnto
BtnCancelar_Click().
Tamo si el programa termina normalmente como debido a una cancelación, aprove-
chamos el e\"emo Proccss_KiIIO para informar al usuario y devolver la interfaz a su
estado inicial (ron d botón Btnúuxdardeshabilitado, y la etiquet.a marcando Inactivo).
El resultado final: menos gasto de r«ursos (d programa principal no ha dI' ej«-u-
lar el bucle constantemente). menos líneas de código y mejor estructuración de todo
el proceso.
Por 0Ir0 lodo, la moyor por" ele 10$ progrom<l$ de con$Olo (y gról.co$l deYueIv'en 01
sistema un COO'90 de &rro< cvondo f,nalizan. lo costumbre es que Sot ~ un cero
si lodo fue bien Yoll'o valor cuando algo lolló
Dcsdc la consola podemos hacer una prueba ejecutando en una venl:lna de termi-
nal estas dos órdcncs consecutivas:
$ 1& -1 Idev
$ echo $1
Al ejecutar echo $1 obtendremos un cero. La she!l del sistema almacenó el último
código de error disponible en la variable S? y, a continuación, lo hemos mostrado
en pantalla: todo fue bien. Ahora ejecutamos la siguiente orden:
$ ls -1 Ifichero/que/no/eziste
$ echo $7
En esta ocasión obtendremos un seis, un código de error que en el caso de! coman-
do ls implica que la ruta no existía (siempre y cuando no haya, por alguna extrai'ta
razón que desconozcamos, un fichero en nuestro sistema cuya ruta sea
lfichero/que/no/existe) .
Sí [lIrI no puede acceder a la URL, por cualquier circunstancia, devolverá un valor dis-
tinto de O. Nosotros podemos leer en nuestro código ese valor, mediante la propiedad
Va/ue, e informar al usuario dd error. A contínuación, modificamos el código del pro-
grama anterior (página 142 en adelante), de forma que el evento Kili quede así:
PUBLIC SUB Process_Kill()
IF LAST. Value<>o TREN
Message.Error ("Error en la descarga")
ELSE
IF heancel • TRUE TREN
cancelado")
ELSE
Message.Info{"Descarga finalizada")
ENt> IF
ENt> "
LblInfo.Text - "Inactivo"
Btncancelar.Enabled - FALSE
ENt>
4. Gestión de procesos

Probemos el programa desconectando el módem de Internet, desenchufando el cable
de red o deshabilitando la red de nuestro sistema. Observaremos que ahora pode-
mos determinar el éxito o fallo de la descarga, además de su cancelación.
:dir 'ciO! de ntrada nd el U ~ o le "lOSF
Los programas, además de emilir información a través de 5tdin y 5tderr, la pueden
recibir a través de la consola, según el usuario teclea órdenes. Esta recepción se rea·
liza mediante la entrada estándar o stdin, ysi tenemos conocimientos de e sabre-
mos que podemos utilizarla con funciones como 5canf() o getcharO, Con Gambas,
podemos empicar el flag FOR WRITE para indicar al intérprete que estamos intere-
sados en escribir datos para el proceso hijo. Una vez lanzado el proceso de este modo,
podemos usar las funciones normales de escritura de archivos con el descriptor del
proceso (PRlNT, WRITE).
Supongamos un programa con un área de texto (TextArea) llamada TxtTexto, en la
Figura 4. Proyecto con boI6n
Contar y áreo de texto TxIÑlxlo.
-.- <&0
....... _ .. _ .... __.. co.- .
.........._ _-"' .. - .
<-, ~ _-...... - .... __.. __.. ~ -
__.. _-_....-
<-_ __ , _ . ~
- - ~ - . . , - - . _ . _ ­
.............. _-,_._-.
_."'_H.......... "'_'__
... _""..~ .. _._.. ~ - ' . - - . ~
que escribimos cualquier cosa, y deseamos conocer el número de líneas (separadas con
retornos de carro), que hemos escrito. Podemos, para ello, usar el comando wc (sig-
nifica Word Countery no otra cosa), con el parámetro -1 (número de líneas). En nues-
tro ejemplo, llamaremos al programa, escribire-
mos el conlCnido de TxtTexto al proceso, y
recibiremos el resultado por la entrada estándar.
Puesto que vamos a leer yescribir, podemos com-
binar los flags READ y WRITE. Para ello, creamos
un proyecto gráfico con un botón BtnContar, con
el texto Contar, y un TatArea llamado TxtTexto,
con el texto en blanco inicialmente para que des-
pués escribamos un texto.
11
PRIVATE hProc AS Process
PUBLIC SUB Process_Read()
DIM sCad AS String
LIta: INPUT ,hproc, ,cad
Message(HEl texto tiene
PUBLIC SUB BtnContar_Click()
H " sCad " H 11neas")
hproc _ EXEC (HWCH, FOR REAl) WRITE
PRINT 'hProc, TxtTexto. Text
CLOSE 'bProc
EN<>
n la función BtnÚlntar_ClickO, ejecutamos el programa indicando al intérprete
ue deseamos acceso de leClura y escritura al proceso, escribimos en el conte-
ido de la caja de texto y, a continuación, ejrcutamos CLOSE sobre el proceso.
ejecutamos wc -1 desde una terminal de línea de comandos.
Ibservaremos que podemos ir escribiendo en el proceso todo lo qUl" queramos. Así,
deamos varias líneas y después pulsamos a la vez las teclas Úlntrol + D.
¡ entonces cuando nos devuelve el número de líneas que hemos escrito. Al man-
lr el carácter especial CTRL+D, l"stamos indicando al proceso que hemos cerra-
) el flujo de datos y, por tanto, procede que él compute lo recibido y devuelva el
sultado.
Ilando en el programa Gambas ejecutamos CLOSE sobre un descriptor de fiche-
',el resultado es similar: se cierra la redirecci6n entre la salida estándar del proce-
hijo y nuestro proceso principal, con lo cual el primero queda informado de qUl."
I recibido todos los datos.
resto del programa es trivial: en el evenlO READ recibirnos la cadena que contie-
el número de líneas y lo mostrarnos al usuario en un mensaje.
A. Gestioo de procesos


Progromoción vi:woJ too SoHwore Lbre
o o o o Notas finalEs sobf'E e objeto Pro«ss
El objeto Proass tiene un método SignaJ() usado por el propio depurador de Gambas.
Pnmite enviar señales al proceso en curso, pero su uso no es aconsejado, ya que inter-
fiere con el resto del código del intérprete.
El objeto dispone también de una propiedad Id, que es un handle o des<riplor del
archivo. Si con()(emos Co C++, se trata del identificador de pr()(eso o PID del pro-
grama hijo que se obtiene tras una llamada a[orkO, que es el modo de crear nuevos
procesos en sistemas UNIX. Este valor puede servir para buscar el proceso, por ejem-
plo. ejecutando ps -le, variar su propiedad con niu. Outilizarlo junto con posterio-
rt$lIa.madas a funciones de- e (veremos en otro capitulo cómo hacerlo desde Gambas)
para controlar dicho proceso.
Los eventos generados al trabajar con procesos son estáticos. Habremos ~ d o
que en los sucesivos ejemplos se ha indicado Proccss_Read y Prouss_KiIl. Si tene-
mos varios procesos en ejecución. siempre podemos diferenciar qué proceso ha gene-
rado el evento mediante la palabra clave LASf y aCluar en consecuencia:
PRIVATE hProcl AS Process
PRIVATE hProc2 AS Process
PUBLIC SUB Proeess_Reado
Ir LAS'l'-hProcl '1'HEN •••
••••• 4. 45HELL
SHELL es similar a EXEC, pero en este caso lanza la shell o intérprete de COman-
dos del sistema, habitualmente BASH, en las distribuciones GNU/Linux y le pasa
el comando que le indiquemos. Esto permite, por ejemplo, dar órdenes al sistema
tales como export o eJ, que son parte de BASH y no comandos independientes.
También da via libre al uso de tuberías Iy operadores de redirección como> o 2>
entre otras características de la shell. La sintaxis de SHELL es la siguiente:
[Variable - 1 5HELL Comnand ( WAIT J ( FOR ( REAIl I
WRITE I READ WRlTE )
Es muy similar a la de EXEC, pero en este caso Command es una cadena de texto y
no una matriz de cadenas, ya que este valor se pasa directamente a la shell del siste-
ma que, dependiendo de sus características, interpretará los espacios y otros símbo-
los especiales de un modo u otro. Queda pues, por tanto, como trabajo para el pro-
gramador, añadir el formateo adecuado para que la shell interprete la orden
correctamente.
4. Gestión de proce!oOs

5. I Sistemas de
bases de datos
Agrandes rasgos, un sistema de bases de dalos es una aplicación
que permite almacenar yconsultar información de forma sencilla. Casi todas
las bases de datos actuales posibilitan la intmr.cc:i6n con el usuario o programador,
a través de un lenguaje llamado SQL Es importante. antes de pro«der a trabajar con
una base de datos, conocer este l('nguaje. m«liante el cual se consultan y modifican
dalos, además de permitir crear la estructura de la misma (tablas, campos, etc.).
Quedo fuero del olcol'lCe de eue ~ b r o upIicor • lenguaje SOl. li bien le ¡ndicofl ..
nos nociones bóWcos o lo Iorgo de los ejemplos . ~ , .
11
J o d O l U O ) s O l e p ¡ ; > J o d O I U C I ' c p c n ) ; > p c u ! ; ' l U ; , w [ e I O l
O W O ) c u n ' I e l ! d s o t ¡ u n S J l u J ! ) c d ; > p U 9 ! ) C l U l O j U ! J p U 9 ! ) c [ ! d m J J c I
o ' O l n l 1 l S U ! u n U J S ; l u o ! ) d ! J ) S u ! J s o u w n ¡ e J p C l ¡ n S U m C [ ' S C U ! W 9 U a p U 9 ! l S ; > S J p
I C U O ! S J j o J d U 9 ! ) C ) l l d c c u n ' J p u e J S 0 P l ; } l U O ; } u n ; } p J o d ' U 9 P S J S e [ e J e d
" O P U c f c q C J l J ! n S J S e J C d l I S O ; > A e l l e u n U J o O : ) u n U J e s e J e e l
o J I U J l U e J ! P 9 ! l J d p e p ! m S ; > s s e ! d o J s n s J ; » e t ¡ J p : : l n d o u e n s n ¡ J , í e ! h : : l J d
u 9 p e J n S y u O ) U ! S J n b l l e l l e J J l l l ! J d ¡ : : l U : : l l e J l ) : : l I X l l l d : : l S : : l s c q e [ ' ¡ e u O ! J l p C c p n , í c o o d
U O ) O { J C ¡ e l S U ! J e l U e J S o J d l : : l : : l p : : l l l d : : l I U : : l ! [ J 1 3 " e l l l J u ; > s U 9 ! J C ¡ C l S U ! e u n u m
a I U : : l p ! J n s e p u J l o d e [ e S n f u o J : : l 1 ! J b S s O l e p : : l p ; l S C q c u n ' O ! ) J J W O J 0 \ l J n b ; , d u n ; > p U 9 ! l
- S J S e [ o J s c [ J e u n : : l p s o u w n [ c S O ] C C A I I C [ ; l J U 9 ! ) C W J O j U ! e [ ' s O A O , í s O : ) J p S O I C p J p
J s e q e u n ' \ c U O S J J d e p u J S e c u n J J S J p ; l l l d O W O ) u 9 p e ) ! I d e c l I n C l C d " e p ! l
- ; l n b J J U 9 p e J I S ! U ! W P C ; l P Z J l I ! J U ; l S C ¡ , í J C ! : : l U C W C s o ¡ c p J p u J l U n l o h p : s ; } [ e l l l J l U e p
- u n j s O I J ; l d s e s o p S J I U ; l S : : l J d J ; > U ; > I J p S O W J t ¡ ' U 9 ! ) i ' J ! [ d c C l l S ; / n l l l e y J S ! p ; / P C l O t ¡ e [ V
" ( S J O " J l ! J b s " M M M / / : d n t ¡ ) J l ! l b s S J ' Z ; l A l e l ' O d ) l J I S J J p J e [
- n d o d s y w s o ¡ e p a p a w q P [ ' x n u ! l / [ ) N 8 u 3 ' ( O : ) u n U ; ¡ s e p e q e J S J J S u : : l p ; ¡ n d ' o l d w : : l I J
J o d ) J C l l O d s U C l l J p S J I ! ) Y j s y w l J S u ; ¡ l ; ¡ n s , í S O l C p J p S J s e q J p J O p ! A 1 a S U I l ; l p U 9 ! J
- P J l S l U ! W P C , í u 9 p P l e l S U ! e ¡ o u ' : ) d U ; ¡ S O S J I l J J J s o u a w S 0 t ¡ J n l l l U : : l w n s
- U D ) ' O ! q l l l P J V " p m l ! l J s ; ¡ / e l n p J I O p O U l u ; ¡ S O U ; ¡ W ¡ e ' e J U Y I ¡ n l l l ) S P W J O j a p u 9 ! x J u m
P l I n J p U ; } l ! U l l J d o u ; ¡ l U J l U l c O I ! q e t ¡ , í ' o d ! n b ; l 0 ! d 0 1 d [ ; > a p s ; , p 0 [ 9 S S J [ q ! S J » P
' S J [ " I D O ¡ s O l e p a p s J s e q U O S J 1 U ; ¡ U l [ e U l J o N " c p ; l J O J d a n b O I U a ! l U ! U J l U P W [ J l c z ! l p a J , í
; ¡ P s e ! d m s e r J J U J 1 U e l U ' ; l S e q c I J e ) ! q n ; > p c t ¡ J O p p W P l S O l d J 3 " o m p o ) S ! P
O J I S J n U U ; ¡ o p e l o [ e O A ! t ¡ J J e u n J n b s y w S J o u s a l e p a p ; / S P q e [ ' O d ! l o p u n S J s p u 3
" ( S l o " ¡ b s Á W " M M M . / / : d l l t ¡ ) O [ J p O W J p o [ d
- W : : l ! J u n " e [ q c l o ; l S C q e p c J U a U J ! l U O J J n b S O l J ! . p y s O l J p u 9 p e J ! q n C [ O l U O ) s J l e l S O l
- J J d S e ; l p ; m e d n ) { l ; > J d J p e l ] o u J n b J l S i ' s 3 " U 9 p e J l [ d e C I ; ¡ P J o p c w e J S o J d [ ; l P
o u ' J O P ! A J J S ¡ J p e ; l l I J I S ; l S J S 1 U \ s e ¡ J p e U l J 1 U ! e m l J n J I S J I J ' " ] " J I U J 1 ] J s o d ! n b : : l S O I U ! I S ! P
J p S ; l p S e J u Y l ¡ n W ! S S J l I O ! X J U O J S P P P A J l ! W J J d , í o p e n s n e p e ) a p O s a J ) e J p s o s l w J ; > d
s O l P I O J I U O ) ' S O I C p J p S J S P q S P I U ! l S ! P J O P ! I \ l ; l S [ 3 " C P C u J J c w l e U 9 ! J I J l U J O j U l
P [ C U O ! l S J S J n b ' 5 0 J l ! Q J p S J s v f j J p l O p i A J J S o p e w e n e W I J J í l o J d u n J 1 S ! x ; } ' O J J l l l ! l d P
U 3 " S o d ! l s o p U J s e l J e J y ! s e p S O U l : : l p o d O J : : l d ' S e l U ! l S ! P S O l C P ; / P s ; ¡ s e q s e l { J n w u n s t x 3
J l ' ! : l J J O M I l O S - U O J 1 0 1 1 S ! A l J 9 ! J O W O J 6 6 J d
1 1
necesidad de la consulta e ingreso de datos desde diversos puestos de trabajo de
forma simultánea. Aquf tendremos que estudiar qué servidor de bases de datos es
el más adecuado para nuestro sistema. En el entorno de software libre, las dos
opciones más probadas y de mayor prestigio son MySQL y PostgreSQL
(htlp:llwww.postgresql.org/). Ambos sistemas poseen, además, versiones con
soporte comercial.
••• •• 5. 2 Bases de datos y Gambas
Gambas tiene estruClurado el acceso a bases de datos mediante drivers. Estos son
módulos de código escritos por diversos programadores espedficamente para comu-
nicarse con una base de datos determinada, lo que permite acceder a distintas bases
utilizando el mismo código. COfllO veremos más adelante, basta con especificar el
tipo de bases de datos a utili7..llr. y ti resto del código funcionará, posiblemente, sin
modificaciones, con independencia de la base de datos utilizada.
Gambas puede manejnr varios tipos de bases de datos. Dispone, en este momento,
de t res drivers espedficos: Sqlite, MySQL y Postgres. Además cuenta con un driver
ODIlC, el cual es un estándar para comunicar aplicaciones con bases de datos. Por
lo tanto, podemos lu:ceder con Gambas a cualquier base que soporte dicho están-
dar. Esto permite entrar, por ejemplo, a bases de MS SQL Servero Firebird.
Ala hora de elegir un driver u otro, tendremos presente que los drivers espedficos
están optimizados y ofrecen una mayor velocidad de transferencia de datos. Sólo
cu:mdo no dispongamos de Ul10 espedfico, usaremos el ODlle.
Adentrándonos en la estructura de Gambas para bases de datos, cualquier aplica.
ción que use esta caracterlslica, nec('sitará el componente gb.db como dependencia.
Los drivers para cada sistema de bas('s de datos son también componentes, pero el
programador no ha de marcarlos como dependencias. Una vez que indiquemos a
qué sistema nos vamos a conectar, el inlérprete de Gambas de cargar el dri-
ver específico.
5 Gestión de de
11

E.los componentes especiale. SO/!:
• gb.db.sq/ile: Sqlite versiÓ!l 2 o onteriOf.
• gb.db.sq/ó/e3: Sqlite versión 3 o poslerÍOf.
• gb.db.mysqI: MySQL
• gb.c/b.poJtgres. PostgreSOL
• gb.c/b.odbc: genérico OOBC.
5. 3 Gambas-database-manager.
el gestor grafico
Antes de explicar el modelo de programación para bases de datos de Gambas, V3IJlO$
a aprender a utilizar el Gestor de Bases de Datos, que es una aplicación escrita en
este programa, la cual dota al entorno gráfico de desarrollo de una herramienta para
administrar, de forma sencilla, múltiples bases de datos.
El Gfltor de Bases de Dlms escrilo en Gamba., H un progrorng ...-n1O y es Software
libre. Por 10010, el ...lUdio de su código nos puede oyucIor o dudo. p""'!Uo1es
que 5Ufjon Q la hora de VIO' el componente gb.db.
CrEar una baSE
Vamos a apunder a crear nuestra propia base. Para ello un proyecto
O bien abrimos cualquiera que)'3 tengaI1lO$ al nuestro equipo. Awdimos al
menú HeTcamientas y seleccionamos el Gestor de Bases de Dalas. Tambitn pode-
mos ej«utarlo directamente desde la consola, con el comando
manager.
Tras pulsar la opóón correspondiente, nos prtguntari una conlrast'ña. Dicha con-
lrasma st' ('JTlp1ea para almac=ar encriptados los datos dt usuarios ycontrasdlas
-_........ _--
..----
F ~ 1. Inlroduttión de
_.
deseemos gestionar desde rste programa, para evi-
tar que otro usuario pueda lurlos con facilidad
consultando los ficheros del entorno Gambas. la
contraseña que introduzcamos habrá de tener 8
caracteres como minimo, y se preguntará cada Vtt
que arranquemos el programa, para desencriptar
contraseñas ya almacenadas en 5eSionrs previas.
Tras rste paso, aparece el gestor en sí, que en principio rslá vacío, ya que no hemos
configurado ninguna conexiÓn.
Figura 2. Gel.Ior de bases de dolos de Gombm.
111
, ...... lO"_••• _._
_.-
OUlD<w_Ioo_
O" _
Pulsamos en el menú &rvidor y elegimos la
opción Nuevo servidor... Hemos de especifi-
car, a continuación, los datos relativos a la
F;gura 3. Opción " " - ~ . conaión que deseamos establecer (Figura 4).
, .. -.
H..."OH....Id....
~
- -
-
--
- -
--

--
Figuro 4. Dotos de la
conexión.
El primer dato, Tipo, se refiere al driver que emple-
aremos: sqlire, sq/iuJ, mY5tlI, postgres u odln:. Host
es el nombre del equipo o dirección IP donde resi-
de el servidor de bases de datos. Como excepción,
para las conexiones sqlite el Host no será otra cosa
que la carpeta donde se encuentran alojadas las
bases de datos, es decir, una ruta absoluta dentro
del sistema de archivos, como puede ser Illomehmm·
riolbases.
11
Progromoción visual oon Software libre
El tercer y cuarto dato son el nombre de Usuario y la Contraseña para acceder al sis-
tema de bases de datos, que determinan los distintos privilegios del usuario.
En el caso excepcional de Sqlite, las bases de datos son simplemente archivos, por 10
que los permisos vendrán definidos por los privilegios de un usuario y su grupo en
el sistema de archivos (lectura y/o escritura). No procede en ese caso, por tanto, espe-
cificar [os datos de usuario/contraseña.
Supongamos dos escenarios básicos. En el primero trabajaremos sobre un servi-
dor MySQL en nuestro equipo, con un usuario llamado (lr/min I y una contraseña
para dicho usuario. En Tipo indicaremos el driver mysq/¡ como Host, al tratarse
del propio equipo, se puede indicar o bien lowlhosr o 127.0.0.1, que es una direc-
ción IP que siempre apunta al propio pe. Introduciremos, después, los datos de
nombre de Usuario y Contraseña.
En cuanto o lo in.tolación y odministroción de MySQL, e. muy recomendable c a m u ~
tor lo do<:umentoción disponible en to propio pógino de e.to bese de dato.:
http://dev.mysql.com/d/X/.
En el segundo escenario, con el que trabajaremos en adelante, crearemos una base
Sqlite. Lo primero que tenemos que hacer es abrir una carpeta nueva para almace-
nar el fichero que contendrá la base de datos. Para ello, desde lfnea de comandos, y
en nuestra carpeta personal, podemos hacer:
mkdir Bases
- •.
También podemos crear la carpeta con Konqueror o
Nautilus, si así lo preferimos.
Ahora rellenaremos los datos de conexión, tal ycomo
aparree en la Figura 5.
- ",..
-
--
. --
Figura 5. Conexión o uno
base Sqlile.
Podremos selecC1Ol'l(Jl' JqI;", a MJIi"'3 depend.endo de los gMtores irutolodon en e1li..-
Iemo Para nuevos desonolos es recomendoble de \o 3 a pom,ioo,
01 elJor más oplimizodo Pero li len.mos que programar poro slSlemos antiguos {por
ejemplo, un dienle que d,spongo de RedHoI 7.01, taI ....z debamos pIonleofflOS el usar
sq/ile en sus ....rsiones anteriores, a fin de no tener que eompilor e in>lalor nvews libre-
rios en el sisrema, cuestión que o veces el dienl{l reclloza o impone.
• Figuro 6.locoIiroci6n del nuevo
........
· __ ·.r.-_I"'l
"IIII!I',,; "•• b...
Ir" 0 ••.....-
)( e ...
O EI iI(
• Figuro 7. Menú contextual cIeI
.......
Una va incluidos los datos, pulsamos OK y el
nutvO servidor quedará reOejado en el árbol de
la izquitrda del gestor. Si creamos distintos ser-
vidores, (dislintas carpetas, o bien algunos
apunlando a servidores MySQL o Postgra,. por
ejemplo), se irán añadiendo al árbol .
Para conectarnos, haremos doble die con el
botón izquierdo del ratón sobre el $('rvidor (o
el botón derteho, si se es zurdo yse liene asi con-
figurado el ratón), y después un die con el botón
derecho para que St' mueslre el menú contex-
tual de opciones (o izquicrdo, para los zurdos).

-----------,,-
o
Ct..,rbasa.
- '"---",..,,'
- -
iI opción erar USUiIrio... si lrabajamos sobre un sistema servidor lk
ases dt dalos (mysql o po1tgres), y ttrlemos pa'misos de administración sobu el ser-
ido•. El uso de tStI opción t$ lrivial: se pugunta el nombu dc usuario ycontrase-
ña ysi a su vt'Z licnc permisos dc
ción; se pulsa OK para añadirlo. Mis ddante
vemoos algUn ejemplo concreto. Seleccionamos
la opción Crear base. Nos preguntará d
Nombre de la base, que en el caso de Sqlire será
el nombre del archivo dentro de la earptta que
Figuro 8. Opción Creor base. previamente indicamos, el cual alojará la base
5. Gestión de bo5e$ de dolos
Progromación
de datos que vamos a crear. Señalamos como nombre
prllebas y pulsamos OK. Ya disponemos de una base
vacía, donde hemos de crear las distintas tablas que
alojarán los datos. Figuro 9. Base pruebas.
11
CrEa,. una tabla
Para crear una tabla, como en el caso del servi-
dor, hacemos doble clie para abrir la base y pul-
samos el botón derecho para obtener su menti
contextual (Figura 10).
Seleccionamos Crear tabla ... Los que se pre-
guntan son el Nombre de la tabla (ponemos dmos
en nuestro ejemplo), y el Tipo.
Este segundo parámetro s6lo tiene sentido en
determinados sistemas servidores, como MySQL,
en los cuales se puede indicar varios tipos de
labias, optimizadas para una u otra larea con-
creta. Salvo que tengamos necesidades especia-
les, podemos dejar los datos con los valores por
defecto.
--
0_.
O Il.mo><: ...
X "".
Figuro 10. Menli contextuol
de lo bose_
r O
Crear tabla
-
- .
Figura 11. Ventano poro
creor uno tobIo.
Una vez pulsemos sobre el botón OK, el gestor aparece en cllado derecho moslrán-
danos la estructura actual de nuestra tabla datos (vacía), para que añadamos la infor-
mación a los campos que aparecen.
Por tanto, vamos a manejar primero la pestaña Campos, con la que crearemos una
tabla para almacenar datos de los libros de nuestra propia colección.
Los campos serán: un identificador único, un número que a su vez pegaremos en el
lomo (forrado) para buscarlo rápidamente, el titulo del libro, el autor, la fecha de
adquisición, el precio que pagamos por él y una breve descripción.
_Ir" ..... ' ......
r ~ ,
'.-
e_o...".. r_·_·_
I I ~ " .
1;1.-- ¡O_M (l-
o .....

_.
• Figurg 12. Gestor de lo tabla.
Hemos de pensar en los tipos de datos que almacenaremos en cada campo:
• Identificador: un número entero.
- Título: una cadena de texto.
• Autor: una cadena de texto.
• Fecha: un dato tipo Fecha.
• Precio: un número real.
• Descripción: una cadena de texto.
Pensor en los tipos de datas nos evitar6, posteriormente, problemas a lo hora de hacer
bUs.quedal, ordeno, 101 dotos por distintos porámetrol, osi como o reducir el tamaño
de la base de daTol y optimizo, lo velocidad de consulTa. Este polO es muy imporlo","
le y me'e<:e lo pel'O dedicarte un tiempo.
También hemos de delimitar la clave principal, que es única y sirve para identificar
cada registro almacenado. La clave única estará formada por varios campos o uno
sólo. En nuestro caso se trata del campo referido al número de identificador.
11
Algunos programadores .. 0Ir0s entornos soI;on diseñar labios doves dodo
que oIgunos de de dolOS lo permiten. Como ,.wlIodo loe 8'!'*oban
lobIas propetlse» o -ores, con dotas duplicados. IenkIs de l'I\OflotjOI' y muy di"'.1es de
gesIiooor, conIorme po$Oba '" ttempo y los dotas oumenkJbon, o \'l!Ce$
por duplicaciones. jomós ie debe trabajor de este modo s.e rompe lodo ""'kljo que
puede opoOtI' uno bese de dotos relaciono!, y loe tupole<:o la Muto y mono
de uno opltcociÓfl
Para crt"3r el primer campo. modificaremos el que el propio geslOr ha creado como
sugerencia, indicando como Nombre ¡(lemificador y Tipo /llreger (es d<'cir, número
entl.'ro). Dejaremos los demás campos en blanco.
x
Longotud por dete<:IO
o JhomeldanoeWne. lsqlil:el· pruÑ>u· datos
" •., .. SOl
1:1 CMnpoI "lndices liloillos
@X¿9-:t
-. "'"

11
Para el resto de campos, pulsamos el botón con el icono rcprtStTlU UN hoja en
blanco, y que sirve pan alladir un nuevo campo. Si nos movemos por los distintos
iconos, aparece un lalo de ayuda que nos indica el significado de cada uno.
Conforme los creemos, rellenamos \os datos (00 ($105 valores:
• Nombre: ritll/o; Tipo: S"i"g; longitud: 40; Valor por defecto: (nada).
• Nombre: autor; Tipo: Strilrg; Longitud: 40; Valor por defecto: (nada).
• Nombre: fecha; Tipo: Fec1la: Longilud: (nada); Valor por ddecto: (nada).
• Nombre: precio; Tipo: F/Otlt; Longitud: (nada); Valor por defecto: (nada).
• Nombre: descripdorl; Tipo: Stril1g; Longitud: 200; Valor por defecto: (nada).
La interfaz deberá de quedar con esle aspecto:
B3 Datos fJ Indice.
..
o h'>on'IeldarlleWlases (sqlitel· pruebas - dalo.lmoddkadol
....
O campos
O X ,!. i
'om'"

!I."'O
'""
lOfl9f!ud Valor por defK!
"
"
figuro 14. Aspecto final de lo creod6n de 1<»
El dato Longitud se aplica sólo a los campos de tipo 5lrillg, y se refiere al número
de caracteres que se pueden almacenar. Conviene ajustar 10 más posible el valor
para no hacer crecer a la base de datos en demas!a y, por tanto, hacer más lentas
las búsquedas y modificaciones posteriores. Aunque sólo guardemos un carácter
en un campo de un registro dado, los sistemas de bases de datos habituales, guar-
dan todo el tamano indicado (en nuestro caso 40 caracteres para el titulo y el autor,
o 200 para la descripción). Si multiplicamos estos valores por un gran número de
registros, comprobaremos rápidamente el ahorro que se consigue con un diseno
racional previo de los tamaños.
11
la langilvd máxima de un campo de texto ,er 200 o 255 caractere', en muchos
de ba..,s de dotos. Por ello, debemos tene, en cuenta lo, tamaños máximos
si planeamos cambiar de gestor de bases de dotos en un futura, me una aplicación
ya desarrollada.
5. Gestión de bases de dolos
11
Cuando creamos un nuevo registro, el campo se rellena, por defecto, con un valor,
que sólo modificaremos para casos específicos. Esto es útil si un dato se repite muchas
veces, y sólo cambia ocasionalmente.
Como hemos podido observar, Gambas reali1;l una abstracción de los tipos de datos,
permitiendo elegir entre unos IIlUY concretos: Boo/ean (dos valores, o
/IJleger (número enlerO), Floal (número real), S"ing (cadena de texto) y Fecha
(fecha/hora). Estos tipos abstraen los de la propia base de datos, (algunos sistemas
contemplan, por ejemplo, "entero "entero corto" o "entero de un byte") asi-
milándolos a los de Gambas y simplificando la transición entre un sistema de bases
de datos y otros.
Si exi.1e nece.idad de optimizar la. tipo. de dolol palO un sistema concreto, la. toblo.
se deben crear con la. herramientas propios de ese sistema de bo", de doto" en lugar
de lo herramienta geoérico de Gamba., pero o cambio .e pierde porlabilidod. E.
decir, ",ró más difícil combior de .islema ge.tor en el futuro, si es necesario por el
aumento de volumen de doto., tecnologia o velocidad requeridos. En general, no e.
oecesario recurrir o optimizaciones de esle nivel, salvo en cosos muy concreIO'.
En cuanto a la clave principal, podemos observar en la Figura 14 que el primer campo,
identificador, tiene una llave amarilla marcada. Podemos pulsar sobre el primer ele-
mento de cada campo para que aparezca o desaparezca dicha llave.
La suma de todos los campos que estt'n marcados con la llave, conforma la clave
principal o identificador único de cada registro. Aunque en nuestro caso, sólo tene-
mos uno.
Estos datos, hasta ahora, se encuentran sólo en fase de diseño. Para grabar la nueva
tabla en la base de datos, pulsaremos el icono que tiene el símbolo de un floppy (dis-
quete). Apartir de este momento, la tabla aparece realmente en la base, lista para
añadir datos o consultarlos.
Los nombres ~ campos u$OOOs en el ejemplo no tienen ocenlos. En general, no se debe
utilizo. alfO COlO que corocleres del alfabeto inglés y número•. Usar ,imbelos como
caracteres con tilde, lo eñe o lo cedilla, separodOles toles como el amper$Ond 1&1 o un
espacio en blanco, pueden dar muchos ooores de cabeza 01 programador en ellutu-
ro, lonto paro uno simple consulto de dolos, como paro lo migración fvluro o airo sis-
tema de boses de dotas. Es uno molo politico de diseño, hoy que evito.lo••iempre.
Una vez creada la tabla, podemos editar los campos, añadir o quitar, siguiendo el
mismo procedimiento.
Ahora podemos pasar a la siguiente pestaña (Figura 15), fndices. Un Indice sirve al
gestor de bases de datos para organizar la información, de forma que más tarde cada
consulta se ejecute lo más rápido posible. Por ejemplo, puede que deseemos hacer
frecuentemente búsquedas indicando el autor, para saber los datos de todos sus libros
que tenemos en nuestra colección.
Para nuestra pequena base de ejemplo no utilizaremos índices, pero su gestión desde
este programa es trivial: basta (on que los creemos, eliminemos o modifiquemos del
mismo modo que hemos hecho para crear los campos de las tablas. Cada índice
puede estar formado por uno o más campos, es decir, puede comprender, por ejem-
plo, el nombre del libro +el autor. A tal efecto, la interfaz proporciona dos botones.
E! primero, Nuevo índice, sirve para anadir un índice a la tabla. Si está formado sólo
por un campo, basta con que indiquemos el nombre de ese campo. Si hay varios, se
puls.ará el botón nuevo campo de índice, tantas vc<:es como sea necesario, para indi-
car, a continuadón, los demás campos que mnforman ese índice.
El otro dato de relevancia es el valor Unique, el cual determina si pueden existir o
no dos registros en los cuales los datos de los campos pertenecientes a un índice sean
iguales. Por ejemplo, en una tabla que contiene datos de CDs, puede interesarnos
,ener un Indice creado a partír de los campos discografica y fecha. Y puede haber
..arios discos editados por esa diswgráfica en un mismo ano, por tanto marcaremos
11
5. Ge!>tiórl de 6o!>es de'da""'o', _
el valor Unique a FALSE. para poder introducir los datos de varK>s discos cuyos cam-
pos sta" coincidentes..
Por el contrario, en una base de datos de alumnos puede un ¡ndice que
comprenda el ONI y su nombre. En este caso, no hay dos personas con el mismo
DNI, luego ese índice es (mico, y marcaremos la casilla Unique con el valor TRUE
para proteger a la tabla de datos duplicados.
-<
..t§.... - - ....-
.•- ;Jt'Y. - a_
;:S;>' __


Figo.ra 15. Cr.oci6n de In&es.
o D o D o Gestiona,. datos dE una tabla
La última pestaña de la interfaz del gestor de bases de datos, Datos, nos permite con·
sultar ymodificar el contenido de la tabla. Dispone de tres bolones; Nuevo registro
(hoja en blanco), Borrar registro (aspa roja) yGuardar dalos (floppy). Hay que lener
siempre presente que, al trabajar con esta interfaz, los datos que anadamos, elimi-
nemos o modifiquemos, sólo SI: actualizan realmente en la base de dalos cuando pul-
samos el bolón para guanhr.
Cada que pulsamos el bolón Nuevo registro, se crea una linea, correspondiente
a un nuevo regislro nl la labia aClual. Podemos desplazarnos por los dislintos cam-
pos de ese regislro, para añadir los dalos correspondientes. También, si la tabla con-
tiene ya datos, podemos modificarlos o bien podemos seleccionar un regislro yeli-
minarlo con la opción Borrar registro.
En este último caso el registro se pone de un color diSlinto para senalar que en la
próxima actualización dicho registro desaparecerá, lo cual nos pl"rmite asegurar-
nos que la solicitud de eliminación es correcta antes de pulsar el botón Guardar
dalos.
-
'o:.
-
".-
----
--
--
.. Figura 16. Pestaña de Dotos.
Introduciremos registros de libros utilizando esta interfaz, para que dispongamos
de algunos datos con los que trabajar en adelante. Recordemos que es importante
pulsar el hotón Guardar datos cuando hayamos terminado la edición.
DOOOO saL
11
Sin escribir aún código Gambas, podemos ya
empezar a trabajar con el lenguaje SQL Como
hemos podido observar, uno de los botones
del geslor de bases de dalos de Gambas con-
tiene un texto SQL Lo pulsaremos para escri-
bir sentencias en este lenguaje.
9
"
~
.. @
el Campos ! fJ Indices IIE Datos
"
D X
. ~
-

_.....- _ . ~
Fi uro 17. ióo SQl.
Nuestra primera consulta servirá para obtener un listado de todos los datos de la
tabla que hemos creado. Para los que no estén muy familiarizados con ellf'nguaje
SQL, adaramos los siguientes puntos: las instrucciones de consulta comienzan con
la instrucción SELECT, a continuación hay que determinar qué queremos consul-
tar (en nuestro caso todos los campos, para lo cual emplearemos el símbolo ') y des-
pués se usa la palabra clave PROM para indicar de dónde obtener esos datos.
)Ql/home/dcamposlBases (sqlile) - pruebas - Petición Sal
~ lB!
'"
"
seleCl • from d a t o ~
.. Figura 18. Lenguaje SOl
5. Gestión de Ixnes de dotos
Programación visual con Software Libre
Al pulsar el botón Ejecutar, obtenemos el resultado de la consulta en la parte
inferior.
9
liI
5 regíslros
,
".Io
I "'"
1...... Ip-
I '''''''P'''''
I
,
dD.J«bJ Gblfll <Oc.bM:tICU'ol
"'"
N....
-
2 Del:aCa'-lII ........ lo&..'O.:=.'G: \;!"U
I;loeotQ
-

,...
Go:J'qe O ....dl ll'O'iiJ4
"''''
N(h'd.s ,'c.cn:la FiOCll(n,' Pdítoa
-
la AJ.&rds

lZOO'Ol oo.
-

¿CUa-. 3"d::I pcr :hn
....""'.
2l,t:¿tIJ
V.- Na.-dJl. eu,.". Ha::JO--' ...."'0'
'---
,
\
.

Fi uro 19. Resultado de la consulta.

Podemos guardar las consultas complejas en un archivo y luego recuperarlos para su
uso posterior, con los botones Guardar petición y Cargar petición. También pode-
mos exportar los resultados de la consulta con el botón Exportar datos, o copiarlo
al portapapeles para pegarlo en una hoja de cálculo como Gnumeric, Kcalc u
OpenOffice Calc.
Para familiarizarnos con SQL, también podemos realizar las siguientes consultas:
1. Mostrar el título y autor, ordenado por el nombre de autor:
select autor, titulo from datos arder by autor
2. Obtener todos los títulos de los libros cuyo precio es maYal" de 15 euros:
select titulo from datos where precio>l5
3. Obtener todos los datos de los libros adquiridos antes del 2004:
select * from datos where fecha<"2004-01-01"
los formatos poro representar fechas y caracteres genéricos (comodines), varían de
uno base de datos o otro, y puede resultar que uno consulto dado sólo funcione paro
un sistema de bases de datos determinado.
4. Obtener todos los títulos que contienen la palabra la:
select * from datos where titulo like "%la%"
Con esta interfaz no sólo podemos consultar, sino que también podemos realizar
cualquier operación permitida por SQL+Sistema Gestor de Bases de Datos. Por ejem-
plo, podemos añadir un nuevo registro en la tabla datos:
insert into datos values ("El lazarillo de Tormes",
"Anónimo",200S-02-03,20.91,"Novela")
Al utilizar instrucciones insert, de/ete o cualquier otro que no dé como resultado un
grupo de registros, el gestor muestro lo leyenda No hay registros, si tuvimos éxito, o
bien un mensaje de error si lo base de datos no aceptó el comando.
• • • • 5. 4 Programación
[J I Modelo de bases de datos
Gambas, a través del componente gb.db, realiza una abstracción de la estructura y
los datos de una base. El primer requisito necesario para esta labor es saber cómo
acceder o conectarse a una base de datos.
De esta tarea se encarga la clase Connection. Creando varios objetos Connection pode-
mos conectarnos a varias bases de datos.
5. Gestión de bases de datos

11
Progrcwnoción YÍsuol con Software Libre
El objrto Co'lntcfion dispone de una de propitdadts para determinar tltipo
de sistnna dt de datos, el nombrt de la ubicación del rtrurso (putde
$tr una rula ti} ti sisttma dt archivos o una dirección IP). Yios datos del usuario qlX'
desta contetarst a dicho sistema. Esta c1ast, junto con la aportan la
infonnación necesaria sobrt nuestra basC' dt datos.. La dast UKr ptrfib nutstm usua-
rio y. por lanlo, nueslros ptrmi$OS de acccso.
La información de una base de datos se almacena en diversa.stablas. Cada tabla se
putde imaginar como una rejilla bidimensional, al estilo de una hoja de cálculo. En
horizontal tenemos los encaba.ados que nos indican la información de cada campo
de nueslra labIa. En Gambas, el componente gb.db aporta una clase T,lb/e, que defi-
ne la estructura de una tabla, yla clase Field que determina las caracterfsticas de un
campo de una tabla.
En vertical se viln acumulando los distintos registros con información. Cuando se
trabaja con bases de datos rtlacionales, el programador no se limita a hojear el con-
tenido de una tabla. sino que. empleando instrucciones SQL. putde consultar pro-
mtdios de valores, sumas, uniones cohen:ntes de los datos de varias labIas, dalos
agrupados por una clave u ordenados según algün crilerio, e1c.
En todo caso, el sistema de bases dt datos devutlve sitmprt el resullado de la con-
sulta como una serie dt rtgistros que disponen de varios campos, es decir, ti} un for-
mato similar al de las propias tablas. los objetos de la clase Rall/t proporcionan el
acccso a dichos registros y(ampos de información. como si se tratara de una labia.
La clase Rtsl.ltField es similar a Fiefd, pero en esle caso no proporciona información
sobre un campo de una labia de una base de datos, sino sobrt un campo de un con-
junto de registros procedentes de una consulta.
o o o o O ConEctandosE poi" códIgo
Vamos a coneetarnos a la base de datos Sqlite que creamos en el primer apartado.
Dependiendo de nuestra versión de Sqlile, usaremos el driver llamado sqlite o tl
Sl/liteJ.
- ..
• FiglKO 20. Formulario FMoifl.
Para ello creamos un pro),ecto grá-
fico llamado MisLibros. Situamos
en él un formulario llamado
FMaill, que será el de arranque, y,
dentro de él, un control Co-
lurnnView llamado Tnb/n, Este
;ontro! ColumnView mostrará los datos de la tabla que habíamos crcado en los
:jercicios anteriores.
\hora vamos a escribir una función que se conecte a la base de datos dentro del códi-
;0 del formulario:
Private hOonn as Connection
PRIVATE FUNCTION Ooneetaz:'Base() AS aoo1ean
IF hConn<>NULL TREN RETURN FALSE

hConn - NEW Conneetion
hOonn.Host _ H/home/usuario/Bases
H
hConn.Name _ Hpruebas
H
hOonn.Type _ Hsqlite"
Tal hOonn. Opan()
IF ERROR TREN
bOonn - NULL
Message. al conectaz:' con la
""""'" TRUE
END IF
RETURN FALSE
END
5. Gestión de de dolos
11
Definimos un objeto Connection que será accC5ible en IOdo el formulario y repre-
senta la (onexión a nuestra base de datos. Despufs se escribe una función
Cone<:larBase que d<,vueive FALSE si tiene éxito o TRUE si falló.
El código conlleva estos pasos:
1. Si ya hay una conexión (si d objeto hConn no es nulo), relornamos inme-
diatamente indicando que ya hay conexión FALSE, de esta forma podremos
llamar sistemáticamente a esta función desde varios puntos sin preocupar-
nos de si ya existe la cone:l"ión O no.
2. Crt'arnos el objeto Conncclion, que en principio no está cont'Clado a ningu-
na base, y proporcionamos la información necesaria p3r.1 concelar: rellena-
mos la propiedad HOSl, que: m el caso <k una base de datos con savidor podria
ser una dirección 11', pero que para Sqlite es una ruta dentro del sistema de
archivos (recuerda sustituir /llOwe!USl/nrio por la ruta donde tu almacenaste
la base del ejemplo); dcspu(:s indicamos clnornbre de la base de datos (prue-
bas), que en el caso de Sqlite es también el nombre del archivo que está den-
tro de Jo¡ carpetalhomeJusuuiolBases; y por último indicamos el tipo de base
de datos;¡J que nos conectaremos, y que sed sqlile o sqlild, de acuerdo con
el disdlo que realizamos con el Gestor €k Bases €k Datos de Gambas. Si nues-
tra conexión se realizará sobre un servidor MySQl, por ejemplo, también lm-
drfamos que rellenar las propiedades Logi" y PaS5wcml, con el nombre de usua-
rio y contraseña de acceso al servidor.
P'uew que oUn no eslornos feolmenle cone<:lodos, podeilios reIlencw lodos ~ cIok>¡
en el «den que deseemos
3. Despues, tratamos de abrir la conexión. Si no fuera posible (por ejemplo, por
una rUla incorrecta o un fallo en el servidor), se disparari un error, que cap-
IUl1lmas con la orden TRY.
4. Si se ha producido un error, nula de nuevo la conexión fallida y retor-
namos con el valor de error, que según hemos decidido, es TRUE.
5. Si, por el contrario, hubo wto, retornamos el valor correspondiente (fALSE).
Acontinuación, vamos a crear una función a la que llamar para cerrar la conexión.
El algoritmo es sencillo, si no hay ninguna conexión, relornamos, en caso contrario,
cerramos la conexión y la hacemos nula para que una próxima llamada a QmectarBase
se aperciba de que no hay una conexión activa.
PRIVATE SUB CerrarConexion()
If' hCOnn • NULl. TREN RE'lVRN
hConn.Close{ )
hConn • NULL
ENe
Consulta dE datos
Al abrirse el formulario, abriremos la conexión. leeremos los datos disponibles, los
representaremos en nuestro controllilbla y cerraremos la conexión. Esto quedada
represelllado de la siguiente manera:
DIH hResul AS Result
DIH Clave AS String
Tabla.ClearO
IF COneetarBase() TREN RE'1'URN
Tabla.COlumns.Count • 5
5 de de
11

Progromación viwol con Software Libre
Tabla.COlumns(O).T8xt - -Titulo-
Tabla.COluans(l).Text _ -Autor-
Tabla.COlumns(2).Text - -Fecha-
Tabla.COlumns(J).Tert - -precio-
Tabla.COluans(4).Tezt - -Descripción-
Tabla.Add(Clave, Clave)
Tabla[Clave)[l] - hResul¡-autor-¡
Tabla[Clave)12) - hResul[-fecha-¡
Tabla[Clave)IJ) - hResul[-precio-)
Tabla [Clave) (4) _ hResul[-descripciOll-1
hResul.MoveNe:rt( )
LOOP
Qerrareonezion()
END
El código trata de abrir la conexión y si fracasa saje de la función. Si todo va bien,
define cinco columnas en nuestro control de tabla, pone elthulo a los encabezados
de columna y procede a rellenar los diferentes registros. Para efectuar esta tarea, pri-
mero consultamos los datos de la tabla, empleando el método bec de nuestro obje-
to hConn, al cual pasamos como parámetro la consulta SQL y nos devuelve un obje-
to de la dase Resulf, que contiene cada uno de los registros provenientes de la consulta.
El objeto ~ u / t tiene un puntero intemo que en cada momento apunta a uno de los
registros. En el estado inicial apunta al primer regislro. si es que hay alguno. Este
objeto dispone de una serie de métodos para mover el puntero. MoveNext (el de
nuestro ejemplo) 10 mueve' al siguiente registro, si aiste; Mcwefuvious, al anterior;
MowFirn, al primero; y Movd.llSl, al último. Con MoveTo podemos especificar un
registro conueto al que desplazarnos.
Cuando estamos situados en un registro, Result nos permite obtener el dato corres-
pondiente a un campo, indicando el nombre del campo como si el objeto fut'se un
Array: en nuestro ejemplo, hResul["autor"] nos devurlve el valor del campo alltor
en el regislro aclllal.
Si como resultado de un IllO'Vimiento del puntero hemos sobrepasado d ullimo regis-
tro o estamos anles del primero. la propiedad Available lOma el valor FalH. mien-
tras que si nos encontramos apuntando a un registro, Available toma el valor Trut.
Igualmente. si no hay regislros resultantes de la wnsulta, Available valdrá False.
(A\'ailable significa Disponible en ingUs).
Con estos conocimientos ya podemos realizar un bucle para rellenar los datos de
nuestra tabla.
Mientras la propiedad Available sea True, lomamos como clave el valor del campo
"titulo", aiiadimos una línea en nuestra tabla identificada por esa clave, ycuyo texto
(la primera columna) es dicha clave. Rellenamos el resto de los campos con los valo-
res provenientes del objeto hResul, y nos movemos al siguiente registro. Tras salir
del bucle, cerramos la conexión y abandonamos la función.
Como último retoque antes de ejecular, ponemos la propiedad $orted del control
ColumnViewa Tme, de modo que el usuario, al pulsar sobre un encabezado de
columna, pueda ordenar el listado por el campo que prefiera. PueSlO que cada regis-
tro en el listado e s t ~ identificado por la misma clave que tiene en la tabla, posterio-
res operaciones de se!ección/mO<!ificación por parte del usuario, no se ven afecta-
,
das por el orden de representación.
5. GestiÓl'l de b o ~ de datos

Progromación con Software libre
El resultado final es éste:
_ o •
TIILllo • kolor Proclo
1$$0 3<l.:J.4
__.r.o. .<>Io<lod 0.""'-10.'''' M"!9:'!!" 2M!
De. (61<0,. 02lU120l12 12'5
L.'.... dtN.""Y R.J.s.oo., O:lllmOO.,C.g
¿0ui411 ondo por .hI? Bob SIlo", 1212112003 23.
FiguI"G 21. finol del proyecto MisLibrm.
No".,..,'C
.....
Fikloofi.
.....,
"""... 1

Aprovechor 105 posibil;dades de ordenación de lo. puede evitar sobrecaro
ga. 01 servidor Oal cliente de boses de dolo. con múltiples consultos.
'J O O Borrar registros
Podemos afladir algo de código para borrar registros. Es decir que cuando el usua-
rio pulse la leda Supr o Del, el registro que esté seleccionado se borre.
PUBLIC SUB Tabla_KeyRelease()
IF Key.Code - Key.Delete TREN
IF Tabla.CUrrent - NULL TREN RETURN
IF Tabla.CUrrent.Selected _ FALSE TREN RETURN
IF ConectarBase() TREN RETURN
TRY hCOnn.Exec(Udelete from datos where titulo-&l",
Tabla.Current.Key)
!F ERROR TREN
Messaqe.Error("Imposible borrar el registro")
ELS'
Tabl•• CUrrent.Delete()
""" ..
CerrarConexion()
Apro\'«hamos el evento Key_Releasc de lluestro control Tabla. Si la teda pulsada
es Del o Supr, primero comprob,ltllOS si existe algún elemento actual en la labIa; si
no es así, salirnos. Si el elemento actual no está seleccionado, también salimos. Por
otro lado. tratamrn; de ahr;r la rorn-xión, y si hay bite, ejn:utam06 una instrucción
SQL para borrar un registro cuf3 clave coincida con la del rrgistro de con-
trol Co/llItlllVinv. Si se produce un error (por una base de sólo lectura). se
informa al usuario. En caso contrario, se borra también el del control para
renejar el cambio. Cerramos la conexión y salimos de la función.
En gene.ol, e' preferIble U"" KeyR"'-o$e YMouM"-'eo$e, o 10$ eqUIVOlente. Pren,
cuondo loe ejl!Cllkl uno o<:c'OO po< po.1e del uwo.io De e.1e modo, cuondo hg p"1.
wdo el botón del .otón, aún l,ene tIempo po'o oporto.1o del con"oI y conc:ek" o,i
una accIón erróneo, onle$ de levanto. el de<lo del ratón De or.o modo, en el evetl'
jo MousePress podrio borrado un registro ,in tiempo pala reacciono,.
Corno podemos observ¡¡r. en el caso siguiente la sentencia SQL (Onstruida de
un modo algo diferente. Tenemos dos parámetros, el primero es parte de la consul-
ta y el segundo contiene el elemento concreto al que nos referimos:
hConn.Ex&c{-delete datos where titulo-.l·,
Tabla.eurrent.Key)
5. Gemón de boSM de datos


Progromoción viwol con ubre
El rnrtodo Exec admite un número variable de parámetros, y a la hora de tratar la
sentencia SQL, Gambas sustituye los indicadores de parámetros (&1, &2, &3... ) por
el parámetro que corresponde en orden (&1 es el primer parámetro exlra, &2 el
segundo... ). Además, formatea el dato según se necesite (por ejemplo, este paráme-
tro corresponde a un dala de tipo String, que en la sintaxis SqJite requiere unas comí-
Uas anles y detrás). Esto es muy útil para tnoojar con datos de lipo fcdJaIhora, cade-
nas de texto y números con decimales, ya que la sintaxis puede variar de un tipo de
bases de datos a otras, e incluso con la misma base puede cambiar según los pará·
metros regionales (formato de fecha, usar coma o punto para decimales, etc.). Con
este sistema, pondremos simplemente un dato tipo Cadena, Booleano, Fecha o
Numero. y Gambas se encargará de dar el formalo adecuado.
Dejar o Gambas lo neo de dor /ormolo o k» dilerenJM hpos de dolos, eviIoro muchos
cambiamos de geslor de de dolos, O prerendemos que lo opl;'
coci6n fu«ione COfTe<:!(Imenle en voriO$ Pe q<Je puedan lener d¡lerenleS
o O O e o Al\adir rEgIstros
Vamos a añadir ahora un formulario llamado FOlia que nos servirá para inlto-
ducir datos y también. en el siguiente aparlado. para editar los ya existentes. Este
formulario tendrá cinco etiquetas, con cualquier nombre. Cinco cajas de texto
llamadas TxtTitulo. TxtAulor, TxtFecha.
TxtPrecio y TxtOescripcion, y dos boto-
nes llamados BtnActptar y BtnCance.lar.
El aspecto general puede ser como el que
vemos en la figura de la derecha
demos poner los textos en las etiquetas
de acuerdo con la caja de texto que
corresponda).
----
-
,
-
figura 22. Formulario fOoto.
Este formulario recibirá una referencia a la conexión con la base de dollas., por tanto.
dispondr.i de una referencia a un objeto Connection.
Por dio tseribir al principio código formulario lo
Así mismo, dispondrá del método RunNcw con el k el for-
mulario principal, pasando como nuestra conexión a la basc', r mos-
trará el formulario de forma modal, a la espera la introducción de datos por parte
del usuario.
PUBLIC SUB RunNew(Dat..a AS Connect.ion)
bCoDn - Data
HE. SbtJl Ib5a J ()
END
El código toma en hConn la al Connection que le y lo
muestra. En cuanto al botón de cancelación, es bien sencillo: basta con indicar al
formulario que se cierre que de la siguiente manera:
PUBLIC SUB BtnCancelar_Click()
HE.ClOH()
En cuanto al botón Aeeptar, en 1'1 la operación de alta de un
registro, utiliundo la instrucción SQL ¡nsert into:
PUBLIC SUB BtnAceptar_Click()
TRY bCOnn.BJ:8C(Ninsert int.o datos values
TJ:t.Aut.or.TeJ:t,
5. Gestión de boJe$ de datos

11
PmgromoÓo
CDate(TztFecha.Text),
TxtDescripeion.Text)
EHD ,.
ME.Close!)
Me•• introducir 108 datos
solicit.ados")
Indicamos al objeto Colllltcfion que ejecute [a sentencia SQl, la cual, para las altas
sigue siempre el mismo palrón:
insert int.o [nombre de la tablal values ([ valor del campo Ij,
Ivalor del campo 2) .... )
Para evitar problemas de formateo, seguimos empleando los parámetros adiciona-
como en el caso antes comentado.
los datos de Título, Descripción y AUlor se pasan directamente, al ser datos tipo
texto.
El dalo del Precio se convierte a número real con CFloal(), y la Fecha se convierte a
dalO fechalhora con COalcO.
Si se produce un error, bien sea por falta de permisos de c5Critura o por datos no
convertibles a fechas o números, por ejemplo, se captura con TRY, y se trala en el
bloque de código CATCH donde indicamos el mensaje de error al usuario.
Si, por el contrario, todo fue bien, se cierra el formulario tras ti alta.
F"tgUIlI 23. úeo06l, de los bables Nuwo
Y$oIir del formulorio principal.
-
• ••
-
Volvamos ahora al formulario princi.
pal (FMain), y añadamos dos botones
para compklar la intafu: uno llanu-
do BtnAlta, para dar de aliOlI un nllt'\'O
ttgistro. yotro BtnÚ"rr.lr, p.an. cnnr
el programa. Como el botón
de salida es de implementar
(recordnnos que ahora rscribimos d
código en Fmain, no en Fdata):
PUBLIC SUB BtDSalir_Click()
HE.Close( )
Para el bolÓn de nuevo registro, como siempre, tratamos de conectar a la base, pero
nos salimos si no lo logramos. Acontinuación llamamos al ml/'todo RunNew de
FOala. Puesto que se muestra de forma modal. el código de esle formulario queda
aqui detenido hasta que el usuario dé un aha o cierre el formulario.
Tras esto, y de nuevo nl nutStn. función. (<<ramos la conexión yUamam05 al méto-
do For,"-OpenO. que, como TtrordaTW\O$., se encargaba de representar los datos
en la labia, para reflejar a51 el alta dada por el usuario.
IF CollectarBase() THEN RE'l\IRH
FData • RunNew(bconn)
CerrarConexion()
f'orllLOpen ( )
11

ProgromociOO visuol (011 Softwore
Ya disponemos de una inlerfaz básica para dar altas. Se pueden mejorar muchas
cosas. Entre otras, se pueden bloquear los cuadl'05 de texlO para que sólo acepten
numems y el signo decimal (en el caso del precio), para que sólo acepte un dalo váli-
do (Omo fttha (en el caso del campo Fecha), y que compruebe la longitud máxima
en el caso de los diferentes campos de texto. También se puede ajustar el formato de
fecha al adttuado para el usuario (aqul usamos directamente el de Sqlile, es d«ir,
dos digilOS de mes I dos dlgitos de dia I dos digitos de año), o lraspasar 105 datos de
vuella al formulario principal para que sólo se actualice el nuevo regislro en lugar
de toda la tabla completa.
o O o o O Modificar rEgistros
Aprov«haremos d formulario de altas para las modificaciones. Cuando d usuario
haga dobk dic sobre uno de los registros, aparecerá el formulario de ahas, con los
datos del regislro aClual, pero eSla vez en modo modificación para que d usuario
cambie sólo lo que quiera. Modificaremos el código del formulario de datos para que
disponga de un flag para indicar si trabaja sobre un alta o modificación, ydispon-
dremos lamM de una rd"ermcia a un objftode la clase Rcsull, que apuntará al
tro actual a modificar. El principio del código del formulario Fdala quedaría asl:
PRIVkTE Editando AS Boolean
hResul AS Result
PJUVM.'II: bCorm AS Comlect:ion
En el mismo formulario añadiremos un nuevo método que, a diferencia de RrmNew
prepara al formulario para elllrar en modo edición. Para dIo recibimos la referenci:
al objelo de la clase Result; ponemos el flag Editando a TRUE; y ponemos en cad:
caja de texto el valor del campo cornspondimte. Tmesto, se mue:slnl de fOrma modal
PUBLIC SUB RunEdit(Data AS Result)
hResul - Data
&d.italldo • 'rRUE
TItTitulo.TeKt -
TxtAutor.Text -
TztFeeha.Text _ hResul(Mfecha
W
)
TztPreeio.Text _ hResul[Mprecio
W
)
TztDescripcion.Text •
ME. ShQWtokldal ( )
Hemos de modificar también el código del botón BtnAceptar para que distinga entre
altas y modificaciones, y actúe en consecuencia. En el caso de la modificación, sitúa
el valor de cada caja de texto en el campo correspondiente, y de existir un error, se
tratará en la zona CATCH al estar protegida cada inserción con una instrucción TRY.
Si hubo éxito, se llama al método Update, que hace que los valores que hemos intro-
ducido en los campos se actualicen realmente en la base de datos. Tras esto, como
en el caso del alta, se cierra ydeS(arga el formulario.
PUBLIC SUB BtnAceptar_Click()
IF Editando TIlEN
TRY - TxtTitulo.Text
TRY • TxtAutor.Text
- TxtFecha.Text
TRY • TztPrecio.Text
TRY - TxtDeseripcion.Text
TRY hResul.update()
.,""
TRY into datos values
(&1,&2,&3,&4,&5)ff, TxtTitulo.Text, TxtAutor.Text,
CDate(TxtFecha. TeJ:t), CFloat (Txtprecio. Text) ,
TxtDescripcion.Tert)
5. Gestión de boses de datos

.10
11
ME.CIase()
introducir lo. datos
aolicit.adoswl
....
Añadir n...-vosluncionolidodes o un elemento yo exhlente, como un bmulorio, puede
ohof,Ol' '*"POy código, pero en OC:O$lOneI puede hoe... el nuevo códi¡Jo complejo y
dificil de monlenef Hay que Klp8SOf el entre cOSle de prog.omoo;ión y "lOI>-
Iomimionlo posIe1ior en codo coso, antes de crear uno nuevo de cód,go o
mo(Micor lo exislenJe
De nuevo en el formulario prindpal, FMoil/, aprovecharemos el evento Activate del
control CollllflnVitw. que se genera al haca dobk dic. para dar acceso a esta nueva
funcionalidad.
PUBLIC SUB Tabla_ACtivate()
IF rahla.Curreot - NUU. TKEN RETtIRN
hResul •
Tabla.Current.Key)
FData.RunEdit(hResul)
Tabla.Current(l] -
Tabla.Current[2] -
Tabla.Current[3] -
Tabla. Current (4) -
CerrareonexiOD()
Como podemos observar, ahora el objeto Result no lo obtenemos como llamada al
método Exee si no con otro nuevo método: Edit. l;¡ razón es que las llamadas a Exee,
que reciben como parámetro una sentencia SQl., son de sólo lectura, es decir, es posi-
ble examinar el comenido de un campo como por ejemplo:
Pero no es posible actualizar el contenido del campo, es decir, no se puede realizar:
que es precisamente lo que nos interesa.
El método Edit no recibe como parámetro una sentencia SQL, sino el nombre de
la tabla que se desea modificar, y C01110 segundo parámetro y posteriores. un fil-
tro y los parámetros de ese filtro. Es fácil entender el modo en que trabaja si par-
limos de una instrucción SQl. y obtenemos las partes que nos interesan para el
método Edil.
que de una tabla Articulas queremos modificar todos aquellos cuyo
:ampo precio sea superior a 20. Una sentencia SQL para obtener ese conjunto de
regist ros seria:
select • from Articulas where precio>20
5. Gestión de de dolos
11

Progromoción .,¡woI con Softwore libre
Para construir I;¡ llamad;¡ al mitodo Edit tendriamos:
dt la tabla: Artkulos.
Fillro: precio mayor qut una cantidad.
Parámetros del filtro: 20, en este caso.
Por tatllo la llamada queda como:
hConn.Edit ( NArticulos·, 20 )
¿Por qul no tmplean SQL directamentt? Porqut las modificaciones
lienen sentido sólo sobI'C' una tabla. No se puedt modificar, por ejemplo, ti resulta-
do dt los regislros que provienen de unir dos tablas, o dt un sumatorio dt los valo-
res dt un campo.
Tras obtener el registro con la llamada a Edit, pasamos el objeto Rnrllt al
formulario de datos, con la llamada a su método Rlmúlil, y bte se mostrará de forma
modal. Al cerrarse el formulario, la ejecución retorna a nuestro método en el cual
aetuali7..amos el contenido de nuestro control QlllmnView para retlejar los cambios
hechos en la tabla de la baSt.
AcOlllinuación, se rep'roducen complttos el código de FMai" y FDala al ser dos
códigos extensos que htmos troceado y modificado sobre la man:ha.
FMAIN
PlU"V1aE hConn AS Connect:.ion
PRIVATE FUNCTION ConectarBase () AS Boolean
IF hConn THEN RE'l'URN f'ALSE
bConn - NEM Connection
hCOnn.Host N/home/usuario/Bases
N
hCOnn.Name _ NpruebaS"
hCOnn.Type • "sqlite
N
TRY hCOnn. Open()
IF ERROR TREN
hCOnn - NULL
Message.Error(UError al conectar con la base")
""""'" TRUE
END IF
RETURN FALSE
END
PRIVATE SUB
IF hConn • NULL TREN RETURN
hCOnn.Close()
hCOnn - NULL
END
DIM hResul AS Result
DIM Clave AS String
Tabla.Clear()
IF COnectarBase() TREN RETURN
5. de bmes de datos
11

visual con Sof!ware Ubre
Tabla.Colwmns.Count: • 5
Tabla.ColumnsIOj.Text
-

Tabla.ColumnsllJ.Text:
-
"Autor"
Tabla.Columns(2J.Text
-
"Fecha"
Tabla.ColumnsI3).Text
-
"Precio"
Tabla.Columns¡4J.Text
-
"Descripción"
hResul _ hConn.Exec("select * from datos")
DO WHILE hResul.Availahle
Clave - hResul[Ntitulo"]
Tabla.Add(Clave, Clave)
TablalClavel [1] - hResul("autor"l
TablalClavel [2] - hResull"fecha"]
TablalClavel [3] - hResull"precio"]
TablalClavel [4] - hResul("descripcion"l
hResul.HoveNext()
CerrarConexion()
END
PUBLIC SUB Tabla KeyRelease()
IF Key.Code - Key.Delate THEN
IF Tabla.CUrrent - NULL TREN RETURN
IF Tabla.Current.Selected - FALSE TREN RETURN
IF ConectarBase() TREN RETURN
TRr hConn.Exec(Mdelete fro- datos where titulo-.l
w
,
Tabl•.
Ir ERROR TREN Messaqe.ErTor(M1qX)sihle eliain.n- el
regisb"O")
cerrareonezion()
Tabla.CUrrent.Delete()
END "
DIM bJlesul AS Result
IF Tabla.CUrrent • NU1L TREN RP:IURN
IF ConectarBaseO 'I'llE:N RE'l'UNf
hResul • hConn.Edit(Mdatos
M
, "titulo-.l
w
,
Tabla.Current.Key)
FData.RunEdit(hResul)
Tabla. Current [O] • hResull ..
Tabla.CUrrent(l) • hResul(Mautoc")
Tabla.CUrrent(2) _ hResul(Mfecha
M
)
Tabla.CUrrent(3) - hResul(Mprecio"]
Tabla.eurrent(t) • hResul(Mdescripcioo")
eerrarCoDe:doo( )
PUBLIC SUB 8tnSalir_Click()
HE . 150\Close( )
11
11
ProgramociÓfl viwal con Software libre
PUBLIC SUB BtnHuevo_Click()
IF Conect:arBase() THEN RE'roRN
FData.RunNew(hOonn)

Fo", Open ()
FDATA
PRIVM'E Editando AS Boolean
PRIVA'l'E bltuul AS aesult
PIUVATe bCoQn AS Conneetion
PUBLlC SUB R\!n'lew(Data AS COrlned;ion)
bConn - Data
ME. ShOllllcdal ()
PUBLIC SUB RunEdit(Data AS Result)
bResul - Data
Edi tanda - TRtIE
TxtAutor.Text -
TxtFecha.Text • hReSul[Nfecha"]
TxtPrecio. Text - hResul( "precio
N
]
TxtDescripcion.Text _
ME.ShowModal()
PUBLIC SUS 8tncancelar_Click()
ME.Closen
150\
PUBLIC SUS BtnAceptar_Click()
IF EdHando TREN
TRY hResul [Ntitulo"] _ TxtTitulo. Text
TRY - TxtAutor.Text
TRY - TxtFecha..Text
TRY hResull"precioN] _ TxtPrecio.Text
TRY hResul(Udescripcion
ff
] • TxtDescripcioD.Text
TRY hResu1.update()
.....
TRY hConn.Exac("insert into datos values
TxtTitulo.Text, TxtAutor.Text,
CDate(TxtFecha..Text), CFloat(TxtPrecio.Text),
TxtDescripcioD.Text)
5. Gestión de boses de dolos
11

END IF
ME.Close()
CATCB
Message.Error("Imposible introducir los datos
solicitados")
END
A lo largo de este código, se abre y cierra la conexión con la base de datos en cada
operación realizada. Con esto, el periodo de tiempo en que los datos se encuentran
en buffers intermedios es menor, reduciendo la posibilidad de corrupciones, ante un
fallo de tensión, por ejemplo. No obstante la carga del servidor y cliente trabajando
de este modo es mayor, y puede ser un modelo excesivamente lento si el volumen de
datos es muy grande, o si sólo se realizan operaciones de lectura. Es conveniente, por
tanto, evaluar la conveniencia o no de mantener la conexión y consultas abiertas en
las distintas operaciones que se efectúen sobre la base de datos.
Ii 5. 5 Otras características
Estructura de las tablas
Gambas también permite examinar la estructura de las tablas de una base. Para ello
se emplea la clase Table y la clase Field. El programador no puede crear objetos de
esas clases directamente, pero puede obtenerlos de una conexión en curso. Esta fun-
ción de ejemplo, lista en la consola la estructura de una tabla, recibe como paráme-
tros una conexión y el nombre de una tabla, y lista sus campos.
PRIVATE FUNCTION ListarTabla ( hConn AS Connection,
NombreTabla AS String)
hTable = hConn.Tables[NombreTabla]
FOR EACH bField IN hTable.Fields
PRINT "-------------"
PRINT "campo: " & bField.Name
SELECT CASE bField.Type
CASE gb.lnteger
PRINT "Entero"
CASE gb.Float
PRINT "Número real"
CASE gb.String
PRINT "Cadena"
CASE gb.Date
PRINT "Fecha/Hora"
CASE gb.Boolean
PRINT "Booleano"
END SELECT
NEXT


END
En ocasiones puede ser necesario examinar una tabla, como al inicio del progra-
ma, para comprobar sus campos. Por ejemplo, en la fase de transición moneda
nacional/Euro en Europa, se hizo necesario almacenar datos de importes en ambas
monedas durante un periodo, en algunos programas. Las versiones actualizadas
de estos programas, al instalarse y arrancar por primera vez, comprobaban la exis-
tencia de estos campos, y actualizaban la base de forma automática. Versiones
posteriores podían eliminar el campo de moneda nacional para ahorrar espacio
en la base.
SQL no es sólo un lenguaje de consulta. Las instrucciones como CREATE TABLE,
DELETE TABLE YALTER TABLE, se utilizan precisamente para la función indica-
da: alterar la estructura de la base y sus tablas cuando es necesario.
5 Gestion de bases de datos
Progromoción visual con Softwore Libre
o O O O O Mas utilidadEs dEl GEstor dE BaSES dE Datos
figura 24. Otros vtitidode1. del Geslor de!loses
do_
• l.d.I., codIIico-' WlF·11
_ .....bIO.... _ •
..-
.....
oe-._
.-
lb", ,... .
La primera de ellas es obtener el
código para crear las tablas de la
base. Situándonos sobre una base
y pulsando el botón derecho.
podemos seleccionar la opción
Crear código Gambas...
Ejecutando
mantJga' podemos encontrar algu-
nas utilidades adicionales.
11
Al acceder a este menú, nos pregentará el nombre del módulo yel procedimiento
para crar el código. Tras indicar estos valores, cerrar y volver a abrir el proyecto, dis·
pondremos de un nuevo módulo con el nombre indicado. que contiene el código
para crear la tabla.
PRClCi'J:JIJRE eru.teD.aUba.se(bCoom AS c:o.mectciOll,
sDat&base AS Stringl
• Geoerated by tbe Gamball databa.e IlliUI3ger -
22/08/2005 10:26:.]
DlM hTable AS Tab1e
MI'IB b'rab1e
.Field•. Addc-titulo-, gb.String, fO)
.Fields.Add(-lIutor-, gb.Striog, fO)
.P"ields.A&1(-fee:b.a", gb.Date)
.P"ie1d•. Add(-precio·, gb.P"1oat)
.Pields.Add(-descripcioa-, gb.String, 200)
"'" HU.
Al inicio del programa, y tras conectar con el servidor de bases de datos, podemos
entonces comprobar si no existe la(s) tabla(s), y llamar a este eódigo para que la(s)
con lo cual se facilita la distribudón del programa en varios equipos., sin nece-
sidad de intervención adicional manual para poner en marcha un sistema nuevo.
GamlHu-databaM:-mantJgtT permite copiar datos entre bases. Podemos, por
ejemplo, pulsar el botón derecho sobre nuestra tabla dtJtos, presionar sobre Copiar,
acceder a otra base de datos, sea 5qlite o de otro tipo, pulsar Pegar, y el gestor crea-
rá la tabla en la otra base, preguntándonos si queremos copiar sólo la estructura de
los campos o también los datos. De esta forma, se facilita la fase de programación.
al poder disponer de varias bases de pruebas, asl como la fase de migración de una
baSC' a otra, al poder copiar datos de la base antigua a la nueva. Este proceso se puede
llevar a cabo para tablas individuales o para una base de datos completa.
5. Ge1,tión de bo5e$ de dolos
11
••••• 6. I Conceptos
la transmisión de dalos a mlVh de una red se estanda·
rizó hace tiempo a n i ~ l de software y hardware. Acm.llme.nle se
trabaja con el llamado modelo de coptJs. Básicamente, este modelo pre-
aislar los diferentes niveles de complejidad de datos, de forma que la sus.
n de una capa no afecte altrabaj<> en olra. Podemos ver hoy en dla que es
,por ejemplo, conectarse a Internet a travh de un módem, una Unea ADSL
ethernet en una red loc.al y, sin embarg<:>, el hecho de tener aparatos tan
en funcionamiento no obliga a disponer de un navegador o un cliente
diferentes para cada situación. Esto se debe al modelo de capas.. El nave-
IÓlo entiende de protocolos de alto nivel, como HTIP OFTP,transfierela
ión a un nivel más bajo y, finalmente, el módem convencional, ADSL o
de red se ocupap.de transportar esos datos segullo;pñX:eda.

o
"%

-_.. -_..._..........
Para no entrar en complejidades, ya que es tarea de un libro sobre redes, dire
que hay un par de lo¡ más bajos, conformados por el hudwilre
tarjetas de red... ) Ylos o módulos del núcleo, que controlan ytrocean la infor.
maóón para emitirla o recibirla por dicho hardwau; Yunos nivel(S por encima.CJW
son los que más nos interesan a la hora de programar con Gambas aplicaciono dt
red, y que son indepcndientts del método de transporte que haya por debajo.
El protocolo más extendido hoy en dla para distribuir información entre equipos es
el protocolo IP, 'lue ddermina qui destino y equipo cada fragmmtock
información que circula por una red. Cada equipo liene un número asignado, n.1.
mado dirttci6n IP es su identificador único. Cada paquete IP de informaci6n es
similar a una carla postal; incluye datos del remitente (lP del equipo de origcn) 1
del destinatario (IP del equipo de destino). Eslas direcciones IP tienen la (orma
XXX.XXX.xxx.xxx; IOn grupos de cuatro números que varian entre Oy255.5tpI-
rados por puntos (por ejemplo: 192.168.0.23 o 10.124.35.127).
Dado que estos números son dif'lciles de recordar. se estableció un sistema que per-
mitla establecer una correspondencia entre nombres y direcciones IP. Este sistema
se denomina DNS y. a lo largo y ancho de Internet y de casi todas las redes 1oc:aks,
se encuentran servidores DNS que reciben consultas acerca de nombres de equipos
y direcciones IP y las traducen en un sentido u otTO. IX- esta (oona. podemos. p«
ejemplo, indicar al navegador que muestre la p.jgina www.gnulinex.org,enlugardc
tener que indicar la dirección IP del equipo que estfl sirviendo esta página.
Los paqueles IP pueden contener cualquier tipo de información, pero encima de esu
niYd se han estabkrido otros dos tambim estándar, que son los protoeob TCP YUDf'.
1. TCP se utiliza para asegulllr la conexión rntre dos equipos: se sabe C'fllodo
momento si el equipo remolo est;i a la escucha. si ha redbido toda la infor-
mación correctamente o hay que volverla a emitir, y se añaden sistemas de'
control de errores para asegurar que un ruido en la línta no ha defo.-mado
los mensajes. Es el protocolo más utilizado en Internet, ya que asegura que
recibamos una p.jgina web o un fichero de forma completa y sin
En cuanto a UOP, es un prococolo de tr.msporte mucho mú simple que TeP,
'f no verifica si realmente existe una conuión entre los dos equipos o si La
información ha sido realmente recibida o no. Es, por tanto, menos fiable. pero
en determinados tipos de tfllnsmisiones. como son las de audio y video en
tiempo real, 10 importante no es que Uegue toda la información (puede haber
pequeños cortes o erroru). sino que el caudal sea constante y lo más rápido
posible. Por ello, tambiln se emplea con lTecuencia en Internet, sobre todo
para los Uamados servidores de sfrNming, que nos ptrmiten escuchar radio,
ver programas de televisión o realizar vidcoconfermcias por la rro.
ra de establecer una comunicación entre dos equipos. el modelo indica que
abrirse un locket. Es algo similar a una bandeja de entrada o salida. como la
administrativos, que tienen una bandeja con los informes pendientes y otra
b que van terminando. El sistema operativo almacena información en la ban-
*' entrada proveniente del sistema remoto, hasta que nueslro programa deci-
r los datos, entonces los procesamos y los dejamos en la bandeja de salida.
operativo se encargará de enviar esa información cuando le sea posible.
no se emplea sólo pua comunicar dos o más equipos. dentro de nuestra
máquina muchos programas se comunican entre si utilizando este sistema.
ejemplo, es el caso de los servidores gráficos o X-Window; el servidor gráfico
. lo que le piden los progfllmas clientes o aplicaciones que han establecido
tocUt con tI.
un tipo especial de socket, llamado local o Unix, que sólo s i ~ para comu-
programas dentro de un mismo sistema, y que está optimizado para realizar
función con gran velocidad y eficacia. permitiendo una comunicación ínter-
....ias veces m;is veloz y con menor consumo de recursos que a travl!s de un
Tepo UOP.
""'''''más arriba. tenemos los llamados protocolos de IlpliCtlcidn. Ya no nos encaro
del transporte de datos. sino del formado de los datos y de la comunicación.
de los protocolos más extendidos es el HTIP que. entre otras COlas, se utiliza
.. ,

D
3
"" ScIIwc•••
en lodo Inltl'ntt pata tnnsmilir r rmbv P'Pn- wm. F$l>blc« d moGo cIr, .....
!.Ir. cómo lultntiarloe, d bmuotn lk b datot • 1n.I'J$lnllu () rmbtr
an:h_a:xnprimidoL.) r cómo fi!WÍW" la mmllltil;aci6n.
Otros protocoloi espedfic05 $O<l d FTP,e5p«WWOOnl b Iransmi$lÓn r
de archivot; TELNET, p;r.n tnbajar con un Imninal dr: 1610 iobrt un Silltmal'ft1lo..
lu; SMTP, I'OP OIMAP p;r.n d como ekctróniro o 105 difmnte5 mm.
inllantinta, como tl JABBER.
Si .... br- Nodo'ClCi6ft llOI ha,.., t t. _, U .... _-.
;= I _ ...... de ....... lipa ',odo(Dl<.... de...ty
.. """"'."'diIroo."lopadeprouM'_'Y8? ")'1"'-'
....... NAJ, .. It.olwo p":Aoo'" tp.6 y... ¡,=wal. IOdo \o qw.... <I)'IIde O ......
_ por __ un _=ilUdodo El"""
de .........-,F*" UI'IQ be- bote -..:tw::. •••'"'_......
de progr_ ..-.d,sribuodol 101 duo. y........
••••• 6. 2 Creando un sErvidor TCP
Nunlril prill1ffil!.lrtil consistiti ni acribir d código dt un TCP: Itri l1li
Im'idor que: aetpUti mnotu, Itm b dalO5 que: tIMan YdtYoIvm•
fa) I b dirnlef,. úumnoI un proarama dr: c:oNOb 1bmIdo MiSrmd"... Estt pro-
srmu lmdti UD único módulo u.m.do ModMaiD.. ED 1Is propirdadr:s dd pro,«'
10 bnnoI dt Idcctionar d a:xnponmlr Ib-Det.
Dentll) dr:I módulo ModMain Itndrnnod: una rdnmcia I un objeto
Dichos ob;c101 te comportan como InVidortl de ti d«ir, te tne1K'nlrall
l
la tSCUChI de pdicioots de conaión de dienles mno!Of o Ioc.tks ni un pumo dc1l'f'
minado. Lo, pUtrlOS se numtTan dtl I a165535 ycida programa qUt co¡tlll
servidor lknlro del ,iSltlTl<1 ut,lita uno de dlOl.
••

11
.'-
..- •
... Gil
e ....
_._._-....
--
... ---
e _ .. O'
• toS _

0'-

-
.- .'
--
_rr- ' *"1
D" .e::J Q
¡> ••• l'I •
. -.-.....
r.... 1. 1'10\11''''"" MiS ....
po.rIO. c,,"..um.o d.ll 01 1024... conoideron.--voclol poro.,.,.;cioo COftO.
e•• Mei•. HTTP, POP. fU', IMAJ' -J y <lO """'*' _\/rilimdoo por 1"'09'0"""
uouono .. di"""" cI.I rooI ....._ T......., pa' _, do obno,
...... , '••• 001 523 ónde "" P"'9'- ejOCUlodo pa' .... o......... ........",
"0"'_
• F l. G _ ...........e-... _y
.. ,.... '" ' .......... lid-._/-"c/_
• 0-';000 múconocidoI como HTTPoFT'Pyatimm un asiplado (por
...... 80 (n d CIJO (\( HTTP)ckl'onNMndu,"bien no hay ninguna ruón
por Ja qU( un KrVioor wdl no pueda .lender, por al punto 9fIS4.
K I1nicam(nl(a un lCU(rdo inlernacion.1 para qU( cualquier clinll( qU(
rnIiur urul Jl(Iición ww, por (;ernplo, Kpa qU(, salvo illilruccionft (Sp«l-
m 0110 Ionllido, ha ck con«Iarw al punto 80 ck 1lI ndquina s.erv;oora.
En nueitroeuo, VImos I t'lTlplnr el puttto 3152. En la función Muo tkI p
al lIliciodt bIt, habmnotlk anr el objttoSt'nc,Soc:ktt,
cificar qut su hIlOIftii InlCf1WC (ti dtcir, qut ClIUlIOCkd TCP1 no UNIX), ti
10 al ddlt atender t indiar1co comimce ron INpeticiones.
o
"%
s,

fWLIC _ lIaJ.. ()
""!dor.""" • lIet..lllUonet
• 315a
ftJ -.nidor.Ullt.11
1,. ftDI PIUft .&nor¡ el *1 ,..J.te
.t....,.r al ,....rto ..pecifiea(So"
-
ObttrvtTTlOS que. la han de el ob;tto 5tfYidor, indicamos qut el Ifttol' dt
pan podtr escribir las rutjnu rn 115 cu.les ITlh'mot"
petidonn que llepo de los dientes.
Ala hora de indkar al scrridor qur $e: poop I la eK\ICN con d mftodo LiIIrs. lo
M«moI protqimdo el códipJ con una ilUlNCCi6n TRY, ¡dl1OlWd mor-
el $istnna no pmnidcw*Iendtr al puerro indicado (por rjmlpIo, si otro ltMCill
lo esluvicl1II utilizando). Y. podemos cj«utar el programa.
Como pockmotobKTvlr,d prosnIlNI pas.1a función Main Y
la a.pmde una ronaión dt un dimlt. Un Jll'OIRIM nomW dt l;'OIUOia, al
11M CSUI función, hubin'a fiNliudo lin mú, pero m tsIt cuoel int&p!ttt (JeInbaI
esl' atendiendo las novtdades que p!K!dan aa1e(rr m ti J()(kt\ que. h. crta60fo
por lanlo, el progralN ligue funcionando.l:lIptl'ando Pflkiona de c1imlrt.
F+ 10 .._.' 'I",t b .....
o ... oocbl no...... • ••didIo' ; • • • E*t
....c_ P''9- de ---. .... no ••' .... *" bode
11..,.0 de t- _......IificoaIl $1\'" hdleto. __ j de
....... IOCUI o lo lKturo de __ de un P' hotoI. ato'oodo..c...--
lo eIicocoa del proceso_
¡UI1lI JnVidor ya I'Slt funcionmdo,aunqlK no hap n«<b. rtalrnttlle o.til. De
si proballlOll' col1C'CUirl105 b conlOla con d prop'lIN tdntt. nUCI·
io iCO'ldor. ob5tn'UftDOl que se amccta e inmcdial1melllC 5C dI'Scon«Ui
t.1.net 121,0.0.1 :nS2
rYlng 121.0.0.1 ...
to 121.0.0.1.
Clp. ch4tr.eur 11 'AJ' .
c\o.ed by forelgn hOlt.
dClAlPo.OgouLine. :-$
..... del ob;do a prcciIammlCi&cc m:íbc UNooncxi6n
dicnlC y. Ji no cspulficamol al d prtlIBIDI que lbamoIltcndnia.1e cinTa.
Ul) ob¡c:o servidor rcribc UN pcticióa <k un dimle. le d ",nto

[)mtro de didlo n'mlo, r e6Io dmuo de 8, podemoI utiliut d nWfo.
Dicho mkodo dcvt.IcM un obJClO Sodd ql.lC UI1ól ronni6n
dimte. Ab hora de m:ibiTo cm'lIr del'" ese dienlC. 5C bari I lI'lvá de
ob,f1o, de ac modo, 5C diiCrmcia a cada diente conectado con un tcrVldor de
ilnin. evitando, por ejemplo, que enviclllOll1olll multados de un dkulo • un

oquiVOCldo:'''

. ,.
En nuestro programa al\adlrC'm05 una matriz de objetos donde guar
ref«encia a cada o b ~ l o diente, yen t'sa malriz iumos añadiendo los d
con«Un.
PRIVM'I servidor AS ServerSoc:kltt
PRIVA'%'! clientes AS NDJ Objectll
.DIM Cliente AS SOCket
Cliente· 5ervidor.A.cceptO
Client...Add(Clie=ta)
PUBLIC SUB Naino
servidor· NEH 5erverSocket AS -servidor"
SlIrvidor. 'l'Jpe • Net. Internet
servidor.Port • 3152
ftJ 5erTidor.ListeDO
Ir IRROR '1'HEIf PRIW1' "Error: el sbt-.
atender al puerto especificado"
...
En nuestro gestor de tvtnlOs Conntction utiliumos el m ~ t o d o AccC'pt, por
siempre aceptamos las conexiones entrantes. No obstante, si lo omitimos ca
determinados, el intento de conexión del cliente se ctecar' automáti
Observamos., por ejemplo, que Acupl nos informa de la dir«ción IP dtI
de conectarst a trav6 del parimetro RemoteHostlP. Si desdramos, por ejem-
plo> sólo conexiones desde nuestro propio equipo (que siempre tiene direc·
óóllI27.0.0.1), podrlamos modificar el código para que se rechacen las conexiones
otras direcciones IP.
DIM Cliente AS SoclliK
Ir THEN
Cliente •
Clientes.Add(Clieate)
ENll Ir
Estos objetos socket, por defecto reciben ya un gestor de eventos llamado Socket.
por lo que los eventos de estos clientes de socket se atenderin en el programa por
una función llamada Sockec + del evento.
En nuestro caso atenderemos a los evflltOS1WJd que se producen cuando se reciben
datos desde ti diente, y ti evento Close, que se produce cuando el diente cierra la
Olntxi6n.
En d caso del evento READ, no5 valdremos de la palabra clave UST. que mantie·
!le una rderencia al último objeto qut ha disparado un evento (en este caso, el dien-
sodet) para tratar los datos qut provienen de tl
Pan. dio. kttemos el socket como si fuera un archivo, con la instrucción READ, en
laque indicamos una cadena que recibe los datos; leeremos la longitud de los datos
disponibles en d socket, determinada por la función LofO y, despub, escribiremos
tsos miSmos datos en tI socket con la instrucción WRITE, de forma que el c1ientt
Ilciba un eco de los datos envLados. pt:ro conw:rtidos a mayúsculas.
6 Red

••
fty REAl) 1IAS'r, .cad, Lof(IAST)
lICad-ucase(.cad)
'1'IU' lfRI'l'E ILAST, .cad, Len(scad)
DIM .cad AS Sulog
_ SCC'·l -....cI()
. -
1M • Cliente....1Jld(LAST)
D' xDd >- O '1'HDl'
DDI lud AS IDt:eger
....
Aunque. programo llIIMI MI di..M pora controlar un equipo de Ionno
Wn .. UI'l díMlt puec» WVir pCII'C COIJopioboi el funcionalll.....
quiIw ....icb qwo 11'. 'lOS dóseñonOo o 1l'IOI'IO, 0I'lfin di dilpOMr o. UI'l do_
P.tra Oost. buscamos el objeto SocUt <kntro de nuestl1l matriz. ylo diminamoa
que desaparezcan las referencias a dicho dimte dmlro de nuestro programa
Ya disponemos de un programa servidor de socket con capacidad para al
múltiples dientes: podemos abrir varias ventanas de terminal, ej«ulando eIII
tdnel 127.0.0.1 3152, Yenviar y recibir datos del SCTVidor. Cada vez que ""....
una caden" y la enviemos Returo, recibiremos la c¡¡dena (0"\"<'
mayúsculas como mpuesta dd servtdor.
o
"%
o
0'1

•• _ ...-... z
'"
¡MmeJdc::....,...
.arct- (lit. ¡........ $=Iop..
'de" Uv..t 127.•.0.1 3152
127.0.8.1. ..
c:.v..cted te 127.8.0.1.
cn.rlCtor lo 'Al',
doeto- o p.awr o "J'\IK'UI..
0.-105 ... PASNl. ... *,l"loD"l' &C
D
F'1gURf 3. Programo $lf'Vidor de sockel.
••••• 6. 3 Un cliEnte TCP
,', '1''''1 "' •• ,,,"'"

..\honro que ya disponemos de un servidor, vamos a crnr un programa cliente.
""""""",, uo prognm, gnlfKa II,m"'" MICI;"'". 000 uo '"mub,;o FMm. y t
UIII. rd"erencia al componente gb.ne! como en el caso anterior. ..
fr..,.eto
[)rI'lIilll'e40
l>U·'irnl',
e eNiClioonIo
D"'_
.........rIet
-
QM6cUo.
ClDo.IOI
InlOfmll1en
ComponotnlUM red
Neneje de Pi'
..
---
figurv 5. Fonnubio FMom.
-
l.W'" '
Dentro del formulario FMain situaremos
dos controles TextBox, llamados TxrIP y
T:aPun1o, en los que d usuario situari la
Din'CCión IP y el Puerto para conectar-
se; un botón llamado BtnContrtar, con el
Progromoción viwol con Softwor-e Libre
lexto Conectar; un TextBox llamado
TxrDatos, en el que el usuario situará los
datos a enviar al servidor, y un etiqueta
llamada LblResuJtado, en la q ~ mostra-
remos el resultado recibido del servidor.
Tambiotn situaremos tres etiquetas informativas con cualquier nombre para guiar al
usuario. Al lanzar el formulario, situaremos unos valores por defecto y pondmnos d
TatBox TxtDatos deshabilitado, ya que en principio el programa no está conttUdo
al servidor. También situart:mos al principio del código una V1IIriable global de tipo
Socket, que representad al diente con el que nos (oncaaremos al servidor.

. e '•• el.... file
~ Cliente AS Socket
LblJtesulUldo.'!'ert .....
btDat.o•• Enabled. - PALSE
lllD
El botón BlnConectar tcndn!. dos funciones: si no estamos concetados, tratará dr
conectar, y si ya lo estamos, desconectan!. del snvidor. Para ello, comprobamos si P
referencia al objeto Socket es nula o no. Por otra parte verificaremos si el dato dt la
dirección IP es válido, asl como d dd pucno indicado.
IOritia.e1 número de puerto usamos dos funciones: ValO, un mimc-
ir de un texto si bkcontiene sólo caracteres nUIlléricoL Si no es asf, dt'VUd-
1... Si hemos obtenido un número, verificamos que se encuentre en el rango
5. Para la dilUción IP, Nrt.Format, que devudve una dirccci6n
. M un tato. si es posibk inl«prrtarlo como tal, o un.¡ cadena vada si no
dir«ción iP.
wz dispont"m05 de los datos, creamos el objeto Sockd y Iratall105 de conectar
IP y puttto dados, y cambiamos d luto del botón a IksC1m«tor.
caso de que ya concelados tratamos de cerrar c1socut, si eslu-
abfito, deshabilitamos el cuadro de lexto de datos y ponemos a NULL la me-
al objeto socket, para destruirlo.
DIM llPUerto AS :lDteger
DIM sIP AS Strizu¡
.....
•.Ten - ...
Ir Cliente • NULL 'l'HDI
TRY nPuerto - Val(TlltPuerto.Tert)
Ir ERROR 'tIIBN
"sage. Error (....-..ro de puerto no dlido")
........
EIm Ir
Ir nPuerto < 1 OR nPuerto > 65535 ftEIf
_SNge.&rrorC"1fl.uo de puerto DO .üido-}
........
_ Ir

S
E


1JI' sU' .. •• _
".1' ¡ .an-C"D1t'ecct6n ti' ea rilida-)
-
-"
CH-.l4o .. _ lIclckft U ·CH_t."
Cli.,te.ac.t ...1.
eU.llte. Port .. ftI'IIerto
Clieoltol.c....neet.( 1
el inttllto de y la (anuIOn real puroe pasar un inluvalo oU littn-
po. Para hemos conectado rnJmcnlc oon el ...,rvidor, cmplearcmNtI
Rndy. que se produu cuando el KTvidor :acepta nUQt..... conexión. En este
e'YeIllo, habilililrcm06 tI cuadro de talO de lUl05 PM'l '1.... d _rio putd;l escri·
bir alIL Tambitn puC'de SUCftkr 'll'C se produzao un mur (por fjnnplG.UIU. ront'"
mil o un nomb..., <k hosI no mconlndG), ni curo cuo K
nn110 Error, q.... aprtWrdwnol pan la • su audodt:tron«!'"
do Ydiminu el lICldtt Iállido.

10
t
VI


'l'RY IfRIft ICliente, Tztll<ltoe. Te:ot,
LeD(btDato..
•••
11" LeD('rrtDatol.Tl!I:ot) :> O _
11" Itey.COde - 1tey.Ret.uro _
'l'RY CL06E ICli...h
Cli...U. - lIUI.oL
'rrtDato..Baabled - 1"AJ..61C
.-
PUBLIC sua btDato._lteyPrea.O
dlo inlrOOuci""mos d código &nlro dd (\'(nIO KqPrcu dd cuadro d( lalo.
oto al (ovlo d( dalOS, lo reali:¡a""mos cuando d u.uario la Re¡um,
acribir ull lalo (O d cuadro
11
En <k .ut(l$dd servidor, puom Ikpmos m vario:s
tos, cad. uno dt los cuaJes .ecibirf"'OS tl1 ti (V('nto R..d dd obj<1o _Ut. ytm¡roI
mutmOl en l. niqoxtl IbIR.,ull.d".
,-.do ............ 1 ...ibon clalGI nod, ......., .. puedo ""V"'or "'"
do dolo> .. rocibon do uno oob _¡q h<ry """ _ ." .-..., Ic> poloit>ol<Clod
<lo """ Iro¡¡- do k>o .x- .
DDl .cad AlI strb>ll
TRI _ ICH...tl, .c.d, tof(Cl1...
U>l...u.1t:.a&1>.ftxt. lbJ......ltado._ , .c.d
Ya tenemos nlleSlTO el""n!e Iilto. Arr'lInlllO$ clllrlidor que crelmos .nltno
le yun. o var;Q ilt$l.nciu de esle prosram.l'ilr' cumprob.1r los rauhadof.

• _X

1
121
.11.0.1
un
. 8ervidorft:P:
POBLIC SUB Main ( )
hora de crear clientes o servidores para producción, debemos tener en cuenta la
ación de los caracteres empleada por el servidor y el cliente. Muchos errores
provenir de no tener en cuenta, simplemente, que Gambas y muchos otros pro-
usan internamente UTF-8 como c o d i ~ c a c i ó n predeterminada, mientras que otros
n ISo-8859·1 o UTF·16. Este programa, por ejemplo, puede tener problemas
ñ y vocales acentuadas. Podemos mejorarlo como ejercicio, convirtiendo las
s enviadas y recibidas entre UTF-8 e 150-8859-1 o 150-8859-15.
• • 6. 4 Clientes y servidores locales
caso del servidor, antes de conectar hemos de especificar que el tipo de servi-
local y una ruta a un archivo que representará el socket servidor.
lo explicado hasta aquí para clientes y servidores TCP, es aplicable a los clientes y
ores locales, la única diferencia se da en el modo inicial de configurar el servicio.
sockets son unos ficheros especiales que el servidor crea dentro del sistema de
. os, y que los clientes tratan de abrir para lectura y escritura de datos. Hemos
er en cuenta que situar uno de estos ficheros especiales dentro de una ~ n i d a d
no sirve para conectar dos equipos diferentes: un socket UNIX o local, s6lo
ede emplear dentro de un mismo equipo.
gen de los sockets TCP, diseñados para conectar equipos remotos, los siste-
(;NU/Linux, y en general cualquier sistema que siga la filosofía de la familia de
as UNIX™, disponen de otro tipo de sockets, que s6lo permiten la conexión
del propio equipo y cuya misión es optimizar la funcionalidad de los sockets
o el cliente y servidor se encuentran en la misma máquina.
, __ CIl!I. ScIro-.
knidor.!ypI • lIet.JIIUnlott
Iel'TlMIr.1'Ort • nS2
ftI' IenLloc-.iJ.I"'O
l' a.Jl tllIII PIDIt "Inw, .1 .. f'Waite
al puen.o -.peclUc:Mo"
...
1
o
DI

lerd-':.!ypI • 1Ift.. LoaLl
IenWoc.hUo a _.-.:- , ."l-'et"
ftI
IP .... __"anw. al IUt.. .. """",,te
au.der al pllU'\O ..,.eeU1cMo"
...
Si ti c6dirIDcon tstIlI'M)d¡fi. • i'.. lpIt n1111df1
U. k (1ft Illl udu't'OapmoI lit lIpl klCkct Ü"
dicnlt hnnclI lit nprcifiar qUf .. collGión k rtalu... WII WIIIUIa cIrIllro dtl
lmII • ardu-. m Iuplit lIlI ¡xwr1l) TCP, pinllo aIlIIlt MiaI B
Cl.II Nd.1.oaI Y11 propiNad Palh lid toUn.
Cl1eate ... lodIet. Al ·CU_te"
eU.te,hUl • tfHr. __ , "/.L-ut"
• -..u-J.
Cl1..u.C ctO
.......... ",...10;::':.:':'.......,.......... _
wOt " '..... ',_01"
ol loo... .. 1o_1IIIIqo>
...... X, .... ,..... ............. _ .................
• 6. 5l1lP
... UDP" po WiC>pW) I"""do' "'_upqo" pciocjpiooM. Ea
.... _ 'Ón_dicnlrr.,· c.. ............. por ... puor-
pm>oin "'>nO<W nw>c:o" 01 (111'(> lodo"'" oIguirn. 11 """"'"" o. ho:d>o.
o clirnlet ••u....... en 11 priclico ol bomnoo ala dio-
110 ""'" dr diod'w uno IplicaciOn ..nido.... dinm. Pt-.. qw "'" alSl<
... poquow"."'.il".. •..,.....tuiolaIP,,......... ,. <ioIo
__ hln."',ol.., _, 't ...-.
do _ 011""'0«*> VOP • ¡m'ft; <ir Iot ob;ttoo do lo dMt UdpSod;n,
'anlo ""'" crear progromu oeni<Io... como prosrama. Par. in;·
1....con unob;rtlldo au cW<," ha d< o......,a1 rnttodo
iDdlmel punto Iood .. 'fU" otliri Iipdo. LoI k"idoo.. l\oItriII do aur
'''' ,......... , Iotdialla. n', ""'""'" 1" """d __
':::.. nwiaf ""toJo ,,·II•• ..... pomo diodo., iradc:p••
• dd puer10 loc.l qw"""f'ln' I'P" ....
proplltcion...,ias propinlodos PO'" i.dtnriroaor loo ¡aquel... Cuan.do
J*II'<IC 01 oo:>deI ptoxtdoll" .. U'" abiD<:i6Ill'flnOla," pnen ""
, .. Spodoo__ t-Io"."" ., P. !·500 <ti .....
............. 1*1 ' ISOWaIWL __......... __
._-... - po!' -
_ po. ¡.
do diotl_,TOflI"I......... ti ,......... ......-

t,
...

Programación visual con Software Libre
En este caso, se hace también al inicio una llamada a Bind, pero asignando el valor
especial Opara indicar que el sistema elija por nosotros cualquier puerto local que
se encuentre libre. Tras esto, rellenamos los datos de TargetHost y TargetPort con
los datos de destino del paquete y enviamos la cadena HOLA.
En el evento READ, leemos los fragmentos de datos procedentes del servidor, los
unimos en la cadena Buffer y cuando ésta toma el valor ADrOS cerramos el socket.
Al cerrarlo, el intérprete Gambas deja de aguardar eventos y finaliza normalmente.
• • • • • 6. 6 Resolución de nombres
El componente de red también aporta una clase DnsClient para obtener la corres-
pondencia entre direcciones lP y nombres de equipo. Si bien el nombre sugiere la
llamada a servicios DNS de resolución, lo cierto es que los objetos de esta clase tra-
tarán de resolver el nombre por todos los medios que disponga el sistema. Lo más
común es que en las redes de área local se emplee el fichero /etc/hosts que contiene
una lista de pares nombre/IP, servidores DNS, LDAP o NIS; mientras que en acce-
sos a Internet se emplee, normalmente, sólo el servicio DNS. El funcionamiento de
esta clase es muy sencillo. Mediante el método GetHostlP se trata de obtener la IP
de un nombre de equipo (Host, Name), y mediante el método GetHostName reali-
zar una resolución inversa, es decir, de dirección IP a nombre de equipo.
Crearemos un proyecto gráfico llamado MiClienteDNS
con una referencia al componente gb.net, así como un for-
mulario llamado Fmain. Dentro de él situaremos un con-
trol Te>.1:Box llamado TxtHost, con su propiedad Text ini-
cialmente en blanco y dos botones, uno llamado BtnTolp
con el texto Obtener IP, y otro llamado BtntoName con
el texto Obtener nombre. En esta ocasión, en lugar de crear
un objeto DnsClient en ejecución, vamos a añadir el con-
trol DnsClient de la lista de controles disponibles en el
diseño del formulario, dentro de la pestaña etwork.
Caja

Form
----
Container
Figura 7. Proyecto
MiClienteDNS.
pI -
imi1ar al d 1
uLario yla
_E. r
¡te
Figura _,
- - t... :z1:.
uíenw:
GBtBosltIP( )
88-_ e 0("" p! o & el! ti .. !RO tI, ,
CJ..... ..
C11 - te. O
MmL e ,SUB BI:ni _ _ _, el. , -O
.1 no son visibles en ti po de .8CIJo'
ro se añaden al formulario como controle, norrTlQo
Fin de facilitar la labor 01 crear programas grá icos. El oqe Dn el' nt,
coso llamado Cliente, $e treo al desarrol ,el formu rio y ¡ste ham que se
o 01 e 'Iodo De/eIe en d' o rormu o io.


.. pt .. • 'ylH<Nls... ... d .. l ..
, _,aul __ :oIs,1<o:a.. .. lP
..... r<dN.b'-·· _d o. .. ...
El oepl><lo QtO el d .....,nLno: la propoedad Hool",
con Lo IP ha _rito d ..suano ni lo c.,. ... 1610; 110_al ....
r ......- r _ramooo ti nlof de la prop...dad HootSo_..
"""'" _...
En omboo 1; la raolución falla. '" .I«r (H,,"IP en ti prUna QIO
r HostNome.., d ...undo) qutdanl ... blInco. T.mbim podemos conlmla. el __
do de .,..... cOn l. propkdod S""IU. Si ro. «"ro. la ltn'llinó C""t'CU-
......&e: oí time un nlor menor que cm>, IIllbo un ..ror. no lO< mcontr61o IP a_
.........
Drd(]i,mt wnbobI pnmj!.t d tnbojo ... modo ............ Ea __
luOón puedo wdu bootruttr 'irmpo,'" .. qut lo ¡lllnW. ck ...
.....- trobojendo ... .-do..........
Pan .m-el """"""naoao, ... clot>oo poaor lo f'l0f t oc! A5yrit. dooI DM
• TRUE. fA::>WIlhoIn - t":".rd códip. v. ... pode""" "' ....
........ ""'d"""'."
dos HOIlNanw.. lklollp rapcctinmmlt, ya '1'" nUemru el eódilIo del ,.......
principal .. ""'" ejt(ul'ndo. ri diornlt ONS nU trabojondo ;nle'rna"'t'ltt. "
dos apelo.."" la P"lIKro es ..pe"" 01 ..wn,o FinÍlhtd. quu< di.para ol ocoNo' el
pmaso; Ylo ....undl .. compl'<lN' ol alado <Ir lo propiedad St., .... '1.... ..wrí"
ndmoro rru.yoor '1.... «YO m..n'.... ti plOU$O" ""ra ... cuno, cero cuando fínoIiI'
con bit.... un nlor menor que cero 1IÍ hubo un <'mIr.
t.uel " .. p<'<IUdto qm,plo rnodifiaDdo d cOcIiF iaiciaI ptnI ... .o'"J
............. Sr _ buck el.,.. o. lo po ,,' I t JitabO,
... _ .. ....,... CbO. Eaaoboodo .. ';O " ............... ,..
__do _ bOI6Il c..' 1""'" ohorut el ......-.
CU_.A8)'1lC .. ftlII
CU..w......- .. 1'lItbt.hrt
cu..U1.GIUooIU'(1
tan 0.01
-
c . u . . w . ~ • ftlII
Cl1_....Up • 1'lItbt.hrt
cu..w.GIUooI..-()
DO .UI Cl1_.'U1tM .. O
tan 0.01
-
••
-

'" o
I •

.....
En l,llI niwl por nw::ima do IOdo lo ...... aban K CDCUnItn di ::::
lfTTP,m el que P noK trata 1610 dr _ronlIlI K1Vidor.lino dt e
un bmaro pan la c:omunM:xi6n mi", dimln rMOl ,idoib. El pmrocoIo H'TTP
a
uno do los mis luJo de InlnlWt. <bdo qL>t,mllT Glras-..
nnplra ..... tnmminr P'Ii......
En el pmU:uIo l-!ITP.d ......idol UJl docull'llef\COm .....
tbda, r lo dtYudw ....>mdo "na trrit <ir CO<I'I'ftKiDoco aura dt la ,
ción de caractnes, control do nrora, nivel de compn:s06n do dal<l5, ':lrnwolit ..
WoIOl binarios, ele.
El protocolo HITP eslablea dof,m.codol principales p;m. toIidl¡), dalOll a1wm·
oo,. El primnn, ymáscomoln por .... ulilizado para m:ibir p:l¡¡inu web en el DI.,,·
gadorCUólndo escribimos uno dir«ción, por es el Uamado rMlQdo GET,tlI
el cual el diemc lan sólo dieila una dirección URl., devolviendo el scrviOOrcl muI·
lado. En el Kgundo mkoOO, lLom»J POST, el el"nt.. no sólo JOIicila la URL.si IICI
q.... ellVÍl lloa tome de informacionellKlicionales qm el K'fTidor PlOU$irt anleJdt
nlv;" d f.o el calO habilual cuando rdlm.arnoo un fonnulario (OlI daD
en una P'gimo wrl> y pu1samoI: el boIón moiar.
G.mbu apo'" en ti componente "....er...u.l, 110 dicnteUamado
Cl"" prowce KU50 • KO'idoru HlTP. E1lnINjo dr n"Joc:iKión ent.e diclUt 1
x'.idor, n[ como Illnl)6n M (o..m&IOI., Cllarea interna cid die"" H1i'i
b apIiad6n que 1610 habri do prmcuparv m pNir un doc ..
Yrftíbirlo..
El dimte lfTTP fi.¡nrioftar dr do. modos: el mh simplr CI el modo ..,..
.... en d que ra:ibimnoI dJftctammlc el documoetMo tnll b Ibmada a b
GETO 1'05T; m el ............ ulnaono, el modo do. trabajo K pana mM al dctC'"
10 para Iof; loOdnI: con la aplkación ni fiancionami.rnlo in""", rKiblC'l'da""
mmtoJ del OOcumallOni cada fYmlO JU:AD qtl4' \lIIirnn<l& m una caoXna·

\
'"
.Up...pe • rAUIK
fttp. 10
fttp.-' •
IIDI ftq llII 1't.(pCl.t.t
"PI .cM .... 'tri""
U ftt•. __ " 0_
PlUft • ....- al U ptoglu."
-
lIbD 'fttp, .c.d, Loflftt,)
--
_u
-...re _ .-laC)
-
.... dtfinimot 'f ctftlTOOO .... ob;r&o <It 1& cWt IlllpCJionlllorrllOdo HIIJ'•
.. prupoodod Nf-' FAL'iI: 1*1'''' el pro<aO.... *",,-a<Icor....
HTTP .......... , ' ........ -a.. .. P'I--"-..... '1 ,
....... ....

de awoI' "fa rftibu la,...... wcb ),II,:JIp=h •
..
• 'fóoodrI, ,d;,(...... ...-....,¡,..-.".. m" , .wM.-.

Indicamos la URL contime d nombre tkl Kl'Yidor yti documento
dmtro de ále.
1.IarnamoI al rnltodo Ca con d fin de rn:ibir la p'gina. con k> que d prtlp1(
interrumpido twu su rtCtp06n twu. un nn)( o hasta QUl' pum 10Jegund
múimo.
l.ttmos ti valor de la propiedad Status qut, como en d casode los lOChuo
te DNS, tendr.i valor mayor que ctro cuando eW; activo, ctro m caso de mIO
que cero en caso de error. Si hay un rrror, lo indicamos por la consola. Si
bien, !ternos, como en el caso dt' los socul$ ocualquier olro Rujo, emplcanc
lruedón Rf.AO ymostramos el contenido de la página wdl recibida por 00
Finalmente, cerramos ti cliente Http.&loesn«('sario,yaquetlcliente
mantener viva la coDuión con el strvidor mientras le es posible, para aa
nta mann'a la recepción de múltiples documentos de un mismo servidor.
El pob:olu un Mmpo en el el MIMdot _uWoe e1..xUt
lo con el ditntIf Si Mel I ••iOi rKibir 'IClrios póg_ de un _ 'Iida o rdzor
pekioi ... POST conMCVtMlI. dtb.iolliOi...p.or la lIlJtn.olXJ6n ClOSE 1610
de kldo el ptCQ$O, con lo cvoIM ganará en vMcidod y .. uIlIizorórl ....
_dol __
En cuanto al ulncrono. ti modo de proceder n UlIetamcnlc ti mis
con los sockcl$: esperar al (\'tolO Rtad para ir I()'todo fragmentos del dOC'
en proctSO de recepción, o al evento Error para atender posibles problemas di
nicación con el servidor.
Al margen de los problemas Rsicos de comunicación, que se detectan con d
Error, d propio protocolo HITP puede especificar códip dt mor en 105 que
nicación/recepción de datol ha sido perfecl•• nivel Rlico. pero se: han pl1l
El caoo ~ a .......- _ doaon_ "' .... _ ....... en d
euyoc-. .,...en dft'fOf 4lH.OuUl ......a_purdoD_d
po tít-. )odJOOleo.-.......--dd ..... odut). IIIa«ur,mw
ddinoltHTTPpo F N po., t purdrnC08•
..... es ~ , 01 c6dia0ck (01 nb1ODapifioo
bica)., R a _ '""""""" dr 1<:1:10 n¡4 ' •• dd eo.-. pro---
por d onvodut-.
do, ,b: .. '-:lo¡,. do dol P'''V'''''''' UIIilizodo e<>or><> _"""" y..,
oo. ""'.lo. a ...... do ......... do _ . .w.. ......... o6la 01 ........
Cado Y__._o6la a"""do .oIao •• dol_
PUK.lC _ MatAO
DIX f t . ~ p .. ~ ~ 1 _ ~
DIX .c.d .. ftr'--9

..

... - "1,up.¡,,'¡.......-'l-..<q/,uJ-
" ...""._t.. < o _
_ "_al ...,iIdr La ""laa"
-
_ Uttp, 1OCIod, tofClltp,
"""
ftlft .\D .. :::.: ... :----'-.
ro. UOI .c.II B' ftt.p.' , •
- """
-
El protorolo IlliJ' pnmitr al diente utrnticarx rara <\nmllinodu p.Ifi'
na. DO lC«sibla al pllbliro m p«lI. El UIUlOO tildo dilopOlWT'" un IlOllIhl'f lit
wUlrio 1 tonlrud\ll. ""1lI inlroduc:i. atol nIora., te 11I dt np«ir"". rlllOfl\bff
lit -notn lo P"'l"f'lad (hnylo ronuawlll en 11 propoedad Inln ...
llamar _ ... nWlodol eno ......
1U000l*1<_dioonoo .. -MOr oc ......._ ..... , ....
<k' ,..." ) ............liJ__ ..
.. ; ;:r.·dIDnlldl"k _".. ,e. d ........
t.
poldodAMllt_ ...........-. .,r"f ' ..................
roIlador do lo aplicación ha do a>n(lCft' do ...ttmaJl<l d lnI!I<lodo q... D«ai-
Madu.oI ....idoc

Plambinl COflt.mpl. d UfO <Ir q...... inf<,""Kión q....
JU&Rbm n_pordlfrOiIb CtlOCO-
II t ........ -.. dio ....... "" ................. al cliaI&e.l'Ialdt ........ por.;rm-
pan Abn' si 10 P4'.... ya ha.1do visitada con .ntcriori<bd PO' dicbo d"',n•.
dtl"tct<>. d dlnlt<' II'ITP 00 acopla Iao.o<::>& provmlnlt... dc1 KrVidc>r. Si lO
..... n1U' "" ordIioo 10 e si: Fík.aw.. a<tindD Ylit
HTTP .. nutnn<lr
ni$lm... trldidooardl,""'pa.. d..ool.....
ilin .al Si la propirdld ...iIÓl • TRUE, .. pmnili •
• dio cocrilltn al6dlcto ... CIlI<lÜ5,con ... cu.al bs __cooblI .. 1"1'-
CtI1I't Yt;«""i6ft cid
<omponmlr InI<'1ld<sarrolk>rfut......

el .....
,.........
• •• 6. B Protcxolo FTP
.... dpi........ KITP.Fll' .. ....... ""ln.......
diMAIdo
.. pu:o. lo tru>omillón Yrt<tpCión de 6dIcroo. La atnK_
• iIb FTP .. ....,.prtIoDIna.lodo_""*"""
.....

CUJIftU .... estnI<'Iun artl6rt:o y ......<n:I coda carpru
......;.",..
""Fll' .. ?! "M' I -,..-...:fI¡l.t-'I! ......
hnnlk: .......t •• AIhr y...,....rdmut do!. ","idor. Coa U'" oinWUI

D
l

muy limibr • la dri dimU' HTTP,tmdmnolqlMindicarla undancb y l4rnu
a los mhOOot Wr() <) Pt<t().
Al ipl qIKni d dimU' KTTP, K pnmiU' la Iftlión de nomlm ck lI5Uario Y~ .
101II ...i6ot.
Ful\lnll >"tiuot:s de elk dimet darúI aa:etO ,1........... de c:arpeW'f coma....... P"f-
IOniliudot. No obstantt, como K ha indicado, ahon es una dast muy lim,bda y
p ~ pbnlnrse como a1lttnl1liv;l d uso dir«lo de ulUidildes comoftp,rurl 0...,..1
pmr.aplicacionacomplt-;a. '11M Ma$ilm iKUIO. ~ FTP,dadoqUl'Ia¡n_
rión dl prtlU'CI& ~ es muy ll'tlCiJla Q)Il Gambu.
• Hoy en dla es comun ofr hablar de
XML como la solución a todos los problemas de
geslión informálica en la empresa. Es cierto, desde luego,
que se encuentra sobrevalorado, posiblemente debido a las cam-
pañas de marketing realiudas por grandes compatlías de software.
No obstante, también es cierto que XML presenla algunas ventajas importantes a la
hora de intercambiar datos entre diferentes sistemas. Pero ¿qué es XML? Pues en
realidad no es nada nuevo ni revolucionario, se trala simple y llanamenle de una
definición de formato para cualquier tipo de documentos.
Cuando necesitamos escribir un fichero de configuración, un documento con
registros extraldos de una base de datos, comunicar datos a un dispositivo, un for-
malo para un fichero de texto o una hoja de cálculo, siempre se le plantea el mismo
11
11
Progromoción visual con Softwore libre
problema al programador: la necesidad de un formato, documentado en el caso
ideal, que defina el modo en que esa información se inserta en un fichero o en un
flujo de datos a través de una red, con el fin de que los programas origen y desti-
no de esos datos puedan escribir o leer cada parte del documento correctamente.
Muchas veces escribir un fichero con un determinado formato es una tarea casi tri-
vial, pero el proceso inverso. la lectura, suele ser engorroso, dado que hay que com-
probar errores, trocear cadenas, comprobar la validez de cada fragmento, elC.
Por otra parte, cada aplicación ha desarrollado hasta hace poco sus propios forma-
tos para el almacenamiento y lectura de la información que maneja, haciendo muy
dillcil eliminar un elemento de una cadena de programas para reemplazarlo por una
aplicación nueva. Esto tiene una importancia grande cuando una empresa se plan-
tea el paso de sistemas propietarios a los que se encuentran encadenados, hacia otros
libres donde obtienen ventajas de pre<io, y capacidad de elección de proveedores y
servicios más justos por la inversión realizada. Los formatos propietarios atan lite-
ralmente al diente a los servicios y deseos de una empresa proveedora.
XML proporciona ayuda en todos [os aspectos comentados: es un estándar que defi-
ne cómo se han dr insertar los datos y los campos en un fichero o flujo. Además, las
herramientas de gestión de documentos XML proporcionan las funciones necesarias
para leer, escribir y verificar los datos embebidos en dichos documentos. Por último,
se trata de un estándar accesible a todos los programadores y casas de software, lo que
proporciona libertad para manejar y comprender el contenido dC' los datos.
El formato de un documento XML C's similar a uno C'scrito con HTML, no obstan-
te hay diferrncias sustanciales. La primera, y más importante, es que XML es un for-
malo de carácter general, pensado para trabajar con cualquier tipo de datos, mien·
tras que HTML se encuentra limitado al diseño de páginas web. La segunda es que,
a diferencia de HTML, donde hay etiquetas, como la de párrafo nuevo «p» que se
suelen dejar abiertas, en XML absolutamente todas las etiquetas deben estar anida-
das, y cada etiqueta abierta debe cC'rrarse. Por otra parte, XML es sensible a mayús-
culas, es decir, una sección que comienza con la etiqueta <p> no es igual a otra que
comienza con la C'tiqueta <.P>.
El aspecto de un fKhero XML simple, puede ser éste:
«Ia<oo'
<w¡uario>
<nombre>Erie smitb</nombre>
<&oeio>l13</soeio>
</usuario>

Los documenlos XML siempre comienzan, en la actualidad, por la cadena <bml
vel'5ion","'.O"l>, en la cUlllse especifica que 1I conlinuación vienen dalos con for-
malo XML Aunque ena etiquetll puede ser obvilldll, siempre es convenierue aña-
dirla, ya que conliene inforrnllción imporlllnle. En esle caso se especifica 1lI versión
de XML que se esl;l utilizando, (¡¡ 1.0, Yque es (¡¡ única que se emplu en la aetua-
lidlld. Si en el futuro una nueva especificación internacional de XML ampliara o
modificara XML, con una VttSión 2.0, por ejemplo, disponer de eu etique!lI en un
documento almacenado hace meses o años garantizará que los programas sigan
sabiendo cómo interpretar lo Que conliene un documento. Por olra parte, los docu-
mentos XML, por dcf«lo, emplean la codificación de caracteres UTF-8. Si por cual-
quier razón hemos de tratar con documentos XML que emplttn otra codificación,
también encontn.remos esa información en la ttiquela inicial:
Acontinuación, Uega ti cuerpo dd documento XML Hay una etiqueta que
da nombre al documento, en t5te caso simplemente datos. Despub. en este docu-
mento vienen los dlItos de los usuarios de una asociación: el nombre yti número de
asociado. Tocio ello encerrado entre etiquetas abiertas y cerradas, de moclo que d
documento queda ordenado en secciones, con varios niveles de anidación.
XML permite que las etiquetas dispongan de atributos. Por ejemplo, podemos pre-
ver que nuestro fichero de datos contemple un número de versión para futuras
7.XN<

11
ampliaciones, y que en elida usuario se anada el año en que entró a formar parte de
la asociación. Los atributos tienen la forma:

Es decir, se indicará el nombre del atributo, un signo de igual y, encerrado entre comi-
llas, el valor de ese atributo. El fichero podría ser ahora asi:
<?Xll\l version_Ul.O" encodiD9"'''ISO-8859-1
U
?>
<datos version-"2.4">
<usuario>
<nombre inicio-"200S">Eric smith</nombre>
<socio>113</socio>
<¡usuario>
</datos>
Una etiqueta que se abra y cierre sin información en su interior, por ejemplo <p><lp>
para designar un párrafo en un documento XHTML, puede simplificarse es<:ribiendo
la etiqueta de apertura con la barra al final del nombre de la etiqueta: <pI>.
Estos son los elementos más básicos de XML, pero más allá existe una amplia gama
de conceptos que quedan fuera del alcance de este manual, y que aportan un gran
número de posibilidades a la gestión de documentos XML: existen etiquetas espe-
ciales para comentarios, un lenguaje para validación de datos, DTD, hojas de estilo
con formato XSL, espacios de nombres, etc. Un buen punto de inicio para aprender
XML es la web http://www.w3schools.com/xmlldefault.asp.dondeseencuentran
tutoriales al respecto, así como enlaces a otras fuentes de información.
7. I Escritura con XmlWriter
La clase Xm/Writer, contenida dentro del componente gb.xml, aporta un modo sen·
cilio para escribir un documento XML. Supongamos que deseamos almacenar en
un programa los datos relativos a varias conexiones telefónicas a Internet. Nos inte-
resará el nombre de la conexión, si está disponible en todo el territorio nacional o
está limitada a una localidad, el teléfono y las DNS, primaria y secundaria, aporta-
das por el proveedor.
Plantearemos un documento en el cual tendremos una sección co'lexioll para carla
conexión, que tendrá un atributo nombre y otro local, este último con dos valores:
\, si es local, O0, si es nacional. Dentro de la set:ción COllexiOll habrá un campo para
almacenar el número de teltfono, asl como otro para los DNS primario y secunda-
rio, los cuales tendrán un atributo que determina si es e\ primario.
Siempre es conveniente empleor nombres de etiquetos y olriootos que no conlengon oceo-
Ioi o corocteres especiales de codo idioma Icomo ñ o poro evitar problemas si o/ros
progJamodofes que debon retocor el programo (1 el Fichero tienen teclodos disrinlos o
empleon PO""'" de XML pobre. que igflOfen olgunos de la codjlicrn:;ión.
tste será el aspecto del fichero XML del ejemplo:
<?xml
<conexiones
<oonexioo
<telefono>l199212321</telefono>
<dns primario-
w
l
w
>127.0.0.2</dns>
<dos primarlo-
w
O->127.0.0.3</do8>
</conexion>
<conexion id.-limbonet
w
local_WO
W
>
<telefono>229943484</telefono>
<dns
<dns
</oonel:ion>
</ooneI:1ooe8>
7 )(Ml
11
ProgramoÓón visual COfl Software libre
Antes de continuar, observemos el formoto. Estó 5eporodo en vorios lineos, o retornos
de corro, y exi51e uno indenloci6n poro indicar los distinlOS niveles de onidocíÓn. Eslo
na es en obsolu'o necesorio, y los porsers de XMl ignoran lo. espocíos en blanco y
tobulociones, O$i como los retornos de corro Esto es sólo uno ayudo poro quien tengo
que consultar o modificor el fichero desde un editor de texto común. Sólo tiene, por
tonto, sentido o nivel humano, y un lichera XMl correcto podrio estor contenido en uno
sólo lineo de texto. Si eslomos acostumbrados o programar en e o CH', sobremos
que con esle lenguaje ocurre lo mismo: los diferenles líneas y lobulacione5 don orden
y legibilidad 01 programe, pero ,,1 mismo podría escribifle en uno solo líneo. En e, 105
llaves y puntos y comas son 5ignificativos, no osi los espacios o retornos de corro.
En XMllo significativo son 105 opertUfas y cíerr"s de etiquelos.
11
A continuación vamos a crear un
programa de consola llamado
EscribeXML, y dentro de él un
único módulo modMain con una
función Maíll.
El programa tendrá una referencia
al componente gb.xml.
--,... ..

t>1I.'O'M1'I.
.•.
D_.
.e_
• 'fil'
D_
Figuro 1. Proyecto EscribeXML.
Definimos y creamos un objeto XmlWriter. Tras esto, lo abrimos con Open para
comenzar la escritura. Este método acepta tres parámetros: el primero, obligatorio,
es el nombre del fichero a escribir, que puede ser una ruta dentro del sistema de
archivos o una cadena en blanco, en cuyo caso se escribirá en memoria, y luego podrt'-
mos obtenerlo como una cadena para, por ejemplo, enviarlo por la red a un equipo
remoto. El segundo es opcional, e indica que deseamos que tenga indentación (como
se comentó antes, para aumentar su legibilidad), o bien si se escribirá en una sola
línea, para ahorrar espacio, a cambio de hacerlo ilegible desde un edilor no especia-
lizado. El tercero, también opcional, sirve para, si se desea, especificar la codifica-
ción, diferente de UTF-S.
• G be. -odule file
PUBLIC SUB Main ( 1
OlM XMl AS x.l.writer
:rm.l .. NEW XllllHriter
TRUE)
Indicor uoo codificoción diFerente sirve poro que eslo quede rellelodo 01 inicio del
documento, pero no real,zará por nosotros lo conversión de los codenos que escribo.
1'10$, toreo q.... hobr_ de hacer con funciones como Con..S. SI procede
Escribimos la primera $«Ción, Hemos de introducir una eüqurta ika¡xr1ura, tarea
que S( realiza con ti StanElcment
Además dispone de un atributo con valor "LO":
En este caso podemos unir I¡s dos instrucciones anteriores en una sola:
StartElemcnt acq>ta un parámetro opcional. consistente en una matriz de cadenas
que sean pares de valores atributo-valor del atributo:
Dentro de esta sección tcncmos cada una de las conexiones definidas. Cornen7-"mos
por la primera que, al igual que antes, es una etiqucta de apertura, con un nombre
ydos atributos, en este caso:
7.XMl

"
I c;or So

11
¡-id
W
, ·caat.uonet
M

Dentro de esta región, disponemos de una nueva apertura de C'tiquC'ta para el telt·
fono:
Contiem:' un lexto que comprende d numero de tdHono:
Tras este paso cerramos la etiqueta:
XIIll.EndEle.ent ()
No obstante, podemos resumir las tres inslTucciones anteriores en una sola, válida
para estos elementOS simplc:s que tan sólo contienen un texto dentro (o nada) y luego
se cierran.
Par;¡ los DNS iniciamos una etiqueta "dos" con un atributo:
Incluil1"Kl5 el texto con la IP:
y finalizamos la sección:
Ial.ltadElement( )
Lo mismo para el segundo DNS:
xm.l.Start.E1ement( "dn.", '''primario'', "O"])
xm.l.Text("127.0.0.3")
xm1.EndE1ement()
cerram05la los
relativos a esa conc:xión:
xml.EndE1ement()
Procedemos de igual manera para ]a segunda conexión, lal y como podemos obser-
var en el siguiente código:
"1"] )
xm1.E1ement("te1efono", "229943484
H
)
xm.l.StartBlement{"dnI
H
, {"primario", "1"])
Xml.Text(H127.0.10.10
H
)
%al.Encl.Element. ()
HO"])
Iml.Tert.("127.0.20.42")
xml.EDdElemeDt.()
xml.EndElement.()
Finalmente cerramos documento para que se escriba. Si hubi6emos especificado
un nombre de seria ahora cuando se \'Olcaria al fichero al habtrlo hecho. en
nuestro caso.
La llamada a nos devuelve una cadena con el documento XM1., que
mostramos por la consola:
PRINT ZIlll.EndDocwaent()
7 XMl

11
Programoción visual con Software libre
El programa completo queda de la siguiente manera:
, Gambas module file
PUBLIC SUB Main()
OIM Xml AS XmlWriter
Xnll - NEW xmlWriter
Xnll. StartElenent (Uconexiones", [Uyersion", u 1.0" J)
ltml. StartElenent ("conexion" , ["id", "castuonat",
"local", "0"1)
ltml.Element("telefono", "1199212321")
ltml. StartElement( "dns", ["primario", "1" J )
Xnll.Text("127.0.0.2")
Xnll.EndElement()
ltml. StartElement ("dDs", ["primario", "O" 1)
xml.Text("127.0.0.3")
xml.EndElement()
Xnll.EndElement()
xml. StartElement ("conexion", [" id", "limbonet",
"local", "1"1)
xml.Element("telefono", "229943484")
ltml. StartElement ("dns", ["primario", "1" 1)
ltml.Text("127.0.10.10")
xml.EndElement()
Xnll. StartElement ("dns", ["primario", "O" 1)
ltml.Text(U127.0.20.42")
XIlll, End.e:lertl&nt ()
XIIl.1.EndElement ()
PR.INT
mm
J ejecutarlo, veremos el documento por la consola. Lo modificamos para que se
;criba en un fichero en lugar de en la consola, lo cual nos servirlo pan. leerlo a con-
nuaci6n en un ejemplo de Je.ctun. de fichero X.\1I.. Pan. eUo modi6caremos el
o Open:
. diminartmos la instrucción PRlNTal final:
XIlll. BndDocument. ( )
n este caso, la llamada al método EndDocument volcar:! el documento en un fiche-
J dentro de nuestn. carpeta personal, llamado conexiones.xml.
El ¡,cltero obiitrto can Opom no 'le ........lco realmente 01 d,seo duro hosto la llamada O
EndD<x:vmem. A 'v vez, el método EndDocvment encorgo de cerror lodos eri.
queros que hubieron quedado obiitrlcs, poro goronri:o. lo coloererocio XMl. de éste
exploramos la clase X",/Writtr, observaremos que, además de los ml!todos
mentados, aporta otros para escribir comentarios y elementos correspondien-
al lenguaje 01'0, entre otras caracterislicas. También dispone de los métodos
áticos Btisd>4 y BjIlHex. que convierten una cadena a las codificaciones con estos
mbres. Dichas codificaciones permiten introducir datos binarios dentro de un
lero XML
7. XMl
11
Progromoción viwoJ con Software lihr


7. 2 Lectura con XmlReadEr

Modelos de lEctura
Al menos existen tres métodos pilra ker los contenidos de un fichtro XML:
l. Un mttodo se en [«r ti fkhero de prinópio a fin. Elltetor v;¡ generan_
do conforme se entra ysale de los distintos nodos del documento, y
los gestores de evenlos escritos por el programador van recibiendo la ¡nfor-
rnación. Esta forma de trabajo aún no se ha implementado en el componen-
te gb.xml, aunque se prevl! su inclusión en futuras versiones.
2. Otro método consiste en cargar el documento completo en memoria, para
luego navegar por él, con lo cual se obtiene gran flexibilidad a costa de un
consumo considerable de recurws del sistema. Este método está parcialmen_
te implementado en Gambas a través de la clase XmlDocrmrtllt, si bien su fina·
lización no está prevista hasta futuras y no se recomienda su empleo
para lectura de ficheros XML No obslante, esta clase ya se emplea para trans-
formaciones XSlT, como veremos más adelante en esle capílulo.
3. Por último. el mtlodo qul." consume menos recursos y aporta baslame sim-
plicidad dI." aprl."nditajl." y uso, es disponer de un cursor, que sólo se mueve
hacia adelanle, de nodo I."n nodo. y que en cada momenlO podemos emplear
para conocer el conlenido y lipo de cada nodo. Si hemos lrabajado con la pla-
taforma .NET"" o Mono'no" nos sed familiar la clase Xnr/RMda y sus deri·
vadas, como Xnr/TextRetlder, que trabajan de la misnla manera. Este modo de
trabajo se encuentra perfectameme soportado en el componl."nte gb.xlIll a tra-
vés de la clase XmiReader.
Planteamiento Inidal
En el caso de Gambas. la lectura de documentos la realiz.1remos utilizando objetos
de la clase XmiReadcr.
El código de lectura resullaré más complejo, al tener en cuenta varios aspectos:
• R«hazar cada fKhero no válido: putdt haber fICheros con formato no XML o
que contienen datos sin sentido para nuestra aplicación.
• Ignorar datos no conocidos: es posible que un documento contenga datOS que
no nos interesan, pero se han añadido al fichero por otra aplicación en previ-
sión de futuros usos (puede haber, por ejemplo, una etiquda <tarifa> dentro
de cada conexión). Tambitn una etiqueta conocida puede contener atributos
desconocidos.
• Orden desconocido: en un fichero XML no es relevante el orden en que se escri-
ben los nodos hijos de un nodo, es d«ir, que estos dos ejemplos deberlan ser
dados por válidos:
<coneJ:ion>
<dnIi>•••
<telefOllO>•..
<dnIi>..
</coneJ:ion>
<coneJ:ion>
<telefono>••••
<dns>•.•
<dns>•••
</coaerloa>
Si la aplicación espera. encontrar el nodo lelefono antes del nodo dns, fallará
allratar el primer fIChero, que, sin embargo, conliene la misma información.
• Ignorar etiquetas sin interés para nuestra aplicación: XML, como indicamos
brevemellle al principio, prevé la posibilidad de alladir comentarios (simila·
res a los comentarios de cualquier progrnma, sin uso para éste pero que aumen-
tan [a legibilidad), nodos OTD, ete. Habremos de pasar sobre estos nodos igno-
r:l.ndolos y sin presuponer si existen o no.
<MI
Progromoc;iót! viwol con Softwore Libre
Cuanlos más posibilidades oñodomos o nueSll'a código de solvor b desoonocido, más
llexible haremos nueslro I.ctor XML poro permitir b lectura dio dokn pwtenienlM, tal
vez, de programo, escrilDs poi" YOrios programadores con bs que OD Ienemos con-
1DdD, o que tienetl petlsornienlDs algo diferentes acerco cIeI conleoido del hci-a.
o O O [] O Un EjEmpo dE: lEctura
Crearemos un proyecto gnlfico llamado LeeXML, con un formulario FMain, que ten-
dnlla propiedad Ammgelll('1I/ con el valor FiI/, y un (mic:o control TrreVIt'W en su inte-
rior Uamado Arbol. El programa contendnl una referencia al componente gb.xml.

g P,,.,.,<l. ·l_.......
--_...~ .....
Olf"i8CJ ..... eu.
t>".'O'hl'1 •
~ .
,;;,.:':;=-~ L
0 __
0 _
0 __
0._
0.-

En la apertura del formulario leeremos el fichero XJ\1L El método Form_Open que-
dará así:
, En primer lugar definimos ('] objeto XmIReader, lo creamos y tratatnos de abrir
el fichero XML. Si el fichero no existe, o !lO atiende a este formato, se genera-
rá un error en ese punto.
PUBLIC SUB f'onU)Pen()
DIH :Jsnl AS XIIIlReader
xml - NEW xmlReader
TIU %al. Open (l1ser.1lCWIle " "/conexione•• 'llDl" )
lP ERROR '!'HEH
Message . .Error("Pallo al -.brir el fichero iIIodie.do")
""""'"
"'" "
• Entramos en un bucle en el que Il"l"mos G1da nodo avanzando por el conteni-
do del ~ Nos intl"n$3. encontrar d primero de tipo EJemalt yque $U nom-
bre sea conexiones. De no ser asl, el fichero no contendría datos de interés y lo
rn::hazarlamos. Pero si es correcto, llamaremos a una (unción RellenaArbol,
donde trataremos estos datos.
DO WIIllZ 1'RUE
IP IJal.Node.Type - XIIIlReaderNodetype.ElBDent THEM
IF Xlll.1.NOOe.Name - "conexiones" '1'llEN
RellenllArbol (XIal)
ELSE
Mes8age.Error("El documento DO oontiene datos
de eoneziODe''')
%al. Clase( )
"'" "
7.XMl

11
Progr
Por cada ¡teración del bucle, empicamos el método Rtad, que sitúa el puntero ¡nter_
no en el siguiente nodo del fichero XML En este proceso, puede darse un error si el
puntero Uega a una zona donde el fichero tStá corrupto, es d«ir, quc no cumple la
norma XML y, por tanto, no puede ser leído.
TR!' XIal. Read ()
IP ERROR 'I'ltEN
Si llegamos al final del fichero (tras el último nodo), terminamos el bucle. Esta cir-
cunstancia s<' puede conocer porque la propiedad Eof del objeto XmlReader loma el
valor TRUE.
Ir lIal. tof TflEN 8REAX
LOO'
Tras la lectura del fichero, cerramos el objeto XmlReadu.
TU Ilal.Close()
Vamos ahora a implementar el procedimiento RellenaArbol. Entramos de nuC\'O
tn el bucle y, en primer lugar, leemos el siguiente nodo para situarnos dentro de
col1uioues.
En este caso habremos de seguir leyendo por cada uno de los elementos cOlJfJCiml
que existen dentro de la etiqueta principal conexiones, y salir de la función cuando
ellcontremos el final de esta etiqueta:
PUBLIC SUB RellenaArbol(x.l AS xm.lReader)
DO HBILE TRUE
'l'R]' Ial. Read. ( )
lF ERROR THEN RETURN
Si tTlcontramos un nodo de: tipo E1e:mc:nt que: se: llame: conexion, Ilamarc:mos a una
función llamada Rellenalte:m para tratarlo. Pero si su nomblT rs desconocido para
nosotros, lo ignoraremos, saltando todo su conte:nido para llegar al siguie:nte: nodo
dd mismo nivd, con el método Nexl.
IF Xml.Node.'l'ype • Xln1ReaderKodeType.El_nt ntEN
IF xml.Node.Name - ntEN
Rellenaltem(xm.l)
TRY xal. Mezt ()
IF ERROR TIIEM BREAK
ELSE
IF xml.Node.Mame -
IF zml.Node.'l'ype - xm1ReaderNocieType.
EndElement ntEN BREAK
END IF
7.XMl

Progromoción viwol con Soft,.,..;¡re Libre
Rel1enaltem es el procedimiento mh complejo, en el cual leeremos el contenido de
cada conexión exitente.
PUBLIC SUB Rellenaltem(Xrnl AS xmlReader)
DIM Limite AS Integer
DIM sNodo AS String
DIM st.ocal AS Stdng
DIM sPrt. AS String
En primer lugar vamos a recoger los datos de los atributos de la t1iqueta cOllmoll.
Para ello, hemos de iterar con la propiedad Attributes del nodo. A lo largo del pro·
ceso de iteración iniciado con fQR EACH, el puntero interno del lector X.MI. pasa-
d por cada uno de los atributos del nodo, que a su \lez son nodos, cuyo nombre y
\lalor es el nombre y \lalor del atributo. Finalizado el proceso de iteración, el puntero
\luel\le al nodo sobre el que estáballlos situados, y con los dalas recabados, añadimo.s
en nuestro control TreeView, un nodo al efecto para su representación gr.Uica.
POR EACII x.l.Node.Attd.bu.te.
:U" :ral.Node.Name - Mid" 'I'BEN .Nodo - :r.l.Node.Value
IF :ral.Node.Name - Mlocal" 'I'BEN aLocal - :ral.Node.
Value
IF sNodo <> .. ~ AND sLocal <> .. ~ THEN
IF sNodo - "O" 'I'BEN
DoY Arbol.Add(sNodo, sNodo " (loeal)")
ELSE
TRY Axbol.Add(sNodo, sNodo & .. (nacional)")
E"''''
Pasamos ahora al interior del rnxIo (olluio" para extraer información de sus nodos
hijo, es decir, las DNS y el número de teléfono. Buscaremos nodos de tipo EltOlent
yen función de su nombre actuaremos de un modo u otro.
TRI x.l. Read ( )
IF ERROR THDf JU:'l'URlf
00 HalLE TRUE
IF xml.Node.Type - xm1ReaderNodeType.Eleroent raEN
SEu;cr CASE XIlll.lJode.N_
Para el caso del tdtfOIlO, pasaremos del rnxIo actual (la Idffono), a! siguim-
te nodo que contendrá el texto con el número de teléfono, (podriamos, no obstan·
te, mejorar el algoritmo contemplando la posibilidad de encontrar algo distinto a
un nodo de texto, cosa que no haremos aquf por no complicar más el código, que
siempre puede resultar complejo al principio).
'1'RY Ilal. RGad ( )
'1'RY Arbol.Add(sNodo & .. tel: .. &
xml.Node.Value, NULL, sNodo)
Si el nodo es de tipo "dns", tendremos que comprobar el valor del atributo que indi-
ca, si es DNS primario o no, y lucg<! leer ellexlo que contiene la IP:
7.J<Ml


ProgromoÓón viwaj con Soltwore libre
CASE "oo.-
s.rw - "O"
P'OR 8ACH Iml.Kode.Attributea
Ir Xal.IlQde.N_ - "pri.ario" TKE:N sPria -
Xal.Node.Value
""""
'l'R]' Ial. Read ( )
Ir aPeia - "O· TBEN
~ y Arbol.Add(&Nodo • "-dns2", "-dns2" •
Xal.Node.Value, NULL, ,Nodo)
ELS'
TRY Arbol.Add(sNodo & "-dosl", "-dnsl" ,
xml.Node.Vslue, MULL, .Nodo)
END 5ELEC1'
Una vez leido el nodo. pasamos al siguiente y continuamos leyendo hasta encontrar
uno de tipo EndElement, donde sabremos que hemos encontrado el final del nodo
LOOP
IF Xml.Node.1'ype - xm1ReaderNodeType. EndElemeD't.
THEN BREA!<
TRY XIal. Real! ( )
11' ERROR TREN BR&U::
LOOP
e n el código complelo apunto:
• r ~ m b a s claaa file
PUllLIC SUB RellenaItem(XIal AS XIII1Reader)
DlM Liait. AS Inteqer
DlM sNodo AS String
DlM sLoeal AS String
DIM sPrim AS St.ring
P'OR EACB Ial.Node.At.t.rlbut.es
If' XIal.Node.KaIIlB - -id- TREN sHodo - Xlal.Node.Vll1ue
If' bLl.NocSe.NaIIlB - -local- TREN sLocaI - XIa1_NocSe.
Value
IP sNodo <> - - ANO aLocal <> .. - TREN
II' sNodo - -o- TREN
TRY Arbol.Add(sNodo, sNodo ~ .. (local)-)
ELSE
TRY Arbol.Add(IHodo, sNodo ~ .. (nacional)-)
END lF
7 IWJ.
11

Programoc::ión visuol con SoItwore Libre
DO WHILB '1'RUE
¡l' IMl.Node.Type - XInl.ReaderNodeType.Elemeot TREN
SELECT CASE :Iml. Node. NillIl8
CASE
TRY XlIIJ.. Read O
TRY Arbol.Add(sNodo • • xml.
Node.Value, NULL, sNado)
.Prila - -O-
f'OJl EACH XlIIJ..Node.Attri.bute.
If' Xal.Hode.NiIIIle - -priAario· 'rBEM shia
- Ial.Hode.Value
""""
TRI' Ial.itead()
Ir .hila - -O- TREN
TRI' Arbol.Add(sNodo • ·-dn.2-, -do.2: - •
:Iml.Nade.Val\le, NULL, .Nodo)
ELS'
TRY Arbol.Add(sNodo • -dnsl: •
xml.Node.Value, NULL, sNodo)
EN!) IF
EN!) SEUCr
TRI %m1.Nert()
Il' ERROR TREN 8RBAX
Il' xal.Node.Type • xalReadedfodeType.EndElemeD1:
............
TRY xml. Read ()
Il' ERROR TREN BREAK
"""
mm
POBLIC SUB RellenaArbol(Xm1 AS Xla.1Reader)
DO WHllZ TRUE
'l'IU xal. Read ( )
Il' ERROR TREN RE'1URX
TRY XIlll.Nex1:()
Il' ERROR TREN BRI:AX
7.XMl
11

p
ENE> lF
Ir IIal.Node.N_ - -conexiones- ANO Xall.Hode.Type
.. &lReadertiodeType. EDdEl-.lt '1'HEH
.....
END lF
LOOP
PUBLIC SUB "0= Open ()
DIM XIIl1 AS XIIl1Reacier
TRY Iml.Open(User.Home & M/oonexione•• ~ · )
IF ERROR THEN
Méssaqe.Error(-Fello al abrir el fichero indiea&O-)
""""'"
END lF
00 li'HILE rRUE
Ir XIIl1.Node.Type - XIIl1ReaderNodetype.Blement TREN
RellenaArbol (XIa1)
ELSE
<Ioeument.o DO contiene datos
de <XXlez!ones )
%al. Close( )
2ND "
2ND "
TRY xm.l. Read ( )
IV ERROR TREN
Message.Error(MPormato XML no
""""'"
2ND "
IV XIal.Eof 'tHEH BREAK
LOOP
'l'Rl' X.l.CloseO
11
'01 ".,.,."
..., "'.......
"".,>7 0.11
---
,.. ,-,...
_, "'.0.10.1"
..., "'0:lO"
Este código dará lugar. al ejecutarse. a una
visión en árbol de los datos conlenidos en
el fichero XML.
• Figuro 3. Rewltado del fichero XML
7 XM1
11
Progromac:ión visual con Software übre
••••• 7.3 XSLT
o o OO O ¿Qué ES X5LT?
Acompañando a XML, XSLT permite realizar conversiones de formatos de docu_
memos. Con XSLT se puede, por ejemplo, convenir datos de un documento XML
en un documento HTML, o cosas más complejas como generar un documento POF
o StarWriter a partir de datos XML que nosotros hayamos diseñado.
Gracias a XSLT se puede separar de 111000 definitivo la información de su represen-
tación, por lo cual se emplea extensivamente en aplicaciones web, que pueden reci-
bir datos de una base remota en formato XML y convertirlos, generalmente, a HTML
para enviarlos al cliente con una representación agradable.
XSLT se basa en unos documentos, con formato XML, llamados plantillas, que con·
tienen las instrucciones necesarias para convertir un determinado documento XML
(con las etiquetas y atributos propios de dicho documento) en otro con distinto
formato.
XSLT es extenso Jnra tratarlo aquí en profundidad aunque, como siempre ocurre
con los eslindares abitrtos y casi nunca con los formatos propietarios, podtrnos
encontrar futntes tspeeíficas de información adicional, por ejemplo tn
http://www.w3schools.com.
Oo o o O Una plantilla de Ejemplo
Cada plantilla XSLT se refiere al contenido de un determinado documento XML
Supongamos un documento XML como éste, en ti que sc enc:utntra un listildo de
socios:
<socio>
<n\mlllro>l12J</n_ro>
~ 1 I t l n L. Aguilar</ncd>re>
<tipo>Sonorario</tipo>
</socio>
<socio>
<numero>2135</numero>
<nombre>salvador G. Tierra</nombre>
<tipo>Regular</tipo>
</socio>
<socio>
<nu:mero>9654</numero>
<nombre>A1berto N. Parra</nombre>
<tipo>Regular</tipo>
</socio>
</socios>
Las plantillas XSLT siempre comienzan con unos identificadores. El primero, de
documento XML, ya lo conocemos, el segundo denota que 10 que viene a continua-
ción es un documento XSLT.
<?xml
<xsl:stylesheet

Tras esto, se escribe el código en sI, en el cual generaremos una tabla HTM Lcon los
:latos.
<Mml>
<body>
<hl>Listado de soeios</hl>
<table
<tP
<th><b>Nro.</b></th>
<th><b>Nombre</b></th>
7, XMl
11
11
ProgromaÓón COI Softw.ore libre
<th><b>Tipo</b></th>
</tr>
<xsl:for-each
,><>
<td><xsl:value-of select_nnumecou/></td>
<td><xal:value-of select_nnombreN!></td>
<td><xsl:value-of select_utipou/></td>
<ttr>
</xsl:for-each>
</table>
</body>
</hbn1>
<h<sl: template>
</xsl:stylesheet>
Como podemos observar, vamos embebiendo las etiquetas HTML; empleamos el
iterador for eaeh para tomar cada elemento del fichero XML; y situamos en cada
punto de la tabla uno de los campos elegidos.
Transformando El dOCUmEnto con Gambas
Hasta aqul, lo que tenemos es un documento XML y una plantilla XSLT, pero ahora
necesitamos un motor que realice la conversión. Para ello guardaremos el fichero
con datos en nuestra carpeta personal como socios.xmJ, y la plantilla corno sodos.xsl.
Creamos un nuevo proyecto de consola llamado TransformaXSLT, con un único
módulo modMain y una referencia al componente gb.xml.xsit.
El código será tan simple como éste:
, Gambas modula file
PUBLIC SUB Hain()
OIM DocUlOOnto AS NEW XmlDocUlOOnt
........ , ....._

DIM Plantilh AS KEM x.1.DocuaIeI:lt.
DIM ReIu.lUdo AS
" '"/socios.Dl1W)
Plant.illa.Open(User.Home "
Resultado - Plant.illa)
)ITl() indicamos anteriormente, la clase XmlDocummI carga y vrrifica un documento
'ofL En este caso cargamos dos documentos: el primero. llamado
)Ct1J11alto, contiene los datos de los socios; d segundo, Plantilla, es la hoja X5lI que
dica cómo transformarla HTML. La única clase que aporta componente
gb.xmLxslr, llamada XSLT, es estática y dispone de un
único método Transform, al cual pasamos como pará-
metros el documento y la plantilla, y devuelve un
11
.istado de socios
1.... ""'_!>no Tipo
llJJuonl,..AgwIat
13l!iSO_O. Tloorn RoquIor
MoIAIbertoN-:-Parn
Figuro l. Rewllodo cito lo
pógino ""¡"'Iidu.
documento nuevo con el formato indicado, en este
caso una página wd>. Escribimos dicha página en un
fichero en nueslra carpeta personal, ysalimos. Si con-
sultarnos ("on el na'Tgador la página obtenida,
mos un como d que muestra en la figu-
ra de la izqukrda.
7. 4 Acerca de XML-RPC
futura versión Gambas 2, dispondrá también de un componente XML-RI'C. Estas
las se refieren al uso de XML como sistema para comunicar dos procesos en dos
¡quinas diferentes. XML·RPC es un subconjunto de XML que define un lengua-
:>ara llamar a procesos remotos.
11
Progromoción viwol con 5ohwore Libre
Un servidor XML-RPC acepta llamadas remotas a sus métodos. El proceso es muy
similar a llamar a una función local dentro de un programa: el diente llama a la fun-
ción pasando unos parámetros (números enteros, cadenas, estructuras de datos... );
y el servidor procrsa la llamada y devuen'( al dicnte un resultado. que también Sttli
una cadena, número. fecha, etc.
El componente XML-RPC aportará varias facilidades para implementar estos pro-
' ~ L
En el lado servidor dispondrá de un parser, en el cual definiremos los nombres de los
métodos que se aceptarán, así como la correspondencia entre estos yotros locales dd
programa servidor. Dt este modo, tan sólo hay que pasar la petición del cliente al ptlr-
ser, el cual se encargará de verificar el número ytipo de los parámetros, ydevolver un
error al cliente, Ollamar a la función local y devolver el resultado al diente.
El servidor podrá funcionar en solitario, implementando un pequeño servicio web
para atender las pt'ticiones, Obien funcionar de modo controlado por la aplicación
servidora, con el fin de implementar CGIs que se sirvan desde Apache, por ejemplo.
En la parte cliente es posible definir la URL del servidor yla forma de Lada méuxlo.
Igualmente podrá actuar en solitario. solicitando mediante una pttición web la Ua-
macla al servidor. Tambil!n se puede crear el documento XML de la pttición, d c j a n ~
do a la aplicación e! diseño de! transporte y re«pción de los datos con e! servidor.
• • a. I Lenguajes
orientados a objetos y
herencia
Ya hemos visto una breve introducción al mundo de la programación
orientada a objetO$. Podemos dfi:ir que un objeto es una herramienta, por ejem-
plo, un túnel de lavado. La clase son 10$ planos de e$<I herramienta, en los cuales
están d ~ r ¡ t o s los distintos cepillos giratorios. los conductos de agua y dClttgnltc,
los secadores de aire caliente, los distintos sensores, el proceso aulom:hico paso a
paso desdC' la entrada del coche hasta su salida, ele.
Cuando creamos un objeto, el sistema nos devuelve una herramienta, en este caso,
un túnel de lavado dispuesto para funcionar, que se ha creado a partir de los planos
que nosotros hablamos escrito en la dase.
-
11
11
Progromoción viwcl COl'l Software übre
Ahora bien, supongamos que romo vnulcdores de túneles de lavado mIlO·
VJT y anadir una fast de encerado a nuC'Slro túnel. Vendn-emos máquinas baratas sin
encnado y más con esta funcionalidad añadWia. La primna opción
PO]')C(Y manos a La obra ron nuevos planos desde Cm), pero esto es costoso en tiem_
po y dinero. lo mejor .seria tomar los planos ya existentes y, a partir de ellos, añadir
la nueva función.
En esto consiste precisamente la herencia: partimos de una clase ya escrita, pro-
bablemenle grande y con mucha funcionalidad, y a partir de ella creamos otra clase
(otros planos) que tiene el mismo rendimienlo del original, más nuevas funcio_
nes que añadimos, la cual hertlla, de ahl viene el la funcionalidad de su
clase padre.
Además de añadir nuevas funcionalidades, podremos modificar el como
portamiento de las ya existentes para adaptarlas a la nueva nlflquina a crear, por
ejemplo, los l:q'iIlos del túne! de lavado con cera tendrán que.ser de un material que
no se disuelva con los productos químicos que componen nuestra cera.
En resumen, 'o'On'lOS a explicar cómo crear clases que prcMen&n de otras, que se com-
partan en pritMra instonc:io coma la original y que oñoden IlU8YOS Ivncionalidades a
modifican algunas de las existenles, eliminando osi la necesidad de escribir las mIS-
mos lineas de código una y airo <tez.
••••• S. 2 Conceptos necesarios
00000 La daSE padre
Empecemos creando los planos de la máquina original, es decir, creemos una clase
plldre. Vamos a escribir una clase a partir de la cual crearemos objelos. Dichos obje·
lOS almacenan varios números reales y, una vez inlroducidos, nos devuelve la media
de todos ellos.
<\hora, vamos a crear un nuevo proyecto de consola, lo llamamos EstudioHerencia
,dentro de él un módulo inicio llamado modMaj/J, que nos servirá pam las
]ruebas.
creamos también una clase, llamada CIsCalcllIQ, en la que escribiremos el
:6digo principal a estudiar.
f"' trot'''! .. I<>Ok 1

[> 11 • '¡ji Mi
l
I •
• (lhludioHeflnc¡"
- adanes
I 'B!IlllIIl!III
-6_·
L

ODa!.
liJ O J, ibm·.,,.., HJE!l
. 6-... -.d<l te ti te

liJ 00 J, •., ,.., E!I E!ll!!! E!I 1M
. 6_a. d»< lit.
Figuro l. Proyedo nuevo de Estv<lioHerencio.
Dentro de ClsCalculo escribiremos el código necesario: una matriz pri-
lada de números reales, donde añadimos cada uno de los números a calcular y
:uatro métodos: el primero, _New, es el constructor que sirve para inicializar la
natriz; el segundo, _Free, libera la matriz al destruir el objeto; el tercero, Add,
lñade un nuevo valor a la serie; y el cuarlO, Average, calcula la media aritmética
le los números almacenados:
, class file
PUBLIC _Numbers AS Float[ J
PI1BLIC SUB _new()
Numbers - NEW Floatl]
8. Hei-encio
11

Programación visual con Software Libre
PUBLIC SUB free()
_Numbers.Clear()
Numbers=NULL
END
PUBLIC SUB Add(Vl AS Float)
Numbers.Add(Vl)
END
PUBLIC FUNCTION Average () AS Float
DIM Nm AS Float
DIM vl AS Float
IF Numbers.Count - O TREN RETURN O
FOR EACH Vl IN Numbers
Nm += Vl
NEXT
RETURN Nm / Numbers . Count
END
A la hora de realizar operaciones matemáticas, que la división por cero no está per-
mitida, hemos de proveer un valor por defecto para ese caso o generar un error en
tiempo de ejecución si procede.
Ahora escribimos algo de código adicional para probar nuestra clase, dentro de
modMain. Nos limitamos a crear un objeto a partir de nuestra clase, introducir tres
valores y mostrar en la consola la media de esos tres números:
PUBLIC SUB Main()
DIM Calculo AS NEW ClsCalculo
Calculo.Add(l2.5)
Calculo.Add(23.8)
Calculo.Add(7.5)
PRINT Calculo.Average()
END
Al ejecutarlo, obtendremos el valor 14.6 si todo fue bien.

un

Figura 2. Ejemplo de motriz Numbers.
PRINT • EO Average
e Numbers
Calculo .
....11I'
Observemos también que nuestra
matriz tiene un nombre algo curio-
so Numbers. La matriz ha de ser
pública porque más tarde la emple-
aremos en la clase hija: si fuera pri-
vada, quedaría restringida al ámbi-
to de la clase original y no podríamos usarla desde las clases hijas.
Ahora bien, si hubiésemos llamado a la matriz simplemente Numbers, el progra-
mador vería esta variable desde el sistema de autocompletado de código.
las clases hijas de otra clase no pueden emplear las funciones, propiedades o varia-
bles privadas de la clase padre.
8. Herencia

Sin embargo. los métodos públicos que
comienzan por el signo de subrayado
no se muestran nul1Cl en el sistema &
autocomplelado ni en el sistema de Figura 3. Vuiiuble. públiw> no ....
ayuda, cuando creamos componentes.
Puesto que en Gambas no uiste el concepto de C++ y otros lk propiedad.
variable o función ProTegida (accesiblt sólo desde la clase ySUS clases hijas), esta fun-
cionalidad nos permite declarar variables públicas no visibles desde el código princi.
pOlI, manteniendo así una interfaz más coherente con nuestros propósilos.
los nombres d. va' jable., J!fopiedodes o fuociones que cOmienzon con un .vbla-
yodo, na se muestron ni en el si.terno d. oUlo<:omplelodo. ni en el d. oY\ldo de
Gomoos
NOTA PARA PROGRAMADORES DE C++
En Gomba••"isten prop,edades. método. y variable. privados o público., pero no
protegido.
e o o o o La clase hIJa. Palabra cIaw: NiERIT5
Supongamos ahora que deseamos tener una nueva clase que se comporte como la
inicial, pero tenga una propiedad adicional, de sólo lectura, que nos devuelve el
número de elementos que hemos almacenado.
Creamnos, cnloncn, una dast llamada ClsCa1culol, en la cual inlroducimnos
al inicio la palabra claVl' lNHERlTSseguida del de la clase padrr (vtT Figura 4).
Esto es todo lo necesario para tener una clase que hereda todas las propiedades de su
clase padrt. Probemos a modificar el código del método l\1ainO de modo que cree-
mos un objt1o de la en lugar de la original
,.. tr_,
o ... "'c:r .ecJ" ..
"'"_';;>M,I.

-.-

-.-
I .(J-
LOOO<.
"!:!I",'!'
-- ...... ,. ""
....." ........ "
.,. ,-,,.,... _"".,,,,.
..,,,,.. _,,,."
..,••, ,».••
,."., "."
..,'" ..,,,,........."
1iI0 J _ ...... ,..¡,,¡.,¡ ·'I,' .. '!!"';>
.-.. ,loo, '''o
,..." ... n,,,,,,\.
Figuro 4. N..eva dOl<! ClsColculo2.
PUBLIC SUB Maill ()
DrH Calculo AS NEW Clscalculo2
Calculo.Add(12.5)
Calculo.Add(23.8)
Calculo.Add(7.5)
PRINT
END
Si ejecutamos ahora el programa, observaremos que el resultado 14.6 es exactamente
el mismo: la nueva clase ya dispone de todos los métodos, propiedades y eventos de
la original, sin necesidad de escribir el código que los implemente.
Para escribir uno ckJse que hereda las caroclerí5ticas de uno clase podre, tecleamos
INHERITS seguido del nombre de kJ clase padre. al inicio del cód;go de la nuevo clase'
Gambas class file
INHERITS ClsCalculo
8. Herencio
11
ProgromoÓón "islIOl con Software libre
NOTA PARA PROGRAMADORES DE C++
En Gambas cedo clase hija tiene uno 5010 clase podre, no exi,t" el concepto de heren-
cia múltiple.
o O O O O Extendiendo funcionalidades. Palabra clave SUPER
La nueva clase CIsCa/culQ tiene poco interés por ahora: hace 10 mismo que la origi.
naL Añadamos entonces en la clase hija la nueva propiedad que nos devuelve el
número de elementos almacenados:
, Gambas class file
INHERITS ClsCalculo
PROPERTY READ Count AS Integer
PRIVAn: FUNCTIOH Count_Read() AS Integer
RETURN SUPER. Nurabers.Ccnmt
Estamos empleando una nueva palabra clave por primera vez, SUPER. Sabemos que
cuando nos referimos a un objeto podemos utilizar, bien el nombre del objeto, o
bien la palabra clave ME cuando nos referimos al objeto actual dentro de la propia
clase. Pues bien, en este caso, la matriz ~ u m b e r s no se encuentra dentro de la clase
C/sCaJculo2, sino dentro de la clase padre ClsCakulo.
Con la palabra clave SUPER no nos referimos al objeto actual, sino al padre del obje-
to actual.
Escribamos ahora el código de la función MainO para aprovechar la nueva caraete·
rística de nuestra clase hija:
PUBLIC St18 Hain ()
DrM Calculo AS NEW ClsCalculo2
Calculo.Add(12.5)
Calculo.Add(23.8)
Calculo.Add(7.5)
PRINT HElementos: W & Calculo.Count & H _ Media: H &

Como es fácil adivinar, el resultado de la ejecución es:
Elementos: 3 - Media: 14.6.
o O O O O Modificando funcionalidadES
Hasta ahora tenemos dos clases, una de las cuales aporta una propiedad adicional
CoI/lit, y sigue siendo poco útil ya que po<!ríamos, sin más, haber añadido esa fun-
cionalidad a la clase original ClsClI/crlio, evitándonos el mantenimiento de dos clases
diferentes. Vamos ahora a explorar la verdadera potencia del concepto de Herenci(l,
y es la posibilidad de reemplazar los metodos y propiedades originales por nuevas
implementaciones que den lugar a resultados distintos: en este caso, la nueva clase,
cuando el método Average sea llamado, borrará lodos los elementos de la matriz para
quedarse en hlanco. De esta forma, tendremos dos clases con diferente funcionalidad
partiendo de llna base común: los ohjetos de la clase padre acumulan números sin
fin, mientras que en la segunda cada llamada a Average los limpia y comiel17A1 de cero.
la clase ChÚllculo2 queda ahora como sigue:
, Gambas class file
INHERITS ClsCalculo
8. HerenciCl
11
Programación visual con Soft.MJre libre
PROPERTY READ Count. AS Int.eqer
PRIVATE FUNCTION Count_ReadO AS Int.eqer
RE'IVRN SOPeR. Numbers.Count.
END
PUBLIC FUNCTION Average() AS Float
DIM Nm AS Float
DIM Vl AS Float
DIH Total AS Inteqer
IF SUPER. Numbers.Count - O TREN RE'IVRN O
FOR EACH Vl IN SUPER. Numbers
Nm .... Vl
Total .... 1
NEXT
SUPER._Numbers.Clear()
RETURN Nm I Total
Ahora existe un método Average dentro de C/sColcuI02, y e,te método reemplaz.o en
lo elaS<'! hi;o el método Average del padre. Cuando llamemos 01 método Average de
un objeto de la eloS<'! CI.Colcul02, el intérprete no 1I0moró a la función original del
padre, 5ino a la implementación de k1 elose hi¡o.
Mo<!ificamos la función MainO de pruebas con este nuevo código para comprobar
el resultado:
PUBLlC SUS Main ( )
DIM caleulo AS NEH ClsC8.leulo2
calculo.Add(12.5)
caleulo.Add(2l.8)
Caleulo.Add(7.5)
PRrNT -Eleaentos: - caleulo.Covnt • - Media: •
C8.lcuIO.AYerltgCl( )
Caleulo.Add(17.5)
C8.lculo.Add(ll.8)
PRINT • calculo.Covnt - - Media: -
Calculo.Averaqe()
Como resultado, obtenemos en consola dos líneas que muestran el funcionamien-
lO de la nueva clase:
Blementos: l - Media: 14.6
Elementos: 2 - Media: 24.65
Si en la primera Unea de MainO definimos ahora que el objeto Calculo pt'rtenece a
b clase JKldre OsCalculo, eliminarnos el uso de CoUllt, que no existe en el padre. y
yolvemos a ejecutar el program¡¡, ob5ttv;¡remos claramente la diferencia:
8.

11
Programación viwol con Software Libre
PUBLIC SUB MainO
DtM Calculo AS NEW Clscalculo
Calculo.Add(l2.5)
Calculo.Add(23.8)
Calculo.Add(7.5)
PRINT "Media: u & Calculo.Average()
Calculo.Add(l7.5)
Calculo.Add(3l.8)
PRINT "Media: u & Calculo .Average ()
En este caso, sc calcula primero la media de los tTes primeros números y luego la
media de los cinco númrros:
Media: 14.6
Media: 18.62
Podrrnos aprovrcharnos más de la herencia, rmplrando la palabra SUPER que vimos
antrrionnente. La clase original ClsCalclllo ya tenia el código necesario para calcu-
lar la media, yen la clase hija CIsCn/CII/o2 tan sólo necesitamos borrar los clrmen-
tos de la matriz una vez calculada la media.
Podrmos, entonces, modificar el código de la nueva función, Average, para que llame a
la original y después borre los elementos, ahorrando, como siempre, tiempo y código:
, Gambas class file
INHERITS Clscalculo
PROPUtit lU:AD COunt AS Illtege.r
END
PUBLIC I'11NC'1'ION AVBraqe() AS Ploat
DIM tia AS ploat
lb - SUl'Ul.Average()
SUPB:R. _ Nwllbenl. Clea.>: ( )
END
La nueva función Average ahora se limita a llamar a la original, implememada en la
clase padre, a almacenar ese valor, borrar los elementos de la matriz ydevolver el valor.
REEmplazando metodos ESPEdaks: _NEw Y_FrEE
Vamos a crear una nueva clase hija de ClsCDlcufo, que SC' comporte como la original,
xro que, en este caso, en el momento de i n i c i a l i z a ~ un objeto de la clase, almace-
ne unos valores. Pongamos de ejemplo una toma de
muestras de temperatura.
Los objetos, al inicializarse, pueden tomar los valores de
temperaturas de la semana anterior de forma automáti-
ca para que, despul!s, el programador introduzca los de
la semana en curso y SC' obtenga la media de la quincena.
Para ello creamos la clase C/sCalculoJ, con este código:
B. Herencio

11
Programación Yiwcl ton Software Libre
• Gambas el••• file
INHERI'rS Clacalculo
SUPER.Add(12. 5)
SUPER.Add.( 15. J)
SUPER.Add.( 18. fo)
SUPER.Add.(19.12)
SUPER.Add(21.15)
SUPER.Add (20. 4)
SUPER.Add(19.5)
mm
Igualmente escribimos y ejecutamos el código de MainO para comprobar d
resultado:
PUBLIC SUB MainO
DIM calculo AS MSW C15Ca1culoJ
calculo.Add(29.2)
PRUft' ~ M e d . i . : .. 6 calculo.Average()
El resultado dt la ejecución es:
Media: 19.&4625
Como era de esperar, por lo explicado anteriormente, se ha ejecutado el método _NewO
de nuestra clase hija. Ahora bien, en este método tan sólo anadimos elementoS,
pero no inicializamos la matriz, por lo que de haberse comportado el intérprete como
en 105 casos anteriores, habríamos obtenido un error en tiempo de ejecución, al tener
en el inicio la matriz con valor Nuli.
Lo que ha ocurrido en realidad, es que al reemplazar el método especial_NewO, el
intérprete ejecuta siempre el método original de la clase padre y luego la nueva imple-
mentación del hijo.
El método especial _New(} no se reemplazo en los clases hijas como en el resto de
métodos a propiedades, en su lugar se llamo siempre al método original_New{} del
padre poro que inicialice todo lo necesario y, después, si existe, se llamo 01 método
_New(} de lo dose hiio. De este modo, el obieto siempre esló listo e inicializado cuon-
do se comienzo o trobo¡or con él.
Añadamos ahora un destructor _FreeO personalizado para nuestra clase heredera,
en el cual indicamos el valor de la variable _Numbers:
, Gambas class file
INHERITS Clscalculo
PUBLIC SUB _New()
SUPER.Add(12.5)
SUPER.Add(15.3)
SUPER.Add( 18.4)
SUPER.Add(19.12)
SUPER.Add(21.15)
SUPER.Add (20.4)
SUPER.Add( 19.5)
8. Herem;io
11

=
if SUPER. Numb6rl-NULL then print NNULO#
END
La ejecudón del programa da ahora como resultado lo que vemos a continua-
ción:
Med.ia: 19.4.l625
""'"
Con esto se demucstra que: d como en el caso dI' ha llamado pri-
mero aJ rnl!todo _Fru de: la original. para llamar luq;o al mllodo _Fru de: la
clase hijn.
Si n05 ha surgido olguno dudo respecto 01 orden de ejecución de algunos Juncia..
nei, recordemos que siempre podremol ejecutor .1 código o poso poro com-
probarlo.
limitacionEs
La principal limitación de: la herencia en Gambas, es que: una clase: no puede ser
hija de: otra que, a su vez. era hija de una tercera.
En otras palabras, sólo hay un nivel de huc:ncia y c:n nuestros ejemplos antcriOTCS
no podriamos crear una ClsCafculo4 que: provinier.l de 05Caku/02o ClsCalcu1oJ,
puesto que: lslas están empleando ya la palabra clave lNHERlTS para indicar qut
heredan [as propiedades de ClsCaJculo.
Esto implica, por ejemplo, que no podemos crear clases que sean herederas de Form,
pues la clase fimn proviene de Window.
••••• 8. 3 Crear un nuevo control con Gambas
::J o o o o PlantEando el código
Vamos a examinar la posibilidad de crear nuevos controles gráficos directamente
desde Gambas, aprovechando el concepto de herencia.
Crear controles nuevos programados en Gambas aporta dos ventajas funda·
mentales: su desarrollo es rápido al trabajar en un lenguaje de alto nivel, y el mismo
:ódigo sirve tanto si programamos con gb.grk, como si lo hacemos con gb.qr,
Jhorrándonos dos implementaciones para un mismo control con diferentes
roo/kirs.
[.as desventajas son una velocidad menor del código al ser interpretado, cuestión
lue tendrá más o menos importancia según la función del nuevo control, asi como
nenor flexibilidad a la hora de moldear el conlrol, dado que trabajaremos sobre los
:ontro[es previamente aportados con Gambas y no sobre un loolkit para C o C++
:omo GTK+ OQT, ni a bajo nivel con X-Windows. 11
:>ara crear un control con Gambas, tenemos que partir de uno que exista ya. Si esta-
nos acostumbrados a trabajar con otros entornos RAD de BASIC o C++, nos sen!
¡¡miliar partir de un control pltlfltil/n con unas propiedades y mflodos básicos para
:rear uno nuevo.
1mcOl\lJoIes creados con Gombos han de partir de un conrrol yo Uiilenfe y crocble,
O iU vez. No M puede portir dj'ecIomente de lo doM base Coolrol, .5 dokir, un ce»
¡.oI creodo con INHERrrs CONTROL no li.oOCÍOllOlÓ, yo que C"'*'" no 6e..- una repte--
senloción grólieo, sino que tl5 simplemente lo boMl q.... define lo. propiedodes, fIléb.
dos y eventos m;nimo. paro Q!rO. controle. rocles (Lobel, &1ton...J.
Juestro nuevo conlrol será una etiqueta a la que llamaremos ColorLAbt!l. similar al
abt!l, pero que muestra el texto con un gradiente de color.
8_ Herencia
Para dibujar texto en diferentes colores, trazaremos cada letra por separado, desde
un color inicial Colorl hasta un color final ColorZ, utilizando un algoritmo algo rudi-
mentario: tomamos la diferencia de valor de los dos colores y vamos aumentando
el valor del color actual por cada nueva letra que dibujamos.
Con el fin de trazar cada letra por separado, tendremos que usar la dase Dmw sobre
un control base que será DmwingArclJ.
ImpJementadon basica
Creamos un nuevo proyecto gráfico, que llamaremos
ColorLabt:l, para nuestras pruebas. Dentro de él, origi-
naremos un formulario FMoio, lambirn para nuestr.u
pruebas. asl como una clase llamada ColorlAbt:l para
implementar el control. Al igual que una nor-
mal, definiremos una propiedad Text con el texto amos-
t> 11 • 'li' ñ 1'1 •
: ltCOloo1. ¡
·-eo. ..


!'.'_ I
,a_
'a_
.. figura 6.
11
trar, y añadiremos dos propiedades nuevas Colorl y proyecto gráfico
Color2 que contienen d valor inki.al y final del gradiente. Cobrf.obe/.
Para manejar las tres propiedades. tendremos tres varia-
privadas: hTexl para el texto. hColorl para el primer color y hColor2 para el
segundo color.
Empezamos. pues. a escribir el código de la dase:
, Gambas clall file
INHERITS Dr_ingArel
PRIVA'1'8 h'lert AS String
PIUVATZ bColorl AS Integer
PRIV1d'Z bColor2 AS Integer
PROPERrI Text AS string
PROPEKI'T Colorl AS Inteqer
PROPERrJ' Color2 AS Inteqer
Implementar las funciones de lectura de las tres propiedades es trivial, basta con
devolver los valores de nuestras variables privadas (recordemos que estamos escri-
biendo el código siempre dentro de la clase ColorlAbd):
RE1URN bColor1
PRIVAn: ftlNCTION Color2_Read() AS Integer
RETURN hColor2
END
RE1URN hTezt
En cuanto a las funciones de escritura, hemos de asignar d valor que d usuario pasa
a nuestras propiedades, y hemos de actualizar el conlrol cada vez que una de ellas
cambia, tarea que realizaremos en una funciÓn llamada RedrawO, aún por definir:
hTest - VI
Redraw()

El
Programación visual COl'l Sohwore Ubre
PRIVATE SUB Colorl_Write(Vl AS Integer)
hColorl - VI
Redraw()
END
PRIVATE SUB Color2_Write(Vl AS Integer)
hColor2 - VI
Re<h'aw( )
END
Llega el punto de implementar RedrawO, para 10 ¡;ual recorreremos cará<:ter por
carácter la cadena almacenada en la variable hText e iremos representando letra por
letra usando los distintos colores del gradiente. Para calcular la posición en el eje X
de cada letra, nos servimos del método Font.WidthO que determina el ancho de
cada letra con la fuente actual del control:
PRIVATE SUB Redraw()
PIM xPos AS Integer
DIM B\lcle AS Integer
DIM hCOlor AS Ioteger
DIM bOiff AS Integer
ME.Clear
hColor • hColorl
IF Len(hTaxt) TREN bOiff - (hColor2 - hColorl) I
Len(hText)
Draw.Begin(ME)
POR Bucle - 1 Te
Dcaw.For8Coloc - bColoc
orav.'l'est(Micl(bTest, Bucle, 1), ltPos, O)
ltPos - ltPos ... SUPER."ooLNiclth(Mid(bTert, Bucl., 1»
bColoc • bColoc ... bOiff
><En
Dcaw.End()
Finalmente, nos interesa que el control se encargue por sr mismo del redibujado de
la ventana. Por defecto, todo lo dibujado sobre un DrawillgArell desaparece si la ven·
tana se oculta tras otra ventana o se minimiu. Para evitarlo, utilizaremos la propie-
dad Cached de DmwillgArell, que se encarga de mantener un buffer y redibujar las
parles expuestas al usuario del control:
SUPER.caebed - ftl.IE

• • •
· - .
• • •
Probemos ahora el control. Nuestro formulario
FMailf tendri unas dimensiolK$de 225x240 pIxt-
les ycontendr.i un botón Uamado BlllPmeba con
el texto Prueba.
.. f'9uro 7. Textodepn.¡ebo d>re El código del formulario consiste en crear un
el formulorio fMoin. control Colorlabel en tiempo de ejecución,
situándolo en el formulario con un texto de ejem-
plo ydos colores definidos para e1gradiente:
8. Herencio
ProgramOClón visual con Software libre
PUBLIC SUB BtnPrueba_Click()
DIM hLabel AS colorLabel
hLabel - NEW ColorLabel(ME)
hLabel.Font.Size - 18
hLabel.Move(O, 0, HE.Width, 100)
hLabel.Colorl - Color.Blua
hLabel.Color2 - Color.DarkBlue
bLabel.Text - NHola desde el
11
Al ejecular el programa y pulsar el botón, podremos ver ya nuestro control en fun-
cionamiento. Ha sido una tarea rápida y sencilla, si bien se puede depurar ba51anle
el código del control. Por ejemplo, este control tendrá problemas con caracteres con
código ASCI] mayor al 127, ya que en la codificación de Gambas (UTF-8) ocupan
más de un byte, rompiendo el algoritmo que recoge el texto lelra por letra.
funciO/lClmiento.
Figura 8. Conlroj CoIorl.abelen
-
[
Se puede solucionar convirtiendo la cadena a una codificación que emplee siempre
un byte por letra (por ejemplo, 150-8859-1) Y
reconvertirlo a UTF-S a la hora de representar-
lo. También podríamos incluir una propiedad
para alinear el texto a derecha, izquierda o cen-
tro, asf como mejorar el algoritmo para obtener
el gradiente, separando los componentes RGB de
cada color, tareas todas ellas que dejamos si esta-
mos interesados en practicar.
Esle nuevo control "" puede reulilizar en todos los programas qve diwñemos aiiodiendc
la Colorlobel al praye<.:to.
8. 4 Nuevos componentes con Gambas
Cuandoabrimos bs de un proyteto ypulsamos la pestafQ Componentes,
observamos los módulos adicionales podemos emplear en un programa escri-
to con Gambas, los cuales aportan nuevas funcionalidades.
Desde Gambas, tenemos tambitn la posibilidad de crear nuevos COmponentes.
Estos pueden ser de cualquier i"dole, aunque en el próximo ejemplo será un com-
ponellle que aporta un control adicional: el CO/orLabel que creamos en el aparla_
do anterior.
Si bien o er_ oqui un r--..o OJO,opoi ...... grófico, los C:Qllopoillit\le$ ie a
opciItoI ..........,;1$ daMK que no Iieoen por "'" e$Iof JWlocioo"",,*,$ can lo inIwfoz grófico.
$GtMt'" aPropen>es
show lIfIIy Compo<H!nu U$.d in
ti
o gIIc..........n
O ,p.coypt
O gII,db
O gII-cM0u9
O gil ......
0 .._
8 gII.p
0 ..-
gb
CofT'pn..... libt....,
MOS.OES crypb"Ig Compo<H!rd
O........
GMT"oNs """""....., r..lI-
GMnba$ ..pru_••_«
somec__
Gr..p-.c", GTlC. tOCll<il co, __
__Ü" ,0,_...1t
.,.." I
Figura 9. Compooenle$ del proyeclo.
Programación " i ~ u a l con Software übre
o O O O O PrEparación del código. Palabra clave EXPORT
Dentro de un programa Gambas, tendremos diversos módulos, clases y formularios.
Implementar un control en Gambas supone ran sólo crear un programa que expor"
tará algunas de sus clases. Preparar un programa Gambas para ser un componente,
simplemente implica definir qué clases serán visibles y cuáles no.
Para indicar que una clase será visible desde el programa principal, se usa la pala-
bra clave EXPORT al principio de la misma antes del resto del código. Por tanto,
en nuestro programa ColorLabel indicamos esta palabra clave al inicio de la clase
ColorLabel:
, Gambas class file
EXroRT
INHERITS DrawingArea
PRIVATE hText AS String
Ahora es necesario compilar el programa para tener un ejecutable con la nueva clase
exportada.
o OOOO Archivos necesarios. ubicaciones
Cada componente Gambas necesita, en primer lugar, del programa en sí, que ten-
drá siempre como nombre gb.x.gambas, donde x será un nombre que nosotros
elijamos.
Apartir de ahora, vamos a llamar a nuestro nuevo componente controles y, por tanto,
el nombre del componente dentro del sistema de archivos será gb.comroles.gambll5.
Es necesaria también una ubicación específica para dicho archivo. Todos los com-
ponentes de Gambas han de estar situados en una carpeta que, salvo que hayamos
compilado Gambas desde los fuentes empleando una opción - -prefu: específica, será
hml/iblgambas2.
Si hemos compilodo Gombos usando uno opción· -prefix distinto de lusr en el Kript
configure (par tendremos que buKor los rulos in<lkooos" partir
de lo que seleccionomOI. oomo lusrllocolll,'blgombos2 en este cosa.
O:Jpiaremos nuestro ejecutable a dicha carpeta, para lo cual, desde la consola y como
mor, entraremos en la carpeta del proyecto y copiaremos el ejecutable con el nuevo
nombre (por supuesto, si lo preferimos, podemos hacerlo con Konqueror o Nautilus):
cp ColorLabel.gambas lusr/lib/gambas2/gb.controles.gambas
los componentes en Gambas necesitan también dc un archivo con extensión .com-
ponent para ser reconocidos como tales. Vamos a crear este archivo a mano con cual-
quier editor. Nosotros vamos a usar gedil. pero puede ser cualquiera (recordemos
que debemos ser root):
gedit lusr/lib/gambas2/gb.controles.camponent
El contt"nido dI." dicho fichero incluye varios parámetros que se exponen a conti-
nuación:
(Component]
Key-gb.controles
Name·Additional controls
Author-Daniel campos
Group-Adicionales
Controls"ColorLabel
Require-gb.qt
...a c1avt" [Component] siempre debe estar al inicio de-! archivo. En el valor Kcy hay
¡Ut" Situar el nombre dd componente sin extensión (en este caso, el fichero gb.com-
lQl1em.gambas que hemos copiado, pero sin J:¡ extensión glllll/¡(lS). En la clave Name
8. Herencio
11
11
se indica el nombre del componente que aparecerá luego como descripción a la hora
de elegir los componentes de un proyecto. En Author situamos el nombre del autor
del componente.
Después vienen una serie de claves opcionales: Group sólo se usa si queremos afla-
dir controles gráficos y supone la pestaña de controles donde queremos que se 31'i3da
el nuevo. Lo mismo se aplica para Controls, que se referirá a cada uno de los con-
troles que queremos que aparezcan en dicha pestana. Requirc se utiliza si nuestro
componente depende de otros, en este caso, de gb.qt. Si hubiéramos compilado el
proyecto para gb.grk, tendría que ser é&ala dependencia indicada.
Una vez creado y guardldo el archivo gb.wlltrole5.wmpouetlt, tenemos finalmente que
copiar dos archivos dentro de /lIsr/sharelgambas2/illfo, que proporcionan informaciÓn
adicional para el intérprete de Gambas.
Dentro de nuestra carpeta del proyecto se han creado también tras dos archi-
vos llamados .list e .info. Si deseamos verlos, recordemos que los archivos que comien-
zan por un punto son ocultos, por tanto, hemos de usar 15 -{l desde la consola o bien
activar la opción de ver archivos ocultos desde Konqueror o Nautilus. Dichos archivos
han de copiarse a su ubicación definitiva con el nombre del componente (en este caso,
gb.controles.info y gb.controles.list):
cp .info /usr/share/gambas2/info/gb.oontroles.info
cp .list /usr/share/gambas2/info/gb.oontroles.list
o O O O O Probando El nuevo componente
Tras estos pasos cerraremos elIDE de Gambas si estaba
abieno y 10 ejecutaremos de nuevo, creando un proyec-
to gráfico llamado MiPrueba en el que añadiremos un
formulario.
Dentro de Proyecto I Propiedades, seleccionaremos la
pestaña de Componentes.
$MiPrueba

,
-l'i-
Cl
ClDala
.. Figuro 10. Formulario
FMoin sobre el
proyecto MiPrveba.
Buscaremos y marcaremos el componente gb.W"fro/es y pulsaremos Aceptar para
tenerlo como dependencia.
.. "'- --- - -- --- "O
Sl.-lIÑ\" c.. , ...... lulI$4d .. fl"IIIKl
0 .._
O ..
O gb.cIebuII
O
0 ..-
O gb_9'k
gb,controles
lC)5,()(S CJ'YlllnO c... "po......

GMntIa 1tebu99,.,
"'prIK'''''' ...._ ...
s...-corc.r....
GrllP'llC" GTK.. tool:ll compoo ......
A"tllors: C.mpo.
Contro'" CoIorl._
Figura 11. Se!IOO6o, del compool8llle gb.conJroIe, como
depe"dencia.
111

-
\
A
.be
lIiI
«
-



-
-
O
=
1::
,
-

.'
'J

- ".:1
L: j
U!

[8]
0
__o
Figuro 12. Pestaña Adicionales de
lo ventona de selección.
Ahora, en la Wnlana de selección de contro-
les aparece una nueva pestaña Adicionales,
tal y como habíamos indicado en ti arc:hi\'U
compolll!llt (Figura 12).
Al situarnos en esta nueva pestaña, aparecen
los controles disponibles. Desgraciadamente,
en este momento no se contempla la posibi-
lidad de que esos controles tengan un icono
propio, por lo que aparecen sin un dibujo
representativo (Figura 13).
Herencio
ProgromoÓón visual con Software libre
No obstante, al situarnos sobre fl con el ratón,
se muestra el botón y el ToolTip indicándonos
el nuevo control.
Figura 13. Ccolroles Adicionales.
Como hacemos con el resto de controles, lo arrastraremos al formulario y lo situa-
remos como deseemos.
• o •
----------------------_.,
11
Figura 14. control Colorl.obell.
Finalmente, en el código del formulario indicamos el texto y los colores de la eti-
queta:
ColorLabell.Font.Size - 16
ColorLabell.Text - uHola desde el componente"
ColorLabell.Colorl • Color.Blue
ColorLabell.Color2 Color.Black
Al ejecutarlo, observamos el resultado. Ya disponemos de un nuevo componente reu-
tilizable en muchos proyectos yque se puede distribuir entre distintos equipos siguien-
do los pasos indicados.
~ - - - - - - - -
Hola desde el componente
- .
Un componente e:.crito en GomOOl es ton ~ un programo que expOflo c1o$es, por
tonlO, se puede depuror fócilmenle hOClendo lo. pruebos cOmO en CUOlquuH otro p<l>
ye<:to para, despOO" distribuí,lo como componente.
8. Herencia
11
• o En realidad, el título Acceso 1I la APl
está lomado de los programadores de Visual
Basic
T
"', en los cuales es muy frecuente realizar llamadas
a funciones externas, alojadas en librerías también externas escri-
tas en lenguaje C. Tal vez, en este caso no sea correcto, dado que Linux
es tan s610 un núcleo yel resto de librerías (incluyendo la estándar de e, glibc)
no son propiamente la AP[ de este sistema operativo, sino campos de utilidades
que se añaden al sistema. Pero, de todas formas, sirve de introducción para el asun-
lo que vamos a tratar.
Un sistema GNU/Linux puede contar con librerías distintas de otro, pero en la prác-
tica siempre vamos a encontrar como mínimo la librería de e (glibc), posiblemen-
te una librería para diseño de interfaces de texto (lIwrses) y, si hay un sistema grá-
fico instalado, las librerías de x ~ Window y otras como glib, gtk+, atk, etc. AJ margen
---
11
Programación visual con Software libre
de éstas, todo sistema suele tener instaladas librerías como lixurl, para acceso a diver-
sos protocolos de red, o libaspell, para corrección ortográfica.
Desde Gambas podemos sacar provecho de las funciones aportadas por estas libre-
rías, declarando funciones externas e indicando la librería en la que se deben bus-
car. El programa aporta, además, ciertos elementos para la gestión de memoria y
punteros. Las Iibrerlas accesibles serán aquellas escritas en lenguaje C, que sigan el
estándar definido (ABl), o bien escritas en otros lenguajes si respetan dicho están-
dar (por ejemplo, escritas con FreePascal). No es posible, en este momento, acceder
a funciones de librerías escritas en C++, al menos de forma directa.
Si bien en sistemas Windows"'" es muy habitual recurrir a este modo de trabajo, hay
que matizar que en Linux muchas tareas se pueden resolver simplemente llamando
a procesos externos, labor más sencilla, por lo general, y menos problemática en la
depuración de los programas. Por tanto, recurrir a la gestión de procesos cuando sea
posible, en lugar de a este sistema, es, en general, una buena idea.
Hay que tener en cuenta que la llamada a funciones externas, tanto desde Gambas
como desde otros lenguajes interpretados (Mono, por ejemplo), requiere un traba-
jo de conversión de tipos, entre otras tareas, lo cual consume un tiempo de proce-
sador. Tratar, pues, de emplear llamadas a funciones con el fin de incrementar la
velocidad del programa, puede no ser una buena idea en todos los casos.
• •• •• 9. I Declarar una función externa
La declaración se debe realizar al principio de una clase o módulo, del mismo modo
que las variables globales. Al principio se declarará la función como PUBLlC o PRI·
VATE, para definir su ámbito, limitado a la clase donde se aloja o a todo el progra-
ma. Por defecto son privadas.
Acontinuación, la palabra clave EXTERN indica que vamos a declarar una función
externa, seguida por su nombre, que será el nativo de la función en la librería.
Hay que tener en cuenta que e si distingue entre mayúsculas y minúsculas y
, por
tanto, tratar de declarar Primf en lugar de printf para la librería glibc, dará como
resultado un error.
Como en el resto de funciones de Gambas, se indicarán los parámetros que reciben
entre paréntesis, y después el tipo de dato devuelto. Opcionalmente, se puede indi-
car al final la librería en que se encuentra la función, así como un alias, o nombre
alternativo, a utilizar desde este programa, para llamar a la función, que se emplea.
rá, por ejemplo, en ciertas funciones cuyo nombre coincide con palabras clave del
lenguaje Gambas. Supongamos la función strcrop de la librería estándar de e, que
$e define rn este lenguaje como:
int strcmp(oonst char *51, const char *52);
La declaración en Gambas será:
EXTERN strcmp(sl AS STRING, s2 AS 5TRING) AS INTEGER IN
ulibc:6
ff
o o o o o Cómo denominar la librería
Tras la palabra clave IN, se presenta entre comillas el nombre de la librería. En prin-
cipio, se puede indicar un nombre simple, como libe o libgstreamer. En ese caso,
Gambas tratará de encontrar la versión más moderna instalada en el sistema. A veces,
sin embargo, puede interesarnos una versión concreta de una librería, en cuyo caso
se renejará indicando el símbolo: tras el nombre y, a continuación, el número de
versión, por ejemplo libgl: J.0.7667 o Ijbc:6.
En sistemas GNUfUnux, dentro de las carpetas /Iib o /usr/lib encontraremos la mayo-
ría de las librerías que hay en nuestro sistema. A partir de esos nombres de archivo,
podemos deducir el nombre de la librería, por ejemplo:
11
/usr/l!b/l!bgl!b-2.0.so.0.600.4
2.0:0.600.4
N
Ulibglib_
9. Acceso a la AP¡
111

Como podemos observar, el número de versión es siempre la serie de números que
se encuentra tras eltexlO .50. en el nombre de archivo, y que todo 10 que viene antes
forma parte del nombre de la librl."ría. En este caso, el valor 2.0 Iras eltexlO libglib-
es parte del nombre y no de la versión. Especificar un número de versión puede ser
problemático (uando se trala de instalar un programa entre diferentes equipos con
distintas distribuciones GNU/Linux instaladas, que pueden tener versiones ligera-
mente diferentes de estas librerias o cambiar tras una actualización del sistema.
Por tanto, hay que aplicar esta característica sólo en casos imprescindibles, o tal vez
emplear el número mayor y dejar el menor y la revisión a elección de Gambas.
Si en un módulo o clase se han de definir varias funciones de una misma librería, no
es necesario especificarla en todas las declaraciones, basta con indicarla como libre-
ría por defecto con la palabra dave LIBRARY y Gambas la empleará en todas las
declaraciones en las cuales no se especifique la librería.
LIBRARY
EXTERN q_utf8_strlen(p AS Strinq, Mx AS Inteqer) AS
Inteqer
EXTERN q_uU8_strup(Buf AS Strinq, Mx AS Inteqer) AS
Pointer
EXTERN qetchar() AS Inteqer IN
Aquí, las dos primeras funciones pertenecen a libglib, y la tercera a libc.
o O O O O El uso dE los alias
Supongamos la función [rec() de la librería estándar de e, que se emplea para libe-
rar memoria asignada, por ejemplo, con malloc(). El problema para dedararla en
Gambas es que ya existe Free como palabra clave reservada, por tanto, tendremos
que indicar un nombre alternativo:
EXTERN FreePointer(ptr AS Pointer) IN EXEC
Ala hora de escribir código Gambas, llamaremos siempre a la función
que internamente Jlamari a la original free de la librería de C.
TIpos de datos
Existe una correspondencia entre los tipos de datos básicos de Gambas y los de C. Hay
que tener cuidado con losfaiscs amigos, un tipo Iougde C, no es un tipo Lollgde Gambas.
sino un tipo Inlega; y un tipojloot de e no es el Floot de Gambas, sino el Sillglt. las
siguientes correspondencias son aplicables a Gambas sobre GNU/Linux J2 bitsllntd.
CORRESPONDENCIA DE DATOS ENTRE C y GAMBAS
e Gamba. e Gamba.
ehor By. long long 10"9
""",
'",",
110o'
Single
inl, long
'0_
JJoobl.
'bo,
El tipo Poinltr de Gambas se emplea para definir un puntero. En Gambas-
GNU/Linux-J2 bits es exactamente igual a Illftger, pero en otras arquite'Cturas podría
cambiar, por lo cual es recomendable utilizar siempre el tipo de dato Pvimer en lugar
de lllfeger para referirse a punteros. El tipo de datos String sólo debe emplearse si la
cadena a pasar como parámetro no va a ser modificada o reasignada por la función
de e, en otro caso debe utilizarse un dato tipo Poinler. Por último indicar que es
posible pasar datos tipo Obj«t, pero no está permitido usar tipos Variallt.
•• 9. 2 Funciones auxiliares
Gambas aporta algunas utilidades para trabajar con llamadas a funciones.
Puntero - Alloe
Integer J )
Tamaño AS Integer 1 , Cantidad AS
9 o lo API_-'- _

Programación visual con Software libre
La función Al10c es similar a la homónima de C: reserva un bloque de
Tammlo'Cmuidlld bytes. En este caso, el intérprete de Gambas lleva, además, un con-
tador de las asignaciones y liberaciones de memoria realizadas, indicando, con un
mensaje de advertencia al final del programa, si quedó memoria sin liberar.
Nueyo Puntero - RealIoc ( Antiguo puntero AS Pointer ,
Tamaño AS Integer , Cantidad AS Integer )
Realloc toma un puntero, previamente asignado con Al/oc o Realloe, y cambia su
tamaño, manteniendo los datos almacenados; devuelve un puntero a la nueva área
de memoria reasignada; y, al igual que Al/oc, mantiene la cuenta de asignaciones/libe-
raciones de memoria.
Free ( Puntero
Free libera un puntero asignado con Al/oc o Realloc, de igual modo que la función
homónima de C, pero manteniendo la cuenta de asignaciones y liberaciones de
memoria.
Muchos librerías aporlon sus funciones propios poro asignar o liberar memoria. Puede
ser nocesorio que empleemos estos funciones en lugor de Al/oc o Free, si así lo requíe-
re el programo, poro monlene. lo coherencio del código y Fvncionolidod de lo librería.
Cadena - Strptr ( puntero AS Pointer )
Cuando una cadena ha de tratarse como un puntero, esta función nos permite obte-
ner una copia como tipo de dato Str;ng, siempre y cuando puntero apunte a una
cadena terminada en carácter \0 (nulo), que es lo habitual cuando se trahaja con C.
Gambas permite escribir y leer en memoria como si fuese otro flujo cualquiera.
Así, utilizando un puntero como parámetro, se pueden utilizar las instrucciones
habituales rn archivos: READ, \VRITE, ele. Entrr otras posibilidades ofrecidas por
esta solución, t5te es el modo actual en el que tl programador puede accwer a los
dalos de una estructura de C.
Está previsto que la versión 2 de Gambas añada el componente gb.api.
Este compollellte 5C está desarrollando para dar soportr directo al trabajo con estruc-
turas de datos y a retrollamadas. que aumentarán y simplificarán las capacidades de
Gambas para manejar librerías externas.
••••• 9, 3 Un ejemplo con Iibaspell
~ 1 1 proporciona UTliI API para corm:ción de texto. permite analiur palabras. irxli-
car si son válidas O no según el diccionario empleado, y ofrecer palabras alternati-
vas a las consideradas incorrectas, entre otras capacidades.
DIsponemos de mós inFormación sobre lioospell en su pagino oficiol:
http://aspell.5OUf'(efoo-ge,net/
Para poder utilizar este código, tendrrmos que instalar Mpell en el sistema, asi como
el diccionario de nuestro idioma.
Por ejemplo, en un sistema gnuLinex 2()()4 en castellano (basado en Debian), los
paquetes instalados en el sistema son:
Qspdl
QspeIl-bill
libtlspell-dev
I15pe/l-es
Iibaspe/ll5
9. Acces,o o lo APl

Programoción visual con Software Libre
---
Crearemos un nuevo proyecto gráfi<:o llamado Aspell,
con un único formulario FMain en el (ual se conten-
cirá un botón llamado BlnChcck, un TextBox llama-
do Txtln, un ListBox llamado Usta y un ProgressBar
llamado Pbar.
Al inicio del código del formulario definirnos las fun-
ciones de libaspell.
LISRAAY "libaspell"
._-
F--

Figura l. Formulario del
proyecto AspeII.

EXTERN AS Pointer
EXTERN AS Palnter, Var AS
String, Value AS String)
EXTERN new_sspell_speller(Cfg AS Painter) AS Painter
EXTERN aspell_error_number(Err AS Palnter) AS Integer
EXTERN aspell_error_message(Err AS Painter) AS
Paloter
EXTERN tO_8spell_speller(Err AS Palnter) AS Palnter
EltTERN aspell_speller_check{Vl AS Painter, V2 AS
String, VJ AS Integer) AS Integer
EXTERN aspell_spelle._suggest(Vl AS Pointer, V2 AS
String, V3 AS Inteqer) AS Pointer
EXTERN aspell_word_list_elements(Vl AS Pointer) AS
Pointer
EXTERN aspell_string_enumeration_next(ptr AS Pointer)
AS Pointer
EXTERN delete_aspell_string_enumeration(ptr AS
Pointer)
EXTERN delete_aspell_config(Cfg AS Pointer)
Al pulsar el botón BtnCheck, realizaremos el proceso de análisis deltexlO introdu-
cido en el cuadro Txtln, para ir mostrando el resultado en la lista.
spell_oonfig AS Pointer
DIH possible_err AS Pointer
DIH spell_checker AS Pointer
DIH suggestions AS Pointer
DIH elemeots AS Pointer
DIH HyStr AS Strinqll
DIH Bucle AS Integer
BufErr AS String
DIM SUllI AS P'loat
DIM hP'tr AS Pointer
DIM sptr AS String
En primer lugar, dividimos el te,;to inlroducido por el usuario en palabras, separa-
das por espacios.
PBar.Value - O
Lista.Clear( )
MyStr - Split(TxtIn.Text,
Sum - 1 I MyStr.Count
Realizamos las primeras llamadas a la libreria libaspel/. Para ello tomamos una con-
figuración por defe<lo y aplicamos dos atributos: el texlO eslará codificado como
lITf-S y se usar.i el diccionario que corre5ponda con el lenguaje del sistema.
Aplicamos la configuración y. de exislir un error (por ejemplo, que el diccionario
no se encuentre disponible), indicamos el mensaje correspondiente:
lpell_config - new_aspell_config()
aspell_ooofig_replace(spell_config.

9 Acceso o lo AA
11

Progromoción con Software libre
aspell_config_replace(spell_config
t


IF aspell_error_number(possible_err) <> O TREN
Message.Error(StrPtr(aspell_error_message
(possible_err)))
""""'"
.,,"
spell_checker - to_aspell_speller(possible_err)
END "
Después entramos en un bucle en el cual se analiza, palabra por palabra, eltex\o
introduddo. En caso de error, se dará una lista de sugerendas, pero si está todo correc-
to, se indicará con un OK.
FOR Suele - O Te MyStr.Count _ 1
PBar.Value - PBar.Value + Sum
MyStr[Bucle] - Trim(MyStr[Buclel)
IF Len(MyStr[Bucle]) > O TREN
IF aspell_speller_check(spell_checker,
MyStr[Buclej, - 1) TREN
1ista.Add("OK -> " & MyStr[Bucle])
ELS'
8ufErr - " ( "
suggestions - aspel1_speller_suggest
MyStr[Bucle], - 1)
e1ements • aspe1l_word_list_elements
(suggestions)
DO MBl:LE TRlJE
hPt.r - aspell_st.riDg_ernaeratiOD_De<tt(el_tS)
l:P bptr - O TREN
BREAK
ELS'
sptr -
lNPOT 'bPtr. sptr
BufErr - BufErr sptr • •
"'" lF
LOOP
BufErr - BufErr &
_> & MyStr(Bucle) & BufErr)
"'" lF
"'" lF
MAZT 0.001
Finalmente liberamos los elementos necesarios empleados en la corrección de texto.
delete_aspell_config(spell_conf!gl
PBar.Value _ 1
••••• 9. 4 Obtener información acerca de la librería
Normalmente, las librerias aportan multitud de constantes ymacros definidas en sus
ficheros de cabecera. Ala hora de trabajar con ellas debemos conocer sus valores, ya
9 Ac;te$O o la AA
11
11
que: no se puede recurrir directamente: a los #indude de C. Veamos este ejemplo, que
utiliza la constante GTILWINDOW_TOPLEVEL:
linclwde <qtk/gtk.h>
int lIlll.in(void.)
{
GtkHindow *viD;
win-gU_wiDdow_Dew(GnC_W'IKDON_TOPLEVEL) ¡
gtk_wldget__how_all(wln)¡
)
Con el fin de conocer el valor de esta constante, o cualquier otra aportada por una
podemos recurrir al menos a (llano métodos:
1. Consultar la documentación de la propia librala, que en este caso (GTK+),
es bastante completa. La podemos encontrar en la siguiente dirección:
hnp:/ldeveloper.gnome.orgldoc/APIf2.0fgtklglk-Standard-Enumefations.
hlml#GtkWindowType.
2. Indicar que GTICWINDOW_TOPLEVEL tiene el valor Ocomo parle de la
enumeración
3. Buscar en los ficheros de cabecera de la tibreria, que se suelen depositar a par-
tir de la ruta !lm/incillde. En el caso que tratamos en el ejemplo, este valor
encuentra en el fichero /usrlirrdlldelgrk-2.0/gtk/gtkerrums.h.
4. CompilaTun pequt"ño programa en e que d ViJ.lor problemitico que
no alcanzamos a averiguar por otros sistemas.
'inelude <gtk/gt,k.b>
Unclude <stdio.b>
void maio(void)
(
)
Podemos ya pasar el pequeño programa a Gambas. Para ello, creamos un programa
de wnsola con un solo módulo mOiiMllill que conlenga este código:
, Gambas module file
EXTERN AS Poioter, Argc AS Pointer)
EXTERN _maio ( )
EXTERN gtk_window_new(WType AS Pointer) AS Poioter
eXTERN gtk_widget_show(wid AS Poioter)
PUBLIC SUll MlIlnO
DIM Win AS Polnt:.er
win - gtk_wiDdow_new(QrX_trINDOW_TOPLEVEL)
gtk_widget_sbow(lfin)

Progromac:i6n viwal CQIl Softwau. Libre
Si lo ejecutamos podemos observar que el resultado es equivalente al del progra-
ma en C.
••••• 9. 5 Resumen
En este momento, Gambas autoriza el acceso a funciones de librerras externas.
La única condición es que sigan el ABI estándar. Las propias instrucciones del pro-
grama permiten reservar y liberar memoria. En el futuro, a travb de gb.llpi (no deta-
llado aqul, pues se encuentra en pleno desarrollo y su interhz puede cambiar), la
gestión de estructuras y retrollamadas será posible.
Pero no se recomienda e:1 uso de esta funcionalidad, salvo que esté plenamente jus-
tificado. Gambas aporla componentes para lareas variadas que cubren buena parle:
de las neusidades que se encuentran en los programas habituales, y su capacidad de:
gestión de procesos uternos lo hace apropiado para casi cualquier tarea. Trabajar
con llamadas a funciones externas puede hacer ti programa más dificil de depurar,
sensible a los cambios en el sistema (actualizaciones de librerlas, cambio de ven;ión
de la distribución... ) y limita la portabilidad del código (por ejemplo, de un sistema
GNU/Linux, donde se desarrolla, a una plataforma freeBSO o, en el futuro, en la
versión \\'indows de Gambas).
MARCAS REGISTRADAS
Los siguientes términos son morcol regi.trodos en Estados Unidos u otros poises:
• el 1,111(1 morco '''9istrodo de Linu. Tarvold•.
• Debion es uno mOfCO registrodo de Software in the Public Intefesl, Inc.
• SUSE es uno morco regiltrodo de SuSE AG.
• Mond'iva e. uno morco registroclo de Mondralesoft SA y """ondrolesoft CorporOlíon.
• GNOME es una morca registrado de lo Fundación GNOME.
• KDE, KDesltop Enviranment, es uno morco registrado de KDE e.V.
• Microsoft, Windows y Visual Bosle son morcas registradas de Micros.oh
• es uno morco registrado de lo Junto de htremoduro.
• Java y todo. 101 nomb<es y lagos basodos en Java 100 morcas regillrodas de Sun
Microsystem., lne.
• UNIX es uno morco registrado de The Open Groop.
• Mazilla y 100 morcas registrados de The Mazillo Orgonization.
• Apple y Macintolh 100 morco. registrados de Apple Compute, Corpa,otion.
OIro. empresas, productos y nombres de servicios pueden ser mOrCaS registrados O
_vicios de otros c:ompoñios.
Apéndice

Comunidad WWW.GAMBAS-ES.ORG

GAMBAS
Gambas Almost Means Basic

Comunidad WWW.GAMBAS-ES.ORG

INFORMACIÓN
Tienes en tus manos el libro COMPLETO de “GAMBAS programación visual con Software Libre” escrito por Daniel Campos y José Luis Redrejo bajo licencia libre. Al libro electrónico original le faltan las páginas 34, 35, 58, 59, 104, 105, 166, 167, 190,
191, 216, 260 y 261. Hemos escaneado e insertado estas páginas faltantes en este nuevo libro electrónico, creando así el libro electrónico completo que todo “gambero” debería leer. Hemos modificado el libro original, añadido las páginas faltantes, unificado todos los capítulos en un único fichero y lo volvemos a hacer público conservando la misma licencia libre. Comunidad WWW.GAMBAS-ES.ORG 06/01/2010

Autores: DANIEL CAMPOS JOSE LUIS RED REjO Responsable editorial: SORAYA MUl'JOZ Responsable de Marketing y Comunicación: ALVARO GARClA Edición: MIRlAM MONTERO Diseño de portada: PICTOGRAMA MaquetaciÓn: ANG EL ESTRADA

ISBN: 978-84-934371-2-3
Depósito Legal: M-41116~200S Edita:

CEDlT UN EDlTORIAL,S.L., 2005
Avda. Portugal, 85- local 28011 Madrid (España)

Tel.: 91 577 03 55 Fax:: 91 577 0618
www.tibrosdelinux.com info@LibrosdeLinux.com
LICENCIA

Se permite la copia y distribución de la totalidad o parle de esta obra sin ánimo dc lucro. Toda copia tOlal O parcial deberá citar expresamente el nombre del autor, nombre de la editorial e incluir esta misma licencia, añadiendo. si es copia literal. la mención "copia literal':

Se autoriza la modificación y traducción de la obra sin ánimo de lucro siempre que se haga conslar en la obra resultante de la modificación el nombre de la obra originaria, el autor de la obra originaria yel nombre de la editorial. La obra resullante también será libremente reproducida. distribuida, colllunicada al público y transformada en términos similares a los expresados en esta licencia.
Impreso en España (Printed in Spain) -Este libro ha sido realizado con Soft"''an- Ubre, concretamente con: OpenOffice.org, Evolulion. Mozilla, GIMP.

PRÓLOGO

La escena se desarrolla en algún lugar en el campo. en verano...

- ¡Abuelo. no te duermas!
~

o has acabado de contarme la historia del ordenador...

¿Eh? .. ah... sí... bueno, bueno...

El abuelo bostezó y pensó en lo que iba a decir. Ya había anochecido y sólo se oia el canto de los griUos y el rechinar de la butaca.

"Cuando mi hermano compró su primer ordenador personal, estaba compuesto de un lector de cintas. de algunos KB de memoria -no recuerdo exactamente cuántosy de un teclado mecánico, cosa poco frecuente en aquella época. Pero, sobre todo,

disponía de un lenguaje BA5IC completo y de un manual que intentaba enseñar la programación paso a paso. Algunos afIas más tarde fui yo el que me compré un ordenador. Los modelos eran más potentes, pero volví a encontrar el lenguaje BASIC y la posibilidad de sacar el máximo rendimiento.

En aquella época, las revistas hablaban de programación, la gente programaba e intercambiaba programas. Algunos copiaban programas que no habían creado y se les llamaba piratas... No, no, todos no tenían un parche negro en un ojo y un garfio en lugar de una mano.

o

a.rorT'ocit"''l

VIS

JOI

r')n

5('"1.&. ~re 1 ibre

Después llegó la época del IBM pe y poco a poco las cosas empezaron a cambiar. Al principio era una enorme caja gris, fea y ruidosa. Pero aumentó en potencia y mientras más potencia adquiría. menos posibilidad había de sacarle el máximo rendimiento. Gracias a un puñado de futuros millonarios teníamos pantallas más grandes, más colores, más sonido, más memoria. más capacidad de almacenamiento. Pero, al mismo tiempo, se chapuceaban los sistemas operativos, se despreciaban los principios elementales de seguridad) se frenaban las aplicaciones, se bloqueaban los formatos de datos, se ocultaba y se mentía sobre el funcionamjento interno del conjunto. El usuario se convertía en un consumidor como cualquier otro. Campai'ias de publicidad gigantescas le conducían a comprar una especie de caja negra de la que seguidamente babía que controlar al máximo la utilización. A pesar de todo. la gente continuaba intercanlbiando y los piratas pirateando.

En cuanto a los que realmente eran capaces de sacar el má:x;mo rendimiento a los ordenadores, tenían que comprarlos y después encerrarlos tras las puertas de un campus o de una cláusula de no divulgación. Si no hacían esto. tenían que dejar de programar. Afortunadamente, las cosas no sucedieron exactamente como estaba previsto y gracias al nacimiento de Internet, y a la mezcla de talentos de numerosos programadores, a menudo voluntarios. idealistas y pragmáticos al mismo tiempo. se impuso un movimjento de liberación y nació, entre otros, el sistema operativo GNU/Linux. Pero esto es otra historia, te la contaré mañana..... La idea de desarrollar Gambas sobre Linux en casa vino principaJmente como reacción a la obligación de utilizar Visual Basic sobre Windows en el trabajo. Cualquier usuario con un poco de idea, cualquier empresa. cualquier administración, necesitan sacar el mayor rendimiento posible a su ordenador, es decir, hacer de

el acceso a librerías específicas: QT. Estos componentes ofrecen. Yo soy su primer usuario y otra de las razones que me ha llevado a crearlo es que todavía no deseo aprender en serio Perlo Python :-) • . SDL. a estas necesidades. lo han ido poco a poco abandonando. Gambas no es un lenguaje creado por programadores profesionales para programadores no profesionales. no hay garbage collector. a pesar de todo. él mismo. como a ellos les pareciera. encerrados en su torre de marfil. es totalmente posible prescindir de él. Es posible escribir componentes que aüaden al lenguaje clases suplementarias.él lo que quieran hacer sin tener las competencias necesarias requeridas por los lenguajes de programación. Gambas no tiene ningún otro punto en común con Visual Basic y es totalmente incompatible con él. he cuidado mucho su simplicidad. Sin embargo.. Pero sus creadores. incompleto y repleto de fallos. Gambas ofrece un entorno de desarrollo integrado. Además. su coherencia. Es ése principalmente el que me permite probar el lenguaje :-). ¿Había quizás desprecio hacia esos usuarios que tenían la pretensión de sacar. Sin embargo.. ni el tiempo para adquirirlas. y nunca insistiré lo suficiente. procedural e interpretado. Finalmente. Con un lenguaje incoherente. sobre todo. mi prioridad es que pueda satisfacer la misma necesidad: conseguir de la manera más simple posible sacar el máximo rendimiento de todas las funciones del sistema operativo subyacente. su fiabilidad y sus facultades de internacionalización. Gambas se inspira. Pero su intérprete es mucho más rudimentario: no hay compilación just-itl-time. GNU/Linux en este caso preciso. moderno. que está. Visual Basic ha respondido. GTK+. Gambas es extensible. y así sucesivamente. en Java: se trata de un lenguaje orientado a objetos. OpenGL. escrito en Gambas. en general. el máximo rendimiento de su herramienta de trabajo? A pesar de que forma parte de la gran familia BASIC y que la interfaz de los programas se dibuja con el ratón.

la versión de desarroUo ofrece la posibilidad de escribir componentes directamente en Gambas. hojas HTM L. pero las cosas se pondrán realmente interesantes con la segunda versión. Es difícil prever de manera precisa cuándo saldrá esta segunda versión. • Martes. etc. Y si. . cómo evolucionará Gambas en el futuro. En cualquier caso. Más tarde. Gambas es el factor que os lleva a utilizar por fin eJ Sofhvare Libre. esta posibilidad permitirá al entorno de desarroUo diseñar algo más que formularios gráficos: tablas. BENOiT. sin necesidad de dominar C O C++. espero que sentiréis como yo el respiro que produce esta libertad.Programación visual con Software Libre La primera versión estable de Gambas salió el 1 de enero de 2005. 16 de agosto de 2005. más en general. como para otros. El trabajo que queda por hacer es todavía enorme y las cosas dependen mucho de los usuarios. espero que tendréis tanto gusto en utilizarlo como yo lo he tenido en crearlo y que participaréis en su evolución. e incluso. En el momento en el que escribo estas líneas.

•....... ..•.. . . . . 23 [J lJ [] III El [] I!II!l1IJ [] IJ l. . I El lenguaje BASre: su historia .. 7 Sistema de componentes .. .. .21 .. . SubrutInas y funcIones. .. 5 Compilación y dependencias 1:1 11 ti o 1:1 . . 6 FamiliarizarsE con el lOE El primer EJemplo. . PROGRAMACiÓN BÁSICA o liI o IJ IJ 41 42 42 . . 35 1. •. 3 Elementos de Gambas . . 4 Cómo obtenerlo l. . . . . 27 29 ooo oo oo o oo aooao O IJ IJ o [J Mejor con un ejemplo grafico . . I Organizadón de un proyecto de Gambas Declaración de variablES.... . . . . 36 CAPiTULO 2. .. . .. . . . . . . . .. . . . . .. . 24 26 mo IJ D o l.. . •.. oooo o aaaa o fndice .. .... . ..íNDice CAPiTULO" ¿OUÉ IJ IJ es GAMBAS? 17 • e o [] 1. . . .. .. . . 32 .... . . .. . . . •...•. . ... . .. . . . 45 2. . . . . . . 18 e a 1. . . Un poco de magia . . . .. . . 2 Un entorno libre e IJ 1... .

.......•••••••........................ 56 2...........................•............. 4 Manejo de cadenas ..... 89 ooooo ODDDCl DOOOD Colores .•..... 54 OpEradonEs logIcas 56 2.....5 Control de flujo ................. 2 Manejo baslco de los controles Posidon Y tarnai'Io Vlsiblldad _•.... 60 lF_ TtiEN.••...........•..........•....•.•..•......... 90 Ratón TEcJado 92 95 • • • •• 3..........•.......... 9 PropiedadES....2 Tipos de datos ..................... 8 ~ CM k:i ItarJa a objetos con GaJT1bas 73 2.......• 72 2..•...•...••••...•..PrOQftlmoción viwol ton Software Lbre • 2......... 63 ~ Y REPEAT .................•••••••..•....... 49 ConY8'SlOn dE tipos .. 6S • • 2. 50 MatricES 52 •• • 2. 6 Entrada Y salida de ficheros .....•.. ElSE ................ 62 FOR .rad0n En El DE dE Gambas 66 • • 2......•......tuI no dE dEsatToIIo 81 81 SS PartIEndo de la COI'lSCMa •••••......•.•..•. 64 0EpI.. Métodos y Eventos 79 CAPiTuLO 3: LA INTERFAZ GRÁFICA 3....•... 60 SelEct ..... I Concepto 8 ti........•.............................•..........•... 7 Control de EM"OI"ES .......................•.... 87 _ 87 89 r o[ Textos l'EIadonados ...... 84 •• • • 3................ 3 Galería de controlES oooo ControlEs baslcos 96 _ 96 .....••••••••.....•.......•.....•...•.. 3 OperacionEs matematicas ....

.........DDDD '00 Otros controle.................................... 111 • • • • • 3...•..... 136 Redirección dE: la salida estándar ............................5 Menús ...2 Gestión potentE dE procesos 125 125 126 • • • • • • 4..................•......•............... 134 RedJrección de la salida estandar de errol"Es . 139 Evento Kill() y la propiedad Value Redirecclón de la entrada estándar.....3 EXEC 127 128 ooooo Palabra clave WArT ooooo O O O o t: El descriptor del procESO ..........................05E 142 O oOa 146 ooooo Notas finales sobl"E el objeto Process 148 148 [ndice • • • • • 4......•.......•.......7 Introducción al dibujo de primitivas CAPíTULO 4: GESTiÓN DE PROCESOS • • • • • 4.... 99 Listas de datos Otros controlEs avanzados 100 101 onDO oo oo • • • • • 3..•...... el uso de C1.... I La ayuda ofrecida por otros programas • • • • • 4.....................4 Diálogos ..........4 SHELL ..•..................•............................•... 101 (J La ciasE Message .............•......•. 130 Redire:cion con ro 133 o o o [1 o ooooo o o o [O [) 1 O o O [J Matar un proceso . 104 Oiálogos pErsonalizados ..... básicos misceláneos ...... 101 o [J ooo la clase Dialog .....•..... 106 ooooo • • • • • 3...6 Alineación de los controlEs ooooo Propiedades de la alinEación 114 114 ooooo ooooo Cont/'Oles con allneaclon predefinida Diseño de una aplicación que aprovecha este recurso 117 ooooo 117 120 • • • • • 3..

......•................ 167 ConectandoSE por codlgo ....................•.•.......5 Otras caracterisUcas .....•................ 190 Estructura dE las tablas .. 198 • • • • 6...........••..........••... 190 o Mas ut:iIldadEs del GEstOl" de Bases de Datos ...•..... 192 CAPITULO 6...............4ocIificar /"EQI5tros ... 7 Protocolo HTTP 220 22S • 6........................•...............•. 1 Slstanas de baSES 151 151 de datos • • • • 5. 213 6............5UDP . t 54 CJNEaruna ~ ..........•.......... I~ lX\OI o GEstionar datos dE tab&a 164 SOL ............. 153 ••• • S......... RED 6.......•.....4 Programadón oo D' _ 167 ModElo dE baSES dE datos ..... IGS • D • 5...•.................2 Creando un SEl"vidoI" TCP ......•........•.... 8 Protocolo FTP .......................•.....•. 168 Consulta dE datos ............ el gestor gratico ooo 000 154 CrEar' una baSE ........ I CoocEptos 195 195 • 6.. 180 5............ 3 Gambas-database-tnanager.....•.......•...•.....•...........•.... 211 6.......CAPITuLO 5: GESTiÓN DE BASES DE DATOS • • 5.. 171 ~b os DOC Borrar 174 AfIacIr rEgistros ........................... 176 11 [ r...........2 Bases de datos y Gambas ...................•.. 3 Un diente TCP 20S 6..........4 Clientes y servidOl"E5 localES .....................6 RESOlución de nombrES 216 • 6..

..... Palabra davE SUPER ModifICando funcionalidades ReempiaziIDdo mÉtodos eSPEciales: _New y 1rEe UlTlttacionEs 269 272 • B..•....... 3 CrEar un nuEVO control con Gambas PlantEando El codigo lrnpIementacion basica 273 273 274 • 8......•...CAPíTuLo 7: XMl 227 ••••• 7..........•.•.4 NUEVOS componentes con Gambas Preparacion dEl código...................•. I Lenguajes orientados a objetos y herencia 8.. u 257 258 258 262 264 265 11 Palabra davE ~rrs ExtmdiEndo fundonaIIdades.... Palabra ciavE EXPORT Archivos necesarios......•..... 240 • 7........... 230 • •••• 7.... 252 ¿Que ES X5LT? 252 252 2S4 ooo o Una plantilla de ejemplo Transformando El docUmEnto con Gambas oo o • 7.. 238 o ~s dE~ra ........•... ~ o ••• PtantEatnientoinictal ................2 Conceptos nEcesarios la ciasE padrE la cIasE hija........................•.......•.... ~ Un ~ de lEctura .......4 Acerca dE XMl-RPC 255 CAPITULO B: HERENCIA 257 • •• •• 8... ubicaciones 279 280 280 Probando El nUEVO componarte 282 ....•.....•..2 Lectura con XmlReader ........... I Escritura con XmlWrlter ......3 X5LT .

..... 288 oI Cómo denominar la libreria ....•................4 ObtEnEJ" Información acerca dE la • • • • • 9............3 Un ejemplo con Iibaspell • • • • • 9.•...5 Resumen librer~ 291 293 297 300 APENDICE: Marcas registradas ........ 301 11 .....•...Progromocion viwoJ roo ~I !:t................•..... 289 El uso de los alias .. 291 • • • • • 9................ ACCESO A LA API ...•..... 287 • • • • 9......•... 290 Tlpos de datos ...........•.......•............- CAPiTULO 9....2 Fundones auxiliares • • • • • 9... I Declarar una función Externa ......................

El autor original de Gambas. recordemos que Coca Cola. Benoh Minisini. 'Gambas casi quiere decir BASIC'. j . la palabra gambas nos sugiere algunas cosas.wCllajo de cera. Tampoco está mal recordar que ya había antecedentes de otros lenguajes de programación con nombre de animal.n. No es la primera vez: que un nombre o una marca bautizados en otros idiomas produce estos extraños cambalaches. es decir. no habla una palabra de nuestro idioma y su inocente ignorancia le condujo a nominar su obra con el acrónimo GAMBAS: Gambas almosr meam BAS/C.• • o Es obvio que para los que hablamos el idioma espaflOl. pero todas ellas bastante alejadas del mundo de los ordenadores en general y del entorno de la programación en particular. como Carnel .o'tuvo que cambiar su pronunciación en China porque la primera versión de su nombre significaba ml/cule el re. o algunos todavía recordamos nuestra cara de asombro al ver los anuncios de un coche al que Suz:uki dio en llamar Pajero.

I El lenguaje BA5IC: su historia El nombre BASIC corresponde a las siglas Begimler's Al/ Pllrposc Symbolic Instrucrion Code (Código para principiantes de instrucciones simbólicas con cualquier propósito J. nos tendremos que ir acostumbrando a que Gambas empiece a sonarnos a algo más que a buen marisco. Gambas intenta no reproducir los errores que se cometieron entonces. De hecho.suol poro desarrollar aplicaciones gróficos o de consola. ••••• l. mU8ve obj8toS en lo pontollo. arrostro objetos desde lo Cojo de HelTClmiento$ y escr~ be código en BA51C poro codo obieto. • Gambas no el ~ólo un lenguoie de prOSroma<:ión. Debia ser un paso intermedio antes de aprender otros más potentes de aquella . aunque en esos casos el nombre estaba en inglés y en español no resultaba tan chocante. El programador diseño los ventonos de formo gráfico. como 10 hizo en su dla Visual Basic mo en Windows. no desea cambiar el nombre. Ya nunca más se podrá decir que construir aplicaciones visuales para Línux es un proceso largo y comple- jo que lleva años de trabajo a gurús y maniáticos de la informática.Progromación viwol coo Softwore libre o Python. lo que sigo nifico que Ilomo automáticamente o 101 procedimientos <:\IOndo el u5\lorio de lo opli. Pero como el tiempo no pasa en vano. etc. Intentaban construir un guaje de programación fácil de aprender para sus estudiantes de licenciatura. la ampliación del lenguaje BASIC alcanza con Gambas amplias cotas de potencia. como Benolt. Hoce posible el desarrollo de oplicociones complicados muy rópidomente. hoce die con 81 rotón. profesionalidad y modernidad. El lenguaje fue desarrollado en 1964 en el Dartmouth College por los len~ matemáticos lohn George Kemeny y Tom Kurtzas. que tiene los derechos de autor. sin abandonar nunca la sencillez y claridad de este lenguaje de programación de alto nivel. Gambas est6 orjenlodo o 8~nlos. coción elige un menú. es tombién un entorno de progro· mod6n v. En fin. Gambas abre el entorno de la programación visual en Linux a todo el mundo.

e mis utilizado en aplicaciones de proce505 de datos. Fue sólo el principio. había que saber electrónica para montarlo.. mientnl$ que FORTRAN era empleado en las aplicaciones científicas. Borland. ambos eran dillciles de aprender. tenfan gran cantidad de reglas en las estructuras de los programas y su sintaxis. El primer programa hecho en BASIC se ejecutó a las 4 de la madrugada del 1 de mayo de 1964. con un tamaño de 4 Kbytes. Figura 1. - Allen.. A finales de los 70. 1 _. la empresa MITS lanzó al mercado un kit de ordenador llamado Altair 8800 a un precio de )97 dólares. hacer un intérprete de BASIC para los nuevos modelos de Altair. solo bytes. con ordenadores del la mano de una habitación.- . Commodore. Además tenía sólo 256 bytes (no es una errata. I>o$ joV<'ncitos vieron un modelo en una revista de electrónica y decidieron montarlo. pero el declive de BASIC habia empezado. En posteriores años siguieron Otras versiones hechas por OlraS compañías como ... como FORTRAN o ALGOL Este último era ellengua.época.... megas o gigas) y se programaba en código máquina a base de O y 1... fue el primer producto que entregó una nueva empreSa llamada Microsoft. ademas. y aquel BASIC... moviendo unos interrupto.. nada de Kbytes. ctundo desarrollaron OOS para IBM y su nuevo Pe. Apple. lonJ:omiento Uis inlerfaces gráficas de ventan:1S que Apple popularizó y Microsoft adoptó con sucesivas versiones de del A1loir 8800." S lUl . Tuvo el mismo impacto en los lenguajes de programación que la aparición del Pe sobre los grandes ordenadores. En 1971 lntel fabricaba el primer microprocesador. Era un ordenador barato.. . Sin embargo.. Y en 1981. Eran William Gates y f'auJ I I\'Mllo1' EIl't1nlIlIcS WariIIo flJIol... Pero pronto las cosas empezaron a cambiar. pero no para gente inexperta. Cuando se desarrolló BASIC eran los tiempos en los que la informática estaba reduida en uniV<'rsidades y grandes empresas. AlIen y Gales hablan portado BASIC ya a un buen número de plafaformas: Atari.. BASIC se hizo inmediatamente muy popular y se empezó a usar tanto en aplicaciones cientificas como comerciales.. Debido a su sencillez.. En 1975.. Le ofrecieron al dueño de MITS. res que tenIa en el frontal.... añadieron también su propio intérprete de BASIC al sislema.

bien por la lentitud de su evolución. Quickbasic y el 20 de marzo de 1991 se lanzó al mercado con el nombre de Visual Basie. Con la popularización de si~emas operatÍVQS libres como GNU/Linux.0. un programador con experiencia en la escritura de compiladores . Ha habido varios intentos que no han cuajado.NET de desarrol1o. a dla de hoy se calcula que entre el 70% Y 80% de todas las aplicaciones desarrolladas en \I. ya que ha cambiado buena 11 parte de la sintaxis añadil!ndole complejidad en contradicción con el esplritu y el nombre del lenguaje. pero entre otras se pun:!e sel'lalar como obvia el uso del lenguaje BASle que fue pensado para un aprendizaje acil. &noit Minisini. Sin embargo. En 2002 fue int~rado en la plataforma . Microsoft reemplazó ese lenguaje por su propia versión de BASIC. apartando al programador de perder tiempo en escribir el código necesario para crear vtTItanas. pero la V('Tsión 3 publicada en ti otoi'Jo de 1996 fue un bito lotal. En cualquier caso. éstas y otras razones hacían prever que la aparición de un entorno equivalente libre seria un l!xito y conlribuirla a la presentación de muchos nue· vos desarrollos que lo utilizarlan. en marro de 1988. st convinieron en un cSlándar y BASIC no era un lenguaje preparado para eslos entornos.Windows{T>O'. que hace un juego de niños el disel'lo de la interfaz gráfica de cualquier aplicación. Otro de los motivos es disponer de un entorno de desarrollo cómodo. bien por su dificultad de uso o por no ser totalmente libres y no haber arrastrado a una comunidad de usuarios detrás. Finalmente.. Al principio fue un verdadero fracaso de venias. El progr. Las causas del txjto de Visual Basic son numerosas. etc. botones. un dts<irrollador de softwart" llamado Ajan Cooper l intenlaba vender una aplicación que permitía personalizar fácilmente el enlomo de ventanas usando el nlÓn. y a la que añadieron un pequeño lenguaje de programación. tanto que aclu¡¡lmenle es el lenguaje de progr..amadón más usado. en lo que para muchos de los Stguidores ha supuesto el abandono de Microsoft. Visual Buic siguió ~Iucionando hasta 10I versión 6. y dqfndole centrarse (¡nicamente en 10I solución al problema qllt cual· quin programa intenta resolver.ama M" lIamabll Tripod y en aquellas fechas consiguió que \~lIliam Gat~ lo viera y le encargara el desarrollo de una nueva versión a la que llamaron Ruby.Ilndows se han hecho con alguna de las vtrsiones de Visual Basic.

como la orientación a objetos y la propia estructura de 105 programas1. y le añadió caracUrislicas comunes en los lenguajes actuales más modernos. • La libertad dr estudiar cómo funciona el programa y adaptarlo a las propias nrcrsidades (libertad 1). t. En enero de 2ooS. El 28 de febrero de 2002 puso en Inlernet la primera versión pública de Gamb¡as: gambas 0. en]¡a que ya se incorporaba un pui\¡ado de componenles desarrollados por otros programadores que colaboraron con 8: Daniel Campos.que estaba harto de luchar contra los hilos de diseno de Visual 8asic. muchos más componentes y un nuevo modelo de objetos que permitirán usar Gambas en un futuro para el desarrollo de aplicaciones web con la misma mosofia y facilidad que actualmente se: usa para aplicaciones de escritorio. Esta versión se consideró suficientemente establr y cerró un cido. El acceso al código Cuente es una condición previa para esto.&noit publicó la versión 1. - . La libertad de usar el programa con cualquier propósito (libertad O) . A partir de esa frclla empezó la programación de la versión 2. como la gestión de errores. y dese¡ab¡a poder usar un enlomo de GNU/Linux Cácil en su dislribución.0. ROO Kudla y Ahmad KahmaJ.0. comenzó a desarrollar su propio entorno para Linux basado en BASIC. Nigel Gerrard.20. el propio entorno de desarrollo fue programado en Gambas desde la primera versión.sta ya induye algunas mejoras en e1lenguaje. Esto significa que se distribuye siempre con el código fuen- te y respeta las cualro libenades que define la Free Software Foundalion: . sirviendo a un tiempo de demostración de la polencia del lenguaje y de delección de necesidades y corrección de errores que se fueron incorporando a las dislinlas versiones. Como prueba de fuego. 11 L 2 Un entorno libre Gambas es un entorno de desarrollo que se distribuye con la licencia GPL GNU (General Pub/ic LicmaJ). LauTnlI Carlier. 8enoít eliminó del diseno del lenguaje bastantes dr los problemas que Visual Basic tenfa.

de eualquier aplicación dNarroUada con este progralTJil. siempre y cuando entregue ti código correspondiente a esas modificadones y res~te los derechos de autor de los ~rrolladord originales. pero pennite a los programadores avanzados que 10 deseen añadir funciona- Ildades al mtorno de desarrollo y crear nuevas herramientas para Gambas. Una API (Interfaz para programar la aplicación) sencilla y bien documentada. algo que es muy de agrad«tt para los qut nnpiezan a programar en Gambas. Una de los engiu\os más comunes en el uso de Software Libre es la crenlcia de que este moddo de desarrollo obliga a que el trabajo se publique gratis. de modo que toda la comunidad se beneficie (libertad 3). El acceso al código fuente es un requisito previo para esto. con las que se puede ayudar al vecino (libertad 2).¡ducción a español 4• Si todos nos animamos a colaborar! en la traducción.con Se twore li • La libertad de distribuir copias. Estas cuatro libertadts permiten que. y que no es habitual en los proyectos de Software Libre. . . por supuesto. quien lo deset. Gambas añade más facilidades para el programador: • Una ayuda muy completa del lenguaje y cada uno de los componentes. La API no es de utilidad inmediata para quien desarrolle con este lenguaje. venda copias de Gambas (entregando siempre el código fuente y respetando esas cuatro libertades) y. pero existe un grupo dc personas trabajando en la \r. lo que facilita a los programadores crear nuevos componentes para Galllbas. pronto estari completa y disponible para el resto de usuarios. lo que es del todo incierto. Aparte de estas libertades propias de la naturaleza de un proyecto de Software Ubre sobre GNU/Linux. Las aplicaciom:s desarrolladas con Gambas put'Ckn O no acognose a la licencia GPL También cualquier programador es libre de alterar el propio lenguaje y modificarlo 11 a su gustO. · La libertad de mejorar el programa y h¡ctr públicas las mejoras a los demás. La ayuda que se publica está cn inglés.

una opción en el entorno de desarrollo para elegir el componente a usar (actualmente se puede elegir entre gtk y ql. . sino a Iibrcriil5 espccfficas que le dotan de más posibilidades. sdl. lada para ser ejecutada en un escritorio Cnome o KDE. son necesarios dislinios elementos: • Un compilador.El lenguaje está preparado para ser independiente del gestor de ventanas que use. que se enc:argati de transformar lodo el código fuenle yarchi- 11 vos que formen parte de un proyeclO hecho en Gambas. 3 Elementos de Gambas Para poder desarroUar y ejecutar programas hechos con Gambas.. En el futuro se pueden desarrollar componentes para Windows. para Gnome o KDE). La palabra (omponenle en Gambas tiene un significado especifico.. en un programa ejecutable. • Un intlrprete capat de hacer que los programas hechos en Gambas sean ejecutados por el sistema operatil'O. ya que no alude a partes gen~ri­ cas. Esta característica no se encuenlra disponible en ningún airo lenguaje aistente. dinintu bases de datos. 1. Fluxbox y otl"05 gestores de ventanas. y los programas no tendtin que modificar su código para que sean aplicaciones nativas de esos entornos. usando las librcrias propias de ese escrilorio y siendo una aplicación nativa de ese entomo. lavé es Gombos~ . Esto significa que. 1. • Componentes que al\aden funcionalidades al lenguaje. una aplicación puede ser compi. antes de compilar. en gtk. sin cambiar una sola linea de código. rooaiones de red. se generan distintas aplicaciones para distintos entornos con el mismo código fuente. Marcando.. escrilorios basados en qt.lo que convierte a Gambas en un entorno único... En la actualidad existen componentes para usar xml.Un entorno de desarroUo que facilite la programación y disct\o de las interfaces gráficas de los programas. aprcsioncs regulares. oprngl. ODBC.

para que los usuarios que lo deseen compilen el código y obtengan todas las parles que Gambas tiene. Algunos de estos serán tratados en este texto. el paquete del código fuente con· tiene las últimas versiones de todo el conjunto en ese momento. publican de forma separada en distintos sitios web las versiones nuevas de estos. es muy probable que lenga fallos no descubkrtos y es seguro que sufrirá cambios en un futu· ro próximo. Esto la hace muy atractiva. Los autores de algunos de los componentes que se han hecho para Gambas.net. De este modo. Estos componentes son desarrollados por distintos programadores. se put'dt' decir que cuando 13enolt hace pública una nueva. Las nuevas versiones se publican siempre en forma de cMigo fuente.sourceforge. 11 mejora y adición de nuevos componentes. 1. Buena parte de las diferencias se encuentran en los nuevos componentes.0. En el momento de escribir estas lineas. Sin embargo. La versión de desarrollo está en continuo cambio. De la rama estable s610 se publican nuevas versiones cuando es para corregir algún fallo que se haya descubierto. por lo que si el lector quiere trabajar con ellos deberá usar la rama de desarrollo. pero todas se env!an a Beno)t Minisini y paS<ln a formar parte de la publicación completa de este lenguaje de programación en la siguiente versión. . En este texto trataremos todas las novedades que la versión de desarro· 110 contiene para que sea el usuario el que escoja con qué rama trabajar. la versión estaole era la 1.Enlaactualidadexistendos ramas de Gambas: la rama estable o 1.11 y no se prevé que haya cambios en el fulurO.0 y la rama de desarrollo o 1. al ser una rama en desarrollo. 4 Cómo obtenerlo Las nuevas versiones de Gambas se publican a través de la página web oficial del pro- ye<to: http://gambas.0. siguien- do las directrices de la AP¡ de Gambas y la documentación publicada al efecto por Belloi' Minisini. debido a la existencia de importantes funcionalidades que no están en la versión f'stablf' (como los componentes gtk yODBC).etc.9 que desembocará en la versión 2.

. como para Fedora y Dcbian. ele. para instalar todos los paquetcs de Gambas. subidos a Debian para que eslén disponibles y usables en esla distribución y en lodas sus derivadas. Unspire. Gentoo.. como Knoppix. la instalación desde paquctes compilados Soe hacc con un bucn puñado de archivos. Slackwarc. En la misma página ".Ii5t de un sisltma Dcbian para instalar La vcrsión más actualizada de los paquetes de Gambas son: Para la vcrsión estable: I gambasl deb http://lpt. Fedora.s A continuación. Existen actualmetlle paqueles disponibles para Debian. en cualquiera de los dos casos.. . Xandros..liDe~.Como In compilación de Gambas y todos los componentes asociados puede ser una tarea dificil para usuarios no expertos. Progeny. En algunos casos. Por este motivo.. QiUnux y SuSoe.org/line~ Para la vcrsión dc desarrollo': deb hUp://_.linez.di dondc sc pucde bajar d código rumte sc mcut"fltran los cnlaccs para la dcscarga dc los paquetcs compilados para cslas distribuciones. Skolelinux. Las lineas del archivo /tfelaptlsourr:tj. eslán disponiblcs tanto los paquctes de la vcrsión establc como la de desarrollo. posteriormentc.orglsources/linez/debilD/ el gl. es común quc se crttn paquetes binarios con la compilación ya hecha y listos para scr instalados cn distintas diSlribucioncs dc gnu/Linux. las últimas VttSiones están sicmpre disponibles antes en los rqJOsilorios dc gnuLinEx hasla que 50n subidos y aprobados cn Ikbian. hay que ejecutar como usuario rool: apt. los paquctcs son realizados en gnuLinEx y.-qet update apt-get install gambas Aunque el código fuente dc Gambas Soe dislribuye en un único archivo comprimido. En d caso dc Dcbian. Mandriva. Guadalinex.

al menos los que el entorno de desarrollo necesita. que son muchos./eonfiqu. deberemos seguir los pasos habituales en Jos sistemas GNU. Las instrucciones anteriores tratarán de compilar e instalar lodos los componentes de Gambas. Si estamos habituados a compilar aplicaciones en sistemas GNU. Es decir.re ~k. Es importante saber que d entorno de desarrollo está hecho sobre las librerías gráficas qt. disponemos ya de un compilador instalado y de bastantes librerías de desarrollo. para poder usar d entorno necesitaremos tener instalado. desde el directorio que se crea al descomprimir y usando un terminal. simplemente no se compilarán y la instrucción . el intérprete (paquete gambas-rwl- time). Por ejemplo. Si no tenemos las libredas correspondientes a alguno de ellos. 5 Compilación y dependencias Si en lugar de instalar paquetes ya compilados para la distribución de gnu/Linux • deseamos compilar Gambas desde el código fuente. descomprimir el archivo con las fuentes y. lllake install La última de ellas debemos hacerla como rool./configure nos informará de ello. y se ha hecho un paquete separado para cada uno de los componentes. sólo sería necesario instalar en el sistema los paquetes gnmbas-rrmtime y gambas-gb-grk. si es un programa que está hecho para el escritorio Gnome y no usa ningún otro componente. Si se quiere ejecutar un programa hecho con este lenguaje. •• l. ejecutar las siguientes instrucciones: . En las distribuciones de Linux se ha seguido d criterio de separar en distintos paquetes el entorno de desarrollo (paquete gmuba>-ide). Si se quiere programar en Gambas son necesarios la mayoría de ellos. estas librerlas de desarrollo con una versión igual .Programación viwal ton Software libre La razón es que no todos son necesarios para eiecutar aplicaciones hechas en Gambas. sólo es necesario gnmbns-rrmtime y un paquete por cada uno de los componentes que el programa use. por tanto. si queremos que el programa esté disponible para todos los usuarios del ordenador. al menos.

.: .._"-""'" o" "oo.....-~::S~. que se usan durante el desarrollo de una aplicación: • ---. • _ _.. como mínimo. - 11 -".e.. r 0 .' sus propias librerías y dependerá de la distribución de Linux que usemos..• ••• " .......] _.. -__... de diseño de interfaces. -.. • -"'....2. .'-'-" ... ... --. seria un desperdicio no aprovcchar uno de los mayores atractivos que el lenguaje tiene: su lOE o entorno de desarrollo. -. la versión dt:! compilador ga: ha de ser lambitn tsla.o superior a la 3."''''' •• •• •• •• ~. 0-:T' Q. __... Enlomo de desarrollo de Gambas.._~~... . EliDE de Gambas ahorra al programador buena parte del trabajo más tedioso.-.... .~...rr_ ~- .....j.""--. con utilidades de ayuda....:Icil su larea. Cada uno de los compontntes titnt dependencias dI. le proporciona herramientas que hacen mucho más f. .. para saber el nombre del paquete que deberemos instalar anles de poder realizar la compilación.-. aUlOcompletado de instrucciones. . _ - figwo 2.•.'-'... _ ' • . ... r". - _ ___... En la imagen siguiente podemos ver algunas de las ventanas más importantes dt'l t'ntorno.--_. -..¡o.... _ •• p" '''l3' ...c: ~ _ --. L 6 Familiarizarse con el lOE Aunque un programa en Gambas se podría hacer perfcctamente usando un editor de texto plano cualquiera.. traducción de programas. ttc......'''''"O"". - 1"0""'.

En ti puede haber. El proyecto está (ormado por una serie de archivos que en Gambas estan SIEMPRE situados dentro de un único dir«torio. el asistente siempre creará un nuevo direc~ torio con el nombre del proyecto y ah! irá introduciendo todos los archivos necesarios para el desarrollo de la aplicación.nI es DalabaH . rec:lenus . sin tener que prwcuparse de otros archivos.... si elegimos en o:ta ventana la opción Nuevo proyecto.. erypt • Figuro 3.. dislintos subdirectorios y organizar todo como se desee. si desde el entorno de desarrollo escogemos un . Antes ck c:l~ir cualquiera de estas opciones es nn:esario Sil~r que lodos los códigos fuc:nte de una apliOld6n h«ha en Gambas es lo que se denomina proy«to. tato y código que (orme parte de la aplicación estará dentro de él. Venlono cJ... Del mismo modo. só[o hay que transportar el directorio con el nombre del proyecto.Progromocióro viwoJ con Software libt'e Cuando ~ arranca Gambas. GbWhois Proyecto. J "".J monilOfllrore .. lo primero que: nos aparttc: es la VC\lana <k bienvenida. usuarioKentros ¡. para enviar a alguien el código fuente de una aplicación hecha en Gambas o cambiarla de ordenador o disco. Aquí se nos orr~ la opción de comenzar un nuevo proyecto o aplicación. Pro"eelos .. abrir un proyecto del que tengamos sus archivos disponibks.. pero cualquier gráfico. Asl. a gusto del desarrollador.. abrir uno usado recienternmle o uno de los numerosos ejemplos que estan incluidos en la ayuda de' Gambas. Por dio. bienvenida.

IX ah! qUl. por 10 que este primer programa sc:ri un programa feo. Vamos a ver cómo hacerlo con el entorno de desarrollo de GAM RAS: • _ .. oe e primer Ejempk) Una de las formas mas habituales de empezar a trabajar con un lenguaje de programación es haciendo un pequeno programa que: muestre el mensaje Hom MUlldo.-- ejemplo holmmmdo y un titulo..n. . ..~--- 1. Mi$lenle de Gomb<. Le damos un nombre al proyeclO. Pulsamos el botón Siguiente (Figura 4). el archivo sc:1i copiado automáticamente al directorio del proyecto. en la venlana anterior (Figura 3).. En el BASIC original. Aparecer. que sea igual al que hubieran hecho los autores de BASIC allá por el ano 1964.. es d&ir. que en BASIC se presentan entre comillas dobles. En aquellos tiempos las interfaces gráficas no existlan.. por J.. ro el que pulsamos Siguiente.ado previo. Comenzaremos haciendo un !rola mundo que sea puro BASIC.' el programa sea tan simple como ese. Figuro 4. la instrucción PRINT sirve para mostrar cualquier cadena de texto en ellerminal. hacer que aparaca un mens¡je en el terminal es tan simple como escribir la línea: ntNT "Hola Mundo" No tl necesario ningún encabez. de lerminal.í un asislentt. 2. Surgiri una nueva venlana para elegir el lipo de aplicación. Por tanto.. Escogemos la tercera opción: Crear un proyecto de texto'.-. _-"--. empezaremos a conocer el entorno de desarrollo y el lenguaje de programación con este tlpico ejemplo.archiyo o un glifico para integrarlo en nuestro trabajo. . Escogemos la opción Nuevo proyerto.

qu~ nos (Stá mirando al abrir ti proyecto). 6). que no lleva interfaz gnUi- -----_. Se abrirá el entorno de desarrollo de Gambas listo para empezar a programar.. ---_ . De mom~nto nos fijamos sólo ~n ti árbol d~ direaorios que: contie:n~. cuyo nombre: indica su finalidad.._-_. principio. A continuación pulsamos el botón OK.__ __----. que contiene las entradas necesarias para guardar y cargar proyectos. po(kmos ocultar la animadón d~ la gamba. manejar la ejecución de los programas. . ~- . .- --'"'--_._ _ . y de ~I cu~lgan tres ramas: Clases y Módulos... almacenar ahi los archivos de datos que la aplicación Desd~ ~I requi~ra. Al ser una aplicación de terminal. el que queremos crearlo.6... _. incluso si Pod~mos dtgir entre son tan simples como el qu~ hemos hecho. sólo ne«:sit Irnos fijamos m la ventalla de la izquierda. Proyecto- """"""""._-~---­ . qut en nuc:slro caso tm~ dri como título: Proytao -ltaIamundo (F'¡gun.. • fis. de momento. aClivar las distintas ventanas del [DE.. y Datos.. Pod~mO$ \'er qu~ la ralzdel árbol es el nombre del proyecto: holamundo. 3.. .. ~tc. Asimple viSla se puede ver el menu superior. pulsamos de nuevo el botón Siguiente y apa- rccm un l'tSumen oon los lbtos dd proyecto (Figura 5).E1iegimos el directorio del disco en e.. _ _ -~-_... Gambas nos da dos formas de realizar Jos programas... personalizar el enlomo (en Herramientas I Pref~as I Otros I Mostnr mascota. En TC'alidad ~sla es. • ca.. una programación . que son para distintos tipos de archivos d~ código fuen· re.. probablemente... la ventana más 11 importante para el manejo del entorno de desarrollo..

Elegimos las opciones Nuevo plo miprogramil. son comentarios que el programador puede/debería poner para facilitar que otros (o él mismo.. Lo haremos justo antes de la Pt. .. tal y como queda reflejado en la figura de la izquierda. Esto apare. paradigma ((pico de los lenguajes de programación más potentes o una programación estructurada simple... no se trata de ningún código de programación y el texto que sigue a la comilla no se ejecuta nunca. con lo que aparecerá nuestra primera tana.ellC so. por ejemven~ línea donde pone END.e "". pulsamos la tecla INTRO. Surgirá una ventana en la que escribimos el nombre del módulo. En azul podemos ver palabras clave del lenguaje BA$IC. Esto indica que la línea es un comentario.~ I Módulo. Cuando después de escribir el código que I Figura 7. <lo. • A [a izquierda vemos un resalte amarillo al comienw de las líneas que han sido modificadas. .modllle. pasado un tiempo) entiendan lo que el programa hace en ese punto.orientada a objetos.. • En color rosado aparece la cadena de texto. Haciendo dic con e! botón derecho de! ratón sobre el árbol de carpetas aparecerá un menú contextua!. Venia"" doode escribir el código.. e! archivo que contenga el código de nuestro programa será una Clase o un Módulo.. es decir. Según ello. y pulsamos el botón OK. Por fin podemos escribir nuestro código en BASIC. Podemos pararnos 11 un instante a ver los distintos colores que se muestran (Figura 7): • En gris aparece una línea que comienza por una comilla simple ('J. •.!I fllml. donde poder escríbir código. Por simplicidad. vemos que el entorno colorea e!texlo de una forma particular. ya sablamos.erá siempre en [as Uneas que contengan modificaciones que no hayan sido compiladas.:. . con el título miprograma. de momento vamos a usar un Módlllo.1• .

ac(pto qU( (n lugar d( (SCogu Cr(ar un proy«:to de tato. Al acabar ti proceso apar«:(!'á de nu(V() la ffntaru de proyecta. Un formulario es d á~ dond( se diseña . puesto que son realmente simples (igualm(nte fáciles de realizar en otros I(ngua~ como Python o cualquier vi(ja v(rsión d( BASIC. Para no repetir nombre. pero (n esta ocasión t(ndrá una rama mú (n (1 árbol: Formularios. Saldrl. arrancando Gambas y creando un Nuevo proyecto siguiendo exactamente los mismos pasos. con el símbolo del Play.gambas Rola lIlUrIdo • Mejor con un EjEmplo gratlco El (jemplo anl«ior moslraba una aplicación d( consola. Es m(jor hac(r el programa Hola MlIndo para ti (ntorno gráfico qU( inunda los (scritorios d( los ordenadores actuales. Para ello. Pulsando DI< 10 generará. (I~iremos Crear un proy«IO grifico. cuando (1 asist(ntt nos pr(S(nt( las distintas opciones. en el menú de la ventana del proyecto hay que escoger: Proyecto I Crear ejecutable. Para comprobarlo se pulsa en el botón verde. Para ello. En realidad. En este caso strá el simple lexlO Holo Mlmdo. Este es lodo el código necesario. Al hacerlo apar«trá una nueva \'entana llamada ConJOla en la que se \-erá la salida de nuestro programa. qU( nos r«:u«(Ú. que está en la pantalla del proyecto.L Bien.sar a una (onsola de Linux. podemos d(nominar al proy«to ltolanlll/ldo2. ya se puede com· pilar el programa para generar un archivo e. Al cerrar ahora el mioma de dc:sarroUo ck Gambas y abrir un IfiITlinal o p. a los vi(- jos tkmpos tk otros sist(mas oper. Para ello empuaremos igual que antes.llivos o a la fonna d( trabajar d( los hackers informáticos. un cuadro de diálogo para elegir el directorio en ti que queremos (TUT ti ejecutable./bol··'ndo.¡. podemos probar su funcionamiento. hacer es( tipo d( programas no demuestra (1 potencial de Gambas. hacemos: josefaOO-004:-$ OI! 9' bes/bol_'ndol jose@aOO-004:-/gaabas/bol"'ndo$ . tn el dimlorio donde se haya creado el ejecutable. ya esl:llislo el programa.iecutable que funciona sin necesidad del entorno de desarrollo.

.• .. El resultado será algo parecido a lo siguiente: . " ~ '_'00 <:l<..... -.u. Por simplieidad.. Pantolla dellormulario.. en este caso ni siquiera hace falta cambiar el nombre.. Los formularios se corresponderán con las ventanas que la aplicación mostrará. en la ventana de propiedades. -o' ._oo . cuadros de texto. <> :fier . ....-'. --_ _.. Haciendo un dic de ratón en él. sólo pulsando en el botón OK aparecerá en pantalla la ventana del formulario y una ventana para escribir código BASIC casi idéntica a la del ejemplo anterior... listas.... "" • Haciendo die sobre la palabra Form en la ventana de la derecha. aparecerán distintos objetos que podemos colocar en los formularios.. Gambas escribe el texto Buttoll/ sobre el ratón. l. correspondiente a la Caja de Herramientas. casillas de venficación. etc. _ 5"'"111 . pero como ese texto no es demasiado intuitivo 10 mejor es cambiarlo... por ejemplo Púlsame.....p ? '000 - • • rFigura 8.. donde se insertan objetos como botones. hacer un die en la línea donde pone Text.-'" . es decir..•. . para dar la forma que queramos. Ahora se puede escribir el nuevo texto.. Haciendo die con el botón derecho del ratón sobre el árbol del proyecto. ¿Qué es Gambos2 . ..la interfaz gráfica de la aplicación... se puede dibujar en el formulario un botón.•...... .. tan sólo hay que arrastrarlo con el ratón y el botón izquierdo pulsado... Para ello hay que pinchar en el botón y después. Entre estos está el icono del botón (se distingue rápidamente por tener la palabra OK escrito dentro)..'- ~. -. sin nada escrito.. elegimos ahora en el menú contextual que aparece: Nuevo I Formulario.

Siguiendo los mismos pasos dibujamos otro botón sobre el formulario.ckO llUIT fFa'se ] Text Picture Border Defilult Cancel -- jpulsame True Fabe False -::J Figura 9.) (Name) (Group) 1 BullO" 1)tnMenuJe 1 x ·0 O O 56 o PÚfseme O ! "O EHIl Forml. . Para ello. aparecerá la ventana de código con un texto ya escrito.. -... por ejemplo.~ PUBLIC SUB btnHensoje_Click() Hessoge.cI.lnfo("Hola Mundo") END Haciendo doble dic sobre el botón Salir.. pasamos a escribir el código BASIC correspondiente.s (Class..Programación visual con Software Libre También.lnfo(~Hola "undo~) Foregfound ~ room. ~ -ti P H. btnMensaje.". P\eltc sta btnSahr_CtJ. . . Resultado final de lo programación de los dos botones. al que añadiremos algo de forma que el código de ese botón quede así: PUBLIC SUB btnMensaje_Click() Message.iQiit Visible Enabled Font BótckQlGUnd y " " 141 True T. D~ Exp~ Mouse fU" falseo 5. . pulsando en la propiedad Name le cambiamos el nombre al objeto botón. Una vez que tenemos diseñada la intefaz gráfica con el formulario y los dos botones. 14: 1 [Modificado) Jtl€>rA.. . Gambes C\eS5 file g Width . haciendo un doble dic con el ratón sobre el botón con el texto Púlsame. escribimos el texto Salir y el nombre btnSalir. escribimos el código que falta: PUBLIC SUB btnSalir_Click() • QUIT END El resultado final debe ser algo como esto: Propíedad. poniéndole.

hay un par de detalles que ya deberían empezar a observarse: • El código BASIC se escribe entre unas líneas que empiezan por PUBLlC SUB y acaban en END. se escribe Message y se pulsa sobre esta palabra. pulsando en el botón verde de la ventana de proyecto el programa se ejecutará.m. tiene ya su venta- na con la barra superior y los típicos botones de maximizar y minimizar. y de forma predeterminada lo escoge para las aplicaciones gráficas. Moviéndonos con los cursores del teclado y pulsando la teda de espacio o INTRO sobre esa palabra. cuenta con dos botones y la aplicación está esperando a que el usuario haga dic en alguno de ellos para actuar. Además.. Hora de experimentar.:.. Aparece un menú entre cuyas opciones se encuentra la palabra Info. • Para que aparezca Message. _ . Sería bueno.:::o:.:.:. que nos ayuda a escribir el código evitando tener que memorizar sentencias y mensajes extraños.::o:. Igual que antes. parando el programa y volviendo a arrancarlo para ver el resultado de las modificaciones tantas veces como queramos.. Por tanto. llegado este punto. • El texto que sigue a PUBLlC SUB lleva el nombre del objeto sobre el que se ha hecho un doble dic. eso significa que el código se ejecutará cuando el usuario haga dic sobre el objeto. quedaba escrito en la ventana de código... Un poco de magia • El entorno de desarrollo de Gambas está hecho con el componente qt. Sin embargo. estas librerías y se puede considerar 2 1 . en este caso la ejecución presenta novedades importantes: es UH programa gráfico.s:. seguido de la palabra Click. Ése es el autocompletado. un programa gráfico hecho en Gambas usa. Aunque no es parte de este capítulo. que perdiéramos un poco de tiempo tocando las distintas propiedades de cada uno de los tres objetos que el programa tiene: el formulario y los dos botones.. ¿Que es G..Info.Con esto ya está el programa terminado.::b. en principio.

Sin ~mbargo. Aplicación holomunda2 - )-I I • I I Hasta el dla de: hoy no existe ningún olro lenguaje: de programación con el que se pueda hacer esto.gb. . Si hemos instalado los paquetes de Gambas correspondientes a la rama de desarrollo. ~rmit~ hacu programas ~nlaza· dos con las libr~ñas d~ Gtk para realizar aplicaciones del tseritorio Gnome. podemos recuperar la aplicación holaI11lmdo2 del ejemplo anterior. incluyendo el paquete gambas. _~nn~ I Figuro 10. 11 MKDE. ~I ponibl~ ~n compon~nt~ glk dis· la versión d~ desarrollo de Gambas. 1"'--.0 estable de ..gtk. ~. -. y seleccionar gb. incluyendo su descripción en el tercer apartado de este capítulo. La interfaz desarrollada por Benolt para su programación hace que hayan sido varios los programadores que han colaborado con él. ir a la ventana de ProyeClo y hacer clic en el menú ProyeClo I Propiedades. • L 7 Sistema de componentes A lo largo de: tos apartados anteriores han aparecido distintas referencias a los componentes de Gambas.' _.lndo2 IJJ)-- • Figura 11. pero antes de KDE y ahora de Gnome. Aplicación holoml. pestaña Componentes. En la versión 1. Estos permiten extender este lenguaje de programación.Progromoción"¡woI con Software Libre una aplicación nativa para el tseritorio KDE. desarrollando nuevos componentes que se van añadiendo a las distintas versiones de Gambas en cada nueva publicación. El resultado al ejecutar la aplicación es que se trata de una nueva. jY sin tocar una sola línea de código! .gtk.

• gh. • gb. El listado de componentes disponibles es amplio y se aumenla continuamente en la versión de desarrollo.9. • gh. ¿Ové es Gamba.crlr/: objetos para construir servidores de red. · gb.mysq/: driver para conectar al servidor de bases de datos MySQL •gb.net.db.dh. •gb./itm/: un navegador web d('1 escritorio KDE.xm/: objetos para parsear archivos XML 1.kde: objetos visuales propios del escritorio KDE.ql.dh.qt.4 de la rama de desarrollo tambi~n se pueden escribir componentes en Gambas.sq/ill': driver para usar bases de datos Sqlite 2.qr.cxt: para objetos visuales de las librerías gráficas qt que no son estándar.postgresq/: driver para conectar al servidor de bases de datos PostgreSQL •gb.Gambas sólo se podían desarrollar en e y C++.q[.editor: un edilor de lexto hecho usando las librerías gráficas qt.qr: para objelos visuales de las librerias gráficas q[. lo que abre numerosas posibilidades futuras ya que es mucho más sencillo hacerlo que en C.x. pero desdc la versión 1.compress: para compresión de archivos con protocolos zip y IJZip2. 11 • gh.kfle. Para la rama estable están fijados [os siguicnles: · gb. • gb. • gb.? . • gb. • gb.llet: objetos para conectar a servidores de red y a puertos serie de comunicaciones.dh: objetos de conexión a bases de datos.

• gbIorm: objetos gráficos para formularios independientes de las librerías gráficas usadas.sdl: objetos para reproducir. •gb..pcre: objetos para usar expresiones regulares en el lenguaje. • gb. driver para conectar a bases de datos a través de ODBC. '''H'''''' '.. 'VO ••..gtk.crypt: objetos para encriptación DES y MDS. mezclar y grabar archivos de sonido.. v4/: objetos para capturar imágenes de cámaras de video en Linux. • gb... • gb.opellgl: objetos para dibujos tridimensionales con aceleración OpenGL.... • gb.q/.'" •gh.gtk: objetos gráficos para formularios de las libreríasgtk. • gh.rpc: objetos para el uso del protocolo rpc-xml.i'Jfo: objetos que proporcionan distinta información acerca de los componentes y el sistema donde la aplicación se ejecuta. • gb. En el momento de es<:ribir estas líneas podemos contar con: • gb. .pdf se utiliza para renderizar documentos pdfdesde aplicaciones hechas en Gambas. . vh: colección de funciones para facilitar la migración desde Visual Basic.sdI) y otros más.image: objetos para dibujos en dos dimensiones con aceleración gráfica. como el gb..db. En la rama de desarrollo existen estos componentes (algunos de los cuales han sido muy mejorados y aumentados.odbc.sdl.. "V" .." OOV'" ~. · gb. con una lista en continuo crecimiento. Tiene los mismos objetos que el com¡xmentegh.."..xml.. • gh. pero enlazan con esta otra librería de desarrollo... •gb.

. el nombre del autor o autores del componente..) u objetos de código (como servidores de red o conexiones a bases de datos).- Co""'.-_..... o'. estos se incorporan a alguna de las pestanas de la Caja de Herramientas del entorno de desarrollo. __-........ [j " .SlIl.' form Cont"ln~r N~twork Figuras 13. 14 Y1S.o o . Figura 12.. el componente gb.... ha de instalarse el paqueOo. ...... ete... ~ ~_ . • == C"JO . . . de forma que si se anade al proyecto.-_ ..... Al hacer dic sobre cada uno de los componentes aparece una pequeña descripción de su función.. o' ""'. 0- 0'< . Los objetos creados pueden ser visuales (como pestañas. o' _ .... Cada uno de los componentes se corresponde a un paquete compilado en la distribución.. y un listado de los controles que están disponibles para el desarrollador si selecciona ese componente (Figura 12)..... _--. _ Sp. Los controles son clases para crear objetos útiles en la programación. ._ ..El listado de componentes disponibles para el programador puede verse en la pestaña Componentes...... Componentes.. por ejemplo. ~ _ te gnmbas-gb-sdJ en los ordenadores donde se quiera ejecutar la aplicación compilada."-'-'-"-... Cl:Jjo de H«ramienlos COll componentes COll ob¡eIos 9r6~COS.. Si el componente tiene objetos visuales... editores de texto. . . _ .. accesible a través del menú Proyecto I Propiedades.. _ .

Jindominio.coope. No lIay que preQ(uporse por etlo.lemo gnuLn&. se programan mediante el U50 de componentes.db o no estarán disponibles los objetos de conexión a bases de datos. Todas las cosas que se pueden hacer con Gambas.hhn/ 2 o. Lo mismo ocurre con las conexiones de red.lnJccio. es po~. Cada componente tkne su propiiJ doc. caplura de video.to en espa- ñol que en o/ros idiomos....fd.gnulinex. Estos objetos nO son parte del lenguaje BASIC.) poro coIobolor en lo documentoelÓn en e)p<lñol http://wiki.e veo completo.htmIHoy ung IJoducción lno ohaoII 01 ~ . no aleda poro nodo o ~u ellKción y suponemm que $Oró cOrf&gido en po~lfIllore5 veniarlf!s del lOE.org/gombaJ/6 /l Si lo insloloc:ión $O hoc. para hacer una aplicación de bases de datos es necesario seleccionar ti com¡>onente gb.ble que e$O menwje aparezco cortado y no ¡. y no son parte del propio lenguaje BASIC.. http://gugJ. ctc.dol de gnulinEx. ..net/licenc:ioJ/ • DocumenIoción de Gamba) tri tipOñoI.fe"'WI(IO) ~lJe Gombo~ y Visuo/ BoK http://wiki. En la n... 7 Debido o lo mayor extensión de lo cooena Creor un proyecto de .. no e~ necelOOO oñodir eua linee lo versión de dewrrollo de Gambas es porre del repos.nu. en la rama de desarrollo sólo está disponible si ha sido seleccionado para su U50 en ti proy«lo.gnulinu. por ejemplo. [sto significa que._of_vb.torlo of.org/gambaJ/210 http://_..gnulinex..:ulIl('ntación que se encutntra incluida en la ayuda de Gambas.. http://wiki.p.com/olan/hrtf>. estable esta documentación está siemp~ available. I J NOTAS 1 http://_.org/gombaJ/ ~ Inl. :ion UIJI (O l • En las imágenes anluiores podemos ver algunos de los objetos gráficos que están disponibles al stlrcdonar los dislimus cumponente. desde un pt>e)!o que ill.org/lic:enJing/lic:enHJ/gpl..

En el Capírulo I ~ vieron ya algu- nos delalles acerca de la programación con Ahora. Estos conceptos se explicarán con extensión en capítulos posleriores. principalmente. la sinlaxis e instrucciones mas importantes del lenguaje BASIC que Gambas. estudiaremos. Buena parte de estas instruc- ciones existen en el BASIC estandar y algunas otras son extensiones propias de . como vimos en el apartado El primer ejtmplo dd Capitulo J. US3 Gambas.• GamNs. Haciéndolo de este modo evitaremos las intrrferencias que puede suponer la explicación de conceptos relacionados con la programación gráfica y los componentes. Aunque sea más espartano. en este capItulo se usarán casi siempre ejemplos de código de consola.

• El proyecto puede contenrr otros archivos de datos. ete. e/nses (contienen el código en BASIC que ejecuta un objeto de esa clase) y Formularios (áreas donde se disena la interfaz gráfica de la aplicación y que se corresponden con las ventanas del programa).. documentos. Las aplicaciones grá- 11 ficas contienen Formularios y Clases. I Organización de un proyecto de Gambas Antes de comenzar con la programación básica hay que resumir algunos conceptos previos: • El código fuente de los programas hechos en Gambas está compuesto de uno o más archivos que forman un proyecto. letras. textos. A los datos que usa un programa se les asigna un nombre identificador. textos. Estos datos pueden ser de muchos tipos: números. y cambiar a lo largo de la ejecución del programa (en ese caso reciben el nombre de variables) o permanecer con un valor fijo durante todo el tiempo (entonces se denominan com/allles). Los archivos que contienen código en BASIC (Módulos y Clases) siempre están estruc- turados de la siguiente manera: • Declaración de variables.. • Subrutinas y Funciones. . etc. · los proyectos de texto sólo contienen MMu/os y/o e/mes.ProgromOCton visual con Software li~r_~ •• •• 2. o o o o o Declaración de variables Los programas manejan datos continuamente. • Los archivos de código pueden ser: M6dulos (contienen código en BASIC que se ejecuta directamente). sin código BASIC para ser ejecutado por la aplicación. Este proyecto se archiva en un direc- torio del mismo nombre. pero también pueden contener Módulos.

Eso produce programas ilegibles en cuanto empiezan a ser de tamaño medio y es una fuente constante de errores. Las variables que se declaren en una subrutina o función sólo se usarán dentro de ellas. Cuando terminen se destruirán. por ejemplo. están disponibles para ser usadas sólo dentro de esa subrutina o función. cadena de texto. Para dl'c1arar una variable en una subrutina o función se emplea la sintaxis: 11 El tipo_variable hace referencia al tipo de dato de la variable: número entero. Para evitar esto. Hay dos lugares donde se pueden declarar las variables. número decimal. Si se declaran al principio del archivo de código (sea un M6dulo o ulla Case) están disponibles para todo el código de ese archivo. fecha_nacimiento. etc. en todas sus subrutinas. sin haber expuesto al principio del programa un listado con las variables que se iban a usar. Progromación básico ! PRtv~) nombre variable AS . etc.BASIC permitía usar variables y constantes sin haberlas dedarado antes. etc. El nombre de la variable lo elige el programador libremente. dependiendo del ámbito en el que se vayan a usar. c. se debl' huir de nombres como a. es decir. Siempre es recomendable que sea algo que indique para qué se va a usar la variable. Eso permite utilizar el mismo nombre de variable dentro de distintas subrutinas y su valor nunca se confundirá o mezclará. Si se declaran dentro de una subrutina o función (en el siguiente apartado se verá con detalle qué son las subrutinas y funciones). Gambas obliga a dedarar las constantes y las variables antes de utilizarlas. b.. edad. Para declarar una variable al principio del M6dulo o e/lIse usamos la sintaxis: ISTATIC] (POBLIC tipo_variable 2. y usar. Es decir. altura.

color. etc. podemos declarar una variable que sea mímrro_t/e-PtTtllS. raza. tendremos algunas variables como color. no se pueden definir dentro de las subrutinas y funciones. pnras se declararía 5TATIC en el código BASIC del archivo de 1." 4 a 3. En este caso. peso. En pocas palabras se podria explicar con un ejemplo: si tenemos una clase perro. ete.1 dase perro.nW'<.Irnoclon YI~uol con . lodos los objetos perros tendrán 3 patas y cada uno seguirá con su propio peso. Sirve para definir un comportamiento especial en todos los objetos de una misma clase. y cada objeto perro tendrá su propio valor en cada una de es.as variables. Si se la declara como PUBl. de forma que si cambiamos su valor dl.. pero no será accesible desde otros ficheros del mismo proyecto. Al mismo tiempo.IC. La palabra STATIC se usa en los archivos de Clase.141592 ~c calidad AS Integer . Las constantes se definen sólo al principio de un archivo de Módrlio o Clase. La sintaxis es: ( POBLIC I PRIVATE ) CONST nombre_constante AS tipo_constante .xmwore llore Si se define la variable como PRIVATE.\ acceder a la variable desde un fichero del proyecto distinto a donde se dedarÓ.. al igual que las variables. Se verá todo • este comportamiento más adelante en este mismo capitulo. la variable mílllero_de. estará disponible dentro de todo el fichero. se podr.. pueden ser privadas o públicas. no en los Módulos.valor Por tanto. Veamos un ejemplo de todo esto: Gambas module file Archivo de Módulo con el nombre: ejemploVariables PRIVATE edad AS Oate PRIVATE altura AS Single PRIVATE OONST Pi _ 3.

Por tanto. Finalmente.PUBLIC SUB Subrutinal () DIM num AS Integer DrM nombre AS String edad-3D num _ 54 PUBLIC SUB subrutina2() DIM nwn AS Integer DIM apellido AS String edad-J2 nlUll 4 En este ejemplo vemos que las variables e<lad y altura se pueden usar en todo el archivo. Existen dos tipos de procedimientos: subrutinas y funciones.o'- _ . por tanto. donde ejemploVariables es el nom· bre que se le ha dado al fichero donde se ha declarado calidad. En BASle el código se organiza dividiéndolo en procedimientos.CIllidad. Una subrutina es un procedimiento que ejecuta algo. pero después de que se ejecute el END de cada una de esas dos subrutinas. Ejemplos de subrutinas 2. vemos que la variable calidad está definida como pública. edad valdrá 30 y. pero no devuelve ningún valor. Vemos también cómo la variable num está definida en las dos subrutinas. o U nWIl • en cualquier otro punto dd programa se o o o Subrutinas y funciones Es impensable escribir todo el código de un programa sin una mínima organización. El valor de nuro desaparece al acabar cada una de las subrutinas y. después de ejecutar la Subrutina2 valdrá 32. Programoción bósic. durante Subrutina I valdrá 54 y durante Subrutina2 valdrá 4. simplemente no existirá y si se hace referencia a producirá un error. después de ejecutar la Subrutina 1. Esto significa que desde cualquier otro archivo del programa se puede hacer referencia a ella mediante el nombre ejemploVariables.

puesto que no sabría por dónde comenzar. ) código que ejecut. por supuesto. Es decir.a la subrutina • Las palabras PUBLle y PRIVATE significan exactamente lo mismo que cuando se definen variables: determinan si la subrutina puede ser llamada sólo desde el archivo donde se ha codificado (PR/VATE) o desde cualquier archivo de la misma aplicaciÓn (PUBLle). Ya hemos visto en el capítulo anterior la sintaxis para declarar las subrutinas.. Si no hubie~ ra subrutina Mai'l. Se pueden pasar tantos parámetros como se desee a una subrutina. que se comportarán dentro de ella como variables declaradas dentro de la propia subrutina. Existen algunas subrutinas con nombres especiales en Gambas.p2 Tipo_da_Variable. pues· lo que se mostró cómo el entorno de desarrollo escribe automáticamente la subru- tina que el programa ejecuta al hacer un die del ralón sobre un botón. ete. Las variables pi.ottwore Libre serían procedimientos para dibujar algo en la pantalla. etc. Gambas daría un mensaje de error al intentar arrancar.. permiten pasarle parámetros a la subrutina. tstas son las siguientes: • Mai1l: existe en todas las aplicaciones de Gambas que sean de texto.Programación Vi5Uol. por lo que el programador no debe US<lr esos nombres. una función es un procedimiento que devuelve siempre un valor al terminar su ejecución. La sintaxis completa es: (PUBLIC I PRIVATE) SUB n<XDbre_de_la_subrut.'_OI!. Es el punto por el que empieza a ejecutarse el programa. declarándolos todos. p2. el proceso para pedir datos al usuario de la aplicación. no en las gráficas.-::. etc. •. Ejemplos de función serían el cálculo de una operación matemática que devuelve un resultado.ina (pl As As Tipo_de_Variable. tocar un sonido. . Sin embargo. desaparecerán al ejecutar el END final.

respectivamente.p2 As Tipo_de_Variable .l subrutina que el programa ejecutará..• _New y -ftee.• ) Tipo_de_Dato 2_ Programación bó~ica . su significado y utilidad. en ella sólo hay una llamada a ejecUlar la subrutina pinta_media pasándole los númel'O$ ente1'0$ 4 Y8 como parámetro. La sintaxis para declarar una función es la siguiente: (PUBLIC As I PRIVATE) FUNCTIOH nombre_de_la_función (pI As Tipo_ds_Variable. Sólo se encuentran en los archivos de clase.e4ia(valorl AS Integer.. el n'Cnto Opcn del formulario con el que se inicia la aplicación es la primtr.8) END PUBLIC SUB pinta_.! apresa. Comienza ejecutando la subrutina Main.con simplicidad la forma de funcionar de las subrutinas. que se ejecuta cuando d usuario de la aplicación hace dic con el ratón sobre el botón btnSa/ir. Ya hemos visto algun ejemplo en el capítulo anterior. debemos crear un nuevo programa de texto siguiendo los pasos explicados en el CtlpítuJo J. sirve par. como btnSD/ir_Qid:O. apartado El primer ejemplo: PUDLIC SUB Main () pinta_~ia(4. En el último apartado de este capítulo se tratarán espcc:ificamente los ~entos. • Objeto_El't'ntcr. la subrutina pinta_media muestra en la consola el ~ul­ tado de hacer la media entre los dos valo~ que han sido pasados como parámetros. valor2 as Integer) PRIN'l' (valad + valor2)/2 END • Aunque éste es un programa poco útil. al crearse y destruirst un objeto. En las aplicaciones gráficas. se ejecutan. se ejecutan automáticamente cuando al Objeto le ocurre el Evenlo. Veamos un programa de ejemplo (para probarlo.

Esto debe hacerse siempre al llamar a una función: la asignación sirve para recoger el valor que se devuelve.nei6n RE"1'URN re.calcula_Media(4.nei6n La declaración es casi idfutica a la de: la subrutina. Sin embargo.u.••• código que ejeeuu la fu. final'" calcula_Media(4. por tanto. (v~t. Veamos otro ejemplo que produce el mismo resultado que el anterior. pero usando una función: PUBLIC SUB Main() DIM final AS Single final . la fu. Es muy imponanle destacar la difen:ncia entrt la forma en que se llama a una subrutina y se llama a una función. Por motivos obvios. ..la_SUlllll33(valorl AS Integer. valor2 as Integer) AS Single RETURN ". ahora vemos que al llamar a la función se usa una asignación. PUBLlC f'UNCTION ealeu. la variable que recoge el valor que la función retorna debe declararse del mismo tipo de dato que el que devuelve la función. En el ejemplo anterior la funciÓn devuelve un dato tipo Single (un número real con decimales) y la variable final se ha declarado. de tipo Single. añadiendo dos cosas más: d tipo de: dalo que la función devuelve en la primera linea y la n«esidad de usar la sentencia RETURN dI" BASIC para indicar el valor a devolver.8) PRINT !iDal • "...8). En el ejtmplo anterior vimos que para llamar a la subrutina sólo se escribía su nomhn: con Sus parámetros entrr paréntesis.l~_de_ejecut:ar ".lorl + valor2)/2 En esta ocasión es la subrutina Main la que: se encarga de pintar m la consola d ~­ lado de la openu:ión.

775. con valores posibles entre -8.647.854.372.767. Revisemos ahora todos los que soporta Gambas: • Bao/can: es un tipo de dato que suele ser el resultado de una comparación.808 Y+9. con valores posibles enlre -1.7014118E+38. • 5/rort: representa un número entero con valores posibles entre -32.372.98846567431105E+307 y +8. • Strillg: se usa para almacenar una cadrna de texto. • Byte: representa un número entero positivo entre O y 255.2. • DrHe: sirve para almacrnar un valor de fecha y hora.7014118+38 y +1.768 y +32.483. según la configuración del ordenador. con decimales.147. En BA51C las cadenas dr trxto se asignan mediante dobles comillas. • Tllleger: representa un número cnlero con valores posibles entre ·2.648 y +2. Sólo acrpta dos valores: Fa/se y Trile (Falso y Verdadero en español). con decimales.036.036. 11 • Long: representa un número enlero con valores posibles entre -9.483.775. sólo conocemos algunos tipos de datos. Hasta el momento. • Single: representa un número real.147. al devolver el dato se representa en el formato local.223.223. 2 Tipos de datos Ya hemos visto a 10 largo de los textos anteriores el uso de variables y cómo se declaran. • FIOrH: representa un número real.854. lnlernamentr. .807. la fecha y hora se almacena en formato UTe.988465674311 05E+307.

Sin embargo. es conveniente usar un tipo Shorl. ConVErSiOn de tipos I Gambas IXrmite distintas conversiones entre tipos de dalos. String.operandol • operando2 En este caso. es decir. Por ejemplo. Por ejemplo: ~.l. para poder realizar la multiplicación. Son conversiones explicitas las que debe hacer el programador al esuibir el código para poder realizar 0lXraciones. Son oonvtrsiones implícitas cuando el propio intérprete de Gambas se tnCarga de gestionarlas. Single Q DDK operudol DDK operando2 operandol. Sen' el programador el que elija el tipo de dato con el que debe ser declarada una variable. 10 lógico es utilizar un dato de tipo bytt (el valor máximo es 255). por lo que a menudo se opla por tipos mayores para no cerrar posibilidades. • Objecl: representa cualquier objeto creado en Gambas. el intérprete convierte. si la edad a guardar es la de un árbol.ultado DDK a. Singlt. si se va a usar una variable para definir la edad dt una persona. ete. puede almacenar un Irrtt¡a.767. mezclar datos de diSlintos tipos.5 operando2-2 ~sultado SiDCJle IDteger a.• Vllrianr: significa eualquiD" tipo de data. tIC. Se dtbe tvilar su uso porque ocupa mis memoria que los ameriores y los cálculos con Variant son mucho más lentos. ya que puede haber árboles con más de 255 anos. . Siempre se ha de tender a USólr los tipos de datos más pequmos. . puesto que ocupan mtnos memoria y el microprocesador los maneja con mis velocidad. Sin embargo. el operando2 a un valor Single. de forma transparente para el programador. eso puede limitar las opciones de la aplicación. ptto no se conocen con más de 32. La forma de hactr la conversión puede ser implicita o explicita.

000 en binario es 11000011010100000. Cboo/(O). una cadena de texto vada o un valor nulo. Si este número es mayor de 255. 2. CDme("09/0ó/1972 01 :45: 12") es el día 6 de septiembre de 1972. sólo el formato inglés mesldía/aiio llOfils:minlllOs:segundos. se corta r("Cogiendo los 8 bits de menor peso. pero hay que tener cui- dado porque no admite el formato de fecha local. verdadero o falso. pero Cbyte( 100000) devuelve 160. Por ejemplo: . • CSllort(expresión). Cboo/(NULL). sus 8 últimos bits son 10100000.Devuelven Fa/se las siguientes operaciones: Cboo/(""). Si no sal>emos ope- 11 rar con números binarios lo mejor que se puede hacer es evitar este tipo de conversiones que resultan en valores tan "sorprendentes". /meger y Long. producirá un error.Estas conversiones se hacen mediante unas funciones que están incluidas en el BASIC de Gambas. Programación básica . Cboo/("Gambil5"). El resultado será falso si la expresión es falsa.767. Clm(expresióII) o C/meger(expresióll). ble. • CByte(expresiólI): convierte la expresión en un valor tipo Byte. . la conversión se hará siempre que sea posi. En el caso de CShort la conversión se realiza igual que para CByte. Primero se con- vierte la expresión a un número binario de 4 bytes. Será verdadero en los demás casos. que pasado de binario a decimal da lugar a 160. Es decir. toste ¡. El valor 160 es debido a que el número 100.Devuelven Trile las operaciones: Cboo/(1). Por ejemplo. pudiendo producirse resultados extraños igualmente si la expresión resulta en un número mayor de 32. la expresión en un número de tipo SlIoTl. • CDme(cxpresióll): convierte la expresión en una fecha. Evidentemente. respectivamente. Cbyte("l r) devuelve 17.S el listado de funciones de conversión existente: • CBool(expresióll): convierte la expresión a un valor booleano. si no lo es. el número 0. y CLo/lg(expresión): convierten.

Str$(CDllIe("09/06/1972 01 :45: 12")) devuelve "06/09/1972 01:45: 12" si la con- figuración local está en español.58) devuelve la cadena de texto 1. Se pueden definir matrices que contengan cualquier tipo de datos> pero con la condiciÓn de que lodos los elementos de la matriz sean del miSmo tipo. finalmente.presi6n debe usar el punto (.) como separador decimaL • CStr(expresión): convierte la expresión en una cadena de texto sin tener en cuenta la configuración local. • 5trS(expresiófl): convierte la expresión en una cadena de texto. a o a a o MatriCES En numerosas ocasiones.nogramoclon V. Str$( /. .WC!I con . Intenta convertir la expresión en un tipo Dnu. cuando se intenta resolver un problema mediante la programación> surge la necesidad de contar con la posibilidad de almacenar distintos datos en una misma variable. si tampoco puede en un número enlero y si. Por tanto. por tanto. O CSlr(CDale("09/06I1972 0/:45: 12:)) devuel- ve "09/06/1972 O/ :45: Ir.) y no la coma (.¡gle(expresión) o CSng(e. tampoco puede la convierte en un tipo Boo/eall. puesto que en este idioma la costumbre es • escribir las fechas en la forma día/mes/año. Cslr( 1. independientemente de si la configuración local indica que el separador decimal es el punto Ola coma. La solución más simple para este problema son las Matrices o Arm)'5. DllIe o algu- no de los tipos numéricos. Por tanto.58) devuelve la cadena de texto 1. Val es la función opuesla de Str$ y. dependiendo del contenido de la expresión. también tiene en cuenta la configuración local del ordenador en el que se ejecuta.58. Del mismo modo.58.)()lfWOre u~e • CS¡. No hay más límite en la dimensión de la matriz que la memoria del ordt'nador y la capacidad del programador de operar con matrices de dimensiones grandes. La c). respectivamente.xpresiÓ'I) y CFQ(lt(expresión) o Cjlt(expresión): convierten. si la configuración local está en espal'iol. la expresión en un número del tipo Sirlgle y Flom. teniendo en cuenta la configuración local. • Vill(expresión): convierte una cadena de texto en un tipo Boolean. si no puede en un número con dKimales.

6 Alumno[Columna. en la matriz: Listndo!3! existirán los valores correspondientes a Lislado!O]. Hay que tener en cuenta que el índice .hetes las dimensiones de la matriz:. fuera del límite.omienz:a a contar en el 0. . ya que hacen falta funciones para añadir nuevos elementos a la matriz.ada una de las celdas de la matriz.ring Para acceder al valor de ..or. Lis/mio!11 y Listado!2].terísticas de la aplicación.ilmente por filas y columnas. no en el l. hay que referirse siempre a Sil índice. J. Si se intenta acceder a Listado{J] dará un error Out ofBOlmds. FilaJ-NHanolo Pérez Rodriguez" • Hemos visto que hay que declarar estas matrices con las dimensiones máximas que van a tener. Es dcrir.lO¡ AS String Dim columna AS Integer Dim fila AS lnteger Columna" 2 Fila. excepto Boolean. JI AS Single DIM Edades[40) AS Integer PRIVATE Esto_no_hay_quien_lo_maneje[4. borrarlos o saber el número de elementos que tiene ésta. se desconoce la dimensión que hará falta para la matriz:. S. 2. añadiendo entre ... 6. Eso supone que el intérprete de Gambas reserva la memor13 necesaria para ellas al comenzar el uso del programa. Con estas matrices se trabaja de forma distinta a las anteriores. Para solventar esta posibilidad Gambas tiene predefinidas matrices unidimensionales dinámicas de todos los tipos de datos. Sin embargo... Por ejemplo: Dim Alumnos[4.La sintaxis para trabajar con matrices es la misma que para las variables. Algunos ejemplos: DIM Notasl2. En una matriz: de dos dimensiones lo podemos identificar fá. 2] AS St. hay ve<::es en que.. por las cara.

La siguiente instrucción inicializa nombres para poder usarlo. .Clear PRINT nombres. • f\ . por ejemplo. Gambas tiene las operaClones habituales en casi todos los lenguajes de programación: . resta. 3 Operaciones matemáticas Cuando se trata de trabajar con números. .Count 'pintará 2 PRINT nombres(ll 'pintará "Antonio" 'La siguiente instrucción vaciará nombres: nombres. Asi podemos añadir valores a la matriz: nombres . 'La siguiente instrucción pintará 3 en la consola PRINT nombres. -. +. Es un paso previo obligado: nombres .COunt 'pintará O ••••• 2. multiplicación y división.Md( ~Manolo") nombres.Remove(l) PRlNT nombres.Progromoción vi~uol con Software libre Con este ejemplo veremos el uso y funciones más usuales al trabajar con matrices dinámicas: DIM nombres AS String(] .Add(~JuanW) ) nombres.COunt • 'La siguiente instrucción borrará la fila de "Juan": nombres. para la suma. y /~ usan.Add(uAntonio W 'Count devuelve el número de elementos de la matriz.NEW Stringll . es el operador de potencia. respectivamente. 4 f\ J = 64.

oll1/(llIímf'ro): devuelve la parte entera de un número. Muy importante: antes de usar Rlld es necesario ejecUlar la instrucción Rarrdomiu que inicializa el generador de números aleatorios.o Para la división hay dos operadores adidonales. Programación básico . Sgrl(mímero): devuelve el signo de un número. \ o DIVy MOD.. ruímero2. • • ROlmd(lllÍmero. la parte entera del resultado de la división y el resto. o o Rud([mÍlrimo/.): devuelve el número mayor. · Mill(mímero/. que devuelven. .): devuelve el número menor.. Es decir. el número estará comprendido entre Oy l. mímero2. se obtendrá el mismo número en sucesivas ejecuciones de Rud. el número eslará comprendido entre el Oy ese valor. 2. Si no se expresa ningún valor para mínimo y máximo.. 9 D/V 2 = 4. • Mllx(7lIímf'roJ.{máximo)): devuelve un número aleatorio comprendido entre minimo y máximo. Aparte de estos operadores existen [as siguientes funciones matemáticas para realizar cálculos más complejos: • Abs(mímero): devuelve el valor absoluto de un número. respectivamente. . Si no se hace. Si sólo se expresa un valor. o Dec(mímero): decrementa un número. Frac(mímero): devuelve la parte decimal de un número.decimllles): redondea un número con los decimales desea- dos.. o • rrlc(mímero): incrementa un número. 9 \ 2= 4 Y9 MOD 4=/P.

O. En Gamb. scr.p OperacionEs Ioglcas Para realizar operaciones ~nlrt variables de tipo Booleat/ o expresiones cuyo resultado sea BooIean. OR. Veamos un ejemplo de su uso: Dim Nombre AS String Dim Apellidos AS String Nombre ~Manuel ~ Apellidos • ~Álvarez G6me z H M . falso. sirven para unir condiciones del tipo: color ('$ verde y no es marrón.l fácil usarlas y entender $U funcionamiento con una simple lraducción al español de las tres primeras: Y. esta operación se utiliza en cálculos con números binarios. En la • práctica."n. en cuyo caso seguro que conocemos perfectamente su funcionamiento. existen algunas instrucciones similares a las que podemos . Es decir. cuando los dos operandos son iguales. que se escribirla: El caso de XOR es más dilleí] de entender puesto que es una operación algo espe<:ial llamada OR exclusil'o. PRINT Apellidos .-r su comportamiento allralarse de las operaciont:S binarias más bási- cas. Antes de proceder a su listado.\. NO. no nos rcsultar. tanto si se trata de aplicaciones de bases de datos. 2 4 Manejo de cadenas Una de las tareas más habituales en los programas informáticos es el uso de cadenas de texto.en casi lodos los lenguajes de programación.i dificil identificarlas y sabc. destacar que existe un ·operador" de cadenas de texto que permite concatenarlas directamente. El resultado de una operación XOR es \'erdadcro cuando los dos operandos son distintos y. se trata del simbolo &.como para la simple salida de mensajes en pantalla. Si lenemos conocimientos de lógica y numeros binarios. En caso conlrario.»se han implementado todas las funciones de cadenas de te:<to del BASIC e'ltándar más las que están presentes en Visual Bask. NOT YXOR. Nombre . Se trata ÁND.

r("Gambas es basic "bas") ff . • RinStr (Cadena. Inicio J): busca la subcadena dentro de la cade- • na y devuelve un número con la posición donde la encontró.onio" insertará una tabulación entre los dos nombres. • Chr$: devuelve un carácter a partir de su código ASCII. ya que en la tabla ASCII el código 10 corresponde a un avance de línea (Une Feed). devuelve un 4. "bas".La salida en consola será: Álvarez G6mez. S) devuelve un J 1. Si se da el valor 1uicio.r("Gambas es basic". SlIbcadena (. Esta función es útil para añadir caracteres especiales a una cadena de texto. por ejemplo: PRINT "Manuel ff & Chr$(lO) & "Ant. sólo que empieza a bUSC3T de derecha a izquierda en la cadena. la búsqueda empezará en esa posición. mientras que: PRINT Inst. SlIbcadena [ . Manuel Veamos ahora el listado de las funciones disponibles para manejar cadenas de texto: • Asc(Cadella. Por ejemplo: PRINT Inst. • hlSrr (Cadena. Inicio J): funciona igual que /nStr. 2_ Programación bósico . devuelve el c&hgo del primer carácter.¡Posició'lj): devuelve el código ASClll del carácter que está en la posición indicada en la cadena dada. Si no se da la posición.

]): sustituye en la cadena patrón los símbolos &]. • Right$(cadena. Por ejemplo: PRINT Replace$(ULinEx es una distribución de Linux u . cada vez que encuentra el texto patrón por el texto reemplazo.Programaclor vl~ual con Software Libre • Lcase$(Cadena): convierte una cadena a minúsculas. Evidentemente. IILin"..nJ): devuelve una cadena que empieza en posición y mide n caracteres. reemplazo2. Left$(cadena. dentro de Cadena.uManuelU. posición (. Si no se especifica n. . Por ejemplo: PRINT Subst$(UEl alumno &1 tiene &2 añosu.U8 U) da como salida la cadena: UE1 alumno Manuel tiene 8 años u ... la cadena devuelta contendrá todos los caracteres a partir de posición. &2. reemplazo] (. I'gnu/Lin") • pinta el texto: Ugnu/LinEx es una distribución de gnu/Linux U • Subst$(Patrón. reemplazo2. • Replace$(Cadena. reemplazo): reemplaza.. . el potencial de esta instrucción se muestra cuando las cadenas de reemplazo son variables de tipo String. p. por las cadenas reemplazo]. patrón.n): devuelve los últimos n caracteres de una cadena.n): devuelve los primeros n caracteres de Llna cadena. • Ucase$(cadena): convierte una cadena a mayúsculas. • Mid$(Cadena...

el separador se considera la coma (." & texto[2] & & texto[3] u. • Space$(n): devuelve una cadena que contiene n espacios en blanco." & texto2[3] 2 Programo Ion bO I o . Las partes de esta matriz se obtienen al trocear la Cadena cada vez que se encuentra uno de los Separadores. Ignorar_nulos}): devuelve una matriz de cadenas de texto.).u '~ " PRINT texto2[O] & & texto2[1] & 11 . u . • String$(n. • Ltrim$(cadena): elimina los espacios en blanco de la parte inicial de una cadena. patrón): devuelve una cadena que contiene el patrón concatenado n veces. • Split( Cadena r.• Len(cadena): devuelve la longitud de una cadena. • Ignorar_nulos es un valor True o False. Si no se especifica ninguno. U) u u = Split(UHabía una vez iun circoi u Ui") 11 PRINT texto[O] & U. • Trim$(cadena): elimina todos los espacios en blanco de una cadena. • Rtrim$(cadena): elimina los espacios en blanco de la parte final de una cadena. Escape." & texto[l] & U. habría que colocar el Escape mar- • cand el principio y final de la parte en la que debe ignorarse el separador. e indica si se deben ignorar o no las cadenas que resulten vacías como consecuencia del troceado. Separadores. Si en algún caso se quiere incluir el Separador en alguna de las cadenas separadas. & texto2[2]~ " & U. Veamos un ejemplo que explique mejor el funcionamiento: DIM texto as String[] DIM texto2 as String[] texto texto2 = Split(UHabía una vez un circo u .

ldor es el espacio en blanco.un circo En el segundo caso se puede ver cómo. Sin embargo. 5 Control de tlujo Son muchas las ocasiones en que el flujo en que se ejecutan las instrucciones en un programa no es adecuado para resolver problemas. se ejecuta otro cosa. según se las va encontrondo. tomar decisiones.. Este tipo de acciones se denomina con- troj de flujo y el BASle de Gambas proporciona un buen juego de sentencias para manejarlo. THEN .vez.. en caso controrio..una.Programación visual con Softwore libre devuelve: Habia. aunque el separ. ELSE Es la sentencia más común paro tomar una decisión: si se cumple una condición. ••• •• 2.una.vez.un H8bia. Su forma más básica es: IF Ell'presi6n THEN ""''' o si lo que se ejecuta es una sola instrucción: IF Expresión TREN sentencia a ejecutar .. etc. no se ha separado el texto un circo al estar rodeado del carácter de escape. repetir cosas. o '1 IF .entonces se ejecuta algo. Todo el código BASIC que hemos visto hasta ahoro ejecuta sus instrucciones de arriba abajo. con frecuencia. habrá que vol- 11 ver atrás.

o- 11 END" IP Edad > 20 'ftlEH PIU1fr "AdultoIP Edad < 2 AMO Bd. 1 TBEN BLSE IP ExpresiÓII.ad >O 'l"HEN !:LSE IF Edad < 12 THEN PRIN'l' "Ni.eger Ir Edad > 20 TBEN PlUJfT -Adult.• 1 J Algunos ejemplos de uso: DIM Edad AS Int. se imprimirá un resultado distinto. I OR IP } Expresión •.La sintaxis completa de la instrucción es: IP Ezpresi6cl I { AMO IP I OR Ir } Ezpred6cl . XIOfl l.ño- ELSE IP Edad < 1B 'l'HEN PRIN'l' "Joven- Dependiendo del valor que tuviera la variable Edad al llegar al primer IF.•..IOSICQ . 1 ( ANO IP .".

. CASE O ro :2 PRlNT ~8inqo.qlresi6a ( 1'0 &xpresión f2 ) ( • . que es mucho mas apropiada.Programoción viwol . Su sintaxis es. Pan. Esa estructura no es cómoda de lef:r ni produce un código limpio. produdtndo un lf d("f¡tro de otro (IF anidados). estos casos aisle la sentencia SELEcr.: SELEC'1' ( CASI: I EXpresión r CASE E. ya puedes votar" CASE 13 1'0 11 PRINT "Joven~ CASE ELSE PRINT "Adulto" "'" SELECT Se trata de un código mucho mis fácil de leer que el anterior. .ión I 1'0 Expresi6n 12 1 [ . 1 • •• J 1 CASE E~pre.011 Softwore ülxe En el caso anterior vimos que en ocasiones el flujo dd programa necesita revisar varias condiciones sobre una misma variable.. ••• 1 DEl'AULT } I { CASE ELSE I Veamos cómo se aplica al mismo ejemplo anterior de las edades: 11 DIM Edad AS ll1t.eger SELEC'1' CASE edad.

Por ejemplo: DDK D AS POR D - ID~eger 10 Te 1 STEP -1 Si se quiere interrumpir un bucle en algún punto. a no ser quC' se especifique un valor a STEP. Se pueden espedficar valores negativos.10 ro 1 STEP _1 PRlNT n NEXT FJ bucle aeobaria <. se puede usar la sentencia BREAK: DIM n AS Integer 11 POR Il . que permite saltarse pasos en d bucle: DIM D AS Integer FORn-1Ta4 IF n-2 TREN CONTlNUE PRINT n . de (orma que se convertirla en una cuenta atrás.noo n valí"". la sentencia fQR es la solución: FOR variable .FOR Cuando se hace necesario contar o realizar una acción un número drterminado de veces. '1'0 EIpresión [ STEP Expresión J El bucle incrrnlenta la Variable de uno en uno.Expresión. 3 Y no se escribirlan los últimos 3 numeros. Tambitll se dispone dI" la sentencia CONTINUE.U:I.

AddC-Aaul-) Matriz·A6dC-Rojo-) Natriz·A6dC.: POR UCB Variable 1M Expresión Pongamos un ejemplo u$3ndo las matrices dinámicas que ya hemos visto en este capillllo: DrM Matriz AS StringlJ DIM Elemento AS String Matriz . la diferencia estriba en que si la condición necesafia para que se ejecute el código es falsa desde el principio.E y REPEAT Cuando se quien: repetir la ejecución de una porción de código en varias ocasiones dependiendo de una condición.Se saltaria el 2 al escribir los valores de n. tenemos dos instrucciones distintas: WHILE y REPEAT. con REPEAT se ejecutara una va y con WHILE no se ejecUl3rá nunca.. La sintaxis de ambas es: . Escribirla como salim: AzulRojoVrrde.NEW Strinq[l • Matriz. WHIl.Verde·) POR EACII Bl~to XIf Natris PRIft El_nto.lnlC del bucle fOR que usa al rt<:orur dementas de una colección. Existe una 5t vilri. como una matriL La sintaxis en este caso es. Su oomponamiemo es casi idéntico.

.'" . . El uso de estas estructuras puede ser peligroso. instrucciones UNTIL COndición En el caso del bucle WHILE existe una variante de la sintaxis consistente en sustituir WHILE por DO WHILE y WEND por LOOP.HIIILE COndición instrucciones y . estaríamos ante un bucle infinito y el programa entraría en situación de bloqueo.. Mundo N i a • PRINT NHola Hundo N i a UNTIL a > 10 Este ejemplo producirá el mismo resultado en la ejIXución del bucle WHILE que en el del REPEAT.•. . depende del programador elegir un formato u otro.'" .. Veamos un ejemplo: .10 PRINT NHola . . en ambos casos escribirá diez veces "Hola Mundo" junto al valor de la variable a que se irá incrementando de 1 a 10. Es exactamente lo mismo.. . . DIM a AS Integer HIIILE a <. Si durante la ejecución del bucle no hay forma de que la condición pase de ser verdadera a falsa.

pero lo habitual es que la mayor parte de las veces no lo haga m el primer inten- to. y es una de las tareas más importantes a reliizar.Fo. además. Tanto si se es un programador aperimentado como si no. eliDE de Gambas dispone de distintas herramientas de dqm- ración. tan sólo hay que colocar el cursor del ratÓn en esa Unea y pulsar la teda F9 o el botón con el slmbolo de la mano levantada. puesto que la aplicación transcurre en distintas ocasiones por la misma porción de código y es posible que el falJo no se produzca la primera vez que se eje- • cUle ese código. que está en la parte superior de la ventana de código. Es decir. pero los fallos en la lógica de la ejcwción del programa se pro- ducirán siempre. lo usual es comprobar si funcio- na.(h.. señalar sitios nl los que el programa se parará para permitir vtr d estado de las variables y en qu~ punto de la ejecución se enCUnltra. por instrucciones de control de flujo como las que hemos ViSIO en este capítulo.o. AS f~l una linea de código. parando la ejecu- ción en la linea ni que M: produce. Para facilitar esta tarea..1'un1o de interrupción en lo linea .j( sta 1ot _ _ (hc1C 1 Para fijar un punto de interrupción en otll .. la dificultad en encontrar los errores es mayor. el entorno de desarroUo suele darnos mensajes indicativos del problema. Las Uneas en las que se fija un punto de interrupción tienen el fondo en rojo. los fallos de sintaxis son cada vez menos comunes. Saber encontrarlos y corrtgirlos 1:5 lo que S(' denomina depuración. \1 Otll . .p oepul'acion En €I DE de Gambas Una VC'Z escrito parte del código de un programa.h. 1'(8. .o' r ••tl de código. Cuando esa lógica pasa. Cuando son fallos de sintaxis. La primera de ellas es la posibilidad de fijar puntos de interrupción.1)elO AS .. 1'Ies1~. Cuando se adquiere una cierta soltura con el lenguaje. los fallos son parte de la rutina. figurg 1.

aparecen tres nuevas pestañas en la parte inferior de la ventana de proyecto. Junto al botón verde CIlt se encuentra un botón de Pausa. En este caso. Por tanlo. como se explicó en el capitulo anterior. La ejecución del programa. y otro más de Stop que permite detenerla en cualquier momento. que permifigura 2. aUlla subrutina o a una fundón. que pulsemos F8. parece producir el mismo efecto (su tecla rápida es Mayúsculas + F8).La misrrna opm¡ción que: crea el punto la elimina. Finalmente. Hadendo esto. sin que veamos el flujo del programa por el procedimiento. con estos dos botones podemos elegir cuando lleguemos a la llamada a un pJ'lXffiimienlo. Así. Ejecución del programa te parar la ejecución. o el icono que muestra la flecha entrando entre las Uaves. cuando pausamos la ejecución del programa. se puede pulsar la tecla de función F8 o cualquiera de los dos botones que se encuenttan a la derecha del símbolo de Stop. si quttmlO$ depurar tambi~n ese procedimiento O simplemente e~­ cutarlo y pasar a la siguiente línta de código. En la pestaña Pila se ve el listado de llamadas enlre procedimientos que se han producido hasta llegar a ese punto del programa. Si hubi~ramos 11 pulsado F8 habrfamos entrado en la subrutina y visto también paso a paso eómo se ejecutan las instrucciones. El botón que está justo a la derecha del Stop y que muestra una flecha saltando por encima de las Ila· ves. En la pestaña Local se ven todas [as variables del procedimiento que se está ejecutando y el valor que tienen en ese momenlo. d entomo de desarrollo saltará a la primer'a linea que se deba correr e irá ej«utando Unea a !inta cada V(l. desde la veolallll Proyecto. es decir. Si se quiere correr la aplicación ejecutando una a una las instrucciones para ir observando por dónde transcurre el flujo del programa. se arranca pulsando en el simbolo verde de Play de la ventana de Proyecto (o pulsando la tecla de función F5). pulsando F9 de nue'iO d fondo rojo d~pareccrá. pero no es asl: el comportamiento cambia cuando el programa llegue a una llamada. este icono ejecutará la llamada y todo lo que tenga que hacer la función o subrutina en un solo paso. podemos saber a través de . mencionado anteriormente.

Y ~ momenlO de la pausa. - " grama tmga declaradas para ver cuál es el resullado o el valor que lienen en el "" F'9UfV 3. escribir y Ittr datos. con INPlIT 51 que hay un buffer intermedio. 2. Gambas trata los ficheros como un flujo de datos (la palabra exacta para esto es Stremn).. de Archivo FOR REAl) I IRPUr 1 ( MRtftl 1 otn'PUT I ( CREA'1'E I APPEHD [lfM"CH I Abrimos un archivo con dislinlas finalidades: • REAO o INPUT: para leer datos. Las operaciones tradicionales con un fichero $On abrirlo. 6 Entrada y salida: ficheros En este aparlado veremos la forma más común de trabajar con ficheros en Gambas.. . en la pestai'la O~r­ V3r podemos introducir cualquier expresión en BASle. Veamos cómo se usan: Archivo . crearlo. • WRITE o OUTPUT: para eS<:ribir datos. puesto que todos son ob~tos de tipo Strtam. en el primer caso no se usa buffer de datos.OPElf lk:ab". con OUTPUT s( se usa. de lo __ lona Proyedo. . con lo que el código para manejar un fichero es igual al códi- 11 go para manejar una conexión de red o un puerto de comunicaciones. Finalmente. el fichero debe existir antes de abrirlo o dará un error.. lo que tiene una implicación muy cómoda: todos los flujos de datos se tra- lan de igual manera. Ptitoñas loco!. incluyendo operacionn con las variables que el pro- I ~· .ProwamociÓl1 visllOl~ SoHwore ubre qué pasos se ha llegado a esa instrucción. con WRITE no hay buffer de datos.. • CREATE: si el fichero no existe se crea. Si no se usa esta palahra.

Gambas lanzará los eventos (que veremos más adelante) File_Rf'<ld y File_lVrite en caso de que se pueda If'('r y escribir en el archivo. dependiendo de algunos signos de puntuación que se pueden colocar al final de la sentf'ncia: • Sí no hay nada desputs de la ExpresióIJ. CLOSE [ . . sin espacios. PRINT [ 'Archivo . la salida de la siguiente instrucción PRINT será en una linea nueva. • WATCH: si se especifica esta palabra. como se ha visto en distintos ejemplos a lo largo de todo este capítulo.• APPEND: los datos se afladen al final del fichero.Si se utiliza una coma en lugar de un punto y coma. la Expresión en el Archi\'o abierto anleriormente. Ahora. cerremos un Archivo que ha sido abierto con la sentencia OPEN. tecleamos la expresión en la consola. 2 Programación básico . Por tanto. la siguiente instrucciÓn PRTNT se escribirá justo detrás de la salida anterior. se añade una nueva línea al final. lo qu~ 11 permite concatenar expresiones en una misma línea usando distintas sen- tencias PRINT. 1 Archivo Escribimos. se añade un. J Expresión J Si no se especifica ningún archivo. lineas o tabulaciones intermedias. con lo que tambitn se pueden concatenar expresiones en una misma línea. • Si hay un punto y coma detrás de la ExprcsiólI. se añade un espacio entre las expresiones. convirtiendo en cadena de texto.! tabulación. • Si hay un punto y coma doble. la instrucción PRINT admite un cierto conlrol de cómo se colocan las expresiones.

. Eaf ( Archivo ) Devuelve True (verdadero) cuando se llega al final del Archivo y Fa/se (falso) en caso contrario. Los datos deben estar separados en el archivo por comas o en distintas líneas. Si no se especifica el Archivo. un dalo y asignamos su valor a Variablel. Variable2. leemos los datos desde la consola. No se debe usar para leer de flujos binarios. el numero de caracteres que se desean sacar en cada operación de escritura. etc. con el parámetro longitud. J Variable En una línea de lexto enlera del Archivo.Prograrr :ión - VIS Jol con 50ft vare libre --- Seguidamente. escribimos. como en el caso de archivos binarios. J Leemos. . Al contrario que con PRINT. también puede usarse con cadenas de texto y permite indicar. Variable2 . sin convertir en cadena de texto.. Es una instrucción que suele usarse en lugar de PRJNT cuando los datos a escribir no son cadenas de texto. se puede fijar la Longitud de la cadena a leer. esperando que el usuario de la aplicación los introduzca. LINE INPUT r 'Archivo . desde un Archivo. J Variable I . la Expresión en el Archivo abierto anteriormente. le asignamos a la Variable. no se pueden usar signos de puntuación para controlar la posición de la escritura. Longitud 1 En cualquier caso. Sí ésta es una cadena de texlO. NRlTE [ 'Archivo . INPUT I 'Archivo . Leemos del Archivo datos binarios y les asignamos su valor a la Variable. 11 READ ( 'Archivo. J Vadablel r . J Expresión [ . Longitud) Se puede decir que es la instrucción opuesta a WRlTE.

lNPU'l' WHILE MOr Eof(Archivo) LIME INPUT 'Archivo.Lof ( Flujo ) Si el Flujo de datos o un archivo.e 11 ~.. PRIHT ~Tengo un byte..c/pasawd J lo . devuelVe' el número de byto que puedt:n 1«rsC' de una sola vez.:J • PUBLIC SUB File Read() DDt iByt. veamos algunos ejemplos de uso: Leer dato..:J DIM Archivo AS File .ng Archho • OPEM "/etc/~swd~ P'OR...eI.e "'" 'Lee el contenido del fichero Iet.. Line. Si en lugar de un archivo o un Socker de una co0ai6n de red o un objelo Proass.. Una Ve'Z vislas las SC'nlencias más comuno para el manejo de flujos de dalos. net en el proyecto) .. i8yt. El evento File_Read .. AS Std..oli que l~: . i8yt. consol. PRIHT Linea CLOSE Archivo . (Requiere seleccionar el componente gb. devuelVe' su tamaño. . de un puerto .e produce cuando baya dat.est..."1e. DIM Archivo AS File DIM Line.r.e AS Byte READ 'Archivo. en l .

'CATCH: se coloca al final de un procedimiento.Me> fue posible el1. Por ejemplo: Borrar el archivo aunque PO e. Las instrucciones para ello son: • TRY Se"rlllóll: ejecuta la sentencia sin lanzar el error aunque se produzca. Gambas implementa las instrucciones necesarias para caplurar los errores y procesarlos según los deseos del programador. tanto si ha habido un error en el procrdimiento como si no lo ha habido. TU 1tn. como intentar borrar un fichero que no existe. el 11 programa continúa por la instrucción que haya desputs del TRY. Las instrucciones que sigucn a continuación se ejecutan siempre. Las instrucciones que siguen a continuación se ejecutan sólo si se ha producido un error ellla ejecución del procedintiento (incluyendo si el error se ha producido en subrutinas o funcioncs llamadas desde el miSntO procedimiento). se producen errores. en la mayor parte de los programas. 7 Control de EI'"J"Or-es Es seguro que. bien por el propio nujo de la ejecución. tanto si hay error como si no. tn alglln momento. bien por acdones dd uSUólrio del prognama. hacer una división por cero.ito IP ERROR '1"SEIf PRIIft' . La forma de hacerlo es implcmell1ando un control de errores para que la aplicación sepa lo que debe hacer en esos casos. Se puede saber si existe error funsultando La sentencia ERROR que valdroi verdadero ° falso.r el archivo· • FlNAUY: se coloca al final de un procedimiento.leba/~ . etc.iat. ha de colocarse delante de CATCH. . Es evidente que ése es un comportamiento que d desarrollador no desea y debe poner las medidas oportunas para evitarlo.L ·/tlap/pn. a continuación. En lodos estos casos. conectar a un servidor web que no responde. Si existe una instrucción F1NALLY.2. Gambas muestra un mensaje: en pantalla y.l"". el programa se rom~ y deja de funcionar. Cc::q:lrobar ai ha tenido é.

etc.Veamos un ejemplo de FINALLY y CATCH: . A día de hoy. s• ejecuta s6lo . incluso CLOSE I Archivo . Este IÍ¡xJ de programación permite re. condiciones. se siguen desarrollando .• hay error CATe" . .olver la mayor parte de los problemas y. Esto significa que los programas tienen eIlIujo que hemos visto hasta ahora: empiezan en un punto de una subrutina y van ejecutando las instrucciones de arriba a abajo. Mostrar un archivo en la consola SUB PrintFile(Nombre_Archivo AS String) DIM Archivo AS File DIN Linea AS String OPEN Nombre Archivo FOR READ AS 'Archivo WHILE NOT EOF(Archivo) LINE INPtrI' 'Archivo. de hecho.. se ha estado usando durante muchos anos. PRINT Linea Linea FINALLY Siempre se ejecuta. con los saltos correspondientes a las llamadas a procedimientos y distintas funciones de control del flujo como bucles. a Programación orientada a objetos con Gambas BA$IC es un lenguaje de programación estructurada. i hay error PRINT "Imposible mostrar el archivo EHD Nombre Archivo • • 2.

Después. facilita la depuración y la colaboración entre distintos programadores en los proyectos que son de gran tamaño y.1ndo la programación orit'ntada a objt'los. un acelerador. Por todas estas razones. Sin embargo. etc. el volante respondería a un giro actuando sobre el eje de las ruedas. tiene un potencial mucho mayor que la programación estructurada. etc. Us. como Smalhalk. como hemos visto. en la que los objetos.1 definición. para la programación gráfica y el uso de la mayor parle de los componentes que se añaden al lenguaje. crearíamos cada uno de los objetos para crear el coche: un volante. Podemos ver cómo funciona todo esto en Gambas pensando en el caso de que tuviéramos que escribir un programa que simulara el comportamienlo de un coche. de programación estructurada. como BA51C o e. el motor respondería incrementando sus revoluciones si recibe una presión del acelerador. dt'finiríamos cada una de las partes del coche mediante un archivo de clase en el que escribirfamos el código BASIC nece~ sario para definir las características de esa parle y la interfaz con la que se comunica con el mundo real. Cada uno de esos objetos respondería a cierlos mensajes. Los lenguajes que adoptan este paradigma. personas y animales nos movemos. como BASIC. un acelerador. escribiendo el código t'n Módl¡/OS. en muchos aspectos. un motor. Es más.utamos accio- nes. Por ejemplo. lal y como ocurre en la vida normal. y basándonos en eS. es común que se aiiadan características de programación orientada a objetos a lenguajes que. un motor. cuatro ruedas. Por ejemplo. Java o C++. definiríamos cómo es un volanle. La programación orientada a objetos se usa cada Jia con más frecuencia porque permite una mejor división de las tareas que un programa debe hacer. ete. cómo es una rueda. desde finales de Jos años 70 se ha venido trabajando también en otro para- digma de programación: la programación orientada a objetos.aplicaciones con lenguajes. cómo es un asiento. La ejecución de estos programas se basa en la interacción de los distintos objetos que definen el problema. varios asientos. 11 Gambas permite hacer programas estructurados a la vieja usanza. Y también posibilita la programación orien~ lada a objetos mediante el uso de Clases. en un principio no la tenían. enviamos mensajes unos a otros y ej('{. . intentan modelar la realidad. no hay más alternativa que el uso de objetos.

por ejemplo: cuadro_de_texto_mllltilíltea que herede de cuadro_dejexto.Cada vez que crealnos un objeto basándonos en el archivo de clase que lo ha definido.c1s: . le añadimos un Módillo con un nombre cualquiera y dos archivos de clase. tste es el código que debemos escribir en el archivo de clase SerVivo. a uno lo llamamos SerVivo y a otro Hombre. A continuación. supongamos que definimos la clase cuadro_de_texto con ciertas caraeterfsticas como tamaiío de texto. Eso significaría que un cuadra_de_texto_multilílJea es un Cfwdra_de_texto al que se le añaden más cosas. O:m Gambas podemos. A continuación. son independientes unos de otros con sus propias variables internas y respondiendo a las distintas acciones según hayan sido definidos todos en la clase. Todo el comportamiento y propiedades del cumlra_de_texto ya están codificados y no hay que volver a hacerlo. podemos crear objetos de esa clase y son clIadros_dejexto. Gambas class file PRIVATE patas AS Inteqer PRlVATE nacimiento AS Inteqer PUBLIC SUB nacido(fecha AS Date) nacimiento· Year(fecha) END 11 PUBLIC SUB PonePatas(numero AS Inteqer) Patas • numero END 2 Programacion bó. crear una nueva clase. Por ejemplo. longitud.ico . decimos que el objeto ha sido instanciada. Otra de las caracterlsticas de la programación orientada a objetos es la Herencill. pero que puede tener caracterlsticas añadidas. etc. además. Veamos un ejemplo sencillo que aclare algunos conceptos. Cuando un objeto hereda de otro objeto significa que es del mismo tipo. para lo que vamos a crear en el entorno de desarrollo un nuevo proyecto de programa de texto. Se pueden instanciar tantos objetos como se desee a partir de una clase y una vez creados tienen vida propia.

cadena "'" PUBLIC FUNCTION Nanbrecaopleto() AS String RETURN Nombre & H H " Apellido "'" y éSle el código a escribir en el Módulo que hayamos creado: • Gambas ~ule file PUBLIC SUB MainO DIM mono AS SerVivo DIM tipejo AS Hombre .Progromación vi§uol con SoHwore ubfe PUBLIC FUNCTION edad () AS Inteqer RETURN Year(Now) .sIl' es el código a escribir en el archivo de clase Hombre.cadena PUBLIC SUB PoneApellido(cadena AS String) Apellido .nacimiento "'" PUBLIC FUNCTION dicePatas() AS Inteqer RETURN patas "'" !:.e/s: • Gambas clas5 tile INHERlTS SOrVivo PRlVATE Nombre AS String PRlVATE Apellido AS String • PUBLIC SUB PoneNombre(cadena AS String) Nombre .

edad() PRINT tipejo. un par de subrutinas con las que se puede asignar el valor a esas variables y dos funciones con las que devuelve valores de algunos cálculos realizados sobre las variables y la fecha actual. Ahi se declaran dos variables: mono y tipejo. Todo el código que se escriba ahí se ejecutará cada vez que se cree un objeto. Tiene un código muy simple: declara un par de variables. PonePatas(3) PRINT mono.mono" NEW SerVivo moDo.PoneApellido(HPérez~) PRINT Upejo.NombreCompleto() "'" Veamos los tres archivos.e/s es muy similar. Si hubieran sido necesarias algunas labores de inicialización de los objetos al ser creados. Y. empezando con el dt' clase SerVivo.PoneNombre(~vicente~) tipejo. el módulo y su procedimiento Maill.nacido(CDate(~2/2/1992~») mono.edadO PRINT mono. tendrán tambi"'n las mismas funciones que un SerVivo y podrán realizar las mismas operaciones. pero con una sentencia nueva: al inicio dd fichero se ha colocado la instrucción INHERITS $erVivo. Al haber hecho eso estamos diciendo que todos los objetos que se instancien de la clase Hombre serán objetos SerVivo y. Programación básica .e/s.dicePatas() tipejo . • El archivo Hombre. finalmente. se harían añadiendo al archivo de dase una subrutina con la sintaxis: PUBLlC SUB _New(). se dedaran como objetos de la 2. NEW hombre tipejo.nacido(CDate(~2/18/1969~» tipejo. por tanto.. pero en lugar de declararlos como uno de los tipos de datos que vimos en los primeros apartados de este capítulo.

L1 mejor forma de aprender. con lo que es una fuente completa de ejemplos. vemos que para crear un objeto de una clase es necesario usar siempre la palabra NEW'. Tal y como está escrito. Aparte del ahorro de código obvio qu!.PiQ9romociC!'!. modificando y cambiando variables. . podemos acceder a sus subrutinas y funciones escribiendo el nombre de un objeto y el procedimiento separados por un punto. La pretensión de este apartado es únicamente servir de mera introducción general y e:-:plicar la sintaxis necesaria para su uso con Gambas. del mismo modo. por ejemplo. Está disponible dentro del directorio apps/src/gambas2 del fichero comprimido que contiene los fuentes de Gambas. 11 Es decir. teniendo en cuenta el día de nacimiento dentro del ano. Además. mejorar el método para cakular la edad. Las clases corresponden a los nombres de los dos archivos de dase que hemos definido. se necesiten seres vivos. También se puede cambiar el nombre de las variables y no afecta a la clase Hombre y al resto del programa. Por tanto. Se han elaborado multitud de libros y artículos sobre la programación orientada a objetos.' supone para la clase Hombre no tener que escribir las funciones que hace un Ser Vivo. El código fuente del entorno de desarrollo de Gambas han· un uso muy amplio de clases y objetos.-. Una vez que el objeto ha sido creado. hay algunas consecuencias más importantes que se deducen de este ejemplo. se puede. si esta subrutina existiera. sin tener que tocar en absoluto la clase Hombre. sino objetos. y el programa seguiría funcionando igual. disfrutar de ella y obtener todo su potencial es probando y viendo ejemplos que la usen extensivamente. Otra de las posibilidades que existe es el uso de los archivos de clase tal y como están en otro proyecto donde. se podría alterar el código de la clase SerVívo. hablando con propiedad. lo que provocará además que se ejecu~ le el código de la subrutina _New del archivo de clase. reutilizando de forma sencilla el código ya escrito. mono y tipejo no son variables. Sólo podemos acceder a los procedimientos que hayan sido declarados en el archi· va de clase como PUBLle.:isuol con Software ubre clase SerVivo y Hombre.

Finalmente.gro'lnd~. separados por un punto. y con ello le cambiaremos el color del fondo. La:. Un ejemplo que ya vimos en el capitulo anterior es el evento Click del botón que se ejecuta cuando hacemos dic con el ratón. Los eventos son. estos objetos disponen de Propiulodes. los eve¡¡/os son subrutinas que se ejecutan para indicar algo que le ha ocurrido al objeto. De he<:ho. Cw1quiera de los objetos que SI' aun a panir de los componentes lienen ya un componamiento definido en su clase. oon frecuencia se dice que Gambas es . Por ejemplo. También podemos cambiar una propiedad mtdiante código haciendo referencia al nombre del objeto y a la propiedad. Para facilitar esas lareu. pero lodos dios COnllenm clases que definen distintos objetos. y lo nt'Ctsario para que ti programador pueda definirlos y haenlos actuar a su conveniencia. Este componamimto inclu~ la interfaz con la que los objetos se van a comunicar unos con OITOS en el programa. podemm asignarle a un formul3rio un valor numérico a la propiedad B(lckgrolllu/. Es el entorno de desarrollo ti que SI' encarga de escribir el código necesario para crearlos. Metados y Eventos Los componentes que cxlimden las posibilidades de Gambas son dt distintos tipos. Mirados y El't'PI'OS.2. Para modificar las propiedades disponemos de la ventana de Propiedades en elIDE (visible al pulsar F4 o desde el menú de la ventana de Proyecto: Vista I Propiedades). en las aplicaciones gráficas. En d ClSO de los com- ponentes que sirven para crtar interfaces gráfICas. sino sólo dibujándolos sobre un formulario despub de haber pulsado el botón con el icono respectivo. Sólo pueden asignarse mediante código y cada objeto tiene su propia cole<:ción de métodos. Por ejnnplo: Forml. estos objetos incorporan un icono a la Ca. pro- piedades permiten cambiar parámetros del objeto. que nos permite hacerlo con una interfaz I gráfKlll sencilla. al darle un valor l una propitdad no estamos sino asignando valores a algunas variables del objeto que bte interpreta internamente para producir un efecto. dejaria el fondo del formulario Fonrrl en color negro.Hide harla que el botón btllSalir se ocultara. Los mhodm son las funciont'$ que el objeto puede realizar. No hay que crear este tipo de objetos escribiendo tl código correspondiente y la palabra NEW. En u:alidad. Por ejemplo: brn5/llir.Bad.a de Herramientas del entomo de desarrollo. 9 Propiedades. los que marcan el flujo del programa.

.nlo Oick. 4 ~ • más. ..._. aparece un menú contextual con d listado de las propiedades (en color violeta) y métodos (en color verde) que el objeto tiene disponibles.. Ev. vemos la opción ~~to. camcle- res se aplican tablas de conversión que asignan un número a código o cada carác· ter. no de letras Para poder usa.. el qm: obliga al programa a ejecutar código respondiendo a sus acciones.(l. 1 . _ -_. Los objel:os en Gambas avisan con los ~tos cada. El listado de propiedades disponibk se puede ver en la ventana de Propiedades. puesto que al escribir el nombre de un objeto y pulsar un punto... Apa. Podemos • • de- gir el evento que queramos y.~ ~ • " " • NOTAS I Los ordenadores s4Io enhenden de número.--. ..un lenguaje de programación orientado a eventos..wikipec!ia. eventos y propiedades que un objeto puede entender. la primera y mis obvia es usando la ayuda. El entorno de desarrollo proporciona varias formas de conocer los métodos. donde se puede encontrar el listado de todas las clases de objetos disponibles. _.. Figura 4. va que: se produce una acción sob~ dios.. Es el usuario de la aplicación al interaccionar. • .recná un menú donde.. la tobla de cooveni6n usada normalmente se llama ASCII En h"p://e.. ent~ otras.. El editor de código también suministra información. con todas las explicaciones y el listado completo de las propiedades. Para los eventos podemos hacer c1ic con el botón derecho sobre un objeto grifico en su fonnu1ario. automáticamente.org/wiki/Auii se pvede ve' lo toblo completa ... Para los objetos gráficos hay algunas ayudas •.. el entorno ya escribini el código correspondiente al principio y al final del procedimiento.. Es el programador el encargado de escribir en las subrutinas que tratan los eventos el código neccurio para responder a eUas. I ~ .• -'.-._.

creando programas de consola. Su don libre.u librmas que facilitan la (nadón de dichas inlerfaces. probahlemenle l1eg6 demasiado larde al escenario para lener un papel relC'vanle.--- • 3. copiar mapas de bits y poco más. una de las primeras librerías de aporo que proporcionaba controles completos. como cualquier aIro lenguaje de programación bien diseilado. Al nivd más bajo. d tradicional siSlemól X· Window tan sólo proporciona una API para mostrar vrntanas. uno de sus pun{OS fuerles es la sencillez para crear interfaces gráficas de usuario. puede trabajar perfe1:lamentc desliga- do de toda libreria gráfica. . a Jo Largo de la historia. dibujar lineas. tradicional de sistemas UNIX"". Lesslif. fue la MotiP". divns. En d mundo GNUfLinux ha aíslido. Sobre dicho sistema. tales como botones o eliqurtas. I Concepto Si bien Gambas.

para el dibujo de bajo nivel. y el rechazo de un sector de la comunidad hacia ambos proyectos (QT y KDE). especialrnrnle a ojos de los usuarios de Windows." aplicaciones gráficas con C++. Un programa que no cumpla esta norma. Fango. habría de ser compilado sobre la versión comercial de QT. no totalmente compatible con el proyecto de la Free Software Foundation. para la gestión de fuentes. 11 En parte como rechazo al tándem QT/KDE. Hoy en dia.. [as líbredas QT en su roidón no comercial. que la compañia ames citada vende y soporta. en principio. Atk.. se distribu[an bajo una Ikencia. Estas librerías. lo cual implica que los programas desarrollados y compilados con QT como base. GTK+ se desarrolló al principio como una libreria gráfica escrita únicamente para el popular programa de dibujo The Gimp (de hecho. han de ser también Software Libre compatible con la GPL. Gdk. que proporciona los elementos de la interfaz gráfica habitulll. utilidades de carácter general sin relación con la interfaz gráfica: Gobject para dotar. y. que está basado en las librerías GTK+. surgió el proyecto GNQME. para el desarrollo dl. se distribuyen bajo licencia GPL. o han decidido reducir los costes al no tener que pagar por la librería gráficll.. Lllicencia de GTK+ es LGPL. de cierta orientación a objetos al lenguaje C. Pero más tarde se escindió de este proyecto para convertirse en una librería de propósito general. de ser bastante feas o incómodas. además. por lo que ha sido utilizada. Su inclusión wmo hase del proyecto de escritorio KDE generó un gran revuelo. . que es un kit de accesibilidad. la OPL.. y en parte para crear una alternativa al popular escritorio KDE. finalmente. creo las librerías QT. En la actualidad. GTK. y no hay que olvidar que de este sistema propietario proviene buena parte de los actuales usuarios de escritorio GNU/Linux. especialmente diseñada para desarrollos en lenguaje C.lrc 1 Las interfaces creadas con estas dos librerías han tenido siempre fama. lodo el proyecto GTK+ está dividido en varios bloques y niveles: Glib. en programas gráficos privativos que no desean contar con el soporte de la versión comercial de QT porque la han visto como una alternativa más cómoda en sus desarrollos. además de en muchos proyectos de Software Libre. GTK significa Gimp Tool Kit). La compañía TrollTech n" por su parte.

una aplicación KDE puede funcionar en un entorno GNOME y vicever~ sa. 3. 11 La particularidad de Gambas es que el código escrito para gb. • Cuestiones de rendimiento. Como se puede suponer por sus nombres. Otros con GTK+. costes en software comercial. de perder homogeneidad en el entorno. a costa. • Aspecto final.gtk y viceversa. Algunos programadores y usuarios se sienten más a gusto con una aplicación QT. lo intedoz gráfico . que también resuenan como alternativas para el desarrollo de programas gráficos.Al margen de estos pesos pesados. existen dos componentes gráficos que proporcionan al programador libertad de elección: gll. GNOME o XrCE (este último. Por lo talllo.t¡1 funcionará exactamente igual si reemplazamos este componente por gb. • Licencia. por ejemplo: • Integración con KDE. Por tanto.gtk. GTK+. el primero utiliza código com~ pilado con QT y el segundo código compilado con GTK+. el programador en cada momento puede elegir el que más se adapte a sus necesidades por diversos motivos. quizá. Gambas ha decidido ser neutral al respecto./11 y gb. senci- lla para el diseño y programación habituales. escrita en C o C++. Aporta una interfaz de alto nivd. No obstante. No obstante. Por tanto. FLTK o WxWidgets. a la hora de implementar dicha interfaz sí que es necesario emplear alguna librería de sustento por debajo. un escritorio ligero basado en GTK+). que no está ligada a los conceptos de QT. hay nombres como FOX. uso de recursos. ni a ninguna otra Iibreda gráfica subyacente. hay muchas alternativas (toolkits) para desarrollar interfaces. que a su vez aportan un aspecto y funcionalidades diferentes. y al menos dos de ellas (QT y GTK+) sirven como base para los dos escritorios más comunes (KDE y GNOME).

. • o ..-.Ó!l viwol con Softwore ü~ • Nece5idades especiales.. 1 ----. ... llamado Ventana. -.NEN Nindow hWin. . que al igual que el resto de componenles. a.!.."'1'1 • Q 11'> - 0- ... Tal vugb. P .._.."- - -_. la libreria de TroUTech'" generalmente empleada en POAs. . (si.ql se pueda compilólr en el futuro sobre Qtopia.Show() . de consola). Afladiremos un módulo modMain y una referencia al componente gb. ------ Escribiremos ahora el siguiente código: PUBLIC SUB Main() DIM hlfin AS Kindow hNin . GTK+ se pufiie compilar sobre DireclFB.. en este caso Controles o Widgets. un sistema gráfico alternativo a X-Window..qt." .. ligero y apIo para sistemas empotrados. ao [J o PartiEndo de la consola Vamos a empaar por el camino dificil para comprender cómo la interfaz gráfica no es más que otro accesorio de Gambas... Crearemos un proyecto de consola.. 'lIJ ". aporta clases a partir de las cuales crearemos objetos. ·...Progromoc.

Esto no asf ya que la ventana.AJ ejecutarlo. y queda en el lazo principal de la librería gráfica.) c1. la interfoz gróRco . mantiene una referencia interna (los objetos Gambas sólo se destruyen si no existe una referencia en toJo el programa). el componente qb. Dicha referencia paJemos decir que se corresponde con la ventana que está dibujada en el servidor gráfico. Por otra parte.qt. tras pulsar el botón derecho. En este progf3111a podemos ver varios efectos.qt como el componente gb. El segundo efecto se debe a que tanto el componente gb. sino directamente del escntoría.).)rio P.)l formul. de modo que el entorno de desarrollo incluye ya. • o o o o o El entorno de desarrollo Para crear un nuevo formulario nos situaremos en la ventana principal del lOE y. asf pues. con la intermediación de la librería gráfica (en este caso QT). cte. En la práctica. Las ventanas son contenedores de primer niveL Un COllfcni'dor es un control que permite situar otros en su interior (botones.) clase de inicio que hrreda las características de 1. es decir. que no necesit. por defecto. para crear un programa gráfico indicaremos directamente en el asistente que deseamos crear un proyecto gráfico. una pulsación del ratón sobre un control). que no cuelga de otro control de nuestra aplicación. extraños. parece que al finalizar la función Main el objeto debería destruirse. Un formulario de inicio es un. Y el adjetivo de pri- mcr nivel se refiere a que no tiene un padre. 3. y nos permite crear un form¡jlario de inicio.)se Form. al ser un control. aparece una ventana solitaria en la pantalla. cuadros de tcxto.gtk son llamados automáticamente tras el método MainO del programa. el programa debería haber finalizado al terminar la función MainO y no ha sido así.)ra mostrarlo. ficos (por ejemplo. El primero es que hemos declarado hWin como una variable local. a primera vista. esperando a que se produzcan eventos grá. y entra en ellaw de gestión de eventos. que desaparecerá cuando pulsemos el botón Cerrar del gestor de ventanas. elegiremos Nuevo I Formulario.) de un método Main en el programa porque el intérprete llama directamente.

. Además. Eventos del coolrol Bu1tol11. automáticamente...!J ARluvo de texto".. pulsando con el botón derecho se puede seleccionar la lista de eventos disponibles para un control. el ¡. El código se irá escribiendo en función de los eventos que generen los con- k.IOl'l VISUal con ~l'IWOrll uore @ ¡.E Figuro 3. por ejemplo. Al pulsar con doble die sobre un control..Ifts~ . se genera.... el ev<"oto Click de los botont"s o los eventos de ralón y tedado de cada control. ""l!. para lo euallos seleccionaremos de la Caja de herramientas y los posicionaremos sobre 105 formularios manteniendo el 11 botón izquierdo pulsado. el encabezado del código correspondiente al evento por defecto (el más característico) del con- trol seleccionado.. S Im.. mientras le damos el tamaño r... troles. . Figura 4. Cootroles disponibles en deseado._o I=~ 'U. Figuro 2. Coja de herramientas... \..rrogramrn.. . ~n . rpM. PO$OS poro crear un nuevo formulario_ Ahora paSólremos a situar los diferentes controles.

... su punto superior izquierdo. es decir. FM. Propiedades X e Y ~ control. Los controles heredan métodos. respectivamente. . 2 Manejo basico de los controles A pesar de que cada control ha sido diseñado para cumplir una función específica. proceden de la clase Contlliner (que a su vez procede de Control) e igualmente tienen muchas características comunes.I. Width y Height con el mismo significado.3. Propiedades W y H: son de lectura y escritura. En cuanto a los contenedores. respectivamente. y determinan la posio "~. la interfaz gráfico . )'0 1 1 o ción del control. comparten buena parte de su interfaz de programación. Left y Top.dol • . que son sinónimas de X e Y. En los contro· les comunes.. IModlRc. escritorio. por lo que todas las caracter[sticas heredadas son aplicables a todos ellos. Dispone de dos propiedades sinÓnimas. propiedades y eventos de la clase Contral. y en el caso de las ventanas es relativa a la esquina superior izquierda del o t figuro S. la posición índicada es relativa a su contenedor. Los controles disponen de otras dos propiedades. 3. o del escritorio en el caso de las ventanas: • Propiedades X e Y: son de lectura y escritura.. y determinan el ancho yalto del control. lo. de modo que aprender a manejar un nuevo control sea tarea sencilla para un programador que ya ha trabajado con otros controles. Posición y tamaño Todos los controles disponen de una serie de propiedades que permiten conocer y modificar su posición y tamaño dentro de su contenedor. Usar una u otra se deja a la elección del programador.

ClientWidth y ClientHeiglu. que si modificáramos las propiedades una por una. lo que mejora el efecto gráfico de la redimensión ante el usuario.H): con él podemos cambiar el tamaño de un control modificando su alto y ancho de una sola vez. que dispone de unas pestañas en la parte superior. Y. en lugar de hacerlo en dos pasos modifi· cando las propiedades Wy H. sitúa a sus hijos por debajo de ellas.Y}: mueve de una sola vez el control a la posición indicada. sino unidades relativas altamarlO de la fuente por defecto del escritorio. todo ello en un solo paso.mas (controles Wjmlow y Form) disponen. pero en este caso las unidades no son pixeles. • • Método Move(X. en lugar de a su contenedor padre. con los cuales además de mover el control se puede redimensionar. • Métodos MoveRe!ative y ResizeRe!ative: son similares a Move y Resize. ve su área útil reducida por dichas barras. Move(X. y permiten conocer la posición de cualquier control relativa al escritorio.H). además. El evento Resize se genera cada vez que cl usuario redimensiona una ventana. respectivamente. y MOI'e cuando se mueve. el control TabStrip.W. de varios cventos relacionados con la posición y tamaño. y ScroI/Vil. Las vent.. Por ejemplo. de las propiedades CJieIllX. Con esta capacidad. por su parte. que determinan. Los contenedores disponen.'W.rr<><: 1m n IJC con:">l' • Propiedades ScreenX y ScreenY: son de sólo lectura. en lugar de hacerlo en dos pasos. que puede mostrar barras de S<:roll. . Existen también una serie de métodos para modificar los controles: • Método Resize(W. respectivamente. el aspecto del formulario será similar para usuarios que utilicen distintas configuraciones de fuentes (por ejemplo. generando una transición más suave ante el usuario. el inicio y la dimensión del área útil para contener controles ¡lijo. grandes en un escritorio a J024x768 o más pequeñas en un escritorio a 800x600). C/ieI1lY. También dispone de dos parámetros adicionales.

. en general. los métodos SIJOw() y Hide() muestran y ocultan. el control. controles toles como eliquekl1 que oparecen y desopo<ecen poro IIomar lo otención delltSUOrio. Con lo que respecta a las ventanas. respectivamente. disponen de dos ("Ventos. Además. • Textos l"E1adonados Todos los controles puedc:n tem~r diversu cadenas de texto. que se disparan cuando se muestran o dejan de estar visibles.odo. De esta forma. Pero.. Para lodos dios. c: INvisibk. cuando el usuario sinie el ratón por encima del área ocupada con el control. que man- tkne lodas sus propiedadc:s. Sllow y Hide. pero no apar«e de cara al usuario.Visibilidad Todo control puede encontrarse: en uno de estos dos estados en un momento dado: Vl$i~. La propiedad Visible: sir\'e para conocer 1'1 estado de visibilidad. abusor de esto lé<:nieo mole. se pueden dar pc<¡uclias informaciones de guia para que el usuario conozca la función de dicho control dentro del programa. que muestran de una u Olra forma. la propiedad ToolTip se encarga de mantener un lexlo que aparecerá como una pequeña ventana flotante. Crear eFecto> de blinLI'lQ. puede ser Util en algono ocasión especial. si se reclama olención par olgún motivo críti<:o. Por ejemplo.to o los uSllOrios y se considera poca aprcpioda en uno inl""¡oz COffee:tomenle diser. la apertura por primera vez de un formulario O ventana genera ti c:venlo Op<'. que significa que aparc:ce rc:presc:fllado ante ti usuario. en todo momento.

Para todos estos contro~ les. las cajas de texto o los bolones. que dispone de varios métodos estáticos. como es el caso de las etiquetas. ColOrES Para cada conlrolse definen dos colores: ForeGrolmd. por comodidad para programadores de otros enlornos. disponen de dos sinónimos: BackCalor y ForeColor. desde el Oal hexadecimal FFFFFF. Las constantes de la clase Calor determinan una serie de colores básicos. Los colores en Gambas son valores numéricos enteros. Ulla base de datos o Estos controles. por ejemplo. La intensidad de cada uno de estos colores básicos varía entre el O(mínimo) yel 255 (máximo). la propiedad Texr es la que determina la cadena a mostrar. salvo en el caso de las ventanas cuyo sinónimo es Title. de forma que cada componente de color viene determinado por sus componentes de rojo. tienen un sinónimo para esta propiedad. puede que sea necesario utilizar la función COl'lv$ para convertir desde otras codifi¡. en su codificación numérica. . denominado Caption. La gestión del color se realiza en Gambas a través de la clase Color.con Software libre Muchos controles disponen de un texto que muestran en su espacio principal. a la hora de representar texto procedente. verde y azul. de de un proceso en ejecución en segundo plano. que es el color de primer plano 11 en el que normalmente se mostrará el texto del controlo parte de sus líneas y dibujos. que es el color de fondo. as! como de una serie de constantes. Puesto que Gambas trabaja con coditkación UTF-S para la interfaz gráfica. Por herencia de otros lenguajes de programación.:aciones. y Background.

Magento color. La ''1twfoz grafica . y devuelve un número represent3ndo al color.Block CoIol.Cyon color. o los formularios de color gris. en este orden. saturación (0-255) y brillo (0-255). verde y azul.DorkMogento "". en este orden.COLOR TONALIDAD NORMAL TONAUDAD OSCURA Negre Blonco Color. Red cotor.1 Cion Magento Noronjo Roso Rojo Violeto Amarillo Gris Verde Gris Cloro El método RGB recibe tres parámetros. las componentes de tonalidad (0-360).DorkRed Color. los cuadros de texto pueden aparecer de color blanco con letra negra.DorkCyon Color.Green Color.Violet colOl. y dependiendo del tema que haya seleccionado el usuario. Por ejemplo.DorkYellow Color. Existen también unas propiedades que determinan los colores del sistema.Grey Color. Estas propiedades permiten conocer los colores actuales para los elementos de la interfaz gráfica: 3.Blon Color.Oronge color.LigntGroy Color.DorkBlue Color.Wnite Color.Yellow Color.DorkGreen Color. las componentes de rojo.Pink color. con valores entre O y 255 para c3d3 uno. 11 El método HSV recibe tres parámetros. y lo devuelve traducido a un color con su codificación numérica habitual.

el puntero.ButtonFoleground Colol. resultando lo combinación dificil de ver.tético particulares del programador. con los que hemos definido en nuestro aplicación. mole!' to o desagradable. En primer lugar se encuentra la representación de éste en el escritorio.Foregrovnd Colo<. Por otro parle.eleccionodo Color del texto en coios de texto Color de landa en coias de texto Color.TextBoáground Color. . blanca o negra. Codo u'uario elige el temo que mós se adopto o sus gustos o necesidad. resoltor de formo claro un texto en uno etiqUf!to).. bolones Color de primer plano general Color de fondo de un elemento . de lo interfaz por caprkho O cuestiones de e.ario por algún motivo de diseño (por ejemplo. cuando seo expresamente nece. Sólo se cambiarón colores de los controles.s visuales.eleccionodo Color de primer plano de un elemento .Background Color.SelectedForegrouod Color. la cual puede tomar como valores las constantes de la clase MOl/se para cambiar su aspecto. cada control dispone de una propiedad Mome. Se consideran constantes para que el ratón adopte diversos aspectos. colore. que habitualmente aparece como una flecha. flechas en diversas orientaciones. cte.i le forzamos O USOr 11 [J otros colores.SelectedBockgrouod Color. como puede ser un reloj (espera). O O O Ratón El ratón es la interfaz por excelencia de cualquier escritorio actual. Al respecto. Textforeground Es poco recomendable cambiar los colore. algunos temas pueden interlerir su. y puede sentirse incómodo . un cursor de texto.Programación visual COl1 Sottware libre Color de Fondo general Color de landa de k>s bolones Color de primer piona de lo. Hemos de distinguir aquí dos apartados. BuHonBoáground Color.

Por tonJo. la posición del ratón dl'ntTO dd (ontrol (MOI'5e. cada control recibe eVl'ntos dd ratón. Dentro de estos evemos. un código bien escrito y escalable. MOIIseUp. Cada control dispone. 3. derecho o central) mediante las propiedades MOII5e. Lo Interfaz grófico .X y Mou5e.Orierttiltion). se prodm:e sólo si hay. el evento MOIl5eMove. y sólo demro de ellos.SaeenX y Mouse. además. Si el valor pasa a cero.:tivamentl'.Delta y MOlIse. MouseWlrcel y MOIISeMOVC. dl'terminan. todos los controles y ventanas de la aplicación mostrarán d puntero con un reloj (indicando al usuario que ha de esperar).Left. Depl'ndiendo del servidor gráfico utilizado en el sistl'ma. se puede emplear la clase Mouse. independientemente del cursor empleado para cada control en concreto. es posible qUl' d cursor pUl'da tener también varios colores. que toman el valor tme si el botón (orrespondiente ha sido pulsado o levantado. un botón pulsado del ratón por parte del usuario. por ejemplo) para cada control. Mouse. que podemos manejar desde 11 el programa. la posición dd ratón respecto al e:saitorio (Mollse.Right o MOII5e.ql y gb. respt'<.los constantes de lo clase Mouse son los mismos para gb.xpm. movió la rueda del ratÓn o movió el ratón de posición.Middle. si el usuario pulsó un botón. se retorna a los cursores habituales. lo levantó. asi como el movimiento sobre la rueda dd ratÓn (Mouse. que aCl'pta una imagl'n y permite dibujar un puntero totalml. de una propiedad Crlrsor.Sa-eertY). al menos. para determinar qué botón se pulsó (izquierdo. sus "olores numéricos son distintos. que es un número entero. Si su valor es mayor que cero. Por otra parle. sino los conslantes de esto clase. En la mayor parte de controles. aporta una propiedad BIISY.pus o . no debe usor volares numéricos para indicar un tipo de puntero. Y). La clase estática ApplicllIioll.glk. Los l'Vl'ntos MOlIseDowrt. no obstanle. no sólo en blanco y negro como los tradicionales."nte personalizado (a partir de un archivo .

que incluye este código: PRIVA'l'E pJ: AS Integer PRIVA'I'E pI' AS Integer Ir NDuse.M:IUM.6a de acuerdo con la variaciÓD de X e Y •••••••••••••••••••••••••••••••••••••• Buttonl. Buttonl.Y) END " p~ • House.X py + House.Este pequcflO ejemplo permite movcr un bolón de posición dmtro de un formulario.Y _ .X. ~l-aeenaao1 posiciones inicial. Ir Mause. cuando el usuario lo arrastl'll mientns mantinlt pulsado el 001611 izquierdo.Y ''''".I • pY .Left TREN DesplazlllllOlll el bot. con un botón Bullon 1.Move(Buttonl. Creamos un formulario Forml.s pI .Mouse.Left '1'IlEN .

Teclado De forma similar al ratón. por tanto. • La clase estática Key proporciona la información necesaria para controlar el teclado dentro de estos eventos. Merm (pulsación del bolón derecho) o Click (pulsación del bolón izquierdo).pooible en e. donde el evento recibe V<lri05 porómelr05 indicando el botón. En el siguiente ejemplo. de modo que se pue<le impedir. todo ello UI conoce o partir de lo infor· moción almacenado en lo do"fl Mou. que en una caja de texto se impriman determinados caracteres. se evita que se propague y. que sólo esló di.A diferencio de 01r05 enlorn05 de de50rroHo.icíón. la pulsación de las teclas Supr (borrado) y BackSpace (borrado hacia atrás) y ellabulador para pasar el foco a otro contro1. El evento MOIlSeDow71 es cancelable. Otros eventos comunes en los controles son DblClick (doble pulsación del ratón). Algunos controles pueden no disponer del evento C1ick. El evento KeyPress es cancelable con la instrucción STOP EVENT.e. lo que significa que empleando la instrucción S1DP EVENT dentro de su código. de igual modo que la clase Mome dentro de los eventos de ratón. el teclado se controla con los eventos KqPres5 y KeyRelease. por ejemplo. evento•.. se bloquea un TextBox. po.to. en Gamba. Para ello llama a STOP EVENT cuando el código de la teda pulsada no es ninguno de los deseados: ef~r1C . Estos no lienen parámetros. ele. según su funcionamiento interno habitual (por ejemplo. un balón no lanzaria el evento Click si se cancela MOllseDown). que el control actúe en consecuencia. de forma que sólo permita la entrada de números.

~ .BackSpace • Retcoceso CASE Rey..Progromoc...gtk aportan una serie de controles básicos para desarrollar una interfaz gráfica... Como el resto de controles...~ .-. -:'¡ dentro de un formulario. .qt como gb. ". -. __ . . .. Su única función es moslrar un texto en una posición J '...9J:.....-- FigurCl 6. se puede modifiGH tanto su color de fondo (Backgrollnd). _ . --. La propiedad Ten es la que determina el texto a mostrar en cada momento. .Tab ' Tabulador CASE ELSE STOP EVENT " ' " SELECT • 3.- ..qt y gb.... __ • . Al margen de este uso básico. . __ _.ón viYJOI con Software ljb~ PUBLIC SUB Text80xl_KeyPress() SELECT CASE Key. 3 Galeria de controles Controles basicos Tantu gb.]01-'. como el color de primer plano (ForeGrolwd).glk. . . . Coda CASE t8 ro 57 ' Códigos ASCII de los números CASE Key.. A continuación se detallan estos controles y sus características principales... • _ _ 'M~_ • Labcl: es una etiqueta simple que contiene una línea de texto de poca longitud. Conlrole~ de gb._.Delate ' Borrado CASE Key.

el ml'todo Se/ect permite seleccionar o resaltar por código una parte del texto. socor provecho de sus características extra.rofico .ado. Pero un programa expresamente diseñado poro troba¡or con gb. Gambos emplea codificación UTF·8 en la interlo~ grófico. no debería obu>or de eMo.. que do ~iempre lo longitud en del texto.responde a los eventos de ratón.1 mé10d0 TexrBox. Asi. gb. no siempre doró el resultado ~u e~perado. indicando una cadena con etiquetas HTML en la propiedad Texr. por lo que un cor6cter puede suponer 1. en las versione~ octuoles_ Por ~u porte. y Se/ectjo/l dola de algunas propiedades para conocer el texto que el usuario ha seleccionado.~ eopo~ de r"pre~entor menos etiquetas HTMl. subrayado y otras caracterfsticas de texto enriquecido. En lugar. se debe emplear .qt puede. pero tiene la particularidad de que es capaz de mostrar texto formateado en HTML. podremos tener texto que combine negrita.gllc.tengrh. Un programo de$Orrol!ooo poro ser independiente del toolkit.9.qr permite kJ inclusión de toblos e imógenes desde un orchillO. en la cual el usuario puede modificar... • • TextBox. copiar. El texto introducido se recibe Omodifica por código mediante la propiedad Texl. ayudado de MOll5ePrrn y MOllseRr/eau. Text) poro conocer lo longitud en caracteres de un texlo. De esta forma. cortar o borrar texlO. coroc1ere~ 3 lo mlcrfoz: . itálica. Además.Text-~~xto con HTML</b><br>Dentro de una <i>etiql1eta. pueden servir para implementar un botón personali7. por 10 que en un momento dado. de una soja línea." El componente gb. TextL8bell. • TextLabel: es muy similar al control Úlbe/. por el contrario. es una caja de textO. 2 o 3 byles de longitud. eKribir Len(Text/loJ< 1.

por ejemplo. si $e encuentro pul$Odo O O no. el método Se/ta. bien 5e 'esoltara 5U elta- do de olgun modo.en y la propiedad Se/eer determinan el texto selecdonado. • CheckBox: muestra un texto determinado por la propiedad Text. El siguiente botón. este control dispone de los métodos Undo y Redo que equivalen a [as órdenes Deshacer y Rehacer de cualquier editor de textos. Puede actuar como un botón normal. Se permite también los retornos de carro. y al pulsarlo otra vez. es similar. Está diseñado para insertarse en barras de herramientas. cuando se pulsa una vez. si su propiedad Toggle vale FALSE. y de valer TRVE lo mostrará con relieve. pero sólo muestra un pequeño icono. como acceso rápido a ciertas funciones comunes. . La propiedad Value sirve para conocer o variar su estado: FALSE significa 'no presionado' y TRUE'presionado'. es un botón normal. 11 sin texto. que mantiene su estado tras una pulsación. Es decir. Además. asl como una propiedad Picture para mostrar un icono identificativo. Este control dispone del evento C/ick que se dispara cuando se pulsa con el botón izquierdo (o derecho si está configurado para zurdos). cambiando el colo< de fardo o el ícooo que loe mue5lra. como un botón normal. El primero. o como un interruptor (como un ToggleBI<tfon). TOO/BlIttOIl. Otro tipo de botón es el ToggleButton. junto con una caja donde el usuario puede pulsar para marcar o desmarcar la opción. dispone de una propiedad Text que indica el texto a mostrar. loo botone5 Toggle pueden ler confu505 con algunol temal de KDE o GNOME.. 5iendo difícil para el U5uorio determino. es decir.Pr~rtHllaclón VI!>Ual con. sale de ese estado. Software Libre ~ · TextArea: se trata de una caja de texto que es capaz contener múltiples Ilneas. si Toggle vale TRUE. queda presionado. eliminan los últimos cambios del usuario o los vuelven a situar en el texto. Como en el caso del TexlBox. habituales en la parte superior de las interfaces. Burton. bto evitora problemas con los futuros U$lKIrios de lo oplicoci60. • Botones: Gambas tiene tres tipos de botones. Cuando 5eO po$j· ble se empleara un CheckBox en lugar de un Togg/eBulton. Así mismo dispone de una propiedad Border que de valer FALSE dará apariencia plana al botón.

la propiedad Border determina su apariencia plana o con relieve y la propiedad Pictllre representa la imagen a mostrar. Un buen ejemplo es su uso para subir o bajar e! volumen en una aplicación que reproduzca audio. Otros controles basicos miscelaneos c:=======:::>~ Otros controles que pueden ayudar a diseñar una interfaz y tienen un propósito mucho más concreto son los que se presentan en la imagen de la izquierda. • PietureBox: este control tiene la función de mostrar una imagen. '1 Figuro 7. hijos de un mismo contenedor. Cuando el usuario activa uno de ellos. y el evento Cliange informa de cada cambio. de forma que e! usuario no sienta que la aplicación está colgada mientras trabaja en segundo plano.La propiedad VaJue indica si el usuario ha marcado o no el CheckBox. • Slider: es similar a ProgressBar en el sentido de que muestra un porcentaje.os valores de volumen se definen entre un rango máximo y mínimo. y en cada momento sólo puede haber uno activado. por lo que se puede empicar como bolón personalizado. Su propiedad Stretch permite adaptar la imagen al tamaño de! Picll¡reBox en cada momento. e! resto se desactiva. • RadioButton: es similar a CheckBox. Sirve para dar idea del avance de un proceso que dura mucho tiempo.. pero en este caso el usuario es quien varla su valor. y e! usuario . están internamente agrupados. • . Otro tipo de oonlro~~. I. • ProgressBar: barra de progreso que muestra un porcentaje de forma gráfica. Responde a eventos de ralón. 'Verdadero o Falso'. por lo que se emplea para seleccionar una opción que excluye a otras dentro de un menú de opciones. Se suele emplear para opciones de configuración que sólo disponen de dos posibles valores: 'Activado o Desactivado'. pero tiene la particularidad de que todos los RadioBllfton existentes. '510 No'.

2. de forma que sea el usuario quien determine [a posición de éste. con los valores TRUE (repro- ducir) o FALSE (detenido). Muestra una animación en formato GIF o MNG. no se trata de un reproductor mul- timedia. y cada uno de ellos está identificado por una clave única de texto. en Gambas los contfoles Slider y ScrollBor deter· minon Sil orientación automóticamente: si son mós anchos que altos serón horizonta· les. ListView: similar a LiS18ox. • MovieBox: a pesar de su sugerente nombre._~<)mo(iÓf1 Vi5U!!L con ~ftwdre libre lo cambia a su gusto. Puede representar un icono junto con cada elemento de la lista. donde existen voriontes horizontales y verticales poro determinados contfoles. y verticales en coso contforio. dispone de capacidades adicionales. La propiedad Made determina si el usuario no puede seleccionar ninguno. La propiooad Va/lIe indica el valor elegido por el usuario. que nos permite hacer búsquedas . habitualmente. s6lo uno o varios. listas dE datos Existen tres controles diseñados para mostrar listas de diferentes modos: 1. Se añaden o eliminan elementos que se repre- sentan como una línea de texto cada uno. El usuario tiene capacidad para seleccionarlos o deseleccionarlos. • ScrollBar: se trata de una barra de scroll para desplazar aIro control. r el evento Clrange señala cada cambio. ListBox: es una lista simple. La propiedad Path determina el archivo a reproducir. • A diferencio de otras interfaces gróficas. El evento C/Jange señala un cambio por parte del usuario en el valor de la escala. sino algo más humilde. sin que el programador deba preocuparse de la sucesión de (fames del archivo que se muestra. y Playing permite el control de la reproducción.

TreeView: sirve para representar elementos en un árbol. . GridView: sirve como representación de parrilla. y una serie de botones para elegir una opción. La clase Message La c1a. que será una información o una pregunla. La clase MesslIgees eslática. en la cual podemos definir un texto. AsI mismo dispone de un cursor interno que puede moverse hacia adelante y hacia atrás.ar uno u airo.de los elementos por su clave. y dispone de una serie de métodos para mostrar distintos tipos de mensajes. de forma que cada nodo puede tener aIras nodos hijos. interactuando con el usuario. pero cada nodo puede disponer de varias columnas. • ColumnView: es similar al anlerior. El usua. que serán reconocibles para el usuario gracias al icono que acampana a la ventana y que da una idea del caráCler del lo " . lo que lo hace apropiado para interactuar con una aplicación de bases de datos. para sdeccion.bla. habitualmente. 3. donde puede representar un campo de una ta. de forma que disponemos de registros agrupados en filas y columnas.s. Es empleado.rio sólo '"e el elemento seleccionado en C1da momentO y puede desplegar la lista. • 3. otros controks avanzados A continuación mostramos otros controles más avanzados: . ComboBox: n una lista desplegable. para interactuar con bases de datos.e Message se encarga de mostrar una ventana modal al usuario. 4 Dialogos Gambas aporta una serie de diálogos auxiliares para mostrar o recabar información.

Q i Contlnuor I M. Lo clase Messoge también puede S&f llamado como uno función. Acbol • "'bol do confinnoc'ón do "lim.. hasta un máximo de tres.o' Figura 10. que normalmente tendrá un texto tal como üK o Aceptar. En estos métodos se situará siempre. y se solicita al usuario su confirmación.. el texto a mostrar y.Error (Texto. Boton3). Sólo permite definir un botón. de modo qoo el código: 11 Es equivalente o: • Message. como primer parámetro. a continuación. Figura 8.lnfo (Texto. Si no se indica el texto de los botones. Mensaje de error. se emplea para indicar un mensaje de error. Boton2... 'ii """"'l" .. o'i. ¡ I Oepu.- ~--: ~ proc...~oc'ón CaJ><:~I.. O~t~"". aparecerá sólo un botón indicando üK para que el usuario acepte la lectura del mensaje. . ).. elteno de los botones. • Message. Boton2. • Arbol [El • Messagc.. Botan 1.Programación vi~ual con Software Ubre mensaje. registro de una tabla.ensaje de eliminación.n. 11 Figura 9..Delete (Texto. Mensaje informoli"O..a para mostrar un mensaje meramente informativo. Boton3): se utiliza para indicar que se va a proceder a eliminar algo (archivo. BOlOnl): se utili7.eje de Erro. Boton 1.

por tanto la Figura 13. Men""ie pora preguntor. Los mensajes son modales..bOI • Message. es posible que los cuadros de diálogo tengan un botón de cerrar.. generalmente para confirmar una acciÓn o una opción de configuración. lo que quiere deár que la interacción de la interfaz de usuario con el programa. Coodro de opción menos peligrosa.Question (Texto. quedan bloqueados hasta que se pulse uno de los botones.bol • Message. o que se estima a ejecutar por defecto. di61ogo COf1 botón de cerror. Boton3): advierte al usuario de que la acción que va a realizar supone un cierto peligro. pérdidas de datos de una tabla que podrian Figura 12.. 60ton2... as! como el flujo de éste. Si el usuario cierra el mensaje de este modo.. .\Varning (Texto. Los métodos de la clase MeSS(lge devuelven un número entero que denota el botón que el usuario pulsó. se habrá de indicar en el botón más alto.Warnin9(~¿Formatear el disco duro?~. advertencia.. " . El primer botón comienla en el número l. Boton3): es una pregunta al usuario. Botonl. .. Boton2. 11 01M hReli AS INTEGER hReli-Melitiage.Meo". "Si".. "No") Dependiendo del gestor de ventanas del sistema. por ejemplo.. I5otonl. se devolverá el número del botón existente más alto (en el ejemplo anterior el 2). Figura 11..¡e de ser útiles aún.

. lound 211OCJOS I9i08lOS 2l108JOS 19/08105 19/08105 19f08lOS _FJ.. Dependiendo del componente.cdrom . -- .. de modo que TRUE significa que el usuario ha pulsado el botón Cancelar..: "'" . IMQtkfN:lldo Il.. odu<~ . . Ventana pora guardar un archivo.) Figura 15.. puede llegar a ser realmente molesta.OpenFileO: sirve para que el usuario seleccione un archivo para su apertura. o-O - 19/08/05 H".. . Las posibilidades que nos ofrecen son las siguientes: • • Dialog..ramaClon visual con Software Li~re Los mensajes se han de emplear con prudencia.... lógicamente..... Apertura de archivo. ... que ahorrarán mucho tiempo de trabajo mecánico al programador de una aplicación gráfica.. tendrán un aspecto similar al resto de aplicaciones GTK + o QT. Tras ser mostrado y seleccionado por el usuario..... contiene la ruta elegida por éste... pero el diálogo está orientado a guardar un archivo... de forma que permite elegir uno que no existe. sirve para situar la ruta inicial y para recabar la ruta seleccionada por el usuario. ·1 H". ?'.. Op•• ""'''CIO \JEsaltonO 'n~ . Una aplicación que continuamente bloquea la interfaz y desvía el foco de atención del usuario.hb . H".. Los métodos de esta clase no toman ningún parámetro. La propiedad Path de la clase se utiliza para situar la ruta inicial en el sistema de archivos...Pr09..Ion.""""" . La clase Dialog Esta clase aporta ciertos diálogos comunes.. Las interfaces de otros sistemas propietarios se han llegado a hacer famosas en los chistes de las oficinas por las continuas preguntas del estilo'¿Está seguro de que.. Como en el caso de OpenFile().. y devuelven siempre un valor Bolean. • Dialog. . "" . y FAL5E significa que aceptó el valor seleccionado. .SaveFüeO: es similar al anterior.Imnt MmiKlio Figura 14. la propiedad Path .

SelectColorO: permite al M-"'.. Para activarla.. '9IOIII1l5 archivos.. La propiedad Color se emplea de modo similar a la propiedad Path de los casos anteriores..... Apertura de carpeta5. Selección del color...~ 1'. es 62 1: Azul: 151 : riombre del (olor: ¡¡t9D909D Ix s:. .. Elección de la fuente. n . Se trabaja sobre la propiedad Font de la clase I :'r''''' Stlllodard SY01bol~ l f _ .t Font EstIlo' Itbhc Jpmel'\o' _ _.OpenFi/e admite un paró metro opcional que habró de tener valor TRUE... O ~alor.._=--.1 . • 157 : usuario seleccionar un color personalizado..:. no :J _""'M .II§11•••19 .. Figura 17. 270 : S-lIturb(IÓn.• ' 12.lns L OpeoSymbol ~nf S. .. H.... Ademó5 de la propiedad Path exi5te una propiedad Paths para obtener 105 valore5 de los archiv05 5eleccionad05. el método Dialog._. \o- -rrt'l.(orom '*"'ftv • Dialog. 1'.. cuando 5e nece5ite elegir mós de uno a la vez... sino una carpeta......0 ~ Bold 60ld Illllhc 10 11 13 14 • Dialog....SelectDirectoryO: en este caso. boDl 19108105 Hoy Hoy ~ . El diálogo permite seleccionar sólo carpetas.... ~'fi(~ . "" • """''''' lUOC/'O!l _ _o -._. w. Nlmbus Sl. sirve tanto para fijar el color inicial como para determinar el elegido por el usuario..SelectFontO: con él se elige una fuente personalizada.. Figura 16.. ..lII'\(elor 1 decir. Acept(lr 1 Dialog.otJ'cI _Iob . 3 La interfaz gráfica . el valor de Path no será un archivo..... Ji 111 J""" ~ _ l .fec... • ~~~~I...105 0III1l5 I¡ +-. • Dialog.. yista prellmlner: abcdefllh'Jk ABCDEFGHIJK ix !:oI'InCel(l"! [a 111 Figura 18.'"1"11""11'• • • • • • • •~.I:¡:. Select Color ¡ ""...1~1-1ound .00 \$hcrltono . _ - F. .. 2)108.. BaJo: 157 : ~erde. .~~~ r -i.

"seleccione imágenes a procesar" Dialog. Se trala de una matriz de cadenas en la que podemos situar. ".Filter: permite indicar filtros para los archivos a mostrar.png".pllg YC. que sirve como indicación de la opción elegida por el usuario.Tille: permite establecer un título para la ventana. Veamos un pequeño ejemplo.er· ["*. Formularios FMain y .lnfo(NAcci6n cancelada ELSE H ) Process_lmageneS(Dialog. el programador puede crear otros personalizados. puede devolver un valor entero.Filt.pl/g.Title . las extensiones de los archlvos a elegir. por ejemplo. .jpg"] IF Dialog.. y los renom- bramos como /l. Dialog. es decir.FDiologo. con un formulario principal de inicio llamado FMain Yotro formulario Hamado FDialogo. Creamos también tres pequeños iconos en for· mato pl/g o los copiamos de la carpeta /r4sr/s/ulrelpixlIlapS del sistema. El formulario principal FMain tendrá un PictllreBox llamado plmagc. etc. que por defecto corresponderá a la acción a realizar (Se/eCl Foru. y un botón denominado bfl/Select con el texto Icono. con los métodos SlzowModa/() o 5howDi/lIQg().). de forma que los tengamos disponibles en la carpeta del programa.OpenFile(TRUE) TBEN Message.pllg. Cuando un formulario se muestra de forma Modal. usando comodines si 10 deseamos.Paths) END " 11 Diálogos personalizados Al margen de los diálogos ya mencionados. El formulario FDialogo dispondrá de tres controles Figuro 19.• Dialog. b. • O¡alog. Creamos un programa gráfico. Se/eel Color.

PidllreBox, cada uno de ellos conteniendo uno de los iconos pllg que habíamos situado en el proyecto, Ylos llamados piel, pie2 Ypido Con el código del formulario FDialogo lo que constguiremos es que cada vn que el usuario pulse uno de los controles PiftllreBox, el formulario, que se moslrali de forma modal, devuelva un valor enttrO que identifquea d ieono pulsado.

KE.Close(l)

ME.Close(2)

11
PUBLIC SUB piel MousetloNn()

KE.Close(3)

END

-----• w·

En cuanto al formulario FMain, la pulsación del botón conducirá a mostrar el formulario FDialogo de forma modal y, en función del valor devuelto, silUali una imagen u otra en el PicwreBax llamado plmage:


FigUfg 20.lmógerles que hemrn situado en el Pidure&x.

Programación v¡~ual con Software libre
PUBLIC SUB BtnSelect_Click()

SELECT CASE FDialogo.ShOWOialog()

CAS'

1

pImage.picture - Picture["a.png"l

CAS"
pImage.Picture - Picture["b.png"]

CAS"
pImage.picture - Picture¡"c.png")
END SELECT

11

Tras ejecutarlo, podremos comprobar el resultado. Si el usuario cierra el formulario modal pulsando el aspa del gestor de ventanas, se devolverá el valor por defec-

to, es decir, cero, lo que equivale a cancelar la selección. Puede plantearse otro pro-

blema más complejo: la necesidad de devolver otro tipo de valores, tales como
cadenas o referencias a objetos. En este caso, la solución del enlero no es válida. Si tratamos de mantener una cadena en una variable del formulario, ésta se liberará tras cerrar el formulario, lo cual no nos sirve. Por ejemplo, modificando el código anterior, de la siguiente manera, para que el formulario FDialogo mantenga una cadena ron el valor elegido:
PUSLIC valor AS String

Valor. Na.pngN ME.Close()

PUBLIC SUB pic2_MouseDown() Valor _ Nb.pngN ME.Closen

Valor. NC.png" ME.Close()

y modificando el formulario principal para que tome el valor de la cadena:
PUBLIC SUB BtnSelect_Click()

11

FDialogo.ShowDialog() IF FDialogo.Valor <>
NN

TREN

plmaga.Picture - Picture(FDialogo.Valor)
END "

No conseguiremos que funcione, ya que la secuencia es la siguiente:
1. La llamada a FDialogo.5howDialogO crea una instancia de la clase FDja/ogo.

2. Tras la pulsación del usuario, se destruye esa instancia y con ella el valor alma-

cenado en la variable pública Valar. 3. La interfm: gróhco

J~r~romación vi~uol_"on

Software übre

3. Al llamar a FDialogo.Valor, se crea otra instancia de FDialogo, que liene la variable Va/ar con su valor por defecto (cadena Vacía).

Podemos solventar este problema por dos caminos:

\. 8 primero consiste en declarar la variable Valor como estática. Así la variable no depende dr cada instancia, si no de la clase, de forma que no se crea ni se destruye en cada llamada a FDialogo.S/lOwModa/().

2. El segundo consiste en aprovechar

Icon

la propiedad Persistent de los formularios. Poniendo su valor a TRUE,

Picture
M,,~k

False

un formulario no se destruye cuando el usuario lo cierra pulsando el aspa del gestor de ventanas, ni sellama al método e/oseO, si no que

Persistent Borde.

• ~,

Figur<I 21. Propiedod Persisten' con valor TRUE.

11

simplemente se oculta. Y si estaba en pantalla de forma modal, el programa abandona esle modo y continua su ejecución normaL

Así pues, en tiempo de diseño siluarcmosla propiedad Persjstent del formulario FDialago a TRUE, y modificaremos el código del formulario FMain para que destruya el formulario de forma expHcila tras haber leído el valor que interesaba.

PUBLIC SUB BtnSelect_Click()

FDialogo.ShoWDialog() IF FDialogo.Valor <>
NH

TREN

pImage.Picture - Picture[FDialogo.Valor]
END "

FDialogo.Delete()

3.5 Menús
La creación de menús es realmente scnólla ya que un
asistente dellDE permite disei'¡arlos. Tan sólo hay que situarse sobre un formulario, pulsar el botón

• • •

• ..•

derecho, y seleccionar la opción Editor de meou...

. ...." ... _

CtrI+~

Los menús se crean como árboles, es dedr, cada menú
de primer nivel, por ejemplo los típicos menús de la barra superior de muchos programas como Archivo,

Editar, Ver, Ayuda, ete., tendrán menús hijos que se
sitúan un nivel más profundo que éste y, a su vez, si
figtJfQ 22. l.ocolizociÓll del
Editor de menú.

estos tienen hijos, se situarán un nivel más profundo.

Todo ello se controla con los botones con forma de flecha, las verticales permiten cambiar el orden de aparición de los menús, y con las horiwntales modificamos [a profundidad de estos.

11

Las propiedades más importantes son el Nombre, que es el nombre del objeto menú
y que corresponderá con su gestor de eventos, el Tftll/O, que es el texto que aparece-

:-

'-

.,_._.. -

rá en la pantalla, un icono a elegir si lo deseamos, y un posihle atajo de te<:lado para acceder sin necesidad del ratón.

r=.:·
_
_

-

Si el nombre de un menú se deja en blanco, éste se muestra como una barra separadora en lugar de una entrada de menú normal.

r
úcno. "'--.
w ....' . _ ,

En la Figura 23 podemos ver un ejemplo con
.¡ ....

-

r

8c<!J

Figura 23. Eiempkl de menús coo
submenús.

I

un menú principal que tiene tres opciones,

y sus correspondientes submenús.

3. La interfaz grófico

. Si en tiempo de diseño pulsamos sobre UIlO de los menús que no tienen hijos. - un menú de primer nil'd ron su propiedad visible a fALSE. --.. 24. que se detecta medianIl' la gestión dd nTIlto Me/m.. .25.!J!!... END Si lo que deseamos es crear un menú de los 11 que se muestran cuando el usuario pulsa..... elIDE nos llenrá dirttlamentc: al evento C/idr: del menú.i el aspecto de: la Figun. f ~ fMoin. PUBLtC SUB f'ornU~nu () mnuEditer.. por C'jemplo.nos al ~ el boa)" dtoedo de un bn-ohio... la pulsación del botón derecho sobre un formulario.-1 -s Figura 2•. porejemplo... tendremos que crear -. al lanzarse el C'\'eIlto del (0... Después.d bot6n derechosobTe un formulario u otro oontrol..-- mulario o control que nos interesa.Popup() END . a nuestro menú invisible que debe mostrarse como un menú contextual: F9. y sus correspondientes hijos. Mroú lfIlI-..El formulario tendr... _~. que es donde: podemos crear el código que se c:j«utari cuando el usuario pulse el menú.. " .. indicaremos ..... .. --.

. u otro menú paro los Irijos del pri- mm).. Rewhodo Al ejeclllar el código.u rontextuol. En euamo a la naturaleza de los menús. 'l'ell:t - "enviar" h3 . v('~mos el resultado al pulsar el botón derecho sobrt ti formulario.NEW Menu(bl) AS "h2. no son más que objl"tos. del me." h2. Los menússt putden crear o <kstruir ~mbién directamnltl" por código: DIM hl AS Menu DIM h2 AS Menu OIM hJ AS Men. • hl . I.. si bien disponen de algunas propiedades comunes como Texlo PicWrc. mIMen. habrá de indicarse su objeto "".. Env r Eh plldre. que podrá ser una ventana o formulario para los menús de primer nivd.Clones A la hora de crear un menú.NEW Menu(HE) h2 . aunque en eSle caso no provienen de la clase Control.Figo.NEW Menu(hl) AS "hJ" .ru 26.".

. Gambas define varia. Sin embargo. 6 Alineación de 105 controles Propiedades de alineación Algunos contene<lores disponen de una propiedad Arrangement que permite deter~ minar cómo se alinean los controles dentro de un contenedor. diseñar interfaces de esta manera puc<le ser algo complicado para gente • sin experiencia. ocupando todo e! espacio en vertical dentro de! contenedor. una vez que se toma algo de pericia. de forma que el programador !iÓlo ha de indicar el modo general de alineamiento y los controles se adap- tarán en todo momento a dicha alineación. lo habitual es encontrar contenedores que definen dónde se situará cada hijo. En principio. La principal es que el diseño de ventanas rc<limensionables con controles variados en su interior es trivial. en olTas librerías gráficas como GTK +. como es típico en las interfaces para Windows'''' o en algunas libredas como QT. el contenedor no decide nada acerca de la posición de sus hijos. dentro de unos limites razonables de tamaño.3. el valor de la propiedad es None. no obstante. o variar su relación alto/ancho. o en las definiciones del lenguaje XUL diseñado por el proyecto Maúlla para aplicaciones web. y la aplicación seguirá manteniendo un aspecto coherente en cada momento. posibllidades de alineamiento para los controles: • None: alineamiento libre. Cada usuario puede agrandar o hacer más pequeña la ventana. ocupando todo el espacio en horizontal dentro del contenedor. aporta grandes ventajas. lo que significa que las posiciones de los controles son libres. • Vertical: todos los controles se alinean de arriba a abajo. Por defeclo. controles se alinean de izquierda a derecha. • Horiwntal: todos lo.

Cada control. . de arriba a abajo. en cuyo interior situaremos dos botones y un RariioBllttOtl. ocupando todo el espacio vertical del contrnedor (Figura 29).. con un sólo formulario dr inicio FMaill. y si falta espacio. por su parte. Tras ejrcutarlo veremos el resultado habitual: un formulario con tres controles algo desordenados. Además de la propiedad general Arrangemenl. Ahora los controles se han situado aliRDdo08ut1onl neados en horizontal. dispone de la propiedad Expand.• LeftRigth: los controles tratan de alinearse de izquierda a derecha. rnos el programa. junto con el resto de controles del contenedor que tengan la propiedad Expmrd a TRUf. miMenu ACCIones Enviar Ehmlnar 11: Para comprobar el efecto de todas estas propiedades. Cambiamos el valor de la propiedad Arrmrgement a Horizontal y ejecuta- • . .. Proyedo Alineación. de izquierda a derecha. Si el control se sitúa sobre un contenedor cuya propiedad Arrangemenr es distinta de Norte. Controles alineados en horizontal. Lo interfaz gróflco . que determina un espacio de separación entre control y control. creamos un nurvo proyecto gráfico llamado Alineacion. se aporta la propiedad Padding. 3. el valor Expand determina si éste. Figuro 29. Figura 28. y si falta espacio. TopBottom: los controles tratan de alinearse de arriba a abajo. que es un espacio que queda libre en el borde del contenedor. tratarán de ocupar el espacio libre que quede dentro del contenedor. y una propiedad Spachtg.

úo altura/anchuro_ . Figura 31. Espacio COl lopOitido entre los controlocbes Ilutlon 1 Y8utton2. el espacio extra será compartido por ambos controles. mientras que el ancho extra queda libre.Progromoción visuol con Softwore übre Ponemos la propiedad Border del formulario a Resizable. modificando el ancho del control Bunon2. todo el espacio del contenedor es aprovechado._. Con esta nueva configuración. Situamos ahora la propiedad Expalld del control Bul\on2 a TRUE. _. Si situamos la propiedad Expand de Bullon 1 también a TRUE. los controles siguen ocupando todo el ancho del contene- dor. de modo que podamos variar su lama no. . Aprovechamiento del e$f>OCio del conter. Hacemos varias pruebas de ejecución cambiando su relación altura/anchura.. 111 Figuro 30. Figura 32. yvolvemos a ejecutarlo.edor. Variación del formulario Como podemos observar. . _.

• Vbox: es un panel con alineación vertical. podemos dar un valor a la propiedad Padding. que permiten realizar 3. sin embargo. u horizontal. Panel.Para dejar espacio visible por el borde del contenedor.icione5 de codo control dentro del contenedor. • Vpanel: sigue el modelo Vpallel. lo interfaz grófica . otros controles tienen esta propiedad implícita y no es modificólble. Además de estos. Los valores indicóldos son píxeles de separación. • Hpanel: sigue el modelo RightToLefl. Una zona de trabajo estar3 formada los tlpicos botones de menú. Supongamos un clon de los exploradores de archivos habitualcs. a a o o o Controles con alineación predefinida Los controles Form (Window). Estos son los siguientes: • Hbox: es un panel que siempre tiene alineación horizontal. El efecto de lo propiedod Arrangemenr no 5e oprecio en liempa de di5eiío. que el usuario pue<le mover para agrandar uno u otro control en detrimento del tamaño de su vecino. pa. podremos revertirk> 5in perder lo. en el caso de Hspljt. los controles Hsplit y Vsplit son contenedores con un modo de na· bajo totalmeme distinto: cada control añadido se muestra sepólróldo por una barra verticóll. • o o [j o O Diseño de una aplicación que aprovecha este recurso A la hora de diseñar una aphcación redimensionable. de e5te modo 5i par error se cambio o un valor no de5f!Ooo. 10 mejor es plantear 3reas de trabajo con distinta funcionalidad y agruparlas en distintos paneles horizontales y verticales. en el caso de Vsplit. TabSrrip y ScrollView permiten definir las propiedades de alineación. y para separar un poco cada control utilizaremos la propiedad 5pacirlg.

T. Paneles Hbox con olineación horizontal. ' .. Por tanto.-:. ~" - .-Software Libre [as tareas más comunes y que presentan un icono y un tooltip explicativo. la propiedad Expmld del panel central habrá de tener el valor TRUE.. .. En primer lugar. No crearemos en este ejemplo el código correspondiente. ... . ..:...-:' ""..::::.••. i figur(l 33. .. .:.. pero si seguiremos los pasos necesarios para crear la interfaz de un modo adecuado. _ ."'::. Por último... que van de arriba abajo. Deseamos que la parte superior con los botones y la inferior con la barra de estado. . tres con· tenedores Hbox.:·._o ~. ..-~ Dentro de ésta.-...l _ - - - _. . ..~ .•.' i . hay tres grandes grupos de trabajo. ... situaremos tres paneles con alineación horizontal..:-.:.~ '• Figura 34.:·. . lo mejor es definir un formulario con la propiedad Amlllgeme7lt situada a Vertical.... .. .¡ TOoIT".:0::·....:-:. .. la zona central muestra los archivos y. ¡ ~eo..ft...-:. es decir.::... ...-- ...~ 9.. ¡ . para conseguir que cada usuario pueda disponer de sus vrnlanas como mejor lo desee.. a su vez......:·... propiedad Arrongemento Ver'ico/.._ . tengan un ancho fijo. i 1 ..-. ~-' H""... aIra zona dr trabajo puede ser la parte inferior. y una zona más grande a la derecha con la vista en detalle de los archivos.­ .-.. es una zona dI' trabajo que comprende otras dos: un árbol con las . . .:.aTpelas a la izquirrda. .::::.... .'. formulario con k.] • .Programación visual 'fl_1l.::.. .:.. ..'. '.::::. . será redimensionable.. .... pero la parte central que contiene el cuerpo de la información útil del programa. Por tanto.. en la que se muestran datos de estado..::.

¡ la con otros botones auxiliuC"$. Di~ Figuro 35. situaremos un contl"nedor Hsp/ir. Introdvc::ción del a TRUE. lo . a la izquierda. Es d mismo diSC'no que la zona de botones principal. Dentro de ~l se colocará. Botones OIIl<iliores • dellormulorio. Dentro del cuerpo SC' situará lIna caja vt"rtical izquierda (~) . según qué parle se quieI'l" hacer u\ensible. de modo que el usuario pueda disponer de una barra --o para modificar d tamaño rdativo del :irbol Yla zona principal de trabajo.__ "l::"'-. . 3. tendrá su propiedad Expmrd a TRUE.1 U: .nlerfoz gról1co cor1trol Hsplit.. una de las cualC"$.__._ _ pero alineada en vl"rtical. del Iormulario fMoin.•_•• ~ . el control TreeView para el árbol. El control Hsp/il debe tener la propiedad Expillld Figura 37. . asi como el conlrol/collView para la zona principal. La parle inferior dispondrá de dos etiqUe1:3.S Label con borde Sunkl'n. para que aproveche todo el espacio libre disponible dentro de su contenedor. ~ .La parte superior contendrá divt"TSOS botones tipo ToolButum. ·r··--Tl--------j1 figura 36. Tras esto. que podemos TC'Saltar con distintos konos.

11 3. figura 38. Dibujar directamente sobre un formulario no tiene demasiado sentido. algo de código para rellenar el árbol y [a vista de iconos. DmwillgArcll dispone de dos modos de trabajo: en el primero. por ejemplo tras pasar otra ventana por encima o minimiwr y maximiwr. que se activa poniendo la propiedad Úlc1lcd a TRUE. el programador puede necesitar dibujar gnificos personalizados. añadiendo.p. Modificación del alto y ancho de la aplicación Alineción. La dase estática Draw se empIca para dibujar sobre un control. en lodo momento. sino que redibuja automáticamente la zona clareada. el control guarda una caché del dibujo realizado y no genera eventos Refresh. la relación de los distintos controles. como en el caso del formulario. sin que sea necesario añadir nin- gún código de cálculo de posiciones por nuestra parle. 7 Introducción al dibujo de primitivas Además de los controles ya diseñados. la cual se encargará de mantener. se pierde el dibujo realizado sin que tengamos control sobre la situación. ya que una vez se refresque la interfaz. pero el evento Refres/¡ nos informa para que redibujemos la parle eliminada. Podemos modificar el alto yancho de la aplicación. . So re l e Ya podemos ejecutar el programa para ver la interfaz. si 10 deseamos. en el segundo. Sin embargo. que puede ser un formulario o el control DmwillgArea. se pierde el dibujo una vez se refresca el control.

Lieozo..- =. se ha de especificar a la clase Dmw qué control será el empleado para dibujar los elementos que indiquemos.Begin(} pasando como parámetro el control deseado. Lienzo. La propiedad Quhed del control Dmwj¡rgArea . crearemos un proyecto gráfico Dibujando..Line(O. y en su inlerior un conlTol DrawillgAmlllamado Lien7. Este código contiene.w.. que contenga un formulario FMain._.EDd( ) 11 Al ejecular el programa y pulsar el l Lit/IUJ. en nuestro caso el control . Begin(LieD.. apar«erá un aspa creada por nueslro código.B) Draw. 1 bolÓn. para cualquier dibujo. O) Draw. Lienzo. para 10 cual se emplea el método Draw. se pondrá II TRUf.Zo) Draw. Lien.W..so.. Como ejemplo.. Figuro 39.. El código del botón Dibujar será el siguiente: Drlnl.B..Line(O.. O.o y un botón Ila· mado Dibujar. Proyedo Dibujando. el mttodo de trabajo siguiente: • En primer lugar.

• Draw. el cual dibuja líneas cuando especificamos los puntos de origen y destino. utilizando lo siguiente: • Draw.Point: puntos.Polyline: varias líneas enlazadas.ProgrOI VI~UQI con Softwm • Tras esto. • Draw. La clase Draw permite dibujar distintos tipos de primitivas: • Draw. rayado en horizontal. · Draw.ForeGround: color de primer plano del pincel. siempre hay que llamar al método Draw.FillColor: color para relleno de elipses o rectángulos.Ellipse: elipses. pasamos a dibujar [as primitivas que deseamos. • Draw.BackGround: color de fondo del pincel.). ete.Rect: rectángulos.FilISlyle: utiliza las constantes de la clase FiIl pan determinar el patrón de dibujado (relleno.Polygon: polígonos. • Draw. 11 • Draw. En todo momento podemos controlar distintos aspectos del dibujado. • Finalmente. líneas y puntos.LincO. .üne: líneas. • Draw. y se liberen los recursos asociados al proceso de dibujado del control.End{) para que la caché del control DrawingArea se dibuje en la pantalla. · Draw. Aquí hemos empleado el método Draw.

lmage: dibuja un gráfico almacenado en un objeto lmage. • Draw."-demás de las primitivas. ?or último.Clip permite seleccionar una área de Clippillg. • Draw. Draw. de modo que todo trazo que luede fuera de él se excluirá de ser realmente dibujado.Font. 11 .Text: dibuja un texto en una posición indicada y con la fuente seleccionada por Draw. es decir.Piclure: dibuja un gráfico almacenado en un objeto Picrure. reducir el ¡rea útil de dibujo a un rectángulo que espedfiquemos. podemos dibujar elementos complejos con: • Draw.

sin embargo. como el gran Mplayer. recubren también aplicaciones sin interfaz gráfi- ca propia.1 La ayuda ofrecida por otros programas Los sistemas GNU/Linux siguen la filosofia de UNIX. Como resultado. es sólo la portada de aplicaciones como cdrecord o mkisofs. en lugar de generar grandes aplicaciones monolíticas. Parte de cUa consiste en crear pequeños programas especializados en cada larea. en GNU/Linux disponemos de muchas pequeñas utilidades de consola capaces de desarrollar casi cualquier tarca que necesitemos. bella e intuitiva que. habitualmente.11 4. son simples [rolll-cllds para aplicaciones de línea de comandos. potentes herramientas de consola. una aplicación sencilla. ReproduclOres de video o audio como Toten! o Kmplayer. Los programas con interfaz gráfica. . Podemos poner como ejemplo el magnífico programa de grabación de CDs y OVOs KJB.

hup. No es ncasario. 5mb. Ontel de emb. acostumbrados a trabajar sólo con los n'Cunos que: apona el propio entorno de programación o añadiendo llamadas ti Id APl. administrar bases de dalos. scp o nf5.who rnó~ -. lo depuración del P'ogrolnO Iombién f. proporcionan todo lo necesario para grabar un CD.. puede resultar cxlraño.ndes ventajas al programador. en la mayor parle de nuestros desarrollos. Basta con consultar la documenta- • ciÓn de un comando y llamarlo tal y como harlamos manualmente desde la con· s. tratar de s.olucionar los problemas de conversión de tipos entre un lenguaje de alto nivel y e. GNU/Linux pennilt desarrollar sin reinventar b. pe:ro este: modelo de segmentación m pequeñas unidades ofuct pronto gn. La shdl bash. ni caer frecuentemente en violaciones de segmento por un descuido en un puntero mal gestionado. común en estos sistemas. Gambas permite sincronizar la ejecución de los dos programas. rueda. convertir formatos de ficheros gráficos o de texto y mu:has tareas más. 4. reproducir video. transmitir ficheros con flp. donde lo llnico que podíamos hacer sin ayuda de la API era lan· zar un proceso y desentendernos de ~l. junto con las herramientas habituales de consola que acompañan a cualquier dismbución. entrar en las complejidades de las diversas librerlas escritas en e. berlo en el código Gombo.:ión visuol con Sof:!ware Libre Para aquellos que provienen del entorno Win321VB.Progromoc. conocer el estado (en ejecución o finalizado) y recibir sus mensajes dI' error por la salida estándar de errores (stdur). comunicarse con él leyendo y escribiendo por la entrada y salida estándar (.cilio: bo5tO probor el comondo diredomente desde un termIno! de 18m y cornprobor Ion rewhodo.Idi.. enviar y recibir correos. t'$IO es.tJout). 2 Gestlon potente de procesos A diferencia de VB.ola del sistema. gestionar servicios LOAP. . trabajando con ¡murias dd sistema cuando va se queda corto.l y .

.ringl Para facilitar la escritul11 de.. como único código. q. La primera instrucción.is que de programas..' [os parámetros.par~.b<f.a. ) De esto formo.to en ejecución se denomina pr0ce50 y a partir de ahora hablaremos de procesos ro. Vamos a ir desgranando poco a poco las diferentes opciones. c.ar.4. lanza e\ comando que indiquemos.pe. desoporece lo (lmbigíi&ckld y lo necelidod d. orchiVO. si Ienemos qlltl ejecutor. la sintaxis de EXfC indica que hemos de pól$3. CommClIld es d único p. btt tjecula el comando qut lt indiqutmo! y 5t d~ntitndt dt él Ahora. aftadimos un módulo de inicio y.oo . qVl'l tiene un e$pOCio en medio. tscribimos: PUBLIC st1B Main() .3 EXEC Existen dos comandos pan lanzar la ejecución de programas dtsde Gambas: éXEC y SHElL Un program.1 fin de eli· mino' lo polibilidod ti.T d comando y los par. Para ello. vamos a crtar un proyteto dt consola con Gambas.lmetros como una matriz o arl1lY de: cadenas: [O 'nd.. el comando tome mi orchivo. En el modo dt trabajo más liimplt dt EXEC. por ejemplo.oclertu especiales como \. EXEC.imetro obligatorio y reprcsmta el comando a ejecutar. indicar mós <. acompañado de los parámetros que escribamos: [Variable-) EXEC [C(llllll8ndll WAIT JI FOR (1tEADIlfRI'l'EIREAD lfRI'I'E) [Te St. evitando los problemas que putden surgir con caracteTd tsp«ialts tales como los espacios.bd como dos porómell'os e<1 Iugor de uno 5610..raal2 . el comondo col ton un nombre 111 de archivo lol como m.

Podemos realizar esta tarea de las Ires maneras que vemos a continuación. y desentenderse de: él. pas.. Hasta aquí todo lo que hace Gambas l'$ ~tar d nuevo proceso.go. o esperar a que el proceso acabe. obtendremos resultados impredecibles: . Si los dos procesos se eje<utan de forma aslncrona. Veamos de nuevo el primer ejemplo con pequeñas lllooificaciones. Se c:¡«ula de: forma asincrona. de eso Formo. roas hemos librado ele unos cuontos lineos de c6digo... podriomos haber hecho también el p<cgromo osi: PUBLIC SUB MainO 0114 scad AS MEK String( J EXEC . el programa principal se detendrá hasla que el proceso haya finalizado de forma normal o debido a algún fallo.• Al erecutor\o se Ionzo el ccmondo 15 con el porómelro -1.. nue$lfO molnz de codellcu ~ ¡ndoooclo d"eclOmente en el «IfTI(Indo.Cad • Pero el intérprete de Gombas es capaz de recOllOCe< VIlO morriz indicando !In codenos enlre corchetes y.vos de lo carpeta octuolen formolo Io. antes de continuar con la siguiente instrucción.indol~ los parámetros. Esto puede: ~r un inconveniente: si lenemos que sincronizar. Ob_mos q. que contiene gran cantidad de archivos. Vamos a hacer un listado de la carpeta Idev. obteniendo un lj~ de ~ arch. t!i decir. c:I programa Gambas sigue su curso sin esperar a que: el proceso hijo finalice. Palabra davE WAIT Si añadimos el flag WA/T a la instrucción EXEC.

.. 1rwxrwxrwx ~. 3 jun 28 10:55 null 28 10:55 parO -> 1pO HOLA DESDE danie1 u>b roo< ~.. .u_lffl PRINT uHOlA DESDE GAMBAS u A continuación. Ohservaremos que.."/dev".. J2 jun 28 10:55 mouseO ~. Hemos conseguido sincronizar la ejecución de dos procesos de forma sencilla. crw-rw---drwxr_xr-J: 2 ~~~ . . simplificando nuestro código.. por ejemplo. "'0' roo< roo< roo< roo< 5 jun 28 10:55 mouse -> psaux U. crw-rw---.PUBLIC SUB Main() exec mm (Ulsu. " 108. crw-rw-rw.. ya que de otro modo tendríamos.U_1U] WAIT PRINT HHOLA DESDE GAMBAS" mm Lo ejecutamos cuantas veces queramos: ya no existe el problema inidal.. 11 O jun 28 10:55 ppp Apliquemos ahora el flag WAIT: PUBLIC SUB MainO EXEC ["ls". y después pasa a la siguiente línea de código... 4. el progra- ma Gambas espera a que termine de ejecutarse 15. Gestión de procesos . lo compilamos y ejecutamos varias veces desde un terminal. ~. 60 jun 28 10:55 net ~.. crw------. crw-rw---. roo< ~..cdvd 4 jun 28 10:55 port roo< roo< roo< ". la frase HOLA DESDE GAM- BAS se introduce de forma caprichosa entre el listado generado por el comando Is: .u/devu. como en el listado de más abajo. crw-r----. " jun 3 99. O jun 28 10:55 parportO 62 jun 28 10:55 pkt.

cuyo códi- go contiene un buen ejemplo de gestión de procesos y que tambit'n podemos estudiar. Si no tenemos cud ya instalado. El descriptor del proceso Habremos observado que al principio de la sintaxis de EXEC. as! como para FreeBSD. mientras esperamos a que finalize el proceso au)[iliar. Lo que descargaremos es un programa en Gambas llamado RtldioGambas.crecer y. y a indicarle que estamos trabajando. Para ello. Tipkamente. Cuando se lanza un proceso. a continuación. si no que debe esperar con paciencia. que no se ha colgado la aplicación. el valor de State es Process. habitualmente una violación de segmento. Como ejemplo.que haber volcado el listado en un fichero. o ProTess. y lo que se recibe es un descriptor del proceso que hemos lanzado. proceso en ejecución. así como actuar sobre éL Lo que nos interesa ahora es la propiedad State. Yast. Los objetos de la clase PfOceSS tienen una serie de propiedades que nos permiten conocer el estado del proceso. aprovecharemos para hacerlo ahora. lo que haremos será dar algo de fredback o información al usuario dr que debe esperar.Running. que recibe algo de retorno tras llamar a EXEC. leerlo y mostrarlo en pantalla. finalizado. es decir. 11 Utilizando esta propiedad tendremos la capacidad de sincronizar los dos procesos de un modo más potente: podremos realizar algunas tareas en nuestro programa Gambas. Vamos a trabajar con la aplicación auxiliar cud. Esta variable es un objeto de la clase Proccss. detenido. Si el programa ya ha terminado. ya que está disponible para todas las distribuciones GNU/Linux habituales. esperar en un buck a que el tamaño del fichero dejase de.Cmshed. RpmDrake o nuestro ges· tor habitual de paquetes en otras distribuciones. la variable Stilte podrá tomar dos valores Process.5ropped. que es un programa de línea de comandos que permite precisamente lo que querernos: descargar un fichero desde una URL. que refleja el estado de ejecución. si finalizó debido a un error grave. consultamos desde Synaptic. vamos a descargar un fichero desde Internet cuando el usuario pulsa un botón. . se indica un valor opcional VARIABLE=.

"-o". La etiqueta tendrá como propiedad Text el valor Inactivo.l. aunque podemos consultar en hupJ/gambas.O. -- l BtnDescarga y una etiqueta llamada Lbllnfo. lo cual no está mal.State .Además.EXEC ["curl w • sUJtL.l.I.Process. El código del formulario será el siguiente: PUBLIC SUB 8tnoesca~a Click() DIM hPt'QC AS Pt'QCess DIM SUrl AS STRING sUrl-"http://qambas."1" CASE "1" .gz.O. en él. tar . un formulario. La VRL es h«vJlgambas. User.orgiradiogambas la existencia de versiones más recientes.qnulinex.tar. vamos a crear un programa gráfico y.org/radiogambasl RadioGambas-l. Ahora. Figura 1.Home & "/RadioGambas.Text CASE "1" Lbllnfo.qz" I DO WHILB hProc.gnulinex..Text .gnulinex.tar. y el botón tendrá el texto Descargar.qz" hProc .orglradiogambaslRadioGambas. con un botón llamado [ . nos sirve para escuchar programas de radio emitidos por Internet.Runninq SELECT CASE Lbllnfo.. Valar Inactiva de la etiqueta y botón Descargar.

de forma que se genera la ilusión de un molinillo. 11 Probom01o modificar .. System. Al terminar. pero ahora lo intedoz de usvorio quedo b1oqveodo duronte lo descmgo. entramos en un bucle que se ejecuta mielllras el proceso está vivo.1 "'" LblInfo."l . sUJ. 1I0modol . "1".tar."nlo es igual de efectivo: el progroma de$Corgo el fichero en ambos cosos.Text _ uInactivo u Més8age.Running. informamos al usuario y ponemos la etiqueta con su valor original.1 programo de formo sincrono. En dicho bucle cambiamos el valor del textO de la etiqueta entre los valores ".". ~T ·/Radiot~mbas. U-o". con 10 que el usuario sabe que algo se está cociendo por debajo.1 programo eliminando el código del molinillo y ejecutando . y recibimos un descriptor del proceso. lo qVll puede hacer pensar que nuestro programo se ha colgado y generar alguna. como explicamos con el Aog WAIT: hProc-EXEC[ ~curl". es decir.Programación visuol CO!1 Software libre CASE w\\w LblInfo.. Seguidamente.Text _ CASE &LSE ~Iw LblInfo.Info(~De8carga finalizada U ) "'" Ejecuramos el proceso con los parámetros ne<:esarios para que 10 descargue en nues· tra carpeta personal con el nombre RadioGambu.taJ. mientras el estado del proceso es Process.Text _ ulu "'" SELECT HAIT 0."'9z~l Ellvneionom.gz. "1" Y"\". Con la instrucción WAlT refrescamos la interfaz.Hane .

de alguno manero.Count .¡lida del programa: PUBLIC SUB Main() 11 DIM scads AS NEW String[J DIM Buf AS String DIM Bucle AS Integer sCuds • Split(Buf. del teléfono. monos leja.Remove(scads. en el peor de los cosos.inútile. Podemos utiliZ<lr la palabra clave TQ para conseguir dos propósitos de forma sencilla: esperar a que el proceso acabe antes de continuar el programa principal y recibir en una cadena de texto la s.ervicio de atención 01 cliente. la salida aparecía directamente en la consola. evoluor en qué coso. por ello. es mejor informar.Remove(O) ~\n~) sCads.1) FOR Bucle· O TO sCads. conviene uSOI WAIT y en cuóle. o nue. imporTonte. 01 usuario poro que monlengo lo colmo y lo. oOO O O Redil'ECc16n con ro En los ejemplos anteriores con el comando /s.COunt _ 1 PRINT Left(scads[Buclel. no. 10) "''''' A Gestión de procesos . lo cual no es útil si queremos procesar la información procedente del comando. sCads.tro . E.

PRIV~ hCancel AS BOOLEAN PUBLIC SUB BtnCancelar_Click{) hCancel-TRUE END . que nos devuelve en la cadena Buf. éste ofrece un método de gran importancia: Kili. puede dividir fácilmente empleando lo fund6n Spli¡. Gracias a KilJ podemos incluir esa posibilidad en nuestro programa.--- La instrucción EXEC aguarda hasta que finalice el comando Is. A continuación.PrQgramociór visual con Software Libre --. pero aún podemos tener más control sobre él. 6tnConcelar El nuevo código es el siguiente: Inactivo. Matar un proceso • Además de [as propiedades cid objeto Process.. vamos a ver cómo llevarlo a cabo. Supongamos que en nuestro programa anterior. Lo solido de los procesos con vario. eliminamos la primera y última (sin información úlil) y mostramos en pantalla sólo la parte del listado correspondiente a los permisos. con texto Cancelar y con el l1ag Enabled a FALSE. Añadimos al programa anterior un botón llJmado BtnCancelar. y utilizando COmO separador el retorno de corro \n. la red es desesperadamente lenta y el usuario decide no esperar e interrumpir la descarga. el cual prrmitr matar o acabar con el proceso en cualquier momento.. almacenando en un buffer la salida estándar del comando. para que inicialmente esté inactivo. procesamos la cadena Buf separándola en lineas con Split. -Figura 2. líneas . Hasta aqul hemos visto cómo sincronizar los dos procesos.

Warnlng("Proceso cancelado n ) LbIInfo.Text CASE ~\\" ~\\~ LbIInfo.tar·9z~ hProc • E1EC (Uc~rl~.gn~linex. ~-o".I. Kill ( ) Message.ECT HAIT 0.R~nnlng CASE LbIInfo.gz~J DO WHILE hProc.Text ~/~ LblInfo.Text _ ~Inactlvon BtnCancelar.Text CASE ~-~ ~-~ 11 LbIInfo.1 IF hCll1>Qol-TR1JE 'I'HEN hProc. User. sUrl.Enabled-PALSE RE'roRN END IF .State SELEeT CASE wl~ Process.Enabled-TRUE sUrl-"http://gambas.org/radiogambas/ RadioGambas-I.Home & ~/RadioGambas.Text _ wln CASE EUlE LblInfo.PUBLIC SUB BtnDescarga_Cllck() DIH hProc AS Process DIM sUrl AS String hCancel-PALSE BtnCancelar.Text __ 1_ END SEt.O.tar.Text CASE ~/~ LblInfo.

En nuestro bucle. la salida estándar de cnOre:!i stderr (o texto impreso por la consola. lOJ dos cominos Jepo- rodo••e utilizan po. los incluidas en la librerla estándar de EJTOf'ES m~nsajcs se ~nv1an a la salida están- dar con la función printf() y a la salida estándar de errores mediante perror(). lo . que Redil'ECdón dE la salida EStandar dE Si estamos familiarizados con el lenguaje C. lo s~undo. para saber si el usuario ha pulsado el pon~mos Dotón Cancelar. utilizando lo $Olido e.olido .. hCancel. si no estamos familiarizados con ese tfrmino).o dilerencior qué tipo. el feedback que hasta aqul hemos proporcionado al usuario es algo pobre: el molinillo no nos sirve para conocer cuál es el estado real de la descarga.olido estándar de errare•. devolvemos la interfaz al estado in3ctivo. lo. curl está emitiendo un podemos apfO\'C'Char. Al iniciar la descarga. ni hacernos id~a d~ cuánlo más habremos de esperar.tándor y."Inactivo" Mesnge. Si el usua- rio pulsa el botón 8InCancc!ar.oje••e envíon. de men. lo primero e. inform3mos al usuario y salimos de la subrutina. comprobamos el valor de hCancel y. dicha variable lOma el valor TRUE. Por lo . ambas e (g/ibc en sistemas GNUfLinux). de ser TRUE. proce$Os pueden enviar le"to o lo consola por dos vía. Aunque ya tenemos sincronización del proceso y podemos acabar con él a nuestro • antojo. esta variabl~ a fALSE.'feltt .Info("Desc:arga finalizada") Dispon~mosd~ una variabl~ global. matamos el proceso con Ki1IO.Progromoción vislIOl con Softwore ulve LOOP LblInfo. inform~ por Sin embargo.

rn:ibir el porcenlaje de descarga y represenlarlo en la eliqueta..tóndor [sidoult se -'e em. nuestro programa Gambas recibirá un evento ErrorO procedente de la clase Process. de advertencia o de error CurI optovecho esto solido poro indicar ele. en lugar del molinillo. Vamos ("ntonces a modifi¡. Gambas permile recoger el contenido lanto de la salida eslándar como de la salida esIándar de errores. el ptogfOmo cwI em. o informati\"O.6n Centrándonos más en curl. La sintaxis de este evento es: PUBLIC SUS Process_Error(IError As String) • En la cadena .tóndor de er'ores [stdenl se emiten mensojes de estodo.e. procedeme del proceso hijo.nlorrnociOO Uril Como \/l!ferrM» en el sigUtenle opor· rado. PRIVArE bCancel AS Boolelln PUBLIC SUB BtnClncelllr_Click() hClncel • TRUE . si está escrito en C).JEITor r«ibircmos el mensaje d(" error. si aplicamos el flag FOR READ a la hora de ejecutarlo.te el hchero recibw:lo poi' la solido eslóndor salvo que indiquemos eKptesomenle el fichero dónde depoSlfOrlo Por lo solido e.tir ..lado de lo descorgo o poro informar de un error en el inten!o de cone~.ar el programa para. d programa va mostrando una barra de progreso formada por el s[ml>olo ti (almohadilla o sostenido) y un indicador del tanto por ciento descargado. si aplicamos el parámetro -ti. Cuando el proceso hijo envla una cadena por la salida ~Iándar de ("rrores (llamando a permrO.

l.e • Process.FALSE Bt.O. User.R"nning HU'r 0.ar.gz-. Kill () Hessage.1 Ir hCan<:e1 • TRUE TImN hProc.p:llgambas. W hProc • EXBC (-cur1-. " ") lbUrato. .ar.BoDe • --''') POR READ 00 WHILE hProc:.ring h<:ance1 ."ht.nCancelar.11 2ND PUBLIC SUB Bt.n<:anee1ar.DIN 5Cad AS St.org/radiogambasl RadioGambas-l.SUlt.(Err) &Cad .Sp1it. "-0-. .Cow1t.nDescarqa_C1ick() DIH hProc AS Process DIH sUr1 AS St.t.gz ·/Radior~mba •• t.Tru.gnulinex.Enab1ed • FALSE RE'l'IIRN 2ND " ux'" .&Cad[scad.(Err."Inactivo- Bt.t.Enab1ed • TRUE 11 sUr1. .~xt.Ten .warning(-Proceso cancelado") LblInfo.ringll Err .

a (se trala de los llamados caracteres ANSI de conlrol).. una \"ez finaliz. esp«ifiqurmos un llchC'ro dondC' drposilar los datos recibidos. La primera opción sería guardar el fichero y. éste se trata en nuestro código: tomamos la cadena.En esta ocasión ejecutamos el programa cud con el parámetro adicional-#."ww. como en nuestros ejrmplos anlC'nores. pero de este modo complicamos el código ya que tenemos ¡¡UC cre3r un fichero en alguna ubicación (por ejemplo. es algo diferenle dr a de los erorres o informali\'os que vimos antes: mm . Por ejemplo. en la URL http'J'. REdlrecclón dE la salida e. en lexlO plano. para representarla en la etiqueta. el :onlC'nido de la salid3 estándar tambii'n puede ser lC'ido y cUTl rnvia el fi<:hero a la . de modo que dt la impresión que la barra de progreso avanz. sino mostrar direclamente su contenido en pantalla. separamos la cadena en varias subcadenas tomando el carácter de espacio como base y nos quedamos con la última subcadena. /fmp). Como indicamos en el anterior 3p3rtado. contiC'ne la licencia GPL original en inglés.tándar u Supongamos ahora que no deseamos gu. eliminamos con Trim{) los posibles caracte~ especiales de conlrol que (uTl U$a para mantener d cursor siemp~ en la misma linea.ardar un fichero.alida estándar salvo que. Cada vez que nuestro programa redbe un evento Error de Pnx:ess.ado el proceso.gnu. que es la que contiene el dato del porcentaje. La sintaxis del eve:nto generado por la -ecrpción de dalos procrdenles de la salida estándar del proceso. leerlo y • representarlo en pantalla.OfW'licensr:oJgpltxt. leerlo y luego borrar- lo par3 no dejar restos en el disco duro.. disponemos de un fichero que..

. Hay que recordar también que Gambas provee una palabra clave. Por ejemplo. cada objeto Process se comporta como un flujo o strellm..-I salida estándar del proceso utilizando LAST como pará- metro de las instrucciones relacionadas con lectura y escritura de procesos. llamándola TxtLicencia. -- PRIVAtt hCancel AS Boolean Figurg 3.. que dentro del evento representa de formó! genérica al objeto que lo generó. Podemos. con su texto inicial en blanco y en ella pondremos el contenido del fichero gpl. lo que en olras palabras significa que podemos trabajar con él del mismo modo que haríamos con ficheros abiertos con OPEN.sCad PRINT sCad Para nuestro programa.Programoción visual con Software libre En esle caso no hay ninguna cadena para recibir la información. LAST. haríamos: PUBLIC SUB Process_Read() DIH sCad AS STRING 11 LINE INPUT 'LAST. para leer una Irnca completa. por tanlO. añadiremos una caja de texto (TextArea).. pudiendo utilizar. El código es el siguiente: "".txl. leer el contenido de]. PUBLIC SUB BtnCancelar_Click() hCancel • TRUE END . conforme lo recibimos.. READ o UNE INPUT.. por el contrario. entonces. Caja de texto btlicencio.

Kill() 4.Text .Running WAIT 0. "_t"1 FOR READ DO WHILE hProc.EXEC (Ucurl".Count . Ubttp://www.Enabled TRUE bProc .Process.Text _ TxTLicencia.1 IF hCance1 TRUF.State .Text _ "" bCancel .sCad(sCad.Text & sCad & "\n w PUBLIC SUB Process_Error(Err AS String) DIH sCad AS String[ 1 Err • Trim(Err) sCad _ Split(Err. TllEN hProc.gnu. Ge~tión de procesos .1] 11 PUBLIC SUB BtnDescarga_Click() DIH hProc AS Process TxtLicencia.org/licenses/ gp1. " ") LblInfo.DIH sCad AS String LINE INPUT tIAST. sCad TXTLicencia.FALSE BtnCancelar.txt".

Tert _ "Inactivo" Btncancelar.Tert _ "Inactivo N Hessage. aguardaremos tranquilamente y sin hacer absolutamente nada en nuestro programa principal hasta recibir el evento Kill().Warning("Proceso cancelado LblInfo. La sintaxis de dicho evento es: PUBLIC SUB Kill() Hasta ahora. sea de forma normal o por un error.Enabled . pero podemos crear una estructura más elegante.FALSE N ) ""'""" END " lOOP LblInfo. bien sea porque el usuario ha decidido cancelar el proceso: PRIVAXE bCancel AS Boolean PRIVAXE bProc AS Process .Programación vi5ual con Software libre Message. más adaptada a la programación orientada a objetos. la clase PrOCe5j emite un evento KillO cuando un proceso ha finalizado. más un retorno de carro para separar cada línea. en nuestro gestor de descarga hemos esperado en un bucle a que el proceso acabe. valiéndonos de dicho evento: en lugar de esperar en un bucle.Info(NDescarga finali:l¡ada") En el evento ReadO leemos una línea y la afiadimos al contenido previo de TxtLiccncia. o Evento KlIIO y la propiedad Value Además del método KiII(). bien sea porque la descarga ha finalizado.

Ge f 1'I:1e proce~ .Tell:t - ~Inactivo" 8tnCancelar.bcancel - TRlJE bProc . KilI ( ) PUBLIC SUB Process_Er~r(Err AS String) OIM scad AS String[] Err _ 'l'rim(Err) sCad _ Split(Err.acad(ICad.Enabled .TRUE TBEN Messlge.lnfo(MDescarga END " finali~ada") LblInfo.Warning{Uproceso cancelado U) ELS' MesS8ge.FALSE PUBLIC SUB BtnDescargs_Click() DIM sCad AS String 4.Count .Text .1] END PUBLIC SUB process_Kill() 111 IF bcancel . u ~) LblInfo.

menos líneas de código y mejor estructuración de todo el proceso.Programoción viwol con Softwore übre TxtLicencia. Ahora [anlamos el proceso y ya no esperamos en un bucle. la moyor por" ele 10$ progrom<l$ de con$Olo (y gról.. Enabled.. El resultado final: menos gasto de r«ursos (d programa principal no ha dI' ej«-ular el bucle constantemente). Por 0Ir0 lodo. y la etiquet.org/llcenses/ 9Pl.. ''http://www.gnu... . para que sea accesible también desde el evento BlnCancdar_OickO.t . matamos el proceso en el mismo evrnto BtnCancelar_Click().._..t~ .1'e:. ] POR READ "'" Hemos cambiado la declaración de hProc de la función BtnDescarga_Clkk() al ini- cio de nuestro formulario.co$l deYueIv'en 01 sistema un COO'90 de &rro< cvondo f.a marcando Inactivo).. Si el usuario decide cancelar la descarga. Tamo si el programa termina normalmente como debido a una cancelación. aprove- • chamos el e\"emo Proccss_KiIIO para informar al usuario y devolver la interfaz a su estado inicial (ron d botón Btnúuxdardeshabilitado.. lo costumbre es que si lodo fue bien Yoll'o valor cuando algo lolló Sot ~ un cero Dcsdc la consola podemos hacer una prueba ejecutando en una venl:lna de terminal estas dos órdcncs consecutivas: $ 1& -1 Idev $ echo $1 .nalizan. bCancel '"' f'ALSB 8tnCancelar. '"' 'l'RlIE hProe '"' E%EC ["curl"..

La she!l del sistema almacenó el último código de error disponible en la variable S? y. e informar al usuario dd error.FALSE ENt> 4. Nosotros podemos leer en nuestro código ese valor. Ahora ejecutamos la siguiente orden: $ ls -1 Ifichero/que/no/eziste $ echo $7 En esta ocasión obtendremos un seis.Warning(~Proceso cancelado") ELSE Message.Al ejecutar echo $1 obtendremos un cero. un fichero en nuestro sistema cuya ruta sea lfichero/que/no/existe) .Error ("Error en la descarga") ELSE IF heancel • TRUE TREN Mes5age. por alguna extrai'ta razón que desconozcamos. modificamos el código del pro- grama anterior (página 142 en adelante)."Inactivo" Btncancelar. Gestión de procesos . a continuación. mediante la propiedad Va/ue.Text . un código de error que en el caso de! comando ls implica que la ruta no existía (siempre y cuando no haya. por cualquier circunstancia.Info{"Descarga finalizada") ENt> ENt> " IF LblInfo. devolverá un valor distinto de O. Sí [lIrI no puede acceder a la URL. lo hemos mostrado en pantalla: todo fue bien. Value<>o TREN Message.Enabled . de forma que el evento Kili quede así: PUBLIC SUB Process_Kill() • IF LAST. A contínuación.

. _ . en la 11 que escribimos cualquier cosa.. Figura 4.~ ~-'.._ -... _.. podemos usar las funciones normales de escritura de archivos con el descriptor del proceso (PRlNT....--. la pueden recibir a través de la consola.."'_'__ . Con Gambas.. WRITE). además de emilir información a través de 5tdin y 5tderr.._._-._­ <&0 .... _"".... Una vez lanzado el proceso de este modo.. <-_ _-_... y deseamos conocer el número de líneas (separadas con retornos de carro). ~ el texto Contar. podemos combinar los flags READ y WRITE. . En nuestro ejemplo...--.. con . Para ello....--~-. ..__ . con el parámetro -1 (número de líneas)... . .. y recibiremos el resultado por la entrada estándar... Puesto que vamos a leer y escribir. además de su cancelación. _ . ._..... Observaremos que ahora podemos determinar el éxito o fallo de la descarga... _.. _ _ . podemos empicar el flag FOR WRITE para indicar al intérprete que estamos interesados en escribir datos para el proceso hijo."'_H..... Supongamos un programa con un área de texto (TextArea) llamada TxtTexto..._ <-.. .. -.... creamos un proyecto gráfico con un botón BtnContar. co... :dir 'ciO! de ntrada nd el U~ o le "lOSF Los programas._ ._. con el texto en blanco inicialmente para que después escribamos un texto. según el usuario teclea órdenes... Esta recepción se rea· liza mediante la entrada estándar o stdin.~ _-"' ______ _-. y un TatArea llamado TxtTexto... escribiremos el conlCnido de TxtTexto al proceso. PRIVATE hProc AS Process PUBLIC SUB Process_Read() DIM sCad AS String . llamaremos al programa. Proyecto con boI6n Contar y áreo de texto TxIÑlxlo. Podemos. desenchufando el cable de red o deshabilitando la red de nuestro sistema...Probemos el programa desconectando el módem de Internet... y si tenemos conocimientos de e sabre- mos que podemos utilizarla con funciones como 5canf() o getcharO. ~ . usar el comando wc (significa Word Countery no otra cosa).. ~ - .. que hemos escrito.... para ello.

Ibservaremos que podemos ir escribiendo en el proceso todo lo qUl" queramos. ejecutamos el programa indicando al intérprete ue deseamos acceso de leClura y escritura al proceso. Así. ~_lHl FOR REAl) WRITE PRINT 'hProc. con lo cual el primero queda informado de qUl. l"stamos indicando al proceso que hemos cerra- ) el flujo de datos y. ~guidalllente. Gestioo de procesos . resto del programa es trivial: en el evenlO READ recibirnos la cadena que contieel número de líneas y lo mostrarnos al usuario en un mensaje.el resultado es similar: se cierra la redirecci6n entre la salida estándar del procehijo y nuestro proceso principal.hproc.LIta: INPUT . a continuación. . ejecutamos wc -1 desde una terminal de línea de comandos. por tanto. Al man- • ¡ lr el carácter especial CTRL+D.cad H " Message(HEl texto tiene sCad " H 11neas") PUBLIC SUB BtnContar_Click() hproc _ EXEC (HWCH. Text CLOSE 'bProc EN<> n la función BtnÚlntar_ClickO. deamos varias líneas y después pulsamos a la vez las teclas Úlntrol + D. Ilando en el programa Gambas ejecutamos CLOSE sobre un descriptor de fiche'. procede que él compute lo recibido y devuelva el sultado. entonces cuando nos devuelve el número de líneas que hemos escrito. escribimos en ~stc el conte- ido de la caja de texto y. TxtTexto. ejrcutamos CLOSE sobre el proceso. A." I recibido todos los datos.

por ejemplo. por ejemplo. siempre podemos diferenciar qué proceso ha generado el evento mediante la palabra clave LASf y aCluar en consecuencia: • PRIVATE hProcl AS Process PRIVATE hProc2 AS Process PUBLIC SUB Proeess_Reado Ir LAS'l'-hProcl '1'HEN ••• ••••• 4. dar órdenes al sistema tales como export o eJ.Progromoción vi:woJ too SoHwore Lbre oooo Notas finalEs sobf'E e objeto Pro«ss El objeto Proass tiene un método SignaJ() usado por el propio depurador de Gambas. . El objeto dispone también de una propiedad Id. 45HELL SHELL es similar a EXEC. ya que interfiere con el resto del código del intérprete. que es un handle o des<riplor del archivo.madas a funciones de- e (veremos en otro capitulo cómo hacerlo desde Gambas) para controlar dicho proceso. ejecutando ps -le. Si con()(emos C o C++. Los eventos generados al trabajar con procesos son estáticos. Pnmite enviar señales al proceso en curso. pero en este caso lanza la shell o intérprete de COman- dos del sistema. Si tenemos varios procesos en ejecución. O utilizarlo junto con posteriort$lIa. Este valor puede servir para buscar el proceso. Esto permite. que son parte de BASH y no comandos independientes. pero su uso no es aconsejado. se trata del identificador de pr()(eso o PID del programa hijo que se obtiene tras una llamada a[orkO. en las distribuciones GNU/Linux y le pasa el comando que le indiquemos. Habremos ~do que en los sucesivos ejemplos se ha indicado Proccss_Read y Prouss_KiIl. que es el modo de crear nuevos procesos en sistemas UNIX. habitualmente BASH. variar su propiedad con niu.

por tanto. pero en este caso Command es una cadena de texto y no una matriz de cadenas. dependiendo de sus características. • 4. añadir el formateo adecuado para que la shell interprete la orden correctamente. Queda pues. como trabajo para el programador. Gestión de proce!oOs . La sintaxis de SH ELL es la siguiente: [Variable WRITE 1 5HELL Comnand ( WAIT J ( FOR ( REAIl I I READ WRlTE ) Es muy similar a la de EXEC.También da via libre al uso de tuberías I y operadores de redirección como> o 2> entre otras características de la shell. interpretará los espacios y otros símbolos especiales de un modo u otro. ya que este valor se pasa directamente a la shell del sistema que.

además de permitir crear la estructura de la misma (tablas. .cc:i6n con el usuario o programador.. m«liante el cual se consultan y modifican dalos.~. li bien le ¡ndicofl . I Sistemas de bases de datos A grandes rasgos. Quedo fuero del olcol'lCe de eue ~bro upIicor • lenguaje SOl.). campos. un sistema de bases de dalos es una aplicación que permite almacenar y consultar información de forma sencilla. Casi todas las bases de datos actuales posibilitan la intmr.11 5. conocer este l('nguaje. . antes de pro«der a trabajar con una base de datos. etc. a través de un lenguaje llamado SQL Es importante. nos nociones bóWcos o lo Iorgo de los ejemplos .

w[eIOl S~ ~1!lbS OWO) ~seq cun 'Iel!dsot¡ un ~p SJluJ!)cd.} 'OJJlll!ld P U3 "Sod!l sop UJ selJeJy!sep SOUl::lpod OJ::ld 'SelU!lS!P SOlCP.lnbJJ U9peJIS!U!WPC.¡W ¡e 'eJUYI¡nlll)S PWJOj ap u9!xJum PlIn Jp S~lU U./P ClOt¡ e[ V "(SJO"Jl!Jbs"MMM//:dnt¡) Jl!lbs SJ 'Z.>Jd Jp el] ou Jnb JlSi' 'l!J~p s3 "U9peJl[de CI..lS::lJd J.'lU.¡nd 'oldw::lIJ Jod) JCllOdsUCll Jp SJI!)Yj syw lJS u.>d sOl PIOJIUO) 'SOICp Jp SJSPq SPIU!lS!P .llld OWO) 'e~JnbJd u9pe)!Ide clIn ClCd "ep!l -.¡ sepeqeJS JJS u::lp.lSeq cI Je)!qn .py sOl Jp u9peJ!qn C[ OlUO) sJlel SOl -JJdSe.í SOlCp Jp SJseq Jp JOp!A1aS UIl ./nll leyJS!p./SPq e[ 'Od!l opunSJs p u3 "(Slo"¡bsÁW"MMM.>U.¡P se!dm ser JJUJ1UelU '.í ppp!lnS~S .> Jod OIUCI 'cpcn).lJ U9!)CWJOjU! e[ 'sOAO.í 'od!nb.lS C¡..lSCq epcJ UaUJ!lUOJ Jnb SOlJ!.l 0!d01d [.íc ood UO) O{JC¡elSU! J elUeJSoJd l::l Jlqp~J ::lp::llld ::lIU::l![J 13 "elllJu.¡lUJlUlcOI!qet¡.lp U9!J -PJlSlU!WPC.>s ~p se!doJ sns J.¡seq sel{Jnw unstx3 Jl'!:l JJOMIlOS.>Aell eun UJ o O:) un UJ eseJ e el -JSl~hJI1 o JIUJlUeJ!P9!lJd pep!mS.p 0[9S SJ[q!SJ»P 'SJ["IDO¡ sOlep ap sJseq UOS J1U.¡/elnpJI OpOUl u.»et¡ Jp::lnd ouensn ¡J.l SJS1U\ se¡ Jp eUlJ1U! emlJnJISJ IJ'"] "JIUJ1]J sod!nb::l SOIU!IS!P JpS.>I Jp SOWJt¡ 'U9!)i'J![dc CllS.lp SeJuYl¡nW!S SJlIO!XJUOJ SPPPA Jl!WJJd .d un.lJOJd anb OIUa!lU!UJlUPW [J lcz!lpaJ.¡Ul[eUlJoN "cp.medn){l.ldse sop SJIU.//:dllt¡) lbs..}p 'O[dlU~f.llIJI S.}[elllJlUep -unj sOIJ.¡ opelo[e OA!t¡JJe un Jnb syw SJ ou salep ap .>s U9!JC¡ClSU! eun um aIU::lp!Jns epuJlod e[ eSnfuoJ ::l1!JbS sOlep::lp .> Jod 'U9PSJS e[ eJed "OPUcfcqCJl J!nSJS eJCd lISO .¡U~!lUeW JOP!I\l.>p ct¡ JOppWPlSOld 11 J3 "omp o)S!P OJISJnU U.lS [3 "CPCuJJcwle U9!JIJlUJOjUl P[ CUO!lSJS Jnb '50Jl!Q Jp SJsvfj Jp lOpiAJJS opewen eWIJJíloJd un J1S!x.¡ SOU.¡ SOSJIlJJJ souaw S0t¡Jnlll U::lwns -UD) 'O!qlllPJ V "pml!lJs.luo!)d!J)Su! J souwn¡e Jp Cl¡nSUm C[ 'SCU!W9U ap U9!lS.¡P JopcweJSoJd [.¡ns.lP ou 'JOP!AJJS ¡Jp e.lP ZJlI!JU.lA lel 'Od)l JISJ Jp Je[ -ndod syw so¡ep ap awq P[ 'xnu!l/[)N8 u3 '(O:) un U.í e!h::lJd u9peJnSyuO) U!S Jnbllelle JJlll!Jd ¡::l U::l leJl) ::lIXllld::lS ::lscq e[ '¡euO!JlpC cpn.Jod OlUO) 'SOpell~)eW¡e sOlep ~p u~wnlOA ¡.í sO:) Jp SOICp Jp Jseq eun '\cUOSJJd epuJSe cun JJS Jp.}l!UllJd ou .> aps.}lUO.í u9pPlelSU! e¡ U~JJ!nNJ ou ':)d I~ U.>p U9!l -SJS e[ o Jsc[J eun::lp souwn[c SO] CCAIIC[.lp .í~ S~ O[JpOW ~ISJ Jp o[d -W::l!J un "e[qcl o .lSCq cun 'O!)JJWOJ 0\lJnb./P s.>p U9!)ClUlOjU! Jp U9!)c[!dmJJ cI o 'Olnl1lSU! un UJ S.¡l.>pcu! .í opensn epe) ap OsaJ)e Jp soslwJ.UOJ 1011S!A lJ9!JOWOJ66Jd .>S Jp ICUO!SJjoJd U9!)C)lldc cun 'JpueJS 0Pl.} un.í JC!::lUCW C so¡cp Jp uJlUnloh p :s.

Gambas puede manejnr varios tipos de bases de datos. el cual es un estándar para comunicar aplicaciones con bases de datos. Sólo cu:mdo no dispongamos de Ul10 11 espedfico. Dispone. Esto permite entrar. MySQL y Postgres. a bases de MS SQL Servero Firebird. Los drivers para cada sistema de bas('s de datos son también componentes. lo que permite acceder a distintas bases utilizando el mismo código. cualquier aplica. sin modificaciones. ••• •• 5. podemos lu:ceder con Gambas a cualquier base que soporte dicho estándar. basta con especificar el tipo de bases de datos a utili7. A la hora de elegir un driver u otro.db como dependencia. en este momento. de t res drivers espedficos: Sqlite.postgresql.llr. el inlérprete de Gambas ver específico. posiblemente. Estos son módulos de código escritos por diversos programadores espedficamente para comunicarse con una base de datos determinada. tratar~ de cargar el dri- 5 Gestión de bose~ de doto~ . tendremos presente que los drivers espedficos están optimizados y ofrecen una mayor velocidad de transferencia de datos. 2 Bases de datos y Gambas Gambas tiene estruClurado el acceso a bases de datos mediante drivers.org/). versiones con soporte comercial. además. por ejemplo. Ambos sistemas poseen. usaremos el ODlle. COfllO veremos más adelante. y ti resto del código funcionará.. Además cuenta con un driver ODIlC. Por lo tanto. con independencia de la base de datos utilizada. ción que use esta caracterlslica. En el entorno de software libre. nec('sitará el componente gb. las dos opciones más probadas y de mayor prestigio son MySQL y PostgreSQL (htlp:llwww. Aquf tendremos que estudiar qué servidor de bases de datos es el más adecuado para nuestro sistema. Una vez que indiquemos a qué sistema nos vamos a conectar.l~ necesidad de la consulta e ingreso de datos desde diversos puestos de trabajo de forma simultánea. pero el programador no ha de marcarlos como dependencias. Adentrándonos en la estructura de Gambas para bases de datos.

p""'!Uo1es que 5Ufjon Q la hora de VIO' el componente gb. Tambitn pode- mos ej«utarlo directamente desde la consola. el gestor grafico Antes de explicar el modelo de programación para bases de datos de Gambas. Para ello d~rrollamos un proyecto nu~ O bien abrimos cualquiera que)'3 tengaI1lO$ al nuestro equipo. que es una aplicación escrita en • este programa.E. múltiples bases de datos. H un progrorng .sq/ile: Sqlite versiÓ!l 2 o onteriOf.-n1O y es Software libre.db.sq/ó/e3: Sqlite versión 3 o poslerÍOf.odbc: genérico OOBC.c/b.mysqI: MySQL • gb..lUdio de su código nos puede oyucIor o '''~ dudo. con el comando gambas-databa~­ manager. PostgreSOL • gb. El Gfltor de Bases de Dlms escrilo en Gamba. Tras pulsar la opóón correspondiente. nos prtguntari una conlrast'ña... V3IJlO$ a aprender a utilizar el Gestor de Bases de Datos. Por 10010. CrEar una baSE Vamos a apunder a crear nuestra propia base.db.db.. • gb.db. de forma sencilla. 5. Dicha conlrasma st' ('JTlp1ea para almac=ar encriptados los datos dt usuarios ycontrasdlas q~ . • gb. el . SO/!: • gb. Awdimos al menú HeTcamientas y seleccionamos el Gestor de Bases de Dalas.los componentes especiale.poJtgres. la cual dota al entorno gráfico de desarrollo de una herramienta para administrar. 3 Gambas-database-manager.c/b..

H. F~ 1.... Gel.. postgres u odln:. _ Pulsamos en el menú &rvidor y elegimos la opción Nuevo servidor.. la contraseña que introduzcamos habrá de tener 8 caracteres como minimo. Hemos de especifi_ car.. O" OUlD<w_Ioo_ _. a continuación."OH.. ..- .---.-_ _-.. para evitar que otro usuario pueda lurlos con facilidad consultando los ficheros del entorno Gambas. mY5tlI.. Opción ""-~.... ~ El primer dato. de que arranquemos el programa. aparece el gestor en sí. -- para las conexiones sqlite el Host no será otra cosa que la carpeta donde se encuentran alojadas las bases de datos.Id. que en principio rslá vacío. Tipo. 111 . sq/iuJ. .. F.--• conexión.. una ruta absoluta dentro del sistema de archivos. como puede ser Illomehmm· Figuro 4.. Como excepción. y se preguntará cada Vtt _.. -. los datos relativos a la conaión que deseamos establecer (Figura 4). para desencriptar contraseñas ya almacenadas en 5eSionrs previas.. ya que no hemos configurado ninguna conexiÓn.. . Inlroduttión deseemos gestionar desde rste programa.. lO"_ • • • _ . Dotos de la riolbases. Host es el nombre del equipo o dirección IP donde reside el servidor de bases de datos.Ior de bases de dolos de Gombm.. es decir. Figura 2. . se refiere al driver que emplearemos: sqlire.gura 3.... Tras rste paso..

-Figura 5.. crearemos una base Sqlite. En el segundo escenario. Para ello. e. con un usuario llamado (lr/min I y una contraseña para dicho usuario. especificar [os datos de usuario/contraseña. Introduciremos. base Sqlile. . al tratarse del propio equipo.to bese de dato. Supongamos dos escenarios básicos. y en nuestra carpeta personal. En el caso excepcional de Sqlite. por 10 que los permisos vendrán definidos por los privilegios de un usuario y su grupo en el sistema de archivos (lectura y/o escritura). las bases de datos son simplemente archivos.mysql.0. podemos hacer: mkdir Bases También podemos crear la carpeta con Konqueror o Nautilus. tal y como aparree en la Figura 5.1.0. - •. los datos de 11 En cuanto o lo in. -. desde lfnea de comandos. por tanto. .Progromoción visual oon Software libre El tercer y cuarto dato son el nombre de Usuario y la Contraseña para acceder al sistema de bases de datos.tolación y odministroción de MySQL. En Tipo indicaremos el driver mysq/¡ como Host. muy recomendable camu~ tor lo do<:umentoción disponible en to propio pógino de e.com/d/X/.: http://dev. Ahora rellenaremos los datos de conexión. pe. Conexión o uno ". se puede indicar o bien lowlhosr o 127. con el que trabajaremos en adelante. después. que es una direc- ción IP que siempre apunta al propio nombre de Usuario y Contraseña. En el primero trabajaremos sobre un servidor MySQL en nuestro equipo. si así lo preferimos. No procede en ese caso. Lo primero que tenemos que hacer es abrir una carpeta nueva para almacenar el fichero que contendrá la base de datos. que determinan los distintos privilegios del usuario.

Gestión de bo5e$ de dolos ..spongo de RedHoI 7. El uso de tStI opción lrivial: se pugunta el nombu dc usuario y contraseña y si a su vt'Z licnc permisos dc administra~ ción. y después un die con el botón derecho para que St' mueslre el menú contextual de opciones (o izquicrdo.. opción Figuro 7.. • • . el cual alojará la base . . 5. se pulsa OK para añadirlo..iI( "IIII!I'. pulsamos OK y el nutvO servidor quedará reOejado en el árbol de la izquitrda del gestor.-----.. que en el caso de Sqlire será el nombre del archivo dentro de la earptta que previamente indicamos..mos que programar poro slSlemos antiguos {por ejemplo.locoIiroci6n del nuevo apunlando a servidores MySQL o Postgra.o ..r.ioo.. haremos doble die con el botón izquierdo del ratón sobre el $('rvidor (o · __ ·. ~ Figuro 6. taI ...\o ver~ 3 a pom..... o bien algunos • ... cuestión que o veces el dienl{l reclloza o impone... Iemo Para nuevos desonolos es recomendoble d.Ct.. Si creamos distintos ser- vidores. Seleccionamos la opción Crear base. para los zurdos)...z debamos pIonleofflOS el usar sq/ile en sus ... si se es zurdo y se liene asi configurado el ratón). Mis ddante -----.rbasa.~ de 01 elJor más oplimizodo Pero li len.". Para conectarnos.. por ejemplo). a fin de no tener que eompilor e in>lalor nvews librerios en el sisrema... )( e .. (dislintas carpetas. ti~ne ~ntido si lrabajamos sobre un sistema servidor lk t$ ases dt dalos (mysql o po1tgres).01.. Opción Creor base. a MJIi"'3 depend. Una va incluidos los datos.. vemoos algUn ejemplo concreto. "•• b.. y ttrlemos pa'misos de administración sobu el ser- ido•.rsiones anteriores. Nos preguntará d Nombre de la base......' Figuro 8.'"---"...endo de los gMtores irutolodon en e1li. O EI el botón derteho. se irán añadiendo al árbol..Podremos selecC1Ol'l(Jl' JqI. un dienle que d.. Menú contextual cIeI iI erar USUiIrio.-_I"'l Ir" 0 •• .

. Señalamos como nombre prllebas y pulsamos OK. para que añadamos la información a los campos que aparecen. con la que crearemos una tabla para almacenar datos de los libros de nuestra propia colección. un número que a su vez pegaremos en el lomo (forrado) para buscarlo rápidamente. en los cuales se puede indicar varios tipos de labias.mo><:. Los campos serán: un identificador único. Los da~os que se pre- 0_. la fecha de adquisición. O Il. Figuro 9. Seleccionamos Crear tabla . Una vez pulsemos sobre el botón OK. . r Figuro 10. Base pruebas.----- . -X "". guntan son el Nombre de la tabla (ponemos dmos en nuestro ejemplo). podemos dejar los datos con los valores por defecto. el autor. el gestor aparece en cllado derecho moslrándanos la estructura actual de nuestra tabla datos (vacía). Salvo que tengamos necesidades especiales. - Crear tabla '~". una tabla Para crear una tabla. Figura 11.Progromación VI~2!. optimizadas para una u otra larea concreta.. Ventano poro creor uno tobIo. CrEa..son Softwar~bre de datos que vamos a crear. hacemos doble clie para abrir la base y pulsamos el botón derecho para obtener su menti contextual (Figura 10). como en el caso del servidor. Por tanto. como MySQL. Ya disponemos de una base vacía. el precio que pagamos por él y una breve descripción. vamos a manejar primero la pestaña Campos. Menli contextuol de lo bose_ O Este segundo parámetro s6lo tiene sentido en -~ 11 determinados sistemas servidores.. el titulo del libro.. donde hemos de crear las distintas tablas que alojarán los datos. y el Tipo.

Hemos de pensar en los tipos de datos que almacenaremos en cada campo: • Identificador: un número entero. • Descripción: una cadena de texto. • Autor: una cadena de texto.. La clave única estará formada por varios campos o uno sólo. '. • ¡O_M (l- • Figurg 12.. 11 Pensor en los tipos de datas nos evitar6. posteriormente. osi como o reducir el tamaño de la base de daTol y optimizo.."r_·_·_ . lo velocidad de consulTa.. '.._Ir" r~.Título: una cadena de texto.quedal." le y me'e<:e lo pel'O dedicarte un tiempo.. También hemos de delimitar la clave principal. .. Este polO es muy imporlo". Gestor de lo tabla.. o .. En nuestro caso se trata del campo referido al número de identificador. que es única y sirve para identificar cada registro almacenado.1. 101 dotos por distintos porámetrol. _.-- e_o.. 1. • Precio: un número real.- .. problemas a lo hora de hacer bUs..... . ordeno. II~". • Fecha: un dato tipo Fecha.

. lsqlil:el· pruÑ>u· datos x 11 " •..1es de \'l!Ce$ gesIiooor.. dodo que oIgunos ~slemos de bo~s de dolOS lo permiten. Valor por ddecto: (nada). Como . .'ro). Tipo: Fec1la: Longilud: (nada). rellenamos \os datos (00 ($105 valores: • Nombre: ritll/o. Longitud: 40. y loe tupole<:o la Muto expon~ y mono tenim~1o de uno opltcociÓfl Para crt"3r el primer campo.on diseñar labios ~n doves únic~. "'" Longotud V~ por dete<:IO Para el resto de campos. SOl 1:1 CMnpoI "lndices liloillos @X¿9-:t a· -. modificaremos el que el propio geslOr ha creado como sugerencia.e rompe lodo ""'kljo que puede opoOtI' uno bese de dotos relaciono!. Tipo: Strilrg. longitud: 40. • Nombre: autor. aparece un lalo de ayuda que nos indica el significado de cada uno.wlIodo loe 8'!'*oban lobIas propetlse» o -ores. Dejaremos los demás campos en blanco. IenkIs de l'I\OflotjOI' y muy di"'.Algunos programadores . Valor por defecto: (nada). • Nombre: fecha. y que sirve pan alladir un nuevo campo. Si nos movemos por los distintos iconos. Conforme los creemos. Valor por defecto: (nada). indicando como Nombre ¡(lemificador y Tipo /llreger (es d<'cir. jomós ie debe trabajor de este modo s. . con dotas duplicados. conIorme po$Oba '" ttempo y los dotas oumenkJbon. número entl. 0Ir0s entornos soI. COlIOlO~idose o por duplicaciones. pulsamos el botón con el icono q~ rcprtStTlU UN hoja en blanco. Tipo: S"i"g. o JhomeldanoeWne..

Valor por defecto: (nada)."'O 'om'" . tamaños máximos si planeamos cambiar de gestor de bases de dotos en un futura.er 200 o 255 caractere'. guardan todo el tamano indicado (en nuestro caso 40 caracteres para el titulo y el autor..!. 11 la langilvd máxima de un campo de texto ~uele .• Nombre: precio. en cuenta lo. los sistemas de bases de datos habituales.dalo. Aunque sólo guardemos un carácter en un campo de un registro dado. Gestión de bases de dolos .. comprobaremos rápidamente el ahorro que se consigue con un diseno racional previo de los tamaños.. La interfaz deberá de quedar con esle aspecto: o h'>on'IeldarlleWlases (sqlitel· pruebas . Longitud: (nada). Por ello. por tanto.. . • Nombre: descripdorl. Conviene ajustar 10 más posible el valor para no hacer crecer a la base de datos en demas!a y. debemos tene.s de dotos. B3 Datos lOfl9f!ud Valor por defK! '"" " " figuro 14. Tipo: F/Otlt. o 200 para la descripción). Tipo: Stril1g.lmoddkadol ®~ . en muchos ~istemas de ba. 5. y se refiere al número de caracteres que se pueden almacenar. O campos OX i eideotlic~ !I. hacer más lentas las búsquedas y modificaciones posteriores.. Aspecto final de lo creod6n de 1<» compo~. Longitud: 200. Si multiplicamos estos valores por un gran número de registros. El dato Longitud se aplica sólo a los campos de tipo 5lrillg. Valor por defecto: (nada). fJ Indice. me una aplicación ya desarrollada.

podemos observar en la Figura 14 que el primer campo. pero o cambio .idad de optimizar la. En cuanto a la clave principal. Si exi. Aunque en nuestro caso.Cuando creamos un nuevo registro. Estos tipos abstraen los de la propia base de datos. sólo tenemos uno. oecesario recurrir o optimizaciones de esle nivel.. si es necesario por el aumento de volumen de doto. Para grabar la nueva tabla en la base de datos. Gambas reali1. se deben crear con la. el campo se rellena. "sí~ o "no~). toblo. E. por defecto. que sólo modificaremos para casos específicos. La suma de todos los campos que estt'n marcados con la llave. y sólo cambia ocasionalmente. tecnologia o velocidad requeridos. Podemos pulsar sobre el primer elemento de cada campo para que aparezca o desaparezca dicha llave. ".l una abstracción de los tipos de datos. se encuentran sólo en fase de diseño. A partir de este momento. por ejemplo. con un valor. tipo. lista para añadir datos o consultarlos. . herramientas propios de ese sistema de bo". "entero largo~. no e. Floal (número real). de dolol palO un sistema concreto. salvo en cosos muy concreIO'. 11 decir.islema ge. de doto" en lugar de lo herramienta geoérico de Gamba. identificador. conforma la clave principal o identificador único de cada registro. "entero corto" o "entero de un byte") asi- milándolos a los de Gambas y simplificando la transición entre un sistema de bases de datos y otros. la tabla aparece realmente en la base. Como hemos podido observar. tiene una llave amarilla marcada. S"ing (cadena de texto) y Fecha (fecha/hora). permitiendo elegir entre unos IIlUY concretos: Boo/ean (dos valores. Estos datos.ró más difícil combior de . Esto es útil si un dato se repite muchas veces. /IJleger (número enlerO).1e nece.e pierde porlabilidod. la. (algunos sistemas contemplan. pulsaremos el icono que tiene el símbolo de un floppy (disquete).. hasta ahora. En general.tor en el futuro.

los demás campos que mnforman ese índice. _ . tantas vc<:es como sea necesario. Una vez creada la tabla. Usar . puede que deseemos hacer frecuentemente búsquedas indicando el autor. el cual determina si pueden existir o no dos registros en los cuales los datos de los campos pertenecientes a un índice sean iguales. por ejemplo. A tal efecto. a continuadón. podemos editar los campos. para saber los datos de todos sus libros que tenemos en nuestra colección. alfO COlO que corocleres del alfabeto inglés y número•. el nombre del libro + el autor. de forma que más tarde cada consulta se ejecute lo más rápido posible.imbelos como caracteres con tilde. basta con que indiquemos el nombre de ese campo.. fndices. Por ejemplo. puede comprender. Ahora podemos pasar a la siguiente pestaña (Figura 15).arios discos editados por esa diswgráfica en un mismo ano. añadir o quitar. la interfaz proporciona dos botones. En general. por tanto marcaremos 5. como paro lo migración fvluro o airo sistema de boses de dotas.lo••iempre. no se debe utilizo. Si hay varios. Ge!>tiórl de 6o!>es de'da""'o'. Nuevo índice.ener un Indice creado a partír de los campos discografica y fecha. siguiendo el mismo procedimiento. E! primero. El otro dato de relevancia es el valor Unique.Los nombres ~ campos u$OOOs en el ejemplo no tienen ocenlos. Por ejemplo. pero su gestión desde este programa es trivial: basta (on que los creemos. Y puede haber . lonto paro uno simple consulto de dolos. es decir. eliminemos o modifiquemos del mismo modo que hemos hecho para crear los campos de las tablas. Si está formado sólo por un campo. se puls. para indicar. lo eñe o lo cedilla. pueden dar muchos ooores de cabeza 01 programador en elluturo.ará el botón nuevo campo de índice. sirve para anadir un índice a la tabla. Cada índice puede estar formado por uno o más campos. puede interesarnos . separodOles toles como el amper$Ond 1&1 o un espacio en blanco. Es uno molo politico de diseño. 11 Para nuestra pequena base de ejemplo no utilizaremos índices. hoy que evito. Un Indice sirve al gestor de bases de datos para organizar la información. en una tabla que contiene datos de CDs.

~ .~j~':. Cada ~z que pulsamos el bolón Nuevo registro. los datos que anadamos. en una base de datos de alumnos puede inler~rnos un ¡ndice que comprenda el ONI y su nombre.ra 15. Nuevo registro (hoja en blanco). Hay que lener siempre presente que. Dispone de tres bolones. . sólo SI: actualizan realmente en la base de dalos cuando pulsamos el bolón para guanhr.. lo cual nos pl"rmite asegurarnos que la solicitud de eliminación es correcta antes de pulsar el botón Guardar dalos.. se crea una linea.:S.':'~'--_ .~..Jt'Y. . Borrar registro (aspa roja) y Guardar dalos (floppy). -< ':. Cr..el valor Unique a FALSE. no hay dos personas con el mismo DNI.. luego ese índice es (mico. correspondiente a un nuevo regislro nl la labia aClual. Por el contrario... En este último caso el registro se pone de un color diSlinto para senalar que en la próxima actualización dicho registro desaparecerá. Datos. al trabajar con esta interfaz. para poder introducir los datos de varK>s discos cuyos cam- pos sta" coincidentes.oci6n de In&es.>' __ Figo. .. También.•.. datos dE una tabla La última pestaña de la interfaz del gestor de bases de datos. y marcaremos la casilla Unique con el valor TRUE para proteger a la tabla de datos duplicados. nos permite con· sultar y modificar el contenido de la tabla. podemos modificarlos o bien podemos seleccionar un regislro yeliminarlo con la opción Borrar registro..a_ . si la tabla contiene ya datos. Podemos desplazarnos por los dislintos cam- pos de ese regislro. En este caso. • • oDo D o Gestiona. para añadir los dalos correspondientes.t§. eliminemos o modifiquemos.

. 'o:.... Introduciremos registros de libros utilizando esta interfaz. Recordemos que es importante pulsar el hotón Guardar datos cuando hayamos terminado la edición.Petición Sal ~ lB! seleCl • from dato~ '" " . para que dispongamos de algunos datos con los que trabajar en adelante. para lo cual emplearemos el símbolo ') y después se usa la palabra clave PROM para indicar de dónde obtener esos datos. a continuación hay que determinar qué queremos consultar (en nuestro caso todos los campos.. Para los que no estén muy familiarizados con ellf'nguaje SQL. podemos ya Indices IIE Datos " ! fJ "_.~ - 11 Fi 9 uro 17. ióo SQl. DOOOO ~ saL Sin escribir aún código Gambas.. Figura 18. Nuestra primera consulta servirá para obtener un listado de todos los datos de la tabla que hemos creado. adaramos los siguientes puntos: las instrucciones de consulta comienzan con la instrucción SELECT. uno de los botones del geslor de bases de dalos de Gambas contiene un texto SQL Lo pulsaremos para escribir sentencias en este lenguaje. @ empezar a trabajar con el lenguaje SQL Como hemos podido observar. Gestión de Ixnes de dotos .. Pestaña de Dotos. • el Campos D X .- ---- Figura 16. Lenguaje SOl 5. _. )Ql/home/dcamposlBases (sqlile) . -- -- ".~ .pruebas .

obtenemos el resultado de la consulta en la parte inferior. "'''' oo.... Obtener todos los títulos de los libros cuyo precio es maYal" de 15 euros: select titulo from datos where precio>l5 3. También pode- • mos exportar los resultados de la consulta con el botón Exportar datos. V.. también podemos realizar las siguientes consultas: 1. Kcalc u OpenOffice Calc.!"U ll'O'iiJ4 lZOO'Ol 2l."'0' . I.. I liI ~ "...'G: "'" \. ....s . ...'O..'Q2 Ip- I '''''''P''''' N.. l~Qt. Resultado de la consulta... 3"d::I pcr :hn AJ..loeotQ • • • 2 Del:aCa'-lII ... Para familiarizarnos con SQL.. Podemos guardar las consultas complejas en un archivo y luego recuperarlos para su uso posterior.dl lo&.... I "'" Gblfll <Oc..t:¿tIJ la ~sdcN:n:rr ¿ CUa-..:=.bM:tICU'ol 1.' Pdítoa N<h"dar~O' Na.&rds . con los botones Guardar petición y Cargar petición. titulo from datos arder by autor 2.Programación visual con Software Libre Al pulsar el botón Ejecutar. Mostrar el título y autor.Io Ci~:Ir'laI dD.cn:la FiOCll(n.. eu.". \ • Fi 9 uro 19..- N(h'd. Ha::JO--' .. '--- . .'c. ordenado por el nombre de autor: select autor.J«bJ 5 regíslros .-dJl. Obtener todos los datos de los libros adquiridos antes del 2004: select * from datos where fecha<"2004-01-01" .""'. o copiarlo al porta papeles para pegarlo en una hoja de cálculo como Gnumeric. Go:J'qe O .

a través del componente gb. varían de uno base de datos o otro. De esta tarea se encarga la clase Connection. El primer requisito necesario para esta labor es saber cómo acceder o conectarse a una base de datos. Creando varios objetos Connection podemos conectarnos a varias bases de datos. realiza una abstracción de la estructura y los datos de una base. sino que también podemos realizar cualquier operación permitida por SQL+Sistema Gestor de Bases de Datos. de/ete o cualquier otro que no dé como resultado un grupo de registros. Obtener todos los títulos que contienen la palabra la: select * from datos where titulo like "%la%" Con esta interfaz no sólo podemos consultar. podemos añadir un nuevo registro en la tabla datos: insert into datos values ("El lazarillo de Tormes". y puede resultar que uno consulto dado sólo funcione paro un sistema de bases de datos determinado."Novela") Al utilizar instrucciones insert. si tuvimos éxito. Gestión de bases de datos .200S-02-03. o bien un mensaje de error si lo base de datos no aceptó el comando. el gestor muestro lo leyenda No hay registros.los formatos poro representar fechas y caracteres genéricos (comodines).db. "Anónimo". 4 Programación Modelo de bases de datos Gambas. Por ejemplo. 4.20. 5.91. • •••• [J I 5.

Cuando se 11 trabaja con bases de datos rtlacionales. En horizontal tenemos los encaba.ados que nos indican la información de cada campo de nueslra labIa. La información de una base de datos se almacena en diversa. por lanlo.db aporta una clase T. La clase Rtsl.Progrcwnoción YÍsuol con Software Libre El objrto Co'lntcfion dispone de una ~rit de propitdadts para determinar tltipo ~.lb/e. e1c. . los objetos de la clase Rall/t proporcionan el acccso a dichos registros y (ampos de información. putde consultar promtdios de valores.. nueslros ptrmi$OS de acccso. Cada tabla se putde imaginar como una rejilla bidimensional. como si se tratara de una labia. ti} un formato similar al de las propias tablas. una rula ti} ti sisttma dt archivos o una dirección IP). sino que. Y ios datos del usuario qlX' aportan la desta contetarst a dicho sistema. y la clase Field que determina las caracterfsticas de un campo de una tabla. En todo caso. que define la estructura de una tabla. o o o o O ConEctandosE poi" códIgo Vamos a coneetarnos a la base de datos Sqlite que creamos en el primer apartado. Dependiendo de nuestra versión de Sqlile. el programador no se limita a hojear el contenido de una tabla. dalos agrupados por una clave u ordenados según algün crilerio. pero en esle caso no proporciona información sobre un campo de una labia de una base de datos. el nombrt de la $tr ubicación del rtrurso (putde CMta~. En Gambas. el componente gb. Esta c1ast.Ia de sistnna dt ~ de datos. el sistema de bases dt datos devutlve sitmprt el resullado de la consulta como una serie dt rtgistros que disponen de varios campos. sumas. La dast UKr ptrfib nutstm usuario y. empleando instrucciones SQL.stablas. En vertical se viln acumulando los distintos registros con información. uniones cohen:ntes de los datos de varias labIas. junto con la cla~ infonnación necesaria sobrt nuestra basC' dt datos. usaremos el driver llamado sqlite o tl Sl/liteJ.ltField es similar a Fiefd. sino sobrt un campo de un conjunto de registros procedentes de una consulta. es decir. al estilo de una hoja de cálculo.

que será el de arranque. y.. \hora vamos a escribir una función que se conecte a la base de datos dentro del códi- .Name _ Hpruebas H hOonn. un control ColurnnView llamado Tnb/n.ecto gráfico llamado MisLibros. Gestión de bo~ de dolos . Opan () IF ERROR TREN bOonn .'Or al conectaz:' con la """"'" TRUE END IF RETURN FALSE END 5.Type _ Hsqlite" Tal hOonn.Host _ H/home/usuario/Bases H hConn. Formulario FMoifl.ontro! ColumnView mostrará los datos de la tabla que habíamos crcado en los :jercicios anteriores. dentro de él. Erl.NEW Conneetion • base~) hOonn.0 del formulario: Private hOonn as Connection PRIVATE FUNCTION Ooneetaz:'Base() AS aoo1ean IF hConn<>NULL TREN RETURN FALSE hConn . Para ello creamos un pro).'Oz:'(~Ez:'l. • FiglKO 20.NULL Message. Este . Situamos en él un formulario llamado FMaill.- .

Definimos un objeto Connection que será accC5ible en IOdo el formulario y repre-

senta la (onexión a nuestra base de datos. Despufs se escribe una función
Cone<:larBase que d<,vueive FALSE si tiene éxito o TRUE si falló.

El código conlleva estos pasos:

1. Si ya hay una conexión (si d objeto hConn no es nulo), relornamos inme-

diatamente indicando que ya hay conexión FALSE, de esta forma podremos llamar sistemáticamente a esta función desde varios puntos sin preocupar-

nos de si ya existe la cone:l"ión

O

no.

2. Crt'arnos el objeto Conncclion, que en principio no está cont'Clado a ninguna base, y proporcionamos la información necesaria
mos la propiedad
HOSl, que: m
p3r.1

concelar: rellena-

el caso <k una base de datos con savidor podria

ser una dirección 11', pero que para Sqlite es una ruta dentro del sistema de

11

archivos (recuerda sustituir /llOwe!USl/nrio por la ruta donde tu almacenaste la base del ejemplo); dcspu(:s indicamos clnornbre de la base de datos (pruebas), que en el caso de Sqlite es también el nombre del archivo que está dentro de Jo¡ carpetalhomeJusuuiolBases; y por último indicamos el tipo de base de datos;¡J que nos conectaremos, y que sed sqlile o sqlild, de acuerdo con

el disdlo que realizamos con el Gestor €k Bases €k Datos de Gambas. Si nuestra conexión se realizará sobre un servidor MySQl, por ejemplo, también lmdrfamos que rellenar las propiedades Logi" y PaS5wcml, con el nombre de usuario y contraseña de acceso al servidor.

P'uew que oUn no eslornos feolmenle cone<:lodos, podeilios reIlencw lodos ~ cIok>¡

en el «den que deseemos

3. Despues, tratamos de abrir la conexión. Si no fuera posible (por ejemplo, por una rUla incorrecta o un fallo en el servidor), se disparari un error, que capIUl1lmas con la orden TRY.

4. Si se ha producido un error, hac~mos nula de nuevo la conexión fallida y retornamos con el valor de error, que según hemos decidido, es TRUE.

5. Si, por el contrario, hubo wto, retornamos el valor correspondiente (fALSE).

A continuación, vamos a crear una función a la que llamar para cerrar la conexión. El algoritmo es sencillo, si no hay ninguna conexión, relornamos, en caso contrario, cerramos la conexión y la hacemos nula para que una próxima llamada a QmectarBase se aperciba de que no hay una conexión activa.

PRIVATE SUB CerrarConexion()
If' hCOnn • NULl. TREN RE'lVRN

hConn.Close{ ) hConn • NULL

ENe

11

Consulta dE datos
Al abrirse el formulario, abriremos la conexión. leeremos los datos disponibles, los representaremos en nuestro controllilbla y cerraremos la conexión. Esto quedada represelllado de la siguiente manera:

DIH hResul AS Result DIH Clave AS String

Tabla.ClearO IF COneetarBase() TREN RE'1'URN Tabla.COlumns.Count • 5

5 Ge~lión de boMl~ de dalo~

Progromación viwol con Software Libre Tabla.COlumns(O).T8xt - -TituloTabla.COluans(l).Text _ -AutorTabla.COlumns(2).Text - -FechaTabla.COlumns(J).Tert - -precioTabla.COluans(4).Tezt - -Descripción-

Tabla.Add(Clave, Clave) Tabla[Clave)[l] - hResul¡-autor-¡


END

Tabla[Clave)12) - hResul[-fecha-¡ Tabla[Clave)IJ) - hResul[-precio-) Tabla [Clave) (4) _ hResul[-descripciOll-1

hResul.MoveNe:rt( )

LOOP

Qerrareonezion()

El código trata de abrir la conexión y si fracasa saje de la función. Si todo va bien, define cinco columnas en nuestro control de tabla, pone elthulo a los encabezados de columna y procede a rellenar los diferentes registros. Para efectuar esta tarea, primero consultamos los datos de la tabla, empleando el método bec de nuestro objeto hConn, al cual pasamos como parámetro la consulta SQL y nos devuelve un objeto de la dase Resulf, que contiene cada uno de los registros provenientes de la consulta.

El objeto ~u/t tiene un puntero intemo que en cada momento apunta a uno de los registros. En el estado inicial apunta al primer regislro. si es que hay alguno. Este objeto dispone de una serie de métodos para mover el puntero. MoveNext (el de nuestro ejemplo) 10 mueve' al siguiente registro, si aiste; Mcwefuvious, al anterior;
MowFirn, al primero; y Movd.llSl, al último. Con MoveTo podemos especificar un

registro conueto al que desplazarnos. Cuando estamos situados en un registro, Result nos permite obtener el dato correspondiente a un campo, indicando el nombre del campo como si el objeto fut'se un Array: en nuestro ejemplo, hResul["autor"] nos devurlve el valor del campo alltor en el regislro aclllal.

Si como resultado de un IllO'Vimiento del puntero hemos sobrepasado d ullimo registro o estamos anles del primero. la propiedad Available lOma el valor FalH. mientras que si nos encontramos apuntando a un registro, Available toma el valor Trut. Igualmente. si no hay regislros resultantes de la wnsulta, Available valdrá False. (A\'ailable significa Disponible en ingUs). Con estos conocimientos ya podemos realizar un bucle para rellenar los datos de nuestra tabla. Mientras la propiedad Available sea True, lomamos como clave el valor del campo "titulo", aiiadimos una línea en nuestra tabla identificada por esa clave, y cuyo texto
(la primera columna) es dicha clave. Rellenamos el resto de los campos con los valo-

res provenientes del objeto hResul, y nos movemos al siguiente registro. Tras salir del bucle, cerramos la conexión y abandonamos la función. Como último retoque antes de ejecular, ponemos la propiedad $orted del control ColumnViewa Tme, de modo que el usuario, al pulsar sobre un encabezado de columna, pueda ordenar el listado por el campo que prefiera. PueSlO que cada registro en el listado est~ identificado por la misma clave que tiene en la tabla, posteriores operaciones de se!ección/mO<!ificación por parte del usuario, no se ven , afectadas por el orden de representación.

5. GestiÓl'l de bo~ de datos

Progromación \I~ual con Software libre
El resultado final es éste:

_ o •
TIILllo •

kolor
~Orw"
~

Proclo
oeJ~'INO. 3<l.:J.4

1$$0

L.'.... dtN.""Y R.J.s.oo., ¿ 0ui411 ondo por .hI? Bob SIlo",

De. (61<0,.

__ ~ .<>Io<lod 0.""'-10.'''' M"!9:'!!" .r.o.

0.0212~

2M!

02lU120l12 12'5 O:lllmOO.,C.g
1212112003 23.

..... ..... ,
Fikloofi.
"""... 1

No".,..,'C

FiguI"G 21. A~to finol del proyecto MisLibrm.

Aprovechor 105 posibil;dades de ordenación de lo.

controle~.

puede evitar sobrecaro

ga. 01 servidor O al cliente de boses de dolo. con múltiples consultos.

'J O O

Borrar registros

Podemos afladir algo de código para borrar registros. Es decir que cuando el usuario pulse la leda Supr o Del, el registro que esté seleccionado se borre.
PUBLIC SUB Tabla_KeyRelease()

IF Key.Code - Key.Delete TREN

IF Tabla.CUrrent - NULL TREN RETURN
IF Tabla.CUrrent.Selected _ FALSE TREN RETURN

IF ConectarBase() TREN RETURN

TRY hCOnn.Exec(Udelete from datos where titulo-&l", Tabla.Current.Key)
!F ERROR TREN

Messaqe.Error("Imposible borrar el registro")

ELS'

ol.io De e.l·. Gemón de boSM de datos .eurrent.r la rorn-xión.1e del uwo.in tiempo pala reacciono. se borra también el r~istro nu~tro con- trol Co/llItlllVinv. se del control para renejar el cambio.i una accIón erróneo. • En gene. Corno podemos observ¡¡r. en el evetl' jo MousePress podrio ~ober borrado un registro . en el caso siguiente la sentencia SQL ~tá (Onstruida de un modo algo diferente. Por otro lado. Pren.. CerrarConexion() Apro\'«hamos el evento Key_Releasc de lluestro control Tabla. si no es así. de ahr.ltllOS si existe algún elemento actual en la labIa. tratamrn. el de<lo del ratón De or.Delete() """ . y si hay bite.1o del con"oI y conc:ek" o. también salimos.Tabl•• CUrrent. cuondo hg p"1. En caso contrario. ejn:utam06 una instrucción SQL para borrar un registro cuf3 clave coincida con la del rrgistro de informa al usuario. o 10$ eqUIVOlente.Key) f~ datos where titulo-. primero comprob. aún l.o modo. el primero es parte de la consulta y el segundo contiene el elemento concreto al que nos referimos: hConn.1e modo.Ex&c{-delete Tabla. Si se produce un error (por e~mplo. e' preferIble U"" KeyR"'-o$e YMouM"-'eo$e. Cerramos la conexión y salimos de la función.otón. salirnos. wdo el botón del . Si la teda pulsada es Del o Supr. Si el elemento actual no está seleccionado. onle$ de levanto. una base de sólo lectura). Tenemos dos parámetros. cuondo loe ejl!Cllkl uno o<:c'OO po< po.ene tIempo po'o oporto. 5.

formatea el dato según se necesite (por ejemplo. &2 el segundo. cadenas de texto y números con decimales. . &3. O prerendemos que lo opl.. El aspecto general puede ser como el que vemos en la figura de la derecha (recor~ . etc. y a la hora de tratar la sentencia SQL.ione$.. Booleano. Formulario fOoto. Con este sistema.). pondremos simplemente un dato tipo Cadena. para editar los ya existentes. &2.lar. usar coma o punto para decimales.Progromoción viwol con ~ ubre El rnrtodo Exec admite un número variable de parámetros. Además. ---figura 22. y Gambas se encargará de dar el formalo adecuado. TxtFecha. en el siguiente aparlado.) por el parámetro que corresponde en orden (&1 es el primer parámetro exlra. - Este formulario recibirá una referencia a la conexión con la base de dollas. oOOeo Al\adir rEgIstros Vamos a añadir ahora un formulario llamado FOlia que nos servirá para inltoducir datos y también. Cinco cajas de texto llamadas TxtTitulo. e incluso con la misma base puede cambiar según los pará· metros regionales (formato de fecha. TxtAulor. ya que la sintaxis puede variar de un tipo de bases de datos a otras. por tanto.' • coci6n fu«ione COfTe<:!(Imenle en voriO$ Pe q<Je puedan lener d¡lerenleS eon~9Uf(x. y dos botones llamados BtnActptar y BtnCance.. Dejar o Gambas lo neo de dor /ormolo o k» dilerenJM hpos de dolos.i de una referencia a un objeto Connection. Este formulario tendrá cinco etiquetas. eviIoro muchos ~I ~ cambiamos de ~5Iemo geslor de ~$ de dolos. demos poner los textos en las etiquetas de acuerdo con la caja de texto que corresponda). Esto es muy útil para tnoojar con datos de lipo fcdJaIhora. Fecha o Numero.. con cualquier nombre. TxtPrecio y TxtOescripcion. dispondr.). Gambas sustituye los indicadores de parámetros (&1.. que en la sintaxis SqJite requiere unas comíUas anles y detrás). este paráme- tro corresponde a un dala de tipo String.

pasando como parám~tro nuestra conexión a la basc'..a AS Connect. SbtJl Ib5a J () END El código toma en hConn la ref~rencia al obj~to Connection que le pa~mos..o datos values (~1. En cuanto al botón de cancelación. Gestión de boJe$ de datos .Aut. es bien sencillo: basta con indicar al formulario que se cierre que de la siguiente manera: PUBLIC SUB BtnCancelar_Click() • HE.'3.&'.TeJ:t. PUBLIC SUB RunNew(Dat. utiliundo la instrucción SQL ¡nsert into: PUBLIC SUB BtnAceptar_Click() TRY bCOnn.TeJ:t. TJ:t~itulo. a la espera d~ la introducción de datos por parte bCoDn . y lo muestra. TJ:t.ClOH() En cuanto al botón Aeeptar.'2.or. en 1'1 realizar~mos la operación de alta de un nu~'o registro. del usuario.Por dio debtt~mos tseribir al principio d~l código d~ est~ formulario lo siguient~: Así mismo. 5.Data HE.BJ:8C(Ninsert int. dispondrá del método RunNcw con el qu~ k Ilama~mos desd~ el for- mulario principal.'5)·.ion) rqu~ mos- trará el formulario de forma modal.

.Text) EHD . Si se produce un error.ados") Indicamos al objeto Colllltcfion que ejecute [a sentencia SQl...o [nombre de la tablal values ([ valor del campo Ij. todo fue bien. . la cual. se captura con TRY. por el contrario. ) Para evitar problemas de formateo. Ivalor del campo 2) . los datos de Título.Text). bien sea por falta de permisos de c5Critura o por datos no convertibles a fechas o números.Er~r(~1lIIposible introducir 108 datos solicit. TxtDescripeion.Text). al ser datos tipo texto. seguimos empleando los parámetros adicional~. CFI08t(TxtP~io. ME. y se trala en el bloque de código CATCH donde indicamos el mensaje de error al usuario.. y la Fecha se convierte a dalO fechalhora con COalcO. por ejemplo.Close!) Me•• aqe.PmgromoÓo CDate(TztFecha. se cierra el formulario tras ti alta. Si. Descripción y AUlor se pasan directamente. como en el caso antes comentado. para las altas sigue siempre el mismo palrón: 11 insert int. El dalo del Precio se convierte a número real con CFloal().

cnnr F"tgUIlI 23. Como siemp~. tratamos de conectar a la base. que.lr. IF CollectarBase() THEN RE'l\IRH FData • RunNew (bconn) CerrarConexion() f'orllLOpen ( ) . de los bables Nuwo el programa. pal (FMain). se encargaba de representar los datos en la labia.an. A continuación llamamos al ml/'todo RunNew de FOala. para dar de aliOlI un nllt'\'O ttgistro. Puesto que se muestra de forma modal. el botón de salida es ~ncillo de implementar (recordnnos que ahora rscribimos d Y $oIir del formulorio principal.• •• Volvamos ahora al formulario princi. código en Fmain."-OpenO. como TtrordaTW\O$.. (<<ramos la conexión y Uamam05 al método For. y de nuevo n l nutStn. para reflejar a51 el alta dada por el usuario. no en Fdata): PUBLIC SUB BtDSalir_Click() HE. y añadamos dos botones para compklar la intafu: uno llanu- do BtnAlta. y otro BtnÚ"rr. pero nos salimos si no lo logramos. el código de esle formulario queda aqui detenido hasta que el usuario dé un aha o cierre el formulario. 11 Tras esto. función.Close( ) Para el bolÓn de nuevo registro. p. como siempre. úeo06l.

'II: bCorm En el mismo formulario añadiremos un nuevo método que. se mue:slnl de fOrma modal PUBLIC SUB RunEdit(Data AS Result) hResul . o O o o O Modificar rEgistros Aprov«haremos d formulario de altas para las modificaciones. y ponemos en cad: caja de texto el valor del campo cornspondimte. Se pueden mejorar muchas cosas. que apuntará al ~­ • tro actual a modificar. Modificaremos el código del formulario de datos para que disponga de un flag para indicar si trabaja sobre un alta o modificación. Tm esto.ProgromociOO visuol (011 Softwore Li~e Ya disponemos de una inlerfaz básica para dar altas. Entre otras. ponemos el flag Editando a TRUE. o lraspasar 105 datos de vuella al formulario principal para que sólo se actualice el nuevo regislro en lugar de toda la tabla completa. dos digilOS de mes I dos dlgitos de dia I dos digitos de año).Data &d. El principio del código del formulario Fdala quedaría asl: PRIVkTE Editando AS Boolean P~ hResul AS Result AS Comlect:ion PJUVM. con los datos del regislro aClual. y dispondremos lamM de una rd"ermcia a un objftode la clase Rcsull. a diferencia de RrmNew prepara al formulario para elllrar en modo edición. para que sólo acepte un dalo válido (Omo fttha (en el caso del campo Fecha). se pueden bloquear los cuadl'05 de texlO para que sólo acepten numems y el signo decimal (en el caso del precio). pero eSla vez en modo modificación para que d usuario cambie sólo lo que quiera. También se puede ajustar el formato de fecha al adttuado para el usuario (aqul usamos directamente el de Sqlile.italldo • 'rRUE TItTitulo.TeKt - hResul[~titu1o~J . y que compruebe la longitud máxima en el caso de los diferentes campos de texto. Cuando d usuario haga dobk dic sobre uno de los registros. es d«ir. aparecerá el formulario de ahas. Para dIo recibimos la referenci: al objelo de la clase Result.

Text • TxtAutor.Text TR~ hResul[~feeha~) TRY TRY hResull~precio~l hResul[~descripcion~J TRY hResul.Text.TxtAutor. TxtTitulo.Text . TxtAutor.Text _ hResul[Mprecio TztDescripcion.Text • TztPrecio."" TRY hCOnn.&2. se llama al método Update.Text _ hResul(Mfecha TztPreeio.Text . Text) .Text • ME.. que hace que los valores que hemos introducido en los campos se actualicen realmente en la base de datos. se cierra ydeS(arga el formulario.&3.update() .TxtDeseripcion. y de existir un error. sitúa el valor de cada caja de texto en el campo correspondiente. ShQWtokldal ( ) W ) hResul(Mdescripcion~1 Hemos de modificar también el código del botón BtnAceptar para que distinga entre altas y modificaciones. En el caso de la modificación. Si hubo éxito. PUBLIC SUB BtnAceptar_Click() IF Editando TIlEN TRY TRY hResulr~titulowl hRe5ul[~autor~) • . Gestión de boses de datos .TxtTitulo.Text.TxtFecha. TxtDescripcion. y actúe en consecuencia.Exec(~insert into datos values (&1.&5)ff.Tert) 5. CDate(TxtFecha. CFloat (Txtprecio. Tras esto. TeJ:t). se tratará en la zona CATCH al estar protegida cada inserción con una instrucción TRY.&4. como en el caso del alta.Text - hResul(Mautor~) W ) TztFeeha.

puede ohof. como un bmulorio..NUU. antes de crear uno nuevo e~uelvro de cód.. PUBLIC SUB Tabla_ACtivate() IF rahla.RunEdit(hResul) . pero en OC:O$lOneI puede hoe.Curreot .go o mo(Micor lo exislenJe 11 De nuevo en el formulario prindpal. aprovecharemos el evento Activate del control CollllflnVitw.... que se genera al haca dobk dic. TKEN RETtIRN hResul • hCOnn. ·titulo-~l·. Añadir n.omoo.10 ME. para dar acceso a esta nueva funcionalidad. FMoil/.Key) FData.Ol' '*"PO y código.adoswl . Tabla.Current.Edit(~datos·..Error(·~sible introducir lo. el nuevo códi¡Jo complejo y dificil de monlenef Hay que Klp8SOf el ~¡Iibno entre cOSle de prog..ión y "lOI>Iomimionlo posIe1ior en codo coso. datos aolicit.CIase() Me5sage..-vosluncionolidodes o un elemento yo exhlente.

Current[2] Tabla. que reciben como parámetro una sentencia SQl. Una sentencia SQL para obtener ese conjunto de regist ros seria: select • from Articulas where precio>20 5.Tabla. El método Edit no recibe como parámetro una sentencia SQL.¡ razón es que las llamadas a Exee..Current[3] Tabla. Current (4) CerrareonexiOD() hResul[~autorNI hResul[~fecha"l hResul[~precio~) hResul[~descripcion") Como podemos observar. es posible examinar el comenido de un campo como por ejemplo: Pero no es posible actualizar el contenido del campo.Current(l] Tabla. no se puede realizar: 11 que es precisamente lo que nos interesa. es decir. Gestión de bo$e~ de dolos . l. y C01110 segundo parámetro y posteriores. 5upong~1l11OS que de una tabla Articulas queremos modificar todos aquellos cuyo :ampo precio sea superior a 20. un filtro y los parámetros de ese filtro. es decir. Es fácil entender el modo en que trabaja si par- limos de una instrucción SQl. son de sólo lectura. sino el nombre de la tabla que se desea modificar. ahora el objeto Result no lo obtenemos como llamada al método Exee si no con otro nuevo método: Edit. y obtenemos las partes que nos interesan para el método Edil.

det~rminada Fillro: precio mayor qut una cantidad.. FMAIN • PlU"V1aE hConn AS Connect:. y bte se mostrará de forma modal.NEM Connection . A cOlllinuación. o dt un sumatorio dt los valores dt un campo. Por tatllo la llamada queda como: hConn. 20 ) ¿Por qul no ~ tmplean ~nttnci. Tras obtener el registro con la llamada a Edit. Al cerrarse el formulario. No se puedt modificar.ion PRIVATE FUNCTION ConectarBase () AS Boolean IF hConn THEN RE'l'URN f'ALSE bConn .. por ejemplo.¡ al mitodo Edit tendriamos: Nombr~ dt la tabla: Artkulos. ti resultado dt los regislros que provienen de unir dos tablas. la ejecución retorna a nuestro método en el cual aetuali7.¡s SQL directamentt? Porqut las modificaciones lienen sentido sólo sobI'C' una tabla. en este caso. con la llamada a su método Rlmúlil.¡ llamad.Edit ( NArticulos·. Nprecio>~l·. Parámetros del filtro: 20.amos el contenido de nuestro control QlllmnView para retlejar los cambios hechos en la tabla de la baSt.Progromoción . pasamos el objeto Rnrllt edilabl~ al formulario de datos. se rep'roducen complttos el código de FMai" y FDala al ser dos códigos extensos que htmos troceado y modificado sobre la man:ha.¡woI con Softwore libre Para construir I.

Name _ NpruebaS" hCOnn.Clear() IF COnectarBase() TREN RETURN 5. Open () IF ERROR TREN hCOnn .Close() hCOnn NULL 11 END DIM hResul AS Result DIM Clave AS String Tabla. Ge~tj6n de bmes de datos .Host N/home/usuario/Bases N hCOnn.NULL Message.hCOnn.Type • "sqlite TRY hCOnn.Error(UError al conectar con la base") """"'" TRUE N END IF RETURN FALSE END PRIVATE SUB CerrarCone~ion{) IF hConn • NULL TREN RETURN hCOnn.

HoveNext() CerrarConexion() PUBLIC SUB Tabla KeyRelease() IF Key.Count: • 5 Tabla.Delate THEN IF Tabla.Exec("select * from datos") - ~Tít:uloH "Autor" "Fecha" "Precio" "Descripción" DO WHILE hResul.Text Tabla.Text Tabla.Text Tabla.Current.CUrrent .Add(Clave.Columns¡4J.hResul("descripcion"l hResul.Text: Tabla. Clave) TablalClavel [1] .Text hResul _ hConn.Code .hResull"fecha"] TablalClavel [3] .Key.hResull"precio"] • END TablalClavel [4] .Colwmns.hResul("autor"l TablalClavel [2] .P~ogroma(ión visual con Sof!ware Ubre Tabla.ColumnsIOj.Columns(2J.Availahle Clave .Selected .FALSE TREN RETURN IF ConectarBase() TREN RETURN .NULL TREN RETURN IF Tabla.ColumnsI3).hResul[Ntitulo"] Tabla.ColumnsllJ.

ErTor(M1qX)sihle eliain.Edit(Mdatos M "titulo-.l w .CUrrent(3) . Tabl•..datos where titulo-. 150\Close( ) .n. .RunEdit(hResul) Tabla.~) Ir ERROR TREN Messaqe.CUrrent.Current.eurrent(t) • hResul(Mdescripcioo") eerrarCoDe:doo ( ) 11 PUBLIC SUB 8tnSalir_Click() HE .Key) FData.TRr hConn. titulo~1 Tabla.hResul(Mprecio"] Tabla.CUrrent • NU1L TREN RP:IURN IF ConectarBaseO 'I'llE:N RE'l'UNf hResul • hConn. Current [O] • hResull . CUrrent.CUrrent(2) _ hResul(Mfecha M Tabla. Tabla.el regisb"O") cerrareonezion() Tabla.CUrrent(l) • hResul(Mautoc") ) Tabla.Delete() END " DIM bJlesul AS Result IF Tabla.Exec(Mdelete fro.l w .

TRtIE . Open () FDATA PRIVM 'E Edita ndo AS Boole an PRIVA 'l'E bltuu l AS aesu lt PIUVA Te bCoQn AS Conn eetion 11 PUBLl C SUB R\!n'l ew(Da ta AS COrln ed.Data Edi tanda . ShOll llcdal () PUBLIC SUB RunE dit(D ata AS Resu lt) bResu l .RunN ew(hO onn) cerra rcone ~ion( ) Fo".ProgramociÓfl viwal con Software libre PUBLIC SUB BtnH uevo_ Click () IF Cone ct:arB ase() THEN RE'roR N FData .ion ) bConn .Data ME.

.Text .Text ..Text). Text TRY TRY hResul[~autor~J IlResull~fecha~J PUBLIC SUS BtnAceptar_Click() IF EdHando TREN . TRY hResu1.Text - hResul(Nautor~J TxtFecha.hResul( "precio N] TxtDescripcion.Text • hReSul[Nfecha"] TxtPrecio.TxtAutor..~3.Text TRY hResull"precioN] _ TxtPrecio.Closen 150\ 11 TRY hResul [Ntitulo"] _ TxtTitulo. TxtDescripcioD.. CDate(TxtFecha.Text _ hResul(Ndescripcion~] ME.~2.~5)~.Exac("insert into datos values (~l.ShowModal() PUBLIC SUS 8tncancelar_Click() ME..TxtAutor.Text).update() TRY hConn.~4. TxtAutor. Text .TxtFecha. CFloat(TxtPrecio.Text) 5.Text. TxtTitulo. Gestión de boses de dolos ..Text TRY hResul(Udescripcion ff ] • TxtDescripcioD.Text.

y lista sus campos. No obstante la carga del servidor y cliente trabajando • de este modo es mayor. NombreTabla AS String) . o si sólo se realizan operaciones de lectura. el periodo de tiempo en que los datos se encuentran en buffers intermedios es menor.END IF ME.Error("Imposible introducir los datos solicitados") END A lo largo de este código. recibe como parámetros una conexión y el nombre de una tabla. evaluar la conveniencia o no de mantener la conexión y consultas abiertas en las distintas operaciones que se efectúen sobre la base de datos. PRIVATE FUNCTION ListarTabla ( hConn AS Connection. pero puede obtenerlos de una conexión en curso.Close() CATCB Message. Para ello se emplea la clase Table y la clase Field. y puede ser un modelo excesivamente lento si el volumen de datos es muy grande. El programador no puede crear objetos de esas clases directamente. ante un fallo de tensión. Es conveniente. lista en la consola la estructura de una tabla. Con esto. por ejemplo. por tanto. se abre y cierra la conexión con la base de datos en cada operación realizada. Ii 5. Esta función de ejemplo. 5 Otras características Estructura de las tablas Gambas también permite examinar la estructura de las tablas de una base. reduciendo la posibilidad de corrupciones.

Date PRINT "Fecha/Hora" CASE gb. Por ejemplo.hTable = hConn. SQL no es sólo un lenguaje de consulta.Boolean PRINT "Booleano" END SELECT NEXT • • END En ocasiones puede ser necesario examinar una tabla.Type CASE gb.Float PRINT "Número real" CASE gb.Fields PRINT "-------------" PRINT "campo: " & bField. Las instrucciones como CREATE TABLE. comprobaban la existencia de estos campos. Las versiones actualizadas de estos programas. en la fase de transición moneda nacional/Euro en Europa. DELETE TABLE YALTER TABLE. se hizo necesario almacenar datos de importes en ambas monedas durante un periodo. como al inicio del programa. y actualizaban la base de forma automática.lnteger PRINT "Entero" CASE gb. en algunos programas.Tables[NombreTabla] FOR EACH bField IN hTable. para comprobar sus campos. al instalarse y arrancar por primera vez.Name SELECT CASE bField. Versiones posteriores podían eliminar el campo de moneda nacional para ahorrar espacio en la base.String PRINT "Cadena" CASE gb. 5 Gestion de bases de datos . se utilizan precisamente para la función indica- da: alterar la estructura de la base y sus tablas cuando es necesario.

.P"ie1d•.Date) ..Striog.Field•. Situándonos sobre una base y pulsando el botón derecho.. fO) .P"ields..teD.mectciOll..Progromoción visual con Softwore Libre o O O O O Mas utilidadEs dEl GEstor dE BaSES dE Datos Ejecutando gambas-dlltaba~­ mantJga' podemos encontrar algu- lb".. del Geslor de!loses .P"1oat) . gb. Addc-titulo-.e IlliUI3ger 22/08/2005 10:26:. PRClCi'J:JIJRE eru.a". figura 24. dis· pondremos de un nuevo módulo con el nombre indicado. nas utilidades adicionales.. 11 sDat&base AS Stringl • Geoerated by tbe Gamball databa.Fields.. ..... gb. cerrar y volver a abrir el proyecto. Otros vtitidode1. gb..A&1(-fee:b. codIIico-' WlF ·11 .] DlM hTable AS Tab1e MI'IB b'rab1e .aUba.. Add(-precio·.._ do_ Al acceder a este menú.String.bIO .Add(-lIutor-.I.d. _ • oe-. podemos seleccionar la opción Crear código Gambas. que contiene el código para crear la tabla. .... La primera de ellas es obtener el código para crear las tablas de la base.se(bCoom AS c:o. fO) . gb.. nos pregentará el nombre del módulo yel procedimiento para crar el código. Tras indicar estos valores. _ • l.

sea 5qlite o de otro tipo. Ge1. 5.Add(-descripcioa-. GamlHu-databaM:-mantJgtT permite tambi~n copiar datos entre bases. al poder copiar datos de la base antigua a la nueva. presionar sobre Copiar.. Al inicio del programa. pulsar Pegar.tión de bo5e$ de dolos .Pields. Podemos. gb. al poder disponer de varias bases de pruebas.. y el gestor crea- 11 rá la tabla en la otra base. y tras conectar con el servidor de bases de datos. acceder a otra base de datos. pulsar el botón derecho sobre nuestra tabla dtJtos. sin nece- sidad de intervención adicional manual para poner en marcha un sistema nuevo. y llamar a este eódigo para que la(s) cr~. asl como la fase de migración de una baSC' a otra. 200) " ' " HU. con lo cual se facilita la distribudón del programa en varios equipos.String. podemos entonces comprobar si no existe la(s) tabla(s). por ejemplo. se facilita la fase de programación. Este proceso se puede llevar a cabo para tablas individuales o para una base de datos completa. preguntándonos si queremos copiar sólo la estructura de los campos o también los datos. De esta forma.

• ••••• 6. I Conceptos la transmisión de dalos a mlVh de una red se estanda· rizó hace tiempo a ni~l de software y hardware.al y. como HTIP O FTP. ADSL o de red se ocupap.llme. n de una capa no afecte altrabaj<> en olra. .por ejemplo. Básicamente.. El naveIÓlo entiende de protocolos de alto nivel. de forma que la sus. este modelo preaislar los diferentes niveles de complejidad de datos. una Unea ADSL ethernet en una red loc. conectarse a Internet a travh de un módem.pñX:eda. Esto se debe al modelo de capas. el hecho de tener aparatos tan en funcionamiento no obliga a disponer de un navegador o un cliente diferentes para cada situación. el módem convencional. Podemos ver hoy en dla que es . finalmente.nle se trabaja con el llamado modelo de coptJs. Acm.transfierela ión a un nivel más bajo y. sin embarg<:>.de transportar esos datos segullo.

. que son los proto eob de esu TCP YUDf'. podemos. ya que es tarea de un libro sobre redes.127).....i a la escuch a.. se estableció un sistem a que permitla establecer una corres ponde ncia entre nombr es y direcc iones IP. IX.-_ . _ . que controlan y trocean la infor. a lo largo y ancho de Intern et y de casi todas las redes 1oc:aks. gnulin ex. y se añade n sistem as de' contro l de errore s para asegu rar que un ruido en la línta no ha defo. Cada paque te IP de inform aci6n es simila r a una carla postal. se encue ntran servidores DNS que reciben consu ltas acerca de nombr es de equipos • y direcciones IP y las traduc en en un sentid o u otTO. xxx. XXX. indicar al navegador que muest re la p. El protoc olo más extend ido hoy en dla para distrib uir inform ación entre equipos es el protocolo IP.jgina www... pero encima niYd se han estabkrido otros dos tambim estándar. Cada equipo liene un númer o asignado. mado dirttc i6n IP es su identi ficado r único..esta (oona . ya que asegur a que reciba mos una p. -_ . 'lue dderm ina qui destino y q~ equipo recibi~ cada fragmmtock o "% inform ación que circula por una red. n. confo rmado s por el hudwi lre (~ tarjetas de red. maóó n para emitir la o recibirla por dicho hardw au.-m ado los mensajes.1. 1. Y unos nivel(S por encima. Dado que estos númer os son dif'lciles de recordar. Este sistema se denom ina DNS y. Eslas direcc iones IP tienen la (orma XXX.23 o 10.. Es el protoc olo más utiliza do en Intern et. y que son indepc ndient ts del métod o de transp orte que haya por debajo. IOn grupo s de cuatro númer os que varian entre O y 255. incluye datos del remite nte (lP del equipo de origcn) 1 del destin atario (IP del equip o de destin o).org . TCP se utiliza para asegul llr la conex ión rntre dos equipo s: se sabe C'fllodo mome nto si el equipo remol o est.CJW son los que más nos interes an a la hora de progra mar con Gamb as aplica ciono dt red.x xx.0.124.enlug ardc tener que indica r la dirección IP del equipo que estfl sirvien do esta página. . p« ejemplo.35.5tpIrados por punto s (por ejemplo: 192...) Ylos dri~rs o módulos del núcleo. dire que hay un par de nivel~ lo¡ más bajos.. Los paqueles IP pueden conten er cualquier tipo de información.¡ .jgina web o un fichero de forma compl eta y sin tf'J'Of CS-_~_. Para no entrar en compl ejidad es..168. si ha redbid o toda la informació n correc tamen te o hay que volverla a emitir .

..ias veces m. sino del formado de los datos y de la comunicación. es un prococolo de tr. operativo se encargará de enviar esa información cuando le sea posible. Por ello. de los protocolos más extendidos es el HTIP que. lo que le piden los progfllmas clientes o aplicaciones que han establecido D 3 tocUt con tI. Es algo similar a una bandeja de entrada o salida. como son las de audio y video en tiempo real. llamado local o Unix. permitiendo una comunicación ínter.msporte mucho mú simple que TeP. un tipo especial de socket. ejemplo.. el servidor gráfico . que sólo si~ para comuprogramas dentro de un mismo sistema. Ya no nos encaro del transporte de datos.is veloz y con menor consumo de recursos que a travl!s de un Tepo UOP. Es. sobre todo para los Uamados servidores de sfrNming.En cuanto a UOP. dentro de nuestra • máquina muchos programas se comunican entre si utilizando este sistema. sino que el caudal sea constante y lo más rápido posible. como la administrativos. el modelo indica que abrirse un locket. ver programas de televisión o realizar vidcoconfermcias por la rro. que nos ptrmiten escuchar radio. . tambiln se emplea con lTecuencia en Internet. ra de establecer una comunicación entre dos equipos. ""'''''más arriba. y que está optimizado para realizar función con gran velocidad y eficacia. que tienen una bandeja con los informes pendientes y otra b que van terminando. entonces los procesamos y los dejamos en la bandeja de salida. hasta que nueslro programa decir los datos. menos fiable. no se emplea sólo pua comunicar dos o más equipos. pero en determinados tipos de tfllnsmisiones.. 'f no verifica si realmente existe una conuión entre los dos equipos o si La información ha sido realmente recibida o no. se utiliza . El sistema operativo almacena información en la ban- *' entrada proveniente del sistema remoto.. por tanto. tenemos los llamados protocolos de IlpliCtlcidn. entre otras COlas. es el caso de los servidores gráficos o X-Window. 10 importante no es que Uegue toda la información (puede haber pequeños cortes o erroru).

.r.c101 te comportan como InVidortl de ~ ti d«ir. _ por "'1lO.. Dentll) dr:I módulo ModMain Itndrnnod: una rdnmcia I un objeto ~ Dichos ob.. .e5p«WWOOnl b Iransmi$lÓn r ~ de archivot. pUtrlOS se numtTan dtl I a165535 y cida programa qUt Ict~1 co¡tlll servidor lknlro del . . ."" ScIIwc••• ~ en lodo Inltl'ntt pata tnnsmilir r rmbv P'Pn. ...«' 10 bnnoI dt Idcctionar d a:xnponmlr Ib-Det.. ~bt~SCOlCltde.... . TELNET..odo(Dl<.. . .. y .. It.m..do ModMaiD... •••'"'_. Otros protocoloi espedfic05 $O<l d FTP. d..iSltlTl<1 ut.. .....tks ni un pumo dc1l'f' minado. NAJ..r. . _ . _ ..wm.) r cómo fi!WÍW" la mmllltil.. .bote ~ -. br.....n tnbajar con un Imninal dr: 1610 iobrt un Silltmal'ft1lo.lrtil consistiti ni acribir d código dt un ~idot' TCP: Itri l1li Im'idor que: aetpUti ~ mnotu.."'diIroo.lita uno de dlOl. Lo. .aci6n. de . ED 1Is propirdadr:s dd pro. lipa '. . U . sa~rfa inllantinta..~_II"_~<~ ~CIlIrI""""""".olwo p":Aoo'" tp.I'J$lnllu () rmbtr ~ ~ an:h_ a:xnprimidoL. Si ...... de progr_ . d bmuotn lk b datot • 1n. .... te tne1K'nlrall l la tSCUChI de pdicioots de conaión de dienles mno!Of o Ioc. """"'.ty ~ .. Estt pro- srmu lmdti UD único módulo u. úumnoI un proarama dr: c:oNOb 1bmIdo MiSrmd"..n d como ekctróniro o 105 difmnte5 prot~dr mm. . ••••• 6. F$l>blc« d moGo cIr. lu.... p.." un _=ilUdodo __ El""" de ....=wal. IOdo \o qw .."lopadeprouM'_'Y8? ")'1"'-' . .. ..Ir. ....= I _ .Nodo'ClCi6ft llOI ha. t t. I'OP OIMAP p. cómo lultntiarloe. . como tl JABBER. <I)'IIde O ...6 y. F*" UI'IQ be.. 2 Creando un sErvidor TCP Nunlril prill1ffil!.sribuodol 101 duo.~ !.... Itm b dalO5 que: tIMan YdtYoIvm • fa) I b dirnlef.:tw::... SMTP.. ¡. . .

....e::J l'I • *"1 Q 0'• -..... O' r. • 0-'. pa' ..ejOCUlodo pa' ... c... por (. •.1 para qU( cualquier clinll( qU( rnIiur urul Jl(Iición m 0110 ww.lender......_.C>«J:::_~ F •• l.... cI.. -.....cioo e Mei•..._-. _ / ...erv. _ . IMAJ' -J y <lO •• uouono .o d.. _rr••• • toS _ ~ ' D" ¡> .. Kpa qU(.. 1'10\11''''"" MiS .......rIO..~:::. por ~mplo. Gil e ._ Gt-IJ~ T .. conoideron. po........."bien no hay ninguna ruón por Ja qU( un KrVioor wdl no pueda .. POP. di"""" """'*' _ COftO...". ha ck con«Iarw al punto 80 ck 1lI ndquina s.. .. .... 11 .000 mú conocidoI como HTTPoFT'Pyatimm un ~ asiplado (por . CIJO (\( K d~ I1nicam(nl(a un lCU(rdo inlernacion. 1.'••• 001 ~ 523 ónde "" P"'9'....--voclol poro.ll 01 1024.I rooI . al punto 9fIS4. l i d ." c / _ e-.. salvo illilruccionft (Sp«l- Ionllido.......ernplo.. 80 (n d HTTP)ckl'onNMndu... \/rilimdoo por 1"'09'0""" _... fU'... _ y • ... .. HTTP.............".'-......oora...-... ----• e .' . G _ .. do obno. ...um.. "0"'_ o.. '" ' ._.

el progralN ligue funcionando.d prosnIlNI pas.~ lIet.&nor¡ el .r el ob.1a función Main Y.'OIUOia.. Y. CJ«U~ al lIliciodt bIt. h. Un Jll'OIRIM nomW dt l.J.nidor.les ITlh'mot" - .~.. al 1.b~ *1 .. podemos cj«utar el programa. ftJ -. pan podtr escribir las rutjnu rn 115 cu. A la hora de indkar al scrridor qur $e: poop I la eK\ICN con d mftodo LiIIrs.En nueitroeuo. cificar qut su hIlO Iftii InlCf1WC (ti dtcir..11 ObttrvtTTlOS que.tto 5tfYidor.~.. crta60fo por lanlo. hubin'a fiNliudo lin mú. indicamos qut el Ifttol' dt ~nlOll ~1'lI "M1'vidor~. habmnotlk anr el objttoSt'nc.. pero m tsIt cuo el int&p!ttt (JeInbaI esl' atendiendo las novtdades que p!K!dan aa1e(rr m ti J()(kt\ que.. si otro ltMCill ~ lo esluvicl1II utilizando).rto . qut ClIUlIOCkd TCP 1 no UNIX).""" • sar.l:lIptl'ando Pflkiona de c1imlrt.Soc:ktt. ti 10 al q~ ddlt atender t fWLIC _ lIaJ. ~ ¡dl1OlW d mor- el $istnna no pmnidcw *Iendtr al puerro indicado (por rjmlpIo. VImos I t'lTlplnr el puttto 3152. ~ ftDI PIUft .. lo M«moI protqimdo el códipJ con una ilUlNCCi6n TRY.. la han de . Como pockmotobKTvlr. En la función Muo tkI p Im. () o ""!dor.~W!doIC" la a..pm de una ronaión dt un dimlt.lllUonet "% • 315a • s..... . al ~ 11M CSUI función.idor.r .te pecifiea(So" petidonn que llepo de los dientes..t. indiar1co q~ comimce ron IN peticiones.Ullt.

lC ~l¡I nWfo..d to 121. r e6Io dmuo de 8....0..0 de 'iO'l~l* t. oocbl no..1. ch4tr.1 .. • • • E*t . . ..F+ 10 .1e cinTa.ed by forelgn hOlt. podemoI utiliut d Dicho mkodo dcvt.. UI1ól ronni6n dimte..de ---. ~.OgouLine. c_ P''9. ob5tn'UftDOl que se amccta e inmcdial1melllC 5C dI'Scon«Ui ~nEJl:"'" t.... o ..IcM un obJClO Sodd ql... De si proballlOll' col1C'CUirl105 ~ b conlOla con d prop'lIN tdntt..IificoaIl $1\'" hdleto.1 :nS2 rYlng 121.0. ... nUCI· io iCO'ldor. rtalrnttlle o. • •• didIo' .til. Ji no cspulficamol al d prtlIBIDI que lbamoIltcndnia... no • •' . Ab hora de m:ibiT o cm'lIr del'" ese dienlC.c. IOCUI o lo lKturo de __ de un P' hotoI. de ac modo.. Ul) ob¡c:o servidor rcribc UN pcticióa <k un dimle.. . .' 'I".0.0. evitando.. le dispa~ d ". dClAlPo."'ct.f1o..t b . por ejemplo.1. :-$ ... *" bode ~ 11..eur 11 'A J' . .ctl~ c\o..aunqlK no hap n«<b.. _ _ j de . . que enviclllOll1olll multados de un dkulo • un oquiVOCldo:''' ~ • . ato'oodo.0._. Clp.do ~ a prcciIammlC i&cc m:íbc UN ooncxi6n dicnlC y.-lo eIicocoa del proceso_ ¡UI1lI JnVidor ya I'Slt funcionmdo. nn.net 121.0... 5C bari I lI'lvá de ob. _... ...~iento del ob. 5C diiCrmcia a cada diente conectado con un tcrVldor de ilnin..nto ~ :~ [)mtro de didlo n'mlo.

el intento de conexión del cliente se ctecar' automáti Observamos. No obstante.. atender al puerto especificado" .cceptO Client. por ejemplo. Internet servidor..A.. si lo omitimos ca determinados.ListeDO Ir IRROR '1'HEIf PRIW1' "Error: el sbt-. que Acupl nos informa de la dir«ción IP dtI .En nuestro programa al\adlrC'm05 una matriz de objetos donde guar ref«encia a cada ob~lo diente. En nuestro gestor de tvtnlOs Conntction utiliumos el m~todo AccC'pt.DIM Cliente AS SOCket Cliente· 5ervidor. 'l'Jpe • Net. por siempre aceptamos las conexiones entrantes. . malriz iumos añadiendo los d PRIVM'I servidor AS ServerSoc:kltt PRIVA'%'! clientes AS NDJ Objectll .. Add(Clie=ta) • PUBLIC SUB Naino servidor· NEH 5erverSocket AS -servidor" SlIrvidor. y en con«Un..Port • 3152 ftJ 5erTidor.. t'sa .

en de los datos laque indicamos una cadena que recibe los datos.~() Clien tes.0 .por ejemde conec tarst a trav6 del parim etro Remo teHos tlP. n cierra la datos desde ti diente .A dd(C lieate ) ENll I r llama do Socke t. • En nuestro caso atende remos a los evflltOS1WJd que se produ cen cuand o se recibe Olntxi6n.1~ THEN Clien te • servidor. Si desdr amos. que manti !le e· el dienuna rderen cia al último objeto qut ha dispar ado un evento (en este caso. dio. despu b. pt:ro conw:rtidos a mayúsculas. determ inada por la función LofO y. de forma que el c1ient Ilciba un eco de los datos envLados.0. t tsos miSmos datos en tI socket con la instrucción WRITE. kttemos el socket como si fuera un archivo. ~dc sodet ) para tratar los datos qut provie nen de tl Pan. que se produ ce cuand o el diente En d caso del evento READ. podrla mos modif icar el código para que se rechacen las ~ otras direcc iones IP. no5 valdremos de la palabr a clave UST. por defect o reciben ya un gestor de evento s progr ama por por lo que los evento s de estos clientes de socket se atend erin en el una función llamada Sockec + Nom~ del evento. con la instrucción READ.1). 0. 6 Red . leeremos la longit ud escribiremos disponibles en d socket. Estos objetos socket. y ti evento Close. plo> lC~tar sólo conexiones desde nuestr o propio equip o (que siempre tiene direc· conexiones óóllI27.0. DIM Clien te AS Soclli K Ir ~tI "~1 27.

Lof(IAST) lICad-ucase (. UI'l díMlt ~que puec» WVir pCII'C COIJopioboi el funcionalll..cad) '1'IU' lfRI'l'E ILAST... MI di. 0I'lfin di dilpOMr o..~c _ SCC'·l -. Len(scad) ...~"e(IDd) Ya disponemos de un programa servidor de socket con capacidad para al múltiples dientes: podemos abrir varias ventanas de terminal...icb qwo 11'.cI() . una caden" y la enviemos pul~ndo Returo.cad.tra Oost.. Yenviar y recibir datos del SCTVidor. UI'l do_ . ej«ulando eIII tdnel 127. buscamos el objeto SocUt <kntro de nuestl1l matriz....... Aunque. programo llIIMI quiIw .1Jld(LAST) D' xDd >..M pora controlar un equipo de Ionno Wn .0. 'lOS dóseñonOo o 1l'IOI'IO.1 3152. - •• DIM ..0.. recibiremos la c¡¡dena (0"\"<' mayúsculas como mpuesta dd servtdor.. Cada vez que "". .O '1'HDl' Client_.. .cad. o P.cad AS Sulog fty REAl) 1IAS'r.. y lo diminamoa que desaparezcan las referencias a dicho dimte dmlro de nuestro programa "% o • 0'1 DDI lud AS IDt:eger 1M • Cliente.

...~e •• _ ~ . c:... .... "J'\IK'UI. ..0. gnlfKa II... Programo $lf'Vidor de sockel.d. QM6cUo. PASNl.. • """"""".."'" F'1gURf 3..rlCtor lo 'Al'. rd"erencia al componente gb. *.\honro que ya disponemos de un servidor...ne! como en el caso anterior.-105 ....m"'" MICI.1. ••••• 6. ~'''''''' '1''''1 "'•• .o p....lI'&'~ (lit... ClDo. vamos a crnr un programa cliente..8. ~ ... t . ....0. 000 uo '"mub. 'de" D .."'". ~dwo fr.-. ~ Uv..awr o cn. uo prognm..1 3152 '" dc.~ doeto.'.. y UIII. EI<~ 'ryt~ '. z ¡MmeJdc::. ~ ¡..•.t 127.eto ~ [)rI'lIilll'e40 l>U·'irnl'.8.l"loD"l' &C 0....cted te 127. 3 Un cliEnte TCP .IOI - rIet InlOfmll1en e~ ComponotnlUM red Neneje de Pi' ....arct- 127..o FMm..0. e eNiClioonIo set~ D"'_ .......v.1.... $=Iop.

Tambiotn situaremos tres etiquetas informativas con cualquier nombre para guiar al usuario. un TextBox llamado TxrDatos. del snvid or. y si ya lo estamos. llamados TxrIP y T:aPun1o.. dos funciones: si no estam os concetados.o•• Enabl ed. - PALSE lllD El botón BlnCo nectar tcndn!. compr obamo s si P referencia al objeto Socket es nula o no. ya que en principio el programa no está conttUdo al servidor. tratará dr conectar. . un botón llamado BtnContrtar... btDa t.. e '•• ~ el. en el que el usuario situará los datos a enviar al servidor. Por otra parte verificaremos si el dato dt la dirección IP es válido. asl como d dd pucno indicado. y un etiqueta llamada LblResuJtado. con el lexto Conectar. en los que d usuario situar i la Din'CCión IP y el Puerto para conectarse. file Clien te AS Socke t LblJt esulU ldo..W'" --' figurv 5.. en la q~ mostra- l. También situart:mos al principio del código una V1IIriable global de tipo Socket. Para ello. Fonnubio FMom.'! 'ert . desconectan!. remos el resultado recibido del servidor.Progromoción viwol con Softwor-e Libre Dentro del formulario FMain situaremos dos controles TextBox. situaremos unos valores por defecto y pondm nos d TatBo x TxtDatos deshabilitado. Al lanzar el formulario.. que repres entad al diente con el que nos (onca aremo s al servidor. • .

..Fo rmat.¡ cadena vada si no dir«ci ón iP. .. dt'VUd- 1. empka~mos Nrt. wz dispont"m05 de los datos. EIm I r _ "sag e .u o de puert o DO ... M un tato. y cambiamos d luto del botón a IksC1m«tor.T ert) Ir ERROR 'tIIBN . creamos el objeto Sockd y Iratall105 de conec tar IP y puttto dados.'l'e rt . verificamos que se encue ntre en el rango 5. Ir Clien te • NULL 'l'HDI TRY nPue rto - Val(T lltPue rto.üido -} ... Para la dilUc ión IP. h~t o•... Si hemos obten ido un númer o.e1 númer o de puerto usamos dos funciones: ValO. deshabilitamos el cuadr o de lexto de datos y ponem os a NULL la meal objeto socket. si eslu- abfito .r o de puert o no dlido ") Ir nPue rto < 1 OR nPue rto > 65535 ftEIf _SNg e. Ten .... lkvud~ un mimcir de un texto si bk contie ne sólo caracteres nUIlléricoL Si no es asf.. DIM llPUe rto AS :lDteg er DIM sIP AS Strizu ¡ • Lb~ul tac\o . que devud ve una dirccc i6n .IOritia.........-. para destruirlo.. Error (. o un. si es posib k inl«pr rtarlo como tal.. Ir .... caso de que ya esluvi~ramos conce lados tratam os de cerrar c1socut.&rr orC" 1fl.

. Para sa~r c~lIdo hemos conectado rnJmcnlc oon el .rvidor.ltI nn110 Error.. Port .. <k hosI no mconlndG).ac." Cli. En este e'YeIllo..an-C"D1t'ecct6n ti' ea rilida-) CH-... eU. _ lIclckft U ·CH_t. q.l4o .. .. cmplearcmNtI c~nlo Rndy.llte.. d _rio putd. aprtWrdwnol pan ~ la ml~ • su audo dt:tron«!'" do Ydiminu el lICldtt Iállido..c...te.UIU...l escri· bir alIL Tambitn puC'de SUCftkr 'll'C se produzao un mur (por fjnnplG.( 1 S E ~ • Enl~ el inttllto de ~Qnexión y la (anuIOn real puroe pasar un inluvalo oU littn- po..neet.t .. conexión..1' ¡ . que se produu cuando el KTvidor :acepta nUQt....1JI' sU' ... ni curo cuo K d~r.. 1... habilililrcm06 tI cuadro de talO de lUl05 PM'l '1. ftI'IIerto Clieoltol. ront'" mil ~:mKb o un nomb. •• _ -" ".

lIUI.Te~t ••• 'l'RY IfRIft ICliente. ..1tey.61C oto al (ovlo d( dalOS.. lo reali:¡a""mos cuando d u.uario acribir ull lalo (O d cuadro T~IDatos. PUBLIC sua btDato.. Te~t) .ado. Tztll<ltoe._lteyPrea. dlo inlrOOuci""mos d código &nlro dd (\'(nIO KqPrcu dd cuadro d( lalo.COde . - • • .1"AJ.U..h Cli..Ret.Baabled .uro _ 11" LeD('rrtDatol. Te:ot.Tl!I:ot) :> O _ • t 10 VI 1blJle.oL 'rrtDato..ult.'l'RY CL06E ICli. pul~ la I~ Re¡um..O 11" Itey. LeD(btDato.

puom Ikpmos m vario:s ~ tos." ....ibon clalGI do dolo> ..0..ltado.. u.. rocibon do uno oob <lo """ Iro¡¡. Arr'lInlllO$ clllrlidor que crelmos .Q ilt$l.. uno dt los cuaJes .d"..d mutmOl en l... puedo ""V"'or "'" ~ _¡q h<ry """ _ ...En cu~nlll'" ~K1n <k ..tl.ull. 1 . ..1r los rauhadof..ftxt. lbJ..x- nod.cad AlI strb>ll TRI _ ICH.1t:.-.nltno le y un.. ..ecibirf"'OS tl1 ti (V('nto R dd obj<1o _Ut. Ic> poloit>ol<Clod .11.....nciu de esle prosram.d Ya tenemos nlleSlTO el""n!e Iilto....-. ~) 11 U>l.c.do k>o .. . y tm¡roI .l'ilr' cumprob... .do .. ~ -~---- • 121 1 .c..a&1>... cad.ut(l$dd servidor.d. niqoxtl IbIR. o var..1 _X • un . ... DDl ._ ... tof(Cl1.

NU/Linux. disponen de otro tipo de sockets. Muchos errores provenir de no tener en cuenta. y que los clientes tratan de abrir para lectura y escritura de datos. os. simplemente. convirtiendo las s enviadas y recibidas entre UTF-8 e 150-8859-1 o 150-8859-15. diseñados para conectar equipos remotos. antes de conectar hemos de especificar que el tipo de servilocal y una ruta a un archivo que representará el socket servidor. 8ervidorft:P: POBLIC SUB Main ( ) . 4 Clientes y servidores locales gen de los sockets TCP. los siste(. sockets son unos ficheros especiales que el servidor crea dentro del sistema de . s6lo ede emplear dentro de un mismo equipo. por ejemplo. es aplicable a los clientes y ores locales. y en general cualquier sistema que siga la filosofía de la familia de as UNIX™. mientras que otros n ISo-8859·1 o UTF·16. Podemos mejorarlo como ejercicio. Este programa. . Hemos er en cuenta que situar uno de estos ficheros especiales dentro de una ~nidad no sirve para conectar dos equipos diferentes: un socket UNIX o local. • • 6.hora de crear clientes o servidores para producción. puede tener problemas ñ y vocales acentuadas. lo explicado hasta aquí para clientes y servidores TCP. que s6lo permiten la conexión del propio equipo y cuya misión es optimizar la funcionalidad de los sockets o el cliente y servidor se encuentran en la misma máquina. caso del servidor. la única diferencia se da en el modo inicial de configurar el servicio. debemos tener en cuenta la ación de los caracteres empleada por el servidor y el cliente. que Gambas y muchos otros prousan internamente UTF-8 como codi~cación predeterminada.

U.oaI Y propiNad Palh lid toUn.:.l'. ~ knido r. """".lJ.. Si ~1llOI ti c6dirID con tstIlI'M)d¡fi. .1 'Ort • -. 11 Cl1eat e ... 1 o • DI lerd.C ctO . ~ lpIt n1111d f1 ..II Nd...!yp I • 1Ift. m Iup lit lIlI ¡xwr1l) TCP. "/. al IUt..a~ ..hUo a _.1 ~ . Al ·CU_ te" eU. • i' ... . pinllo aIlIIlt MiaI B~ Cl. ~ k (1ft Illl udu't'O apmoI lit lIpl klCkct 1amIdo~. WII WIIIUI a cIrIllro dtl lmII • ardu.peclU c:Mo" . Cl1.te .-.'''M_''' CIl!I. .u-J...te au..It. Ü" dicnlt hnnclI lit nprcifiar qUf .L. ."l-' et" ftI "~ido.1'Or t • nS2 ftI' IenLl oc-.iJ .eeU 1cMo" .. .u .de r al pllU'\O . .':. LoaLl IenWo c.. ScIro-.ut" Cl~. _ _ "anw.. .. .".!ypI • lIet. collGión k rtalu. __ . .o -.hUl • tfHr.() IP .JII Unlott Iel'TlM Ir. lodIet. .I"'O l ' a...Jl tllIII PIDIt "Inw . f'Waite al puen. __~"'''''.1.

.... proplltcion.. ....."'. .M.do J*II'<IC 01 oo:>deI ptoxtdoll" ..... dinm.....~ iDdlm el punto Iood .... qw "'" alSl< __ . ho:d>o. .......:':'........ LoI k"idoo . ..m~••u. _ ~....nido.._ '....il". _ ..n... pomo diodo.-........ hln..."". 'anlo ""'" crear progromu oeni<Io. por ....l qw """f'ln' I'P" . 't <ioIo .TOflI"I. <ir Iot ob....... Spodoo_ _ P... Pt-.._01" wOt " ol loo. do diotl_ . • 6." ha d< o... X................. do _ 011""'0«*> VOP • ¡m'ft.........::':. poquow".. po.. .. "'_upqo" pciocjpiooM. l\oItriII do aur '''' .. nwiaf ""toJo . Iotdialla. U'" abiD<:i6Ill'flnOla......... n'............... ""'""'" 1" """d __ • t.... como prosrama..rtlldo au cW<. Par... 11 priclico ol bomnoo ala dio- 'Ón_dicnlrr."" ...." pnen "" ~..· 1 ... ....... Ea lodo"'" oIguirn... UDP" po WiC>pW) I"""do' "'~::....ias propinlodos PO'" i. 5l1lP ........"'.. _ . 'fU" otliri Iipdo. Cuan..... d~le.· c.....ol....... - ...tuiolaIP. con unob. ...10. in. !·500 <ti .. puor- pm>oin "'>nO<W nw>c:o" 01 (111'(> ~ o clirnlet rnIm. 1o_1IIIIqo> .a1 rnttodo 8. ... ' : : :... iradc:p•• • dd puer10 loc. ....... ...... 11 """"'"" o.... 1*1 ' ISOWaIWL _ _ .. ... .....ttoo do lo dMt UdpSod..·II•• ~ .... '..dtnriroaor loo ¡aquel..... _.. •. - p¡! ' o . ..".............. en 110 ""'" dr diod'w uno IplicaciOn .. _ _ t-Io". ti ......... _ ..

.

.

En esta ocasión. vamos a añadir el control DnsClient de la lista de controles disponibles en el diseño del formulario. Mediante el método GetHostlP se trata de obtener la IP de un nombre de equipo (Host. Dentro de él situaremos un control Te>. • • • • • 6. • Form ---Container .:~p:~~.net. Si bien el nombre sugiere la llamada a servicios DNS de resolución. Name). normalmente.Programación visual con Software Libre En este caso. en lugar de crear un objeto DnsClient en ejecución. LDAP o NIS. Figura 7.i. lo cierto es que los objetos de esta clase tratarán de resolver el nombre por todos los medios que disponga el sistema. se hace también al inicio una llamada a Bind. los unimos en la cadena Buffer y cuando ésta toma el valor ADrOS cerramos el socket. Caja del!J~ ··:··:. y mediante el método GetHostName realizar una resolución inversa.tl:···. y otro llamado BtntoName con el texto Obtener nombre. con su propiedad Text inicialmente en blanco y dos botones.:·:. leemos los fragmentos de datos procedentes del servidor. 6 Resolución de nombres El componente de red también aporta una clase DnsClient para obtener la correspondencia entre direcciones lP y nombres de equipo. En el evento READ. el intérprete Gambas deja de aguardar eventos y finaliza normalmente. Tras esto. dentro de la pestaña etwork. Lo más común es que en las redes de área local se emplee el fichero /etc/hosts que contiene una lista de pares nombre/IP. uno llamado BtnTolp con el texto Obtener IP.1:Box llamado TxtHost. Al cerrarlo. es decir. rellenamos los datos de TargetHost y TargetPort con los datos de destino del paquete y enviamos la cadena HOLA. sólo el servicio DNS. así como un formulario llamado Fmain. Crearemos un proyecto gráfico llamado MiClienteDNS con una referencia al componente gb. El funcionamiento de esta clase es muy sencillo. de dirección IP a nombre de equipo. pero asignando el valor especial O para indicar que el sistema elija por nosotros cualquier puerto local que se encuentre libre. mientras que en accesos a Internet se emplee. Proyecto MiClienteDNS. servidores DNS.

te.8CIJo' ro se añaden al formulario como controle. GelI:Bc:i~8t11f8ll11eiO . imi1ar al d 1 Figura _. !RO tI. El oqe Dn el' nt. norrTlQo Fin de facilitar la labor 01 crear programas grá icos.el formu rio y ¡ste ham que se o 01 a~'cQr e 'Iodo De/eIe en d' o rormu o io. ..¡te uLario y la r _E. pI - .SUB BI:ni _ _ _. -O CJ. el. MmL e ... $e treo al desarrol . :z1:.t.1 no son visibles en ti po de . ~I.. uíenw: - ~ ... ~ C11 . coso llamado Cliente.. .. GBtBosltIP ( ) 88-_ e ~In 0("" p! o & el! ti .

...nLno: con Lo IP GflKooIN~l la propoedad Hool"... compl'<lN' ol alado <Ir lo propiedad '1....'. la raolución falla.t d tnbojo ..pe"" 01 . """'" _ ......."" la P"lIKro es . blInco. no lO< mcontr61o IP a _ • Drd(]i. Ea __ ....wrí" ndmoro rru. v. . ya '1'" nUemru el eódilIo del . l .. .. ""'" ejt(ul'ndo..mm~ d . ......... r<dN.....mbim podemos conlmla. t.... ... • 'ylH<Nls.. 1""'" ohorut el .... modo . _ ..mt wnbobI pnmj!....... .... dooI DM • TRUE... quu< di.I~ bdpn..I«r (H.....ror..1<o:a..... ck . un nlor menor que cero 1IÍ hubo un <'mIr..O " . . Pan .Kl.wn.... lP o..o FinÍlhtd. ..... En omboo ~ 1........" St..'" ... . ~HoMl .... principal . 1610..' t JitabO.dad HootSo_ ....&e: oí time un nlor menor que cm>... d ....... propkdod S""IU.. I ~ ..yoor '1. qut lo ¡lllnW. o. clot>oo poaor lo f'l0f t oc! A5yrit... cOn l... ..o'" J ...~KrdImo ..... undo) qutdanl . Si ro.... cero cuando fínoIiI' con bit.....b'-·· _d __ ~PO.....d~d . ""'d"""'... .. lo po .plo rnodifiaDdo d cOcIiF iaiciaI ptnI . .inrnrdiota .. CbO.. " dos apelo....' ~pc... Ylo ... Eaaoboodo .-do . IIllbo un .... "' . pode""" doGtlHoolIP(loGd~... «YO m.. ... dos HOIlNanw .el """"""naoao.... ri diornlt ONS nU trabojondo .... . _ _ do _ bOI6Il c. '" prop.... d ......r _ramooo ti nlof de la prop. ... _....para ol ocoNo' el pmaso...rd códip.. ti plOU$O" ""ra .... r ........... fA::>WIlhoIn ~ - t":".m... la ~Iución ltn'llinó C""t'CU- .nle'rna"'t'ltt. pt . undl .aul .. «"ro.. T.. . . cuno.n'.... . ~l~ ni ~ El oepl><lo QtO el n.u el " ."IP en ti prUna QIO r HostNome..... lklollp rapcctinmmlt.-.. 1 1 0 _ al . luOón puedo wdu bootruttr 'irmpo.......6n' :oIs. suano lo c. Sr _ buck el. el __ do de . .trobojendo .. p<'<IUdto qm.. ~ ha _rito d ........

-() DO . ftlII CU.UI Cl1_..~ • • ftlII Cl1_ .. . - ..U1....GIUooIU'(1 tan 0.GIUooI.w. 1'lItbt.w ..CU_.. ..hrt cu.w..01 c..u.01 •• .. O - tan 0..Up • 1'lItbt.A8)'1lC .'U1tM .hrt cu..

e diclUt 1 x'.tlI el cual el diemc lan sólo dieila una dirección URl. el modo do. lLom»J POST. tnmminr P'Ii. control do nrora.idoib.. n[ como Illnl)6n M (o.lino dt e un bmaro pan la c:omunM:xi6n mi".. En el Kgundo mkoOO.. rKiblC'l'da"" mmtoJ del OOcumallO ni cada fYmlO JU:AD qtl4' \lIIirnn<l& m una caoXna· .. dimln r MOl .. 6.l... trabajo K pana mM al dctC'" 10 para Iof. <bdo qL>t.. G. y máscomoln por ......" d ~ f.rnlo in""". ~:: tbda.. ulnaono..... ~ lo dtYudw .m. devolviendo el scrviOOrcl muI· lado. en d que ra:ibimnoI dJftctammlc el documoetMo tnll b Ibmada a b GET O 1'05T.mllT nnplra .. El pmrocoIo H'TTP a uno do los mis a~id06.>mdo "na trrit <ir CO<I'I'ftKiDoco aura dt la . dalOll a1wm· oo.. nivel de compn:s06n do dal<l5... ellVÍl lloa tome de informacionellKlicionales qm el K'fTidor PlOU$irt anleJdt nlv.. r o '" I • ción de caractnes......1oluJo de InlnlWt... Cllarea interna cid die"" H1i'i ..... loOdnI: con la aplkación ni fiancionami.... En el pmU:uIo l-!ITP.... El protocolo HITP eslablea dof..m&IOI.. El dimte lfTTP ~ fi. es el Uamado rMlQdo GET. ele.... .idor... no sólo JOIicila la URL.er.llI niwl por nw::ima do IOdo lo ~ .d dim~JOIicJta. Cl"" prowce KU50 • 110 dicnteUamado HII~ KO'idoru HlTP. b apIiad6n que ~ 1610 habri do prmcuparv m pNir un doc Y rftíbirlo........si IICI q.7P~HIIP En l. modos: el mh simplr CI el modo . El primnn.. idol UJl docull'llef\COm . ':lrnwo lit .codol principales p..arnoo un fonnulario (OlI daD en una P'gimo wrl> y pu1samoI: el boIón moiar.m el que P noK trata 1610 dr _ r o n lIlI K1Vidor. toIidl¡)... el el"nt.o el calO habilual cuando rdlm.mbu apo'" en ti componente "... E1lnINjo dr n"Joc:iKión ent.· • gadorCUólndo escribimos uno dir«ción..... ulilizado para m:ibir p:l¡¡inu web en el DI. por ~plo.. aban K CDCUnItn di : : : : lfTTP... WoIOl binarios.. u..m...¡nrioftar dr do. Glras-. m el .

_ _ " 0_ ptoglu ..':. ~:~'~". Lofl ftt.. -.al ~ U lIbD 'fttp . 1~_< lcfi nm. -a. ' . ._/~· U ftt•..a <Icor.t.) • \'" It ~ .. '1 .. "fa rftibu la. 10 fttp ... .. P'I --" -. prupoodod Nf. .. tamb om"" ".Up.II'--.-...... . .~....... ..... .. . ..pl'07'C'l:lO de awo I' • 'fóoodrI... ~~ ~~ ~< It ~~ ~M ~' f~ ~< .... .. .r&o <It 1& cWt IlllpCJionlllorrllOdo HIIJ'• ..... .(.c. m" .p.. .. ....... .-....1 "_. ob. .... * " ..(p Cl...." -_u HTTP . .:JIp=h • ..wM. wcb )...pe • rAUIK fttp ..t "PI . ~'I imc Out.. 'tri"" .' FAL'iI: 1*1' ''' el pro<aO . ..¡. PlUft • ....r e _ IIDI .. .. dtfinimot 'f ctftlTOOO ." .-' • ~t.-laC ) ftq llII 1't. ....II..-.d..cM .d.

.. activo.iolliOi. pero se: han pl1l . l.. !ternos..yaquetlcliente mantener viva la coDuión con el strvidor mientras le es posible. con lo cvoIM ganará en vMcidod y . El pob:olu HTTP~. cerramos ti cliente Http.. para aa • nta mann'a la recepción de múltiples documentos de un mismo servidor. dtb. POST conMCVtMlI. 1..AO y mostramos el contenido de la página wdl recibida por 00 Finalmente. d propio protocolo HITP puede especificar códip dt mor en 105 que ~ nicación/recepción de datol ha sido perfecl•• nivel Rlico. o al evento Error para atender posibles problemas di nicación con el servidor.or la lIlJtn.. emplcanc lruedón Rf. con k> que d prtlp1( interrumpido twu su rtCtp06n twu.Indicamos la URL q~ contime d nombre tkl Kl'Yidor y ti documento dmtro de ále. como en d caso de los lOChuo te DNS.. Al margen de los problemas Rsicos de comunicación.i valor mayor que ctro cuando eW. Si hay un rrror.IarnamoI al rnltodo Ca con d fin de rn:ibir la p'gina. como en el caso dt' los socul$ o cualquier olro Rujo. ti modo de proceder n UlIetamcnlc ti mis con los sockcl$: esperar al (\'tolO Rtad para ir I()'todo fragmentos del dOC' en proctSO de recepción. un Mmpo en el ~ el MIMdot _uWoe e1. ctro m caso de mIO que cero en caso de error. un nn)( o hasta QUl' pum 10 Jegund múimo.xUt lo con el ditntIf Si Mel I •• iOi rKibir 'IClrios póg_ de un _ 'Iida o rdzor pekioi. tendr.olXJ6n ClOSE 1610 de kldo el ptCQ$O.&loesn«('sario. uIlIizorórl . Si bien.ttmos ti valor de la propiedad Status qut.. _dol _ _ En cuanto al m~odo ulncrono. lo indicamos por la consola.p. que se detectan con d Error.

• .oIao . Cado Y _ _ ......-... 01 c6dia0ck a _ t . .w.... pro--- bica). ~~1_~ DIX ... "' . .. do .... a .. po ....--dd . en d purdoD_d purdrnC08• IIIa«ur... do _ '-:lo¡..en dft'fOf 4lH...~p ........... (01 nb 1ODapifioo '•• dd eo. '""""""" dr 1<:1:10 n¡4 do.. . odut)..... oo... ""'. ftr'--9 ..lC _ MatAO DIX ft. •• d o l _ PUK.....mw ... .lo.... es ~ .. do dol P'''V'''''''' UIIilizodo e<>or><> _"""" y.b: ..._ doaon_ euyoc-. ddinoltHTTPpo F N po.OuUl tít-. )odJOOleo.... o6la 01 . _ o6la a""" do ........-.... R por d onvodut-...c.. _ ..a_ ..El caoo ~ a ...d .

liJ_ _ . . .¡.. -MOr <k' . ~ poldodAMllt_ ..II B' ftt.. . atol nIora.......~ .e.. llamar _ ..._ ..._t...p....... ) . .....-. .. tofClltp....<q/. 1OCIod. ... _ < o_ " _ al ....."1. te 11I dt np«ir"".......... .. -'l-..uJ- _ " ... ....up.. d ...-......~.."".....r"f ' ....... ftlft ...c. . ""1lI inlroduc:i.:r.\D :::_~.' .""" ro. • UOI .:: ......" oc .'¡... t..Ifi' na....·dIDnlldl"k _". ..iIdr La ""laa" Uttp... El UIUlOO tildo dilopOlWT'" un IlOllIhl'f lit wUlrio 1 tonlrud\ll. ..~ . . """ ~ft • ..... nWlodol en o . DO lC«sibla al pllbliro m p«lI..~:::.. .. 1U000l*1<_dioonoo . .' El protorolo IlliJ' pnmitr al diente utrnticarx rara ~ibir <\nmllinodu p.... rlllOfl\bff lit -no tn lo P"'l"f'lad (hnylo ronuawlll en 11 propoedad ~ Inln ...-..

d UfO <Ir ~ q.... ."ido r. .o<::>& provm lnlt.....<n:I . ~ ~ el ........... ".. Si la propirdld Upd¡:'~in .. 1"1'CtI1I't ~ Yt.. dtl"tct<>......... KITP ..dp i.......Fll' .l'Ialdt ... ya ha..... diMAIdo ~ .. ""ln...roIlador do lo aplicación ha do a>n(lC ft' do ... inf<....""'p a. n1U' "" ordIioo 10 ~ e si: Fík."...al ~..... ~. • •• 6. a<tin dD Ylit HTTP .. dc1 KrVidc>r.. pu:o. coda carpru ""Fll ' .... La atnK_ • l D • ~:::. d dlnlt< ' II'ITP 00 acopla Iao....... .. "M' I -.ntcriori<bd PO' dicbo d"'. JU&Rbm IItcliorntlOy'P''''~'''' n _ pordl frOiI b CtlOCO - II t .....""Kión q..iIÓl • TRUE.... idoc : ~:::H:':lP lambinl COflt....oI .. .prtIoDIna. B Prot cxol o FTP .... d..mpl.... trldid ooard l........ dio . D«aiMadu ... hnnl k: ~ ...... t•• AIhr y.t -'I! ....... "" . nutnn <lr ni$lm ....a w ......n• .....con .:f I¡l.U Ibdi dtJ .......:"" l· ..r mpan Abn' si 10 P4'.. Coa U'" oinWU I ?! ... .... cu.....al bs _ _ cooblI ....... ... al cliaI&e........ InI<'1ld<sarrolk>rfut. Si lO . estnI<'Iun artl6rt:o y ..ool... ttmaJl< l d lnI!I<lodo q..........1d o visitada con .... pmni li • • ~_ dio cocrilltn al6dlc to .... . iIb FTP . por.. ilin .lodo_""*""" CUJIftU ..«""i 6ft cid ~ <omp onmlr . CIlI<lÜ5. .. lo tru>omillón Yrt<tpCión de 6dIcroo.rdmut do!.....

..tmdmnolqlMindicarla un dancb y l4rnu a los mhOOot Wr() <) Pt<t(). como K ha indicado..dadoqUl'Ia¡n_ rión dl prtlU'CI& ~ es muy ll'tlCiJla Q)Il Gambu.. 10 1II .....muy limibr • la dri dimU' HTTP.. i6ot.. Ful\lnll >"tiuot:s de elk dimet darúI aa:etO .... K pnmiU' la Iftlión de nomlm ck lI5Uario Y~.. No obstantt.. de c:arpeW 'f coma.. ~ FTP..l d uso dir«lo de ulUidildes comoftp.1.rurl 0.... ahon es una dast muy lim.a.bda y p~ pbnlnrse como a1lttnl1liv.aplicaciona complt-. • .... P"f- IOniliudot.1 pmr. Al ipl qIK ni d dimU' KTTP. '11M Ma$ilm iKUIO.

Pero ¿qué es XML? Pues en realidad no es nada nuevo ni revolucionario. Es cierto. No obstante. Cuando necesitamos escribir un fichero de configuración. un formalo para un fichero de texto o una hoja de cálculo. que se encuentra sobrevalorado. también es cierto que XML presenla algunas ventajas importantes a la hora de intercambiar datos entre diferentes sistemas. siempre se le plantea el mismo .11 • Hoy en dla es comun ofr hablar de XML como la solución a todos los problemas de geslión informálica en la empresa. un documento con registros extraldos de una base de datos. se trala simple y llanamenle de una definición de formato para cualquier tipo de documentos. comunicar datos a un dispositivo. desde luego. posiblemente debido a las campañas de marketing realiudas por grandes compatlías de software.

mien· tras que HTML se encuentra limitado al diseño de páginas web. lo que proporciona libertad para manejar y comprender el contenido dC' los datos. 11 . en XML absolutamente todas las etiquetas deben estar anidadas. documentado en el caso ideal. la lectura. La primera. donde hay etiquetas. XML es sensible a mayúsculas. trocear cadenas. no obstante hay diferrncias sustanciales. La segunda es que. y capacidad de elección de proveedores y servicios más justos por la inversión realizada. elC. El formato de un documento XML C's similar a uno C'scrito con HTML. escribir y verificar los datos embebidos en dichos documentos. hacia otros libres donde obtienen ventajas de pre<io. y cada etiqueta abierta debe cC'rrarse. Los formatos propietarios atan literalmente al diente a los servicios y deseos de una empresa proveedora. es que XML es un formalo de carácter general. y más importante. Por otra parte. como la de párrafo nuevo «p» que se suelen dejar abiertas. Muchas veces escribir un fichero con un determinado formato es una tarea casi trivial. una sección que comienza con la etiqueta <p> no es igual a otra que comienza con la C'tiqueta <. Por último. Esto tiene una importancia grande cuando una empresa se plantea el paso de sistemas propietarios a los que se encuentran encadenados. es decir. pensado para trabajar con cualquier tipo de datos. se trata de un estándar accesible a todos los programadores y casas de software. Además. haciendo muy dillcil eliminar un elemento de una cadena de programas para reemplazarlo por una aplicación nueva. las herramientas de gestión de documentos XML proporcionan las funciones necesarias para leer. suele ser engorroso. XML proporciona ayuda en todos [os aspectos comentados: es un estándar que define cómo se han dr insertar los datos y los campos en un fichero o flujo. dado que hay que comprobar errores. comprobar la validez de cada fragmento. con el fin de que los programas origen y destino de esos datos puedan escribir o leer cada parte del documento correctamente. pero el proceso inverso. cada aplicación ha desarrollado hasta hace poco sus propios formatos para el almacenamiento y lectura de la información que maneja. que defina el modo en que esa información se inserta en un fichero o en un flujo de datos a través de una red.Progromoción visual con Softwore libre problema al programador: la necesidad de un formato.P>. a diferencia de HTML. Por otra parte.

disponer de eu etique!lI en un documento almacenado hace meses o años garantizará que los programas sigan sabiendo cómo interpretar lo Que conliene un documento. con una VttSión 2. en este documento vienen los dlItos de los usuarios de una asociación: el nombre y ti número de asociado. Por olra parte.0.XN< . Yque es (¡¡ única que se emplu en la aetualidlld. Uega ti cuerpo dd documento XML Hay una etiqueta inici~ que da nombre al documento.remos esa información en la ttiquela inicial: • A continuación. emplean la codificación de caracteres UTF-8.l utilizando. los documentos XML. por la cadena <bml vel'5ion". Tocio ello encerrado entre etiquetas abiertas y cerradas.El aspecto de un fKhero XML simple. en la cUlllse especifica que 1I conlinuación vienen dalos con formalo XML Aunque ena etiquetll puede ser obvilldll. en la actualidad. Por ejemplo. en t5te caso simplemente datos. ya que conliene inforrnllción imporlllnle."'. Despub.O"l>. podemos pre- ver que nuestro fichero de datos contemple un número de versión para futuras 7. XML permite que las etiquetas dispongan de atributos. por dcf«lo. de moclo que d documento queda ordenado en secciones. (¡¡ 1. Si por cualquier razón hemos de tratar con documentos XML que emplttn otra codificación. Si en el futuro una nueva especificación internacional de XML ampliara o modificara XML.0. siempre es convenierue añadirla. con varios niveles de anidación. por ejemplo. puede ser éste: «Ia<oo' <w¡uario> <nombre>Erie smitb</nombre> <&oeio>l13</soeio> </usuario> </da~> Los documenlos XML siempre comienzan. también encontn. En esle caso se especifica 1lI versión de XML que se esl.

así como enlaces a otras fuentes de información. 7. aporta un modo sen· cilio para escribir un documento XML. etc. Los atributos tienen la forma: definicion-~valorw Es decir.w3schools.asp.O" encodiD9"'''ISO-8859-1 U ?> <datos version-"2.xml. contenida dentro del componente gb. El fichero podría ser ahora asi: <?Xll\l version_Ul. encerrado entre comillas. pero más allá existe una amplia gama de conceptos que quedan fuera del alcance de este manual. el valor de ese atributo. DTD.com/xmlldefault. hojas de estilo con formato XSL. y que en elida usuario se anada el año en que entró a formar parte de la asociación. por ejemplo <p><lp> para designar un párrafo en un documento XHTML. Estos son los elementos más básicos de XML.4"> <usuario> <nombre inicio-"200S">Eric smith</nombre> <socio>113</socio> <¡usuario> </datos> 11 Una etiqueta que se abra y cierre sin información en su interior. espacios de nombres. Un buen punto de inicio para aprender XML es la web http://www.dondeseencuentran tutoriales al respecto. y que aportan un gran número de posibilidades a la gestión de documentos XML: existen etiquetas especiales para comentarios. un signo de igual y. se indicará el nombre del atributo. Supongamos que deseamos almacenar en . un lenguaje para validación de datos.ampliaciones. I Escritura con XmlWriter La clase Xm/Writer. puede simplificarse es<:ribiendo la etiqueta de apertura con la barra al final del nombre de la etiqueta: <pI>.

w O->127.10</dns> primario-nO~>127.42</dns> </oonel:ion> </ooneI:1ooe8> 7 )(Ml . Plantearemos un documento en el cual tendremos una sección co'lexioll para carla conexión. que igflOfen olgunos o~ros de la codjlicrn:. que tendrá un atributo nombre y otro local.0.w w <dos primarlo.0. asl como otro para los DNS primario y secundario. Siempre es conveniente empleor nombres de etiquetos y olriootos que no conlengon oceoIoi o corocteres especiales de codo idioma Icomo ñ o ~). aportadas por el proveedor.OW?> <conexiones <oonexioo version_~l. este último con dos valores: \. primaria y secundaria. si es nacional. el teléfono y las DNS. O0. poro evitar problemas si o/ros progJamodofes que debon retocor el programo (1 el Fichero tienen teclodos disrinlos o empleon PO""'" de XML pobre.2</dns> <dns primario.ión. si es local.0. Dentro de la set:ción COllexiOll habrá un campo para almacenar el número de teltfono.lO. si está disponible en todo el territorio nacional o está limitada a una localidad. 11 tste será el aspecto del fichero XML del ejemplo: <?xml versi(ln_~l.un programa los datos relativos a varias conexiones telefónicas a Internet. Nos interesará el nombre de la conexión.-limbonet w local_WO W <telefono>229943484</telefono> <dns <dns primarlo--l~>127.0.3</do8> </conexion> > <conexion id. los cuales tendrán un atributo que determina si es e\ primario.Ow> id-~castuonet~ local-~O~> <telefono>l199212321</telefono> l >127.0.20.O.

""l> • 'fil' Figuro 1. enviarlo por la red a un equipo remoto. para ahorrar espacio. e indica que deseamos que tenga indentación (como se comentó antes. que puede ser una ruta dentro del sistema de archivos o una cadena en blanco. El tercero. Tras esto. lo abrimos con Open para comenzar la escritura. sentido o nivel humano.. . El programa tendrá una referencia al componente gb.. en cuyo caso se escribirá en memoria. y luego podrt'mos obtenerlo como una cadena para. Sólo tiene. y los porsers de XMl ignoran lo. Si eslomos acostumbrados o programar en e o CH'.'O'M1'I. En XMllo significativo son 105 opertUfas y cíerr"s de etiquelos. diferente de UTF-S. observemos el formoto. obligatorio. es el nombre del fichero a escribir. t>1I. Este método acepta tres parámetros: el primero. si se desea. o bien si se escribirá en una sola línea. O~lIIl1'. también opcional.ProgramoÓón visual COfl Software libre Antes de continuar. y un lichera XMl correcto podrio estor contenido en uno sólo lineo de texto. A continuación vamos a crear un 11 programa de consola llamado EscribeXML. O$i como los retornos de corro Esto es sólo uno ayudo poro quien tengo que consultar o modificor el fichero desde un editor de texto común. sobremos que con esle lenguaje ocurre lo mismo: los diferenles líneas y lobulacione5 don orden y legibilidad 01 programe. En e. Eslo na es en obsolu'o necesorio.. o retornos de corro. Definimos y creamos un objeto XmlWriter. y dentro de él un único módulo modMain con una función Maíll.•.xml. sirve para.1 mismo podría escribifle en uno solo líneo.e_ D_ --.. El segundo es opcional. especificar la codificación.D_. 105 llaves y puntos y comas son 5ignificativos. y exi51e uno indenloci6n poro indicar los distinlOS niveles de onidocíÓn. a cambio de hacerlo ilegible desde un edilor no especializado. . pero . Estó 5eporodo en vorios lineos. . por tonto. para aumentar su legibilidad). no osi los espacios o retornos de corro. ~- . Proyecto EscribeXML. por ejemplo. espocíos en blanco y tobulociones.

es una etiqucta de apertura. Hemos de introducir una eüqurta ik a¡xr1ura. SI toreo q.. NEW XllllHriter xml. consistente en una matriz de cadenas que sean pares de valores atributo-valor del atributo: Dentro de esta sección tcncmos cada una de las conexiones definidas. Cornen7-"mos por la primera que.writer :rm.l. TRUE) Indicor uoo codificoción diFerente sirve poro que eslo quede rellelodo 01 inicio del documento. tarea que S( realiza con ti m~todo StanElcment • Además dispone de un atributo "version~ con valor "LO": En este caso tambi~n podemos unir I¡s dos instrucciones anteriores en una sola: StartElemcnt acq>ta un parámetro opcional.l .XMl .zará por nosotros lo conversión 1'10$. -odule file PUBLIC SUB Main ( 1 OlM XMl AS x. al igual que antes. hobr_ de hacer con funciones como Con.. con un nombre y dos atributos. de los codenos que escribo.• G be.. procede Escribimos la primera $«Ción.S. en este caso: 7..Open(~~. pero no real..

¡ los DNS iniciamos una etiqueta "dos" con un atributo: Incluil1"Kl5 el texto con la IP: y finalizamos la sección: Ial. podemos resumir las tres inslTucciones anteriores en una sola.ent () 11 No obstante. Dentro de esta región." I c. disponemos de una nueva apertura de C'tiquC'ta para el telt· fono: Contiem:' un lexto que comprende d numero de tdHono: Tras este paso cerramos la etiqueta: XIIll.ltadElement( ) .(Mconexion~. válida para estos elementOS simplc:s que tan sólo contienen un texto dentro (o nada) y luego se cierran.uonet M • xml. Par.artElemant. ·caat.or So • ¡-id W .EndEle.St.

"229943484 xm.("127.(H~". que mostramos por la consola: PRINT ZIlll..Lo mismo para el segundo DNS: xm. H ) {"primario". '''primario''.() xml.42") xml.0.StartE1ement.Text(H127. "1"]) Xml. lal y como podemos observar en el siguiente código: "1"] ) xm1.E1ement("te1efono".Text("127.Encl.3") xm1. en nuestro caso.".10 H) %al. "O"]) xm.() Finalmente cerramos ~I documento para que se escriba.EndDocwaent() 7 XMl .Element.StartBlement{"dnI H .Tert. seria ahora cuando se \'Olcaria al fichero al habtrlo hecho.E1ement( "dn. () z.l. La llamada a EndDocum~nl nos devuelve una cadena con el documento XM 1.l.l.10. Si hubi6emos especificado un nombre de fich~ro.EndE1ement() Procedemos de igual manera para ]a segunda conexión.Start. '''pr~io''. ~n m~moria.20. • HO"]) Iml.EndElement.l.cerram05la ~liqu~la "con~xion" qu~ conli~ne los e1cm~nlos ant~riores relativos a esa conc:xión: xml.EDdElemeDt.0.EndE1ement() Fina]m~nl~.0.0.

Programoción visual con Software libre El programa completo queda de la siguiente manera:

, Gambas module file

PUBLIC SUB Main()

OIM Xml AS XmlWriter

Xnll - NEW xmlWriter

Xnll. StartElenent (Uconexiones", [Uyersion",

u

1.0" J)

ltml. StartElenent ("conexion" , "local", "0"1)

["id", "castuonat",

11

ltml.Element("telefono", "1199212321") ltml. StartElement( "dns", ["primario", "1" J ) Xnll.Text("127.0.0.2") Xnll.EndElement() ltml. StartElement ("dDs", ["primario", "O" 1) xml.Text("127.0.0.3") xml.EndElement() Xnll.EndElement()

xml. StartElement ("conexion", [" id", "limbonet", "local", "1"1) xml.Element("telefono", "229943484") ltml. StartElement ("dns", ["primario", "1" 1) ltml.Text("127.0.10.10") xml.EndElement() Xnll. StartElement ("dns", ["primario", "O" 1) ltml.Text(U127.0.20.42")

XIlll, End.e:lertl&nt () XIIl.1.EndElement ()

PR.INT

:ral.~t()

mm

J ejecutarlo, veremos el documento por la consola. Lo modificamos para que se
;criba en un fichero en lugar de en la consola, lo cual nos servirlo pan. leerlo a connuaci6n en un ejemplo de Je.ctun. de fichero X.\1I.. Pan. eUo modi6caremos el o Open:
~o­

. diminartmos la instrucción PRlNT al final:

XIlll. BndDocument. ( )

11
........ lco

n este caso, la llamada al método EndDocument volcar:! el documento en un ficheJ

dentro de nuestn. carpeta personal, llamado conexiones.xml.

El ¡,cltero obiitrto can Opom no 'le

realmente 01 d,seo duro hosto la llamada
lo~

O

EndD<x:vmem. A 'v vez, el método EndDocvment ~e encorgo de cerror lodos

eri.

queros que hubieron quedado obiitrlcs, poro goronri:o. lo coloererocio XMl. de éste

exploramos la clase X",/Writtr, observaremos que, además de los ml!todos mentados, aporta otros para escribir comentarios y elementos correspondienal lenguaje 01'0, entre otras caracterislicas. También dispone de los métodos áticos Btisd>4 y BjIlHex. que convierten una cadena a las codificaciones con estos mbres. Dichas codificaciones permiten introducir datos binarios dentro de un lero XML

7. XMl

Progromoción viwoJ con Software lihr

• •

7. 2 Lectura con XmlReadEr
Modelos de lEctura

Al menos existen tres métodos pilra ker los contenidos de un fichtro XML:

l. Un mttodo se ba~ en [«r ti fkhero de prinópio a fin. Elltetor v;¡ generan_ do ~nlos conforme se entra y sale de los distintos nodos del documento, y
los gestores de evenlos escritos por el programador van recibiendo la ¡nforrnación. Esta forma de trabajo aún no se ha implementado en el componente gb.xml, aunque se prevl! su inclusión en futuras versiones.

2. Otro método consiste en cargar el documento completo en memoria, para
luego navegar por él, con lo cual se obtiene gran flexibilidad a costa de un consumo considerable de recurws del sistema. Este método está parcialmen_

te implementado en Gambas a través de la clase XmlDocrmrtllt, si bien su fina·

lización no está prevista hasta futuras v~iones, y no se recomienda su empleo

para lectura de ficheros XML No obslante, esta clase ya se emplea para transformaciones XSlT, como veremos más adelante en esle capílulo. 3. Por último. el mtlodo qul." consume menos recursos y aporta baslame simplicidad dI." aprl."nditajl." y uso, es disponer de un cursor, que sólo se mueve hacia adelanle, de nodo I."n nodo. y que en cada momenlO podemos emplear

para conocer el conlenido y lipo de cada nodo. Si hemos lrabajado con la plataforma .NET"" o Mono'no" nos sed familiar la clase Xnr/RMda y sus deri· vadas, como Xnr/TextRetlder, que trabajan de la misnla manera. Este modo de trabajo se encuentra perfectameme soportado en el componl."nte gb.xlIll a tra-

vés de la clase XmiReader.
Planteamiento Inidal En el caso de Gambas. la lectura de documentos la realiz.1remos utilizando objetos de la clase XmiReadcr. El código de lectura resullaré más complejo, al tener en cuenta varios aspectos:

• R«hazar cada fKhero no válido: putdt haber fICheros con formato no XML o que contienen datos sin sentido para nuestra aplicación.

• Ignorar datos no conocidos: es posible que un documento contenga datOS que no nos interesan, pero se han añadido al fichero por otra aplicación en previsión de futuros usos (puede haber, por ejemplo, una etiquda <tarifa> dentro de cada conexión). Tambitn una etiqueta conocida puede contener atributos desconocidos. • Orden desconocido: en un fichero XML no es relevante el orden en que se escriben los nodos hijos de un nodo, es d«ir, que estos dos ejemplos deberlan ser dados por válidos:

<coneJ:ion>
<dnIi> •••

<telefOllO> •..
<dnIi> ..

</coneJ:ion>

<coneJ:ion> <telefono> ••••
<dns> •.• <dns> •••

</coaerloa>

Si la aplicación espera. encontrar el nodo lelefono antes del nodo dns, fallará allratar el primer fIChero, que, sin embargo, conliene la misma información.

• Ignorar etiquetas sin interés para nuestra aplicación: XML, como indicamos brevemellle al principio, prevé la posibilidad de alladir comentarios (simila· res a los comentarios de cualquier progrnma, sin uso para éste pero que aumentan [a legibilidad), nodos OTD, ete. Habremos de pasar sobre estos nodos ignor:l.ndolos y sin presuponer si existen o no.
<MI

Progromoc;iót! viwol con Softwore Libre

Cuanlos más posibilidades oñodomos o nueSll'a código de solvor b desoonocido, más

llexible haremos nueslro I.ctor XML poro permitir b lectura dio dokn pwtenienlM, tal
vez, de programo, escrilDs poi" YOrios programadores con bs que OD Ienemos con1DdD, o que tienetl petlsornienlDs algo diferentes acerco

cIeI conleoido del hci-a.

o O O [] O Un EjEmpo dE: lEctura
Crearemos un proyecto gnlfico llamado LeeXML, con un formulario FMain, que tendnlla propiedad Ammgelll('1I/ con el valor FiI/, y un (mic:o control TrreVIt'W en su interior Uamado Arbol. El programa contendnl una referencia al componente gb.xml.
g

--_
~

P,,.,.,<l. ·l_.......
~

Olf"i8CJ . . . . .

... ..... eu.

t>".'O'hl'1 •

,;;,.:':;=-~ 0 __

.

L

0._ 0.0 0

_ __

En la apertura del formulario leeremos el fichero XJ\1L El método Form_Open quedará así:

, En primer lugar definimos ('] objeto XmIReader, lo creamos y tratatnos de abrir
el fichero XML. Si el fichero no existe, o
rá un error en ese punto.
!lO

atiende a este formato, se genera-

NOOe.Error("Pallo al -.ElBDent THEM • IF Xlll. De no ser asl. Clase ( ) "'" " 7.XMl .brir el fichero iIIodie.PUBLIC SUB f'onU)Pen() DIH :Jsnl AS XIIIlReader xml .do") "'" " """"'" • Entramos en un bucle en el que Il"l"mos G1da nodo avanzando por el conteni- do del ~ Nos intl"n$3.Type .Name . el fichero no contendría datos de interés y lo rn::hazarlamos. Pero si es correcto.1lCWIle " "/conexione•• 'llDl" ) lP ERROR '!'HEH Message .NEW xmlReader TIU %al.Error("El documento DO oontiene datos de eoneziODe''') %al. donde trataremos estos datos.XIIIlReaderNodetype. llamaremos a una (unción RellenaArbol.Node. DO WIIllZ 1'RUE IP IJal. encontrar d primero de tipo EJemalt yque $U nombre sea conexiones. . Open (l1ser."conexiones" '1'llEN RellenllArbol (XIal) ELSE Mes8age.1.

empicamos el método Rtad. que sitúa el puntero ¡nter_ no en el siguiente nodo del fichero XML En este proceso. leemos el siguiente nodo para situarnos dentro de col1uioues. y salir de la función cuando ellcontremos el final de esta etiqueta: . En este caso habremos de seguir leyendo por cada uno de los elementos cOlJfJCiml que existen dentro de la etiqueta principal conexiones. 11 Ir lIal. cerramos el objeto XmlReadu. terminamos el bucle.Progr Por cada ¡teración del bucle. TR!' XIal.Close() Vamos ahora a implementar el procedimiento RellenaArbol. TU Ilal. tof TflEN 8REAX LOO' Tras la lectura del fichero. es d«ir. Read () IP ERROR 'I'ltEN Si llegamos al final del fichero (tras el último nodo). quc no cumple la norma XML y. puede darse un error si el puntero Uega a una zona donde el fichero tStá corrupto. Esta circunstancia s<' puede conocer porque la propiedad Eof del objeto XmlReader loma el valor TRUE. no puede ser leído. Entramos de nuC\'O tn el bucle y. por tanto. en primer lugar.

Read.Node. lo ignoraremos.Name - ~conexion~ ntEN Rellenaltem(xm.El_nt ntEN IF xml. Ilamarc:mos a una función llamada Rellenalte:m para tratarlo.'l'ype • Xln1ReaderKodeType.Node.l AS xm.XMl . saltando todo su conte:nido para llegar al siguie:nte: nodo dd mismo nivd.lReader) DO HBILE TRUE 'l'R]' Ial.'l'ype .Node. ( ) lF ERROR THEN RETURN Si tTlcontramos un nodo de: tipo E1e:mc:nt que: se: llame: conexion. con el método Nexl. Pero si su nomblT rs desconocido para nosotros. EndElement ntEN BREAK END IF 7.xm1ReaderNocieType.PUBLIC SUB RellenaArbol(x. IF Xml. Mezt () IF ERROR TIIEM BREAK ELSE IF xml.Mame - ~ooneziones~ IF zml.Node.l) TRY xal.

pasad por cada uno de los atributos del nodo.Progromoción viwol con Soft.Name .Name - Mid" 'I'BEN .. el puntero \luel\le al nodo sobre el que estáballlos situados.Node.Node.Nodo . cuyo nombre y \lalor es el nombre y \lalor del atributo. ~ AND sLocal <> .bu..Node. • Para ello.l. A lo largo del pro· ceso de iteración iniciado con fQR EACH.. Value IF sNodo <> . POR EACII x.te.. en el cual leeremos el contenido de cada conexión exitente. y con los dalas recabados.Attd. AS String En primer lugar vamos a recoger los datos de los atributos de la t1iqueta cOllmoll..Node. ~ THEN IF sNodo .. que a su \lez son nodos.Node.:ral.ocal AS Stdng DIM sPrt. el puntero interno del lector X.Uica. un nodo al efecto para su representación gr. PUBLIC SUB Rellenaltem(Xrnl AS xmlReader) DIM Limite AS Integer DIM sNodo AS String DIM st.:r."O" 'I'BEN .. Finalizado el proceso de iteración.MI.Value IF :ral. añadimo. :U" :ral.Mlocal" 'I'BEN aLocal . hemos de iterar con la propiedad Attributes del nodo.¡re Libre Rel1enaltem es el procedimiento mh complejo.s en nuestro control TreeView.l.

l. NULL.xm1ReaderNodeType..Add(sNodo. a! siguimte nodo que contendrá el texto con el número de teléfono. pasaremos del rnxIo actual (la ~iqueta Idffono). Buscaremos nodos de tipo EltOlent yen función de su nombre actuaremos de un modo u otro.Type .Node.Eleroent raEN SEu.lJode.N_ • Para el caso del tdtfOIlO. tendremos que comprobar el valor del atributo que indica. & xml. . mejorar el algoritmo contemplando la posibilidad de encontrar algo distinto a un nodo de texto.Add(sNodo & ~-tel". sNodo & . es decir. sNodo) Si el nodo es de tipo "dns".. las DNS y el número de teléfono. y lucg<! leer ellexlo que contiene la IP: 7. sNodo " ELSE ~ (loeal)") TRY Axbol.Value. RGad ( ) '1'RY Arbol.DoY Arbol. (podriamos.Node. si es DNS primario o no.Add(sNodo. que siempre puede resultar complejo al principio). (nacional)") E"'''' Pasamos ahora al interior del rnxIo (olluio" para extraer información de sus nodos hijo. no obstan· te.tel: .. '1'RY Ilal.cr CASE XIlll.J<Ml . TRI x. cosa que no haremos aquf por no complicar más el código. Read ( ) IF ERROR THDf JU:'l'URlf 00 HalLE TRUE IF xml.

EndElemeD't.Node. THEN BREA!< .rw - "O" P'OR 8ACH Iml. NULL. pasamos al siguiente y continuamos leyendo hasta encontrar uno de tipo EndElement. donde sabremos que hemos encontrado el final del nodo LOOP IF Xml.Add(&Nodo • "-dns2". xml.N_ .Node. Read ( ) Ir aPeia .Vslue.Node.xm1ReaderNodeType. .Attributea Ir Xal.Nodo) ELS' TRY Arbol.Add(sNodo & "-dosl".Nodo) • END 5ELEC1' Una vez leido el nodo. .Kode.ProgromoÓón viwaj con Soltwore libre CASE "oo."pri.Value. "-dns2" • Xal. "-dnsl" .s.Value """" 'l'R]' Ial.ario" TKE:N sPria - Xal."O· TBEN ~y Arbol.IlQde.Node. MULL.1'ype .

At.ring 11 P'OR EACB Ial. Real! ( ) 11' ERROR TREN BR&U:: LOOP e n el código complelo apunto: • r~mbas claaa file PUllLIC SUB RellenaItem(XIal AS XIII1Reader) DlM Liait. (nacional)-) END lF 7 IWJ.TREN sHodo . AS Inteqer DlM sNodo AS String DlM sLoeal AS String DIM sPrim AS St. sNodo ~ . Value IP sNodo <> .NocSe.rlbut.Node..NaIIlB .KaIIlB .Add(sNodo.Add(IHodo..t. .-local.-id.Node.Node..TRY XIal.-o..TREN TRY Arbol.TREN II' sNodo .es If' XIal. sNodo ~ . .ANO aLocal <> .XIa1_NocSe.Vll1ue If' bLl.Xlal. (local)-) ELSE TRY Arbol.TREN sLocaI .

Node.Add(sNodo • ·-dn.• :Iml.Attri.2: . Node. -do.l~.XInl.Value..Prila .Type . NillIl8 CASE ~talafono" TRY XlIIJ.Value TRI' Ial.-priAario· 'rBEM shia .Hode.. NULL.hila .TREN TRI' Arbol.-O.2-.Node.Add(sNodo • ~-tel~. sNodo) EN!) IF EN!) SEUCr .Nade.ReaderNodeType. NULL.Nodo) ELS' TRY Arbol.itead() """" Ir .Val\le. -dnsl: ~ • xml. ~tel: ~ • xml.Ial. .Hode.Programoc::ión visuol con SoItwore Libre DO WHILB '1'RUE ¡l' IMl. Read O TRY Arbol. If' Xal.-Of'OJl EACH XlIIJ.Value.Node.Add(sNodo • ~-dn.Elemeot TREN SELECT CASE :Iml.bute. sNado) • .Node. NULL.NiIIIle .

. Il' xal.. Read () Il' ERROR TREN BREAK mm """ POBLIC SUB RellenaArbol(Xm1 AS Xla.Nex1:() Il' ERROR TREN BRI:AX 7..1Reader) 11 DO WHllZ TRUE 'l'IU xal...Nert() Il' ERROR TREN 8RBAX ...Node.Type • xalReadedfodeType..TRI %m1.XMl ...EndElemeD1: TRY xml.. Read ( ) Il' ERROR TREN RE'1URX TRY XIlll.

N_ .. END lF LOOP • PUBLIC SUB "0= Open () DIM XIIl1 AS XIIl1Reacier TRY Iml..Node.Hode.Type .Home & M/oonexione•• ~·) IF ERROR THEN Méssaqe.Node..XIIl1ReaderNodetype...Error(-Fello al abrir el fichero indiea&O-) END lF """"'" 00 li'HILE rRUE Ir XIIl1.p ENE> lF Ir IIal. EDdEl-.Type . &lReadertiodeType.lt '1'HEH .-conexiones.Blement TREN .ANO Xall.Open(User.

.. Read ( ) IV ERROR TREN Message... '01 ".. .10.l.. Rewltado del fichero XML • 7 XM1 ...1" ..11 ..CloseO --0.. "".. "'..Error(~&1 <Ioeument..o DO contiene datos de <XXlez!ones ~ ) %al. "'0:lO" Figuro 3..." Este código dará lugar.l...>7 .Error(MPormato XML no válido~) """"'" 2ND " IV XIal.Close ( ) 2ND " 2ND " TRY xm.-.. _ .Eof 'tHEH BREAK 11 LOOP 'l'Rl' X. a una visión en árbol de los datos conlenidos en el fichero XML. "'. al ejecutarse...0.RellenaArbol (XIa1) ELSE Message..

a HTML para enviarlos al cliente con una representación agradable.com. podtrnos encontrar futntes tspeeíficas de información adicional.3 XSLT o o O O O ¿Qué ES X5LT? Acompañando a XML. o cosas más complejas como generar un documento POF o StarWriter a partir de datos XML que nosotros hayamos diseñado. XSLT se basa en unos documentos. llamados plantillas. XSLT es extenso Jnra tratarlo aquí en profundidad aunque. Gracias a XSLT se puede separar de 111000 definitivo la información de su representación. en ti que sc enc:utntra un listildo de socios: 11 <socio> <n\mlllro>l12J</n_ro> ~1Itln L. que pueden recibir datos de una base remota en formato XML y convertirlos. Con XSLT se puede.Progromac:ión visual con Software übre ••••• 7. XSLT permite realizar conversiones de formatos de docu_ memos. Aguilar</ncd>re> . por ejemplo tn http://www. con formato XML. generalmente.w3schools. convenir datos de un documento XML en un documento HTML. O o o o O Una plantilla de Ejemplo Cada plantilla XSLT se refiere al contenido de un determinado documento XML Supongamos un documento XML como éste. por ejemplo. como siempre ocurre con los eslindares abitrtos y casi nunca con los formatos propietarios. que con· tienen las instrucciones necesarias para convertir un determinado documento XML (con las etiquetas y atributos propios de dicho documento) en otro con distinto formato. por lo cual se emplea extensivamente en aplicaciones web.

w3.orq/1999/XSL/Transform~> Tras esto. de documento XML. se escribe el código en sI. Parra</nombre> <tipo>Regular</tipo> </socio> </socios> Las plantillas XSLT siempre comienzan con unos identificadores. el segundo denota que 10 que viene a continuación es un documento XSLT. XMl .O~ xmln8. <Mml> <body> <hl>Listado de soeios</hl> <table <tP border-~l#> <th><b>Nro. Tierra</nombre> <tipo>Regular</tipo> </socio> <socio> <nu:mero>9654</numero> <nombre>A1berto N. en el cual generaremos una tabla HTM L con los :latos. El primero.O#> <xsl:stylesheet ver8ion-#1. ya lo conocemos. <?xml 11 version-~l.x81-~http:// www.</b></th> <th><b>Nombre</b></th> 7.<tipo>Sonorario</tipo> </socio> <socio> <numero>2135</numero> <nombre>salvador G.

Creamos un nuevo proyecto de consola llamado TransformaXSLT. Transformando El dOCUmEnto con Gambas Hasta aqul.xsl. con un único módulo modMain y una referencia al componente gb. y la plantilla corno sodos.ProgromaÓón vi~. empleamos el 11 iterador for eaeh para tomar cada elemento del fichero XML.xml. vamos embebiendo las etiquetas HTML. lo que tenemos es un documento XML y una plantilla XSLT.><> <td><xsl:value-of select_nnumecou/></td> <td><xal:value-of select_nnombreN!></td> <td><xsl:value-of select_utipou/></td> <ttr> </xsl:for-each> </table> </body> </hbn1> <h<sl: template> </xsl:stylesheet> Como podemos observar. y situamos en cada punto de la tabla uno de los campos elegidos. pero ahora necesitamos un motor que realice la conversión.xmJ. ~I COI Softw. Para ello guardaremos el fichero con datos en nuestra carpeta personal como socios.ore libre <th><b>Tipo</b></th> </tr> <xsl:for-each 8elect·~socios/socion> . Gambas modula file PUBLIC SUB Hain() OIM DocUlOOnto AS NEW XmlDocUlOOnt .xsit. El código será tan simple como éste: .

Rewllodo cito lo pógino ""¡"'Iidu. al cual pasamos como parámetros el documento y la plantilla.Open(User.Tran8fo~(Documento... 7... Estas las se refieren al uso de XML como sistema para comunicar dos procesos en dos ¡quinas diferentes.lUdo AS ~t ~to.DIM Plantilh AS KEM x.. es la hoja X5lI que dica cómo transformarla ~n HTML.Home " Resultado - XSLT.1. Escribimos dicha página en un fichero en nueslra carpeta personal. La única clase que aporta ~I componente gb... ..Open(User. Tloorn RoquIor MoIAIbertoN-:-Parn ~ Tipo ~no' Figuro l. .istado de socios 1. 'ofL ~n En este caso cargamos dos documentos: el primero. llamada XSLT. llamado )Ct1J11alto.xmLxslr. 11 ··.AgwIat 13l!iSO_O.. contiene los datos de los socios. XML·RPC es un subconjunto de XML que define un lengua:>ara llamar a procesos remotos.. y devuelve un documento nuevo con el formato indicado.Bome " '"/socios.. DIM ReIu.. la clase XmlDocummI carga y vrrifica un documento m~moria._ único método Transform.illa. en este caso una página wd>. y salimos. dispondrá también de un componente XML-RI'C.~slW) Plant. 4 Acerca de XML-RPC futura versión Gambas 2. d segundo. Plant.Dl1W) '"/aoeios. ver~­ mos un ~u1tado como d que ~ muestra en la figura de la izqukrda.illa) )ITl() indicamos anteriormente. es estática y dispone de un ~_ti . . Plantilla. Si consultarnos ("on el na'Tgador la página obtenida..·1I0~:J ..DocuaIeI:lt. ""'_!>no llJJuonl...

Igualmente podrá actuar en solitario. etc. por ejemplo. fecha. solicitando mediante una pttición web la Uamacla al servidor. Tambil!n se puede crear el documento XML de la pttición. y devolver un error al cliente.. con el fin de implementar CGIs que se sirvan desde Apache. el cual se encargará de verificar el número y tipo de los parámetros. en el cual definiremos los nombres de los métodos que se aceptarán. estructuras de datos. implementando un pequeño servicio web 11 para atender las pt'ticiones.).. cadenas. dcjan~ do a la aplicación e! diseño de! transporte y re«pción de los datos con e! servidor. En la parte cliente es posible definir la URL del servidor y la forma de Lada méuxlo. tan sólo hay que pasar la petición del cliente al ptlr- ser. O llamar a la función local y devolver el resultado al diente. O bien funcionar de modo controlado por la aplicación servidora. . y el servidor procrsa la llamada y devuen'( al dicnte un resultado. El componente XML-RPC aportará varias facilidades para implementar estos pro'~L En el lado servidor dispondrá de un parser. así como la correspondencia entre estos y otros locales dd programa servidor.Progromoción viwol con 5ohwore Libre Un servidor XML-RPC acepta llamadas remotas a sus métodos. El servidor podrá funcionar en solitario. que también Sttli una cadena. El proceso es muy similar a llamar a una función local dentro de un programa: el diente llama a la función pasando unos parámetros (números enteros. número. Dt este modo.

ele. que se ha creado a partir de los planos que nosotros hablamos escrito en la dase. La clase son 10$ planos de e$<I herramienta. Podemos dfi:ir que un objeto es una herramienta. I Lenguajes orientados a objetos y herencia Ya hemos visto una breve introducción al mundo de la programación orientada a objetO$. el sistema nos devuelve una herramienta.11 • • a. . un túnel de lavado. en este caso. los conductos de agua y dClttgnltc. los distintos sensores. por ejemplo. Cuando creamos un objeto. el proceso aulom:hico paso a paso desdC' la entrada del coche hasta su salida. en los cuales están d~r¡tos los distintos cepillos giratorios. un túnel de lavado dispuesto para funcionar. los secadores de aire caliente.

la funcionalidad de su 11 En resumen. pero esto es costoso en tiem_ po y dinero. t~rmino. ••••• S. 2 Conceptos necesarios 00000 La daSE padre Empecemos creando los planos de la máquina original. supongamos que romo vnulcdores de túneles de lavado d~amos mIlO· VJT y anadir una fast de encerado a nuC'Slro túnel. eliminando osi la necesidad de escribir las mISmos lineas de código una y airo <tez. una vez inlroducidos. Vendn-emos máquinas baratas sin encnado y ot~ más ca~ con esta funcionalidad añadWia. nos devuelve la media aritm~tica de todos ellos. los l:q'iIlos del túne! de lavado con cera tendrán que. la cual hertlla. por ejemplo. de ahl viene el clase padre.seria tomar los planos ya existentes y. a partir de ellos. más nuevas funcio_ nes que añadimos. que se comIlU8YOS partan en pritMra instonc:io coma la original y que oñoden Ivncionalidades a modifican algunas de las existenles. La primna opción ~ PO]')C(Y manos a La obra ron nuevos planos desde Cm).Progromoción viwcl COl'l Software übre Ahora bien. En esto consiste precisamente la herencia: partimos de una clase ya escrita. Vamos a escribir una clase a partir de la cual crearemos objelos. Además de añadir nuevas funcionalidades. probablemenle grande y con mucha funcionalidad. 'o'On'lOS a explicar cómo crear clases que prcMen&n de otras. creemos una clase plldre. . y a partir de ella creamos otra clase (otros planos) que tiene el mismo rendimienlo del original. añadir la nueva función. es decir. Dichos obje· lOS almacenan varios números reales y. podremos modificar tambi~n el como portamiento de las ya existentes para adaptarlas a la nueva nlflquina a crear.ser de un material que no se disuelva con los productos químicos que componen nuestra cera. lo mejor .

es el constructor que sirve para inicializar la natriz. L. y el cuarlO. .gO~Q [> 11 • '¡ji Mi lI • • (lhludioHeflnc¡" . HJE!l -.. lo llamamos EstudioHerencia . d»< lit. ibm·. donde añadimos cada uno de los números a calcular y :uatro métodos: el primero. el tercero.<\hora. lñade un nuevo valor a la serie. E!I .NEW Floatl] 8. I<>Ok 1 D"'GCl'.d<l te ti te I 'B!IlllIIl!III -6_· L ODa!.. ... libera la matriz al destruir el objeto. _New.dentro de él un módulo ]ruebas. llamada CIsCalcllIQ.adanes liJ O J. ~ ~ •. ~s class file PUBLIC _Numbers AS Float[ J PI1BLIC SUB _new() Numbers .J..~modMaO'1 -~~------- liJ 00 J. 6-. Hei-encio . Add. _Free... que nos servirá pam las creamos también una clase. vamos a crear un nuevo proyecto de consola.. calcula la media aritmética le los números almacenados: . E!ll!!! E!I 1M Figuro l. f"' trot'''! ~ . Proyedo nuevo de con~ Estv<lioHerencio. el segundo.. en la que escribiremos el :6digo principal a estudiar. Average. d~ inicio llamado modMaj/J.... <\d~lllás.. 11 una matriz pri- Dentro de ClsCalculo escribiremos el código necesario: tendr~mos lada de números reales. 6_a.~.

hemos de proveer un valor por defecto para ese caso o generar un error en tiempo de ejecución si procede. que la división por cero no está permitida.Programación visual con Software Libre PUBLIC SUB free() _Numbers.Count - O TREN RETURN O FOR EACH Vl IN Nm Numbers += Vl NEXT RETURN Nm / Numbers . Count END A la hora de realizar operaciones matemáticas. .Clear() Numbers=NULL END PUBLIC SUB Add(Vl AS Float) Numbers.Add(Vl) END PUBLIC FUNCTION Average () AS Float • DIM Nm AS Float DIM vl AS Float IF Numbers.

Average() END Al ejecutarlo. Ejemplo de motriz Numbers. . • las clases hijas de otra clase no pueden emplear las funciones. quedaría restringida al ámbito de la clase original y no podríamos usarla desde las clases hijas. Herencia .8) Calculo.. el programador vería esta variable desde el sistema de autocompletado de código. obtendremos el valor 14. Nos limitamos a crear un objeto a partir de nuestra clase.. 8. Observemos también que nuestra un matriz tiene un nombre algo curioso Numbers. propiedades o variables privadas de la clase padre. Calculo .Add(23.Add(7.5) PRINT Calculo. Ahora bien.5) Calculo. La matriz ha de ser pública porque más tarde la emplearemos en la clase hija: si fuera privada..11I' • PRINT • E O Average e Numbers Figura 2. introducir tres valores y mostrar en la consola la media de esos tres números: PUBLIC SUB Main() DIM Calculo AS NEW ClsCalculo Calculo.6 si todo fue bien. dentro de modMain.Add(l2. si hubiésemos llamado a la matriz simplemente Numbers.Ahora escribimos algo de código adicional para probar nuestra clase.

e o o o o La clase hIJa.r-----------' no se muestran nul1Cl en el sistema & autocomplelado ni en el sistema de Figura 3. ni en el d. de sólo lectura. J!fopiedodes o fuociones que cOmienzon con un . ~.. método. en lugar de la original . y variable.edades. pero tenga una propiedad adicional.terno d. oY\ldo de Gomoos • NOTA PARA PROGRAMADORES DE C++ En Gomba••"isten prop. Puesto que en Gambas no uiste el concepto de C++ y otros kngua~ lk propiedad. na se muestron ni en el si.. Probemos a modificar el código del método l\1ainO de modo que creemos un objt1o de la segun<la~. pOlI. manteniendo así una interfaz más coherente con nuestros propósilos. los nombres d. que nos devuelve el número de elementos que hemos almacenado. privados o público.o. los métodos públicos que comienzan por el signo de subrayado rC~. va' jable. Esto es todo lo necesario para tener una clase que hereda todas las propiedades de su clase padrt. oUlo<:omplelodo. cuando creamos componentes. ayuda. pero no protegido.Sin embargo.. variable o función ProTegida (accesiblt sólo desde la clase y SUS clases hijas). públiw> no . cnloncn. esta funcionalidad nos permite declarar variables públicas no visibles desde el código princi.. en la cual inlroducimnos nomb~ al inicio la palabra claVl' lNHERlTS seguida del de la clase padrr (vtT Figura 4).vblayodo. Palabra cIaw: NiERIT5 Supongamos ahora que deseamos tener una nueva clase que se comporte como la inicial.c. una n~ dast llamada ClsCa1culol.. Vuiiuble. Creamnos.C""lCoc.

. al inicio del cód. _.Add(12. . observaremos que el resultado 14.••...(JII~~ LOOO<.loo..6 es exactamente el mismo: la nueva clase ya dispone de todos los métodos..Add(23." -.Add(7. tecleamos INHERITS seguido del nombre de kJ clase padre..»...Ave~age() Si ejecutamos ahora el programa. " . .... n...¡..¡:. .. '!!"'..... ·'I. ..•• I ...¡. Herencio .-.... propiedades y eventos de la original....go de la nuevo clase' Gambas class file INHERITS ClsCalculo 8. _ . "'c:r !.I....-.-." ....: .:....' ......<!l·' "!:!I"..... ".... " .. "".. N.\. o .5) Calculo.. ..... .'" ...5) PRINT END calculo. tr_.. 1iI0 J _ ...~...>M.. sin necesidad de escribir el código que los implemente. . --..........8) Calculo... Para escribir uno ckJse que hereda las caroclerí5ticas de uno clase podre."..> Figuro 4.ecJ" .. PUBLIC SUB Maill () DrH Calculo AS NEW Clscalculo2 Calculo.. . 1iI0J'lil"~c. "" " ...eva dOl<! ClsColculo2." ._~i......"'"_'..¡ ..Ql(--~ ..'!' .... '''o .

Gambas class file INHERITS ClsCalculo PROPERTY READ Count AS Integer 11 PRIVAn: FUNCTIOH Count_Read() AS Integer RETURN SUPER. Escribamos ahora el código de la función MainO para aprovechar la nueva caraete· rística de nuestra clase hija: . la matriz ~umbers no se encuentra dentro de la clase C/sCaJculo2. Sabemos que cuando nos referimos a un objeto podemos utilizar. sino dentro de la clase padre ClsCakulo. no exi. bien el nombre del objeto. Con la palabra clave SUPER no nos referimos al objeto actual. o bien la palabra clave ME cuando nos referimos al objeto actual dentro de la propia clase. Pues bien. SUPER. o OO O O Extendiendo funcionalidades.ProgromoÓón "islIOl con Software libre NOTA PARA PROGRAMADORES DE C++ En Gambas cedo clase hija tiene uno 5010 clase podre. sino al padre del objeto actual. naL Añadamos entonces en la clase hija la nueva propiedad que nos devuelve el número de elementos almacenados: . Nurabers.t" el concepto de herencia múltiple.Ccnmt Estamos empleando una nueva palabra clave por primera vez. Palabra clave SUPER La nueva clase CIsCa/culQ tiene poco interés por ahora: hace 10 mismo que la origi. en este caso.

De esta forma. y es la posibilidad de reemplazar los metodos y propiedades originales por nuevas implementaciones que den lugar a resultados distintos: en este caso. Vamos ahora a explorar la verdadera potencia del concepto de Herenci(l. Gambas class file INHERITS ClsCalculo 8.Add(7. una de las cuales aporta una propiedad adicional CoI/lit. la clase ChÚllculo2 queda ahora como sigue: .8) Calculo. sin más.Add(12. mientras que en la segunda cada llamada a Average los limpia y comiel17A1 de cero.Media: 14.Add(23. el resultado de la ejecución es: Elementos: 3 . cuando el método Average sea llamado.Ave~age{) W & Calculo. y sigue siendo poco útil ya que po<!ríamos. evitándonos el mantenimiento de dos clases diferentes. la nueva clase. o O O O O Modificando funcionalidadES Hasta ahora tenemos dos clases.5) Calculo. haber añadido esa fun- 11 cionalidad a la clase original ClsClI/crlio. tendremos dos clases con diferente funcionalidad partiendo de llna base común: los ohjetos de la clase padre acumulan números sin fin.PUBLIC St18 Hain () DrM Calculo AS NEW ClsCalculo2 Calculo. HerenciCl .Count & H _ Media: H & Como es fácil adivinar.5) PRINT HElementos: Calculo.6. borrará lodos los elementos de la matriz para quedarse en hlanco.

Colcul02. Numbers Nm .Count . END PUBLIC FUNCTION Average() AS Float DIM Nm AS Float DIM Vl AS Float DIH Total AS Inteqer IF SUPER. AS Int. Vl 1 Total .Clear() RETURN Nm I Total Ahora existe un método Average dentro de C/sColcuI02..eqer RE'IVRN SOPeR.eqer PRIVATE FUNCTION Count_ReadO AS Int.o el método Average del padre.MJre libre PROPERTY READ Count..Count. Numbers.. NEXT SUPER.te método reemplaz...Programación visual con Soft. Numbers. Cuando llamemos 01 método Average de un objeto de la eloS<'! CI.o en lo elaS<'! hi. 5ino a la implementación de k1 elose hi¡o. y e..O TREN RE'IVRN O FOR EACH Vl IN SUPER._Numbers. el intérprete no 1I0moró a la función original del padre. .

Mo<!ificamos la función MainO de pruebas con este nuevo código para comprobar el resultado:

PUBLlC SUS Main ( )

DIM caleulo AS NEH ClsC8.leulo2

calculo.Add(12.5) caleulo.Add(2l.8) Caleulo.Add(7.5) PRrNT -Eleaentos: C8.lcuIO.AYerltgCl( ) Caleulo.Add(17.5) C8.lculo.Add(ll.8) caleulo.Covnt • - Media: •

~

~

~

PRINT

·Elemen~:

~

calculo.Covnt

~

- - Media: -

~

Calculo.Averaqe()

Como resultado, obtenemos en consola dos líneas que muestran el funcionamienlO

de la nueva clase:

Blementos: l - Media: 14.6 Elementos: 2 - Media: 24.65 Si en la primera Unea de MainO definimos ahora que el objeto Calculo pt'rtenece a

b clase JKldre OsCalculo, eliminarnos el uso de CoUllt, que no existe en el padre. y
yolvemos a ejecutar el program¡¡, ob5ttv;¡remos claramente la diferencia: 8.
~encio

Programación viwol con Software Libre
PUBLIC SUB MainO

DtM Calculo AS NEW Clscalculo

Calculo.Add(l2.5) Calculo.Add(23.8) Calculo.Add(7.5)

PRINT "Media:

u

& Calculo.Average()

Calculo.Add(l7.5) Calculo.Add(3l.8)

PRINT "Media:

u

&

Calculo .Average ()

11

En este caso, sc calcula primero la media de los tTes primeros números y luego la media de los cinco númrros:

Media: 14.6 Media: 18.62
Podrrnos aprovrcharnos más de la herencia, rmplrando la palabra SUPER que vimos antrrionnente. La clase original ClsCalclllo ya tenia el código necesario para calcular la media, yen la clase hija CIsCn/CII/o2 tan sólo necesitamos borrar los clrmentos de la matriz una vez calculada la media. Podrmos, entonces, modificar el código de la nueva función, Average, para que llame a la original y después borre los elementos, ahorrando, como siempre, tiempo y código:

, Gambas class file INHERITS Clscalculo

PROPUtit lU:AD COunt AS Illtege.r

END

PUBLIC I'11NC'1'ION AVBraqe() AS Ploat

DIM tia AS ploat

lb - SUl'Ul.Average()
SUPB:R. _ Nwllbenl. Clea.>: ( )

END


ESPEdaks: _NEw Y _FrEE
ne unos valores. Pongamos de ejemplo una toma de muestras de temperatura.

La nueva función Average ahora se limita a llamar a la original, implememada en la

clase padre, a almacenar ese valor, borrar los elementos de la matriz y devolver el valor.

REEmplazando metodos

Vamos a crear una nueva clase hija de ClsCDlcufo, que SC' comporte como la original, xro que, en este caso, en el momento de inicializa~ un objeto de la clase, almace-

Los objetos, al inicializarse, pueden tomar los valores de
temperaturas de la semana anterior de forma automática para que, despul!s, el programador introduzca los de la semana en curso y SC' obtenga la media de la quincena. Para ello creamos la clase C/sCalculoJ, con este código:

B. Herencio

Programación Yiwcl

ton

Software Libre

• Gambas el••• file INHERI'rS Clacalculo

SUPER.Add(12. 5) SUPER.Add.( 15. J) SUPER.Add.( 18. fo) SUPER.Add.(19.12) SUPER.Add(21.15) SUPER.Add (20. 4) SUPER.Add(19.5)
mm

11

Igualmente escribimos y ejecutamos el código de MainO para comprobar d resultado:

PUBLIC SUB MainO

DIM calculo AS MSW C15Ca1culoJ

calculo.Add(29.2) PRUft'
~Med.i.:

.. 6 calculo.Average()

El resultado dt la ejecución es:
Media: 19.&4625

Como era de esperar, por lo explicado anteriormente, se ha ejecutado el método _NewO de nuestra clase hija. Ahora bien, en este método tan sólo anadimos elementoS,

pero no inicializamos la matriz, por lo que de haberse comportado el intérprete como en 105 casos anteriores, habríamos obtenido un error en tiempo de ejecución, al tener en el inicio la matriz con valor Nuli.

Lo que ha ocurrido en realidad, es que al reemplazar el método especial_NewO, el

intérprete ejecuta siempre el método original de la clase padre y luego la nueva implementación del hijo.

El método especial _New(} no se reemplazo en los clases hijas como en el resto de métodos a propiedades, en su lugar se llamo siempre al método original_New{} del

padre poro que inicialice todo lo necesario y, después, si existe, se llamo 01 método _New(} de lo dose hiio. De este modo, el obieto siempre esló listo e inicializado cuondo se comienzo o trobo¡or con él.

Añadamos ahora un destructor _FreeO personalizado para nuestra clase heredera, en el cual indicamos el valor de la variable _Numbers:
, Gambas class file INHERITS Clscalculo

11

PUBLIC SUB _New()

SUPER.Add(12.5) SUPER.Add(15.3) SUPER.Add( 18.4) SUPER.Add(19.12) SUPER.Add(21.15) SUPER.Add (20.4) SUPER.Add( 19.5)

8. Herem;io

por ejemplo. Esto implica. po~ nei. puesto que: lslas están empleando ya la palabra clave lNHERlTS para indicar qut heredan [as propiedades de ClsCaJculo. sólo hay un nivel de huc:ncia y c:n nuestros ejemplos antcriOTCS no podriamos crear una ~ ClsCafculo4 que: provinier. recordemos que siempre podremol ejecutor . limitacionEs La principal limitación de: la herencia en Gambas. .4.ia: 19. para llamar luq. como en el caso dI' _N~. Numb6rl-NULL then print NNULO# END La ejecudón del programa da ahora como resultado lo que vemos a continuación: Med. es que: una clase: no puede ser hija de: otra que.l de 05Caku/02 o ClsCalcu1oJ. a su vez. era hija de una tercera. que no podemos crear clases que sean herederas de Form. ha llamado pri- mero aJ rnl!todo _Fru de: la clase hijn.o al mllodo _Fru de: la • Si n05 ha surgido olguno dudo respecto 01 orden de ejecución de algunos Juncia.l625 ""'" Con esto se demucstra que: d intttpr~c:.= if SUPER. d~ original.1 código o poso poro com- probarlo. En otras palabras. pues la clase fimn proviene de Window..

qr. tenemos que partir de uno que exista ya. rocles (Lobel. un ce» ¡.. y el mismo :ódigo sirve tanto si programamos con gb..nimo.oI creodo con INHERrrs CONTROL no li.. O iU vez. No M puede portir dj'ecIomente de lo doM base Coolrol. paro Q!rO. Si estanos acostumbrados a trabajar con otros entornos RAD de BASIC o C++. dos y eventos m. Juestro nuevo conlrol será una etiqueta a la que llamaremos ColorLAbt!l. . 3 Crear un nuevo control con Gambas ::J o o o o PlantEando el código Vamos a examinar la posibilidad de crear nuevos controles gráficos directamente desde Gambas. ni a bajo nivel con X-Windows. define lo. Jhorrándonos dos implementaciones para un mismo control con diferentes roo/kirs.5 dokir. fIléb. 11 :>ara crear un control con Gambas. &1ton.. dado que trabajaremos sobre los :ontro[es previamente aportados con Gambas y no sobre un loolkit para C o C++ :omo GTK+ O QT.. similar al abt!l. controle.oOCÍOllOlÓ. [.••••• 8. nos sen! ¡¡miliar partir de un control pltlfltil/n con unas propiedades y mflodos básicos para :rear uno nuevo. propiedodes. cuestión lue tendrá más o menos importancia según la función del nuevo control.grk. pero que muestra el texto con un gradiente de color. como si lo hacemos con gb. asi como nenor flexibilidad a la hora de moldear el conlrol.. sino que tl5 simplemente lo boMl q.una repte-senloción grólieo. J..as desventajas son una velocidad menor del código al ser interpretado. Crear controles nuevos programados en Gambas aporta dos ventajas funda· mentales: su desarrollo es rápido al trabajar en un lenguaje de alto nivel. yo que C"'*'" no 6e. aprovechando el concepto de herencia. 8_ Herencia . 1m cOl\lJoIes creados con Gombos han de partir de un conrrol yo Uiilenfe y crocble.

obe/. N~ proyecto gráfico 11 Cobrf. ImpJementadon basica Creamos un nuevo proyecto gráfico.al y final del gradiente. implementar el control. origit> 11 • 'li' ñ ¡ 1'1 • : ltCOloo1.. y añadiremos dos propiedades nuevas Colorl y Color2 que contienen d valor inki. Al igual que una ~iquela normal. privadas: hTexl para el texto.'_ . trazaremos cada letra por separado. Para manejar las tres propiedades. hColorl para el primer color y hColor2 para el segundo color. lambirn para nuestr. Dentro de él.a_ 'a_ . definiremos una propiedad Text con el texto amostrar. a escribir el código de la dase: . que llamaremos ColorLabt:l. Gambas clall file INHERITS Dr_ingArel PRIVA'1'8 h'lert AS String PIUVATZ bColorl AS Integer PRIV1d'Z bColor2 AS Integer PROPERrI Text AS string PROPEKI'T Colorl AS Inteqer PROPERrJ' Color2 AS Inteqer .Para dibujar texto en diferentes colores. desde un color inicial Colorl hasta un color final ColorZ. ~e_ naremos un formulario FMoio. pues. para nuestras pruebas. ·-eo.. Con el fin de trazar cada letra por separado. asl como una clase llamada ColorlAbt:l para ll~~ I !'. utilizando un algoritmo algo rudimentario: tomamos la diferencia de valor de los dos colores y vamos aumentando el valor del color actual por cada nueva letra que dibujamos. tendremos tres variab1e~ figura 6. Empezamos.u pruebas. . tendremos que usar la dase Dmw sobre un control base que será DmwingArclJ.

basta con devolver los valores de nuestras variables privadas (recordemos que estamos escribiendo el código siempre dentro de la clase ColorlAbd): RE1URN bColor1 PRIVAn: ftlNCTION Color2_Read() AS Integer RETURN hColor2 END • RE1URN hTezt En cuanto a las funciones de escritura. y hemos de actualizar el conlrol cada vez que una de ellas cambia.Implementar las funciones de lectura de las tres propiedades es trivial.VI Redraw() . aún por definir: hTest . hemos de asignar d valor que d usuario pasa a nuestras propiedades. tarea que realizaremos en una funciÓn llamada RedrawO.

Programación visual COl'l Sohwore Ubre PRIVATE SUB Colorl_Write(Vl AS Integer) hColorl .ual recorreremos cará<:ter por carácter la cadena almacenada en la variable hText e iremos representando letra por El letra usando los distintos colores del gradiente.Clear hColor • hColorl IF Len(hTaxt) TREN bOiff Len(hText) (hColor2 .VI Redraw() END PRIVATE SUB Color2_Write(Vl AS Integer) hColor2 . nos servimos del método Font.hColorl) I Draw.Begin(ME) . para 10 ¡. Para calcular la posición en el eje X de cada letra.WidthO que determina el ancho de cada letra con la fuente actual del control: PRIVATE SUB Redraw() PIM xPos AS Integer DIM B\lcle AS Integer DIM hCOlor AS Ioteger DIM bOiff AS Integer ME.VI Re<h'aw( ) END Llega el punto de implementar RedrawO.

End() Finalmente. Herencio .bColoc orav. nos interesa que el control se encargue por sr mismo del redibujado de la ventana. Nuestro formulario FMailf tendri unas dimensiolK$de 225x240 pIxtles y contendr. situándolo en el formulario con un texto de ejem- . que se encarga de mantener un buffer y redibujar las parles expuestas al usuario del control: • SUPER. Bucle.POR Bucle .ltPos . • • • • • • el texto Prueba. Para evitarlo.¡ebo d>re el formulorio fMoin.. ltPos. SUPER. bOiff ><En Dcaw..1 Te Len(b~st) Dcaw. plo y dos colores definidos para e1gradiente: 8. todo lo dibujado sobre un DrawillgArell desaparece si la ven· tana se oculta tras otra ventana o se minimiu.IE Probemos ahora el control.. Bucl. O) ltPos .caebed ."ooLNiclth(Mid(bTert. 1» bColoc • bColoc .i un botón Uamado BlllPmeba con ·. El código del formulario consiste en crear un control Colorlabel en tiempo de ejecución. 1)..ftl.. Textodepn. utilizaremos la propiedad Cached de DmwillgArell.For8Coloc ... f'9uro 7.'l'est(Micl(bTest. Por defecto.

Se puede solucionar convirtiendo la cadena a una codificación que emplee siempre un byte por letra (por ejemplo.Colorl .DarkBlue bLabel. rompiendo el algoritmo que recoge el texto lelra por letra.ProgramOClón visual con Software libre PUBLIC SUB BtnPrueba_Click() DIM hLabel AS colorLabel hLabel .NEW ColorLabel(ME) hLabel.Move(O. este control tendrá problemas con caracteres con código ASCI] mayor al 127. También podríamos incluir una propiedad para alinear el texto a derecha.abelen funciO/lClmiento.Blua hLabel.Font. Conlroj CoIorl.Width. si bien se puede depurar ba51anle 11 el código del control. [ - Figura 8.Text . Por ejemplo.:to. podremos ver ya nuestro control en funcionamiento. Esle nuevo control "" puede reulilizar en todos los programas qve diwñemos aiiodiendc la do~ Colorlobel al praye<. izquierda o centro. 100) hLabel.Color. 0. tareas todas ellas que dejamos si estamos interesados en practicar. asf como mejorar el algoritmo para obtener el gradiente. ya que en la codificación de Gambas (UTF-8) ocupan más de un byte.18 hLabel.Color.Color2 . .NHola desde el ColorLabel~ Al ejecular el programa y pulsar el botón. separando los componentes RGB de cada color. Ha sido una tarea rápida y sencilla. 150-8859-1) Y reconvertirlo a UTF-S a la hora de representarlo.Size . HE.

1$ daMK que no Iieoen por "'" e$Iof JWlocioo""._.... GTlC.o OJO.... 1t .c~ O gil .. _ _ _« 0 .... tenemos tambitn la posibilidad de crear nuevos COmponentes. 4 Nuevos componentes con Gambas Cuando abrimos bs prop~de un proyteto y pulsamos la pestafQ Componentes. ." I Figura 9....8.OES crypb"Ig Compo<H!rd O...... tOCll<il co....:cn.._ 8 gII. grófico.....*......db gII-cM0u9 MOS.p..$ can lo inIwfoz grófico.. observamos los módulos adicionales qu~ podemos emplear en un programa escrito con Gambas... $GtMt'" aPropen>es ii~"'iU prO~CI ti show lIfIIy Compo<H!nu U$... Si bien ~ o er_ oqui un r--..coypt O gII..p O somec_ _ _ _ Ü" GMT"oNs """"".p-.. los C:Qllopoillit\le$ ie ~miton a opciItoI ... libt....gb ... aunque en el próximo ejemplo será un componellle que aporta un control adicional: el CO/orLabel que creamos en el aparla_ do anterior.d in o gIIc.0.c".lIGMnba$ .. ~ r.pru_ •• Gr...opoi .n CofT'pn... Estos pueden ser de cualquier i"dole... O ..... 0 . los cuales aportan nuevas funcionalidades.. . Desde Gambas. Compooenle$ del proyeclo.....

Todos los componentes de Gambas han de estar situados en una carpeta que. será hml/iblgambas2. salvo que hayamos compilado Gambas desde los fuentes empleando una opción . Por tanto. Gambas class file EXroRT INHERITS DrawingArea PRIVATE hText AS String Ahora es necesario compilar el programa para tener un ejecutable con la nueva clase exportada.-prefu: específica. Preparar un programa Gambas para ser un componente. en nuestro programa ColorLabel indicamos esta palabra clave al inicio de la clase ColorLabel: . o O OO O Archivos necesarios. Palabra clave EXPORT Dentro de un programa Gambas. ubicaciones Cada componente Gambas necesita.x. del programa en sí. . tendremos diversos módulos. se usa la palabra clave EXPORT al principio de la misma antes del resto del código. A partir de ahora. Para indicar que una clase será visible desde el programa principal. Es necesaria también una ubicación específica para dicho archivo. Implementar un control en Gambas supone ran sólo crear un programa que expor" tará algunas de sus clases. clases y formularios. en primer lugar.Programación "i~ual con Software übre oO O O O PrEparación del código.comroles. que tendrá siempre como nombre gb. donde x será un nombre que nosotros elijamos. simplemente implica definir qué clases serán visibles y cuáles no. por tanto.gambll5.gambas. vamos a llamar a nuestro nuevo componente controles y. el nombre del componente dentro del sistema de archivos será gb.

gambas lusr/lib/gambas2/gb.." dicho fichero incluye varios parámetros que se exponen a continuación: 11 (Component] Key-gb.Si hemos compilodo Gombos usando uno opción· -prefix distinto de lusr en el Kript configure (par eiemplo.controles.'blgombos2 en este cosa.com- lQl1em. podemos hacerlo con Konqueror o Nautilus): cp ColorLabel. Herencio . pero sin J:¡ extensión glllll/¡(lS).gambas los componentes en Gambas necesitan también dc un archivo con extensión . entraremos en la carpeta del proyecto y copiaremos el ejecutable con el nuevo nombre (por supuesto. Vamos a crear este archivo a mano con cualquier editor. el fichero gb.a c1avt" [Component] siempre debe estar al inicio de-! archivo. para lo cual. En el valor ¡Ut" Kcy hay Situar el nombre dd componente sin extensión (en este caso..com- ponent para ser reconocidos como tales. O:Jpiaremos nuestro ejecutable a dicha carpeta.gambas que hemos copiado. pero puede ser cualquiera (recordemos que debemos ser root): gedit lusr/lib/gambas2/gb. tendremos que buKor los rulos in<lkooos" partir de lo que seleccionomOI. En la clave Name 8.controles.qt . Nosotros vamos a usar gedil.controles Name·Additional controls Author-Daniel campos Group-Adicionales Controls"ColorLabel Require-gb. desde la consola y como mor. oomo lusrllocolll./usr/loco~. si lo preferimos.camponent El contt"nido dI.

que proporcionan informaciÓn adicional para el intérprete de Gambas. Dentro de Proyecto I Propiedades.list oO O O O Probando El nuevo componente ~ $MiPrueba Tras estos pasos cerraremos elIDE de Gambas si estaba abieno y 10 ejecutaremos de nuevo. que se referirá a cada uno de los con- troles que queremos que aparezcan en dicha pestana.grk. Si deseamos verlos. Dichos archivos han de copiarse a su ubicación definitiva con el nombre del componente (en este caso.list /usr/share/gambas2/info/gb. Lo mismo se aplica para Controls.se indica el nombre del componente que aparecerá luego como descripción a la hora de elegir los componentes de un proyecto. Formulario FMoin sobre el proyecto MiPrveba.wmpouetlt. hemos de usar 15 -{l desde la consola o bien activar la opción de ver archivos ocultos desde Konqueror o Nautilus. en este caso. por tanto.4odule~ ClDala ~Clda"e~ . En Author situamos el nombre del autor del componente. dos archivos llamados . tenemos finalmente que copiar dos archivos dentro de /lIsr/sharelgambas2/illfo.qt.controles.info. tendría que ser é&ala dependencia indicada.info y gb. seleccionaremos la pestaña de Componentes. Requirc se utiliza si nuestro componente depende de otros. Si hubiéramos compilado el proyecto para gb.list): cp ..controles. creando un proyecto gráfico llamado MiPrueba en el que añadiremos un formulario.info /usr/share/gambas2/info/gb.oontroles. recordemos que los archivos que comienzan por un punto son ocultos. Después vienen una serie de claves opcionales: Group sólo se usa si queremos afladir controles gráficos y supone la pestaña de controles donde queremos que se 31'i3da el nuevo. Figuro 10. gb.list e . -l'iCl r. Una vez creado y guardldo el archivo gb. 11 Dentro de nuestra carpeta del proyecto se han creado también tras comp~ar.wlltrole5. .info cp . de gb. .oontroles.

.. . como depe"dencia. ~ ~H "'prIK'''''' .controles A"tllors: o~ C..()(S CJ'YlllnO c. gb.. por lo que aparecen sin un dibujo representativo (Figura 13). "'- --..r.._ ...:1 -.. ~ ~._ O . OM_"'CIK'C~ GMntIa ~. tool:ll compoo .. • 1:: O L: j \ A .- gb_9'k s.be .. en la Wnlana de selección de controles aparece una nueva pestaña Adicionales..--- "O Sl.._ 111 Figura 11. tal y como habíamos indicado en ti arc:hi\'U compolll!llt (Figura 12). Se!IOO6o.cIebuII O gb. Desgraciadamente..-corc..W"fro/es y pulsaremos Aceptar para tenerlo como dependencia....... lulI$4d .Kion 1tebu99.e~'" O lC)5.~ O gb..Buscaremos y marcaremos el componente gb. GrllP'llC" GTK."po.mpo...' -lIiI ~ • « Ahora. del compool8llle gb..... en este momento no se contempla la posibilidad de que esos controles tengan un icono propio.- -.~ • [8] - ~o Al situarnos en esta nueva pestaña....-lIÑ\" c .. = ~-= ".. aparecen 0 de los controles disponibles.. Herencio _ _o Figuro 12.. fl"IIIKl 0 .. .. 0 . 'J U! ...conJroIe.. Contro'" CoIorl. Pestaña Adicionales lo ventona de selección.

control Colorl..uHola desde el componente" ColorLabell.Font. Ya disponemos de un nuevo componente reutilizable en muchos proyectos y que se puede distribuir entre distintos equipos siguiendo los pasos indicados.Colorl • Color.Color2 Color. • ----------------------_.obell.16 ColorLabell. lo arrastraremos al formulario y lo situaremos como deseemos.Black Al ejecutarlo. Figura 13. Como hacemos con el resto de controles.ProgromoÓón visual con Software libre No obstante. Ccolroles Adicionales.Blue ColorLabell. al situarnos sobre fl con el ratón. en el código del formulario indicamos el texto y los colores de la eti- ColorLabell. observamos el resultado. se muestra el botón y el ToolTip indicándonos el nuevo control.Text . Finalmente. o • 11 queta: Figura 14.Size . .

~-------- - . Hola desde el componente Un componente e:.lo como componente.crito en GomOOl es ton ~ un programo que expOflo c1o$es. pruebos cOmO en CUOlquuH otro p<l> ye<:to para. por tonlO. Herencia . se puede depuror fócilmenle hOClendo lo. despOO" distribuí. 11 8.

Un sistema GNU/Linux puede contar con librerías distintas de otro. las librerías de x~ Window y otras como glib. etc. sino campos de utilidades que se añaden al sistema. sirve de introducción para el asunlo que vamos a tratar. AJ margen . en este caso no sea correcto. glibc) no son propiamente la AP[ de este sistema operativo. en los cuales es muy frecuente realizar llamadas a funciones externas. Pero. alojadas en librerías también externas escri- tas en lenguaje C. Tal vez. pero en la prác- tica siempre vamos a encontrar como mínimo la librería de e (glibc).--• o En realidad. el título Acceso 1I la APl está lomado de los programadores de Visual Basic T "'. posiblemente una librería para diseño de interfaces de texto (lIwrses) y. atk. gtk+. si hay un sistema gráfico instalado. dado que Linux es tan s610 un núcleo yel resto de librerías (incluyendo la estándar de e. de todas formas.

Tratar. Por tanto. recurrir a la gestión de procesos cuando sea posible. para corrección ortográfica. No es posible. además. para acceso a diversos protocolos de red. acceder a funciones de librerías escritas en C++. del mismo modo que las variables globales. en este momento. puede no ser una buena idea en todos los casos. declarando funciones externas e indicando la librería en la que se deben buscar. • •• •• 9. . todo sistema suele tener instaladas librerías como lixurl. de emplear llamadas a funciones con el fin de incrementar la velocidad del programa. que será el nativo de la función en la librería. hay que matizar que en Linux muchas tareas se pueden resolver simplemente llamando a procesos externos. El programa aporta. seguida por su nombre. escritas con FreePascal). limitado a la clase donde se aloja o a todo el progra- ma. requiere un trabajo de conversión de tipos. o bien escritas en otros lenguajes si respetan dicho estándar (por ejemplo. en lugar de a este sistema. 11 Hay que tener en cuenta que la llamada a funciones externas. Por defecto son privadas. ciertos elementos para la gestión de memoria y punteros. una buena idea. pues. y menos problemática en la depuración de los programas. por lo general. Desde Gambas podemos sacar provecho de las funciones aportadas por estas librerías. tanto desde Gambas como desde otros lenguajes interpretados (Mono. A continuación. al menos de forma directa. la palabra clave EXTERN indica que vamos a declarar una función externa. lo cual consume un tiempo de procesador. que sigan el estándar definido (ABl).Programación visual con Software libre de éstas. Al principio se declarará la función como PUBLlC o PRI· VATE. por ejemplo). es. para definir su ámbito. I Declarar una función externa La declaración se debe realizar al principio de una clase o módulo. Si bien en sistemas Windows"'" es muy habitual recurrir a este modo de trabajo. labor más sencilla. o libaspell. en general. entre otras tareas. Las Iibrerlas accesibles serán aquellas escritas en lenguaje C.

que define rn este lenguaje como: int strcmp(oonst char *51. por ejemplo.0. podemos deducir el nombre de la librería.0:0.so. dentro de las carpetas /Iib o /usr/lib encontraremos la mayoría de las librerías que hay en nuestro sistema.4 2. tratar de declarar Primf en lugar de printf para la librería glibc. o nombre alternativo. que se emplea. e si distingue entre mayúsculas y minúsculas y. Opcionalmente. En ese caso. puede interesarnos una versión concreta de una librería. En sistemas GNUfUnux. el número de versión. La declaración en Gambas será: EXTERN strcmp(sl AS STRING. y después el tipo de dato devuelto. A veces. Supongamos la función strcrop de la librería estándar de $e e. en ciertas funciones cuyo nombre coincide con palabras clave del lenguaje Gambas. dará como Como en el resto de funciones de Gambas. se indicarán los parámetros que reciben entre paréntesis. como libe o libgstreamer. se puede indicar al final la librería en que se encuentra la función.600. Acceso a la AP¡ . por ejemplo: Ulibglib_ /usr/l!b/l!bgl!b-2. a continuación. const char *52).7667 o Ijbc:6. rá. en cuyo caso se renejará indicando el símbolo: tras el nombre y.0. por tanto. En principio. así como un alias.0.Hay que tener en cuenta que resultado un error. A partir de esos nombres de archivo. por ejemplo libgl: J.4 N 9. Gambas tratará de encontrar la versión más moderna instalada en el sistema. se presenta entre comillas el nombre de la librería. se puede indicar un nombre simple. para llamar a la función. s2 AS 5TRING) AS INTEGER IN ulibc:6 ff 11 o o o o o Cómo denominar la librería Tras la palabra clave IN. a utilizar desde este programa. sin embargo.600.

50. Pointer EXTERN qetchar() AS Inteqer IN Mx AS Inteqer) AS Mx AS Inteqer) AS ~libc:6P Aquí. El problema para dedararla en Gambas es que ya existe Free como palabra clave reservada. por ejemplo. las dos primeras funciones pertenecen a libglib. y la tercera a libc. el número de versión es siempre la serie de números que se encuentra tras eltexlO . hay que aplicar esta característica sólo en casos imprescindibles. LIBRARY ~libglib-2. no es necesario especificarla en todas las declaraciones. tendremos que indicar un nombre alternativo: EXTERN FreePointer(ptr AS Pointer) IN Plibc:6~ EXEC .POl. Especificar un número de versión puede ser problemático (uando se trala de instalar un programa entre diferentes equipos con distintas distribuciones GNU/Linux instaladas. con malloc(). Por tanto.rlm~ Como podemos observar. oO O O O El uso dE los alias Supongamos la función [rec() de la librería estándar de e. que pueden tener versiones ligera- mente diferentes de estas librerias o cambiar tras una actualización del sistema. Inteqer EXTERN q_uU8_strup(Buf AS Strinq. o tal vez emplear el número mayor y dejar el menor y la revisión a elección de Gambas. Si en un módulo o clase se han de definir varias funciones de una misma librería.0 Iras eltexlO libglibes parte del nombre y no de la versión. en el nombre de archivo.0~ 111 EXTERN q_utf8_strlen(p AS Strinq. que se emplea para libe- rar memoria asignada. y que todo 10 que viene antes forma parte del nombre de la librl. el valor 2. basta con indicarla como librería por defecto con la palabra dave LIBRARY y Gambas la empleará en todas las declaraciones en las cuales no se especifique la librería. En este caso. por tanto."ría.

long '0_ '".". CORRESPONDENCIA DE DATOS ENTRE C y GAMBAS e ehor Gamba. pero no está permitido usar tipos Variallt. •• 9. e long long Gamba. By. sino el Sillglt. En GambasGNU/Linux-J2 bits es exactamente igual a Illftger. El tipo de datos String sólo debe emplearse si la cadena a pasar como parámetro no va a ser modificada o reasignada por la función de e. 2 Funciones auxiliares Gambas aporta algunas utilidades para trabajar con llamadas a funciones. en otro caso debe utilizarse un dato tipo Poinler. 10"9 Single """. F~PointeT. llamaremos siempre a la función que internamente Jlamari a la original free de la librería de C.Alloe Integer J ) 9 Acc~ o lo API_-'- _ . un tipo Iougde C. por lo cual es recomendable utilizar siempre el tipo de dato Pvimer en lugar de lllfeger para referirse a punteros. no es un tipo Lollgde Gambas.A la hora de escribir código Gambas. TIpos de datos Existe una correspondencia entre los tipos de datos básicos de Gambas y los de C. sino un tipo Inlega. pero en otras arquite'Cturas podría cambiar. Hay que tener cuidado con losfaiscs amigos. Tamaño AS Integer 1 . 'bo. 110o' JJoobl. inl. El tipo Poinltr de Gambas se emplea para definir un puntero. Cantidad AS Puntero . Por último indicar que es posible pasar datos tipo Obj«t. y un tipo jloot de e no es el Floot de Gambas. las siguientes correspondencias son aplicables a Gambas sobre GNU/Linux J2 bitsllntd.

si así lo requíere el programo. pero manteniendo la cuenta de asignaciones y liberaciones de memoria.ng. devuelve un puntero a la nueva área de memoria reasignada. lo coherencio del código y Fvncionolidod de lo librería. y cambia su tamaño. y. Cantidad AS Integer ) Realloc toma un puntero. además. esta función nos permite obtener una copia como tipo de dato Str. En este caso. manteniendo los datos almacenados. Nueyo Puntero .Programación visual con Software libre La función Al10c es similar a la homónima de C: reserva un bloque de Tammlo'Cmuidlld bytes. indicando. si quedó memoria sin liberar. un con- tador de las asignaciones y liberaciones de memoria realizadas.Strptr ( puntero AS Pointer ) Cuando una cadena ha de tratarse como un puntero. se pueden utilizar las instrucciones . mantiene la cuenta de asignaciones/liberaciones de memoria. Free ( Puntero • Free libera un puntero asignado con Al/oc o Realloc. previamente asignado con Al/oc o Realloe. Gambas permite escribir y leer en memoria como si fuese otro flujo cualquiera. Tamaño AS Integer . Muchos librerías aporlon sus funciones propios poro asignar o liberar memoria. Puede ser nocesorio que empleemos estos funciones en lugor de Al/oc o Free. al igual que Al/oc. de igual modo que la función homónima de C. utilizando un puntero como parámetro. poro monlene.RealIoc ( Antiguo puntero AS Pointer . siempre y cuando puntero apunte a una cadena terminada en carácter \0 (nulo). el intérprete de Gambas lleva. Así. Cadena . que es lo habitual cuando se trahaja con C. con un mensaje de advertencia al final del programa.

irxli- car si son válidas O no según el diccionario empleado. asi como el diccionario de nuestro idioma. Está previsto que la versión 2 de Gambas añada el componente gb. Acces. Entrr otras posibilidades ofrecidas por esta solución. en un sistema gnuLinex 2()()4 en castellano (basado en Debian).5OUf'(efoo-ge.habituales rn archivos: READ. los paquetes instalados en el sistema son: Qspdl QspeIl-bill libtlspell-dev I15pe/l-es Iibaspe/ll5 9. Por ejemplo. y ofrecer palabras alternativas a las consideradas incorrectas. 3 Un ejemplo con Iibaspell ~11 proporciona UTliI API para corm:ción de texto. DIsponemos de mós inFormación sobre lioospell en su pagino oficiol: • http://aspell.net/ Para poder utilizar este código. tendrrmos que instalar Mpell en el sistema. ele. t5te es el modo actual en el que tl programador puede accwer a los dalos de una estructura de C. \VRITE. que aumentarán y simplificarán las capacidades de Gambas para manejar librerías externas. Este compollellte 5C está desarrollando para dar soportr directo al trabajo con estructuras de datos y a retrollamadas. ••••• 9.api.o o lo APl . permite analiur palabras. entre otras capacidades.

V3 AS Inteqer) AS Pointer EXTERN aspell_word_list_elements(Vl AS Pointer) AS Pointer EXTERN aspell_string_enumeration_next(ptr AS Pointer) AS Pointer EXTERN delete_aspell_string_enumeration(ptr AS Pointer) EXTERN delete_aspell_config(Cfg AS Pointer) Al pulsar el botón BtnCheck. VJ AS Integer) AS Integer EXTERN aspell_spelle. para ir mostrando el resultado en la lista. V2 AS String. I~'I~ F-- . EXTERN EXTERN new_aspell~confi9() AS Pointer AS Palnter. Figura l. . con un único formulario FMain en el (ual se conten- cirá un botón llamado BlnChcck. Value AS String) EXTERN new_sspell_speller(Cfg AS Painter) AS Painter • EXTERN aspell_error_number(Err AS Palnter) AS Integer EXTERN aspell_error_message(Err AS Painter) AS Paloter EXTERN tO_8spell_speller(Err AS Palnter) AS Palnter EltTERN aspell_speller_check{Vl AS Painter. un TextBox llamado Txtln._suggest(Vl AS Pointer. un ListBox llamado Usta y un ProgressBar llamado Pbar. Var AS aspell~confi9_replace(Cf9 String. Formulario del LISRAAY "libaspell" proyecto AspeII.Programoción visual con Software Libre --- ~---- Crearemos un nuevo proyecto gráfi<:o llamado Aspell. realizaremos el proceso de análisis deltexlO introducido en el cuadro Txtln. V2 AS String._- Al inicio del código del formulario definirnos las funciones de libaspell.

.D~ spell_oonfig AS Pointer DIH possible_err AS Pointer DIH spell_checker AS Pointer DIH suggestions AS Pointer DIH elemeots AS Pointer DIH HyStr AS Strinqll DIH Bucle AS Integer D~ BufErr AS String DIM SUllI AS P'loat DIM hP'tr AS Pointer DIM sptr AS String En primer lugar.Count Realizamos las primeras llamadas a la libreria libaspel/.Value .1 I MyStr. separadas por espacios.Clear( ) MyStr . Para ello tomamos una configuración por defe<lo y aplicamos dos atributos: el texlO eslará codificado como lITf-S y se usar.new_aspell_config() aspell_ooofig_replace(spell_config. Sum . de exislir un error (por ejemplo. Aplicamos la configuración y.Split(TxtIn. Application.8nvl~LANG~J) ~lang~. 11 ~ ~) PBar. 9 Acceso o lo AA .to inlroducido por el usuario en palabras.i el diccionario que corre5ponda con el lenguaje del sistema.O Lista.Text. dividimos el te. que el diccionario no se encuentre disponible). indicamos el mensaje correspondiente: lpell_config .

PBar.aspel1_speller_suggest (spell~checker. palabra por palabra.to_aspell_speller(possible_err) END " Después entramos en un bucle en el cual se analiza. pero si está todo correcto. eltex\o • introduddo. MyStr[Bucle].Error(StrPtr(aspell_error_message (possible_err))) """"'" ." spell_checker . En caso de error.Value . se dará una lista de sugerendas.. .1) e1ements • aspe1l_word_list_elements (suggestions) .. se indicará con un OK.Value + Sum MyStr[Bucle] .1) TREN 1ista.Count _ 1 PBar. .Trim(MyStr[Buclel) IF Len(MyStr[Bucle]) > O TREN IF aspell_speller_check(spell_checker. FOR Suele ." ( " suggestions .Add("OK ELS' -> " & MyStr[Bucle]) 8ufErr . MyStr[Buclej.O Te MyStr.Progromoción "i~uol con Software libre aspell_config_replace(spell_config t "utf-8~) ~encodiDg"t IF aspell_error_number(possible_err) <> O TREN Message.

riDg_ernaeratiOD_De<tt(el_tS) l:P bptr .BufErr & lista. 4 Obtener información acerca de la librería Normalmente.aspell_st. sptr BufErr . ya 9 Ac.Value _ 1 ••••• 9.te$O o la AA .r .001 Finalmente liberamos los elementos necesarios empleados en la corrección de texto.DO MBl:LE TRlJE hPt.BufErr " ' " lF ~ sptr ~ • • LOOP BufErr . delete_aspell_config(spell_conf!gl PBar. A la hora de trabajar con ellas debemos conocer sus valores.O TREN BREAK ELS' sptr lNPOT 'bPtr. las librerias aportan multitud de constantes y macros definidas en sus ficheros de cabecera.Add(~ERROR ~)~ ~ _> & MyStr(Bucle) & BufErr) " ' " lF " ' " lF 11 MAZT 0.

orgldoc/APIf2.h.) { GtkHindow *viD. CompilaTun pequt"ño programa en e que muest~ d ViJ. 4. Buscar en los ficheros de cabecera de la tibreria. hlml#GtkWindowType. . Consultar la documentación de la propia librala. es bastante completa. podemos recurrir al menos a (llano métodos: 1. que se suelen depositar a partir de la ruta !lm/incillde. 2. 3. que utiliza la constante GTILWINDOW_TOPLEVEL: linclwde <qtk/gtk. Indicar que GTICWINDOW_TOPLEVEL tiene el valor Ocomo parle de la enumeración GtkWindowT~. que en este caso (GTK+). La podemos encontrar en la siguiente dirección: hnp:/ldeveloper.in(void. este valor ~ encuentra en el fichero /usrlirrdlldelgrk-2.lor problemitico que no alcanzamos a averiguar por otros sistemas.0fgtklglk-Standard-Enumefations.h> int lIlll. win-gU_wiDdow_Dew(GnC_W'IKDON_TOPLEVEL) ¡ gtk_wldget__how_all(wln)¡ ) 11 Con el fin de conocer el valor de esta constante.gnome. o cualquier otra aportada por una lib~ria. Veamos este ejemplo.0/gtk/gtkerrums. En el caso que tratamos en el ejemplo.que: no se puede recurrir directamente: a los #indude de C.

gtk_wiDdow_new(QrX_trINDOW_TOPLEVEL) gtk_widget_sbow(lfin) .k.'inelude <gtk/gt.b> void maio(void) ( ) Podemos ya pasar el pequeño programa a Gambas. Argc AS Pointer) ) EXTERN gtk_window_new(WType AS Pointer) AS Poioter eXTERN gtk_widget_show(wid AS Poioter) PUBLIC SUll MlIlnO DIM Win AS Polnt:.b> Unclude <stdio.er win . Para ello. Gambas module file EXTERN EXTERN ~k_ioit(Argv ~k_maio ( AS Poioter. creamos un programa de wnsola con un solo módulo mOiiMllill que conlenga este código: .

. y su capacidad de: gestión de procesos uternos lo hace apropiado para casi cualquier tarea.) y limita la portabilidad del código (por ejemplo. Las propias instrucciones del programa permiten reservar y liberar memoria. en la versión \\'indows de Gambas). de un sistema GNU/Linux. Libre Si lo ejecutamos podemos observar que el resultado es equivalente al del programa en C. La única condición es que sigan el ABI estándar. a travb de gb. cambio de ven.Progromac:i6n viwal CQIl Softwau. Gambas aporla componentes para lareas variadas que cubren buena parle: de las neusidades que se encuentran en los programas habituales. Pero no se recomienda e:1 uso de esta funcionalidad.. sensible a los cambios en el sistema (actualizaciones de librerlas. Trabajar con llamadas a funciones externas puede hacer ti programa más dificil de depurar. a una plataforma freeBSO o. Gambas autoriza el acceso a funciones de librerras externas. salvo que esté plenamente justificado. en el futuro.ión de la distribución . 5 Resumen En este momento. la gestión de estructuras y retrollamadas será posible. donde se desarrolla. En el futuro. ••••• 9.llpi (no detallado aqul. • . pues se encuentra en pleno desarrollo y su interhz puede cambiar).

• Debion es uno mOfCO registrodo de Software in the Public Intefesl. K Desltop Enviranment. • Java y todo. • KDE. uno morco registroclo de Mondralesoft SA y """ondrolesoft CorporOlíon.trodos en Estados Unidos u otros poises: • linu~ el 1. registrados de Apple Compute. productos y nombres de servicios pueden ser mOrCaS registrados O _vicios de otros c:ompoñios. Windows y Visual Bosle son morcas registradas de Micros.oh Corporo~an. • UNIX es uno morco registrado de The Open Groop. • Microsoft. Corpa. empresas.. • SUSE es uno morco regiltrodo de SuSE AG. OIro. Apéndice . Inc. 101 nomb<es y lagos basodos en Java 100 morcas regillrodas de Sun Microsystem.111(1 morco '''9istrodo de Linu. • Mond'iva e. • GNOME es una morca registrado de lo Fundación GNOME. • Mazilla y Firero~ 100 morcas registrados de The Mazillo Orgonization.MARCAS REGISTRADAS Los siguientes términos son morcol regi. • 9nulinE~ es uno morco registrado de lo Junto de htremoduro.V. Tarvold •.otion. lne. • Apple y Macintolh 100 morco. es uno morco registrado de KDE e.