Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

lndice 
. . 
Agradecimientos ....................................................................................................................... 6 
Contactar con el autor .............................................................................................................. 7 
Siete versiones y contando ..................................................................................................... 29 
La estructura del libro ............................................................................................................ 31 
Normas usadas en este libro ............................................................................................ 32 
Parte I . Bases ......................................................................................................................... 33 
1 . Delphi 7 y su IDE .............................................................................................................. 35 
Ediciones de Delphi ................................................................................................................ 36 
Una vision global del IDE ..................................................................................................... 37 
Un IDE para dos bibliotecas ............................................................................................ 38 
. . Configuration del escritorio ..................................................................................... 38 
Environment Options ....................................................................................................... 40 
Sobre 10s menus ................................................................................................................. 40 
El cuadro de dialog0 Environment Options .............................................................. 41 
TO-DO List .......................................................................................................................... 41 
Mensajes ampliados del compilador y resultados de busqueda en Delphi 7 .............. 43 
El editor de Delphi ................................................................................................................. 44 
El Code Explorer ............................................................................................................... 46 
. . Exploracion en el editor ................................................................................................... 48 
Class Completion .............................................................................................................. 49 
Code Insight ...................................................................................................................... 50 
Code Completion ......................................................................................................... 50 
Code Templates ............................................................................................................ 52 
Code Parameters .......................................................................................................... 52 
Tooltip Expression Evaluation ................................................................................... 53 
Mas teclas de metodo abreviado del editor .................................................................... 53 
Vistas que se pueden cargar ............................................................................................. 54 
.............................................................................................................. Diagram View 54 
Form Designer ......................................................................................................................... 56 
................................................................................................................ Object Inspector 58 
Categorias de propiedades .......................................................................................... 60 
Object TreeView ................................................................................................................ 61 
Secretos de la Component Palette ......................................................................................... 63 
Copiar y pegar componentes ............................................................................................ 64 
De las plantillas de componentes a 10s marcos ............................................................. 65 
Gestionar proyectos ................................................................................................................ 67 
Opciones de proyecto ........................................................................................................ 69 
.............................................................................................. Compilar y crear proyectos 71 
Ayudante para mensajes del compilador y advertencias ......................................... 73 
Exploracion de las clases de un proyecto ....................................................................... 74 
Herramientas Delphi adicionales y externas .............................. .......... .............................. 75 
Los archivos creados por el sistema ..................................................................................... 76 
Un vistazo a 10s archivos de codigo fuente .................................................................... 82 
El Object Repository ............................................................................................................... 84 
Actualizaciones del depurador en Delphi 7 ......................................................................... 87 
2 . El lenguaje de programaci6n Delphi .......................................................................... 89 
Caracteristicas centrales del lenguaje .................................................................................. 90 
Clases y objetos ....................................................................................................................... 91 
Mas sobre metodos ............................................................................................................ 93 
Creacion de componentes de forma dinamica ............................................................ 94 
Encapsulado ............................................................................................................................ 95 
............................................................................................ Privado, protegido y public0 96 
Encapsulado con propiedades ......................................................................................... 97 
Propiedades de la clase TDate ................................................................................... 99 
Caracteristicas avanzadas de las propiedades ........................................................ 100 
Encapsulado y formularios ............................................................................................. 101 
........................................................................... Aiiadir propiedades a formularios 101 
......................................................................................................................... Constructores 103 
....................................................................................... Destructores y el metodo Free 104 
El modelo de referencia a objetos de Delphi ..................................................................... 104 
Asignacion de objetos ..................................................................................................... 105 
Objetos y memoria ........................................................................................................... 107 
................................................................................... Destruir objetos una sola vez 108 
..........................................................................................Herencia de 10s tipos existentes 109 
................................................................................ Campos protegidos y encapsulado 111 
............................................................................... Herencia y compatibilidad de tipos 113 
......................................................................................... Enlace posterior y polimorfismo 114 
................................................................................... Sobrescribir y redefinir metodos 11 5 
Metodos virtuales frente a metodos dinamicos ............................................................ 117 
......................................................................................... Manejadores de mensajes 117 
.......................................................................................................... Metodos abstractos 118 
Conversion descendiente con seguridad de tipos .............................................................. 119 
................................................................................................................... Uso de interfaces 121 
..................................................................................................... Trabajar con excepciones 124 
........................................................................... Flujo de programa y el bloque finally 125 
..................................................................................................... Clases de excepciones 127 
.......................................................................................................... Registro de errores 129 
.............................................................................................................. Referencias de clase 130 
Crear . componentes usando referencias de clase ....................................................... 132 
. . 3 . La biblioteca en tiempo de ejecuc~on ......................................................................... 135 
........................................................................................................ . Las unidades de la RTL 136 
...................................................................................... Las unidades System y SysInit 139 
Cambios recientes en la unidad System .................................................................. 140 
Las unidades SysUtils y SysConst ................................................................................. 141 
.................................................................................. Nuevas hnciones de SysUtils 142 
........................................ Rutinas extendidas de formato de cadenas en Delphi 7 144 
La unidad Math ............................................................................................................... 145 
Nuevas funciones matematicas ................................................................................ 145 
.................................................................................. Redondeo y dolores de cabeza 147 
Las unidades ConvUtils y StdConvs ............................................................................. 148 
La unidad DateUtils ........................................................................................................ 148 
La unidad StrUtils ........................................................................................................... 149 
De Pos a PosEx .......................................................................................................... 150 
.............................................................................................................. La unidad Types 151 
....................................................................................... La unidad Variants y VarUtils 151 
Variantes personalizadas y numeros complejos ..................................................... 152 
Las unidades DelphiMM y ShareMem ......................................................................... 154 
Unidades relacionadas con COM .................................................................................. 154 
...................................................................................................................... Convertir datos 154 
................................................................................................... iConversiones de divisas? 158 
........................................................................................ Gestion de archivos con SysUtils 162 
La clase TObject ................................................................................................................... 163 
Mostrar information de clase ........................................................................................ 167 
4 . La biblioteca de clases principales ............................................................................. 169 
.............................................................................................. El paquete RTL. VCL y CLX 170 
...................................................................................... Partes tradicionales de la VCL 171 
La estructura de CLX ..................................................................................................... 172 
Partes especificas de VCL de la biblioteca ................................................................... 173 
.............................................................................................................. La clase TPersistent 173 
La palabra clave published ............................................................................................. 176 
Acceso a las propiedades por su nombre ...................................................................... 177 
La clase TComponent ........................................................................................................... 180 
............................................................................................................................ Posesion 180 
La matriz Components ......................................................................................... 181 
.............................................................................................. Cambio de propietario 182 
......................................................................................................... La propiedad Name 184 
. . Elimination de campos del formulario ......................................................................... 185 
...................................................................................... Ocultar campos del formulario 186 
.................................................................................... La propiedad personalizada Tag 188 
...................................................................................................... ............................ Eventos : 188 
Eventos en Delphi ........................................................................................................... 188 
Punteros a metodo ....................................................................................................... 189 
Los eventos son propiedades ......................................................................................... 190 
Listas y clases contenedores ............................................................................................... 193 
Listas y listas de cadena ............................................................................................... 193 
................................................... Pares nombre-valor (y extensiones de Delphi 7) 194 
Usar listas de objetos ................................................................................................. 195 
...................................................................................................................... Colecciones 196 
Clases de contenedores............................................................................................. 196 . . . . 
............................................................................ Listas asociativas de verification 198 
Contenedores y listas con seguridad de tipos .......................................................... 199 
Streaming ............................................................................................................................... 202 
La clase TStream ............................................................................................................. 202 
......................................................................................... Clases especificas de streams 204 
.............................................................................................. Uso de streams de archivo 205 
........................................................................................ Las clases TReader y TWriter 206 
Streams y permanencia ................................................................................................... 207 
.................................................................................. Compresion de streams con ZLib 213 
................... Resumen sobre las unidades principales de la VCL y la unidad BaseCLX 215 
........................................................................................................... La unidad Classes 215 
.............................................................................. Novedades en la unidad Classes 216 . . ............................................................................................. Otras unidades prlncipales 217 
5 . Controles visuales ........................................................................................................... 219 
...................................................................................................... VCL frente a VisualCLX 220 
.......................................................................... Soporte dual de bibliotecas en Delphi 222 
......................................................................... Clases iguales, unidades diferentes 223 
DFM y XFM ............................................................................................................... 224 
.......................................................................................................... Sentencias uses 226 
............................................... Inhabilitar el soporte de ayuda a la biblioteca dual 226 
Eleccion de una biblioteca visual .................................................................................. 226 
................................................................................................... Ejecucion en Linux 227 
........................................................... Compilacion condicional de las bibliotecas 228 
.......................................................................... Conversion de aplicaciones existentes 229 
......................................................................................... Las clases TControl y derivadas 230 
Parent y Controls ............................................................................................................ 231 
Propiedades relacionadas con el tamafio y la posicion del control ........................... 232 
........................................................................ Propiedades de activation y visibilidad 232 
Fuentes ............................................................................................................................. 233 
Colores ............................................................................................................................. 233 
La clase TWinControl (VCL) ........................................................................................ 235 
................................................................................... La clase TWidgetControl (CLX) 236 
................................................................. Abrir la caja de herramientas de componentes 236 
Los componentes de entrada de texto ........................................................................... 237 
El componente Edit ................................................................................................... 237 
El control LabeledEdit ............................................................................................. 238 
El componente MaskEdit .......................................................................................... 238 
Los componentes Memo y RichEdit ........................................................................ 239 
...................................................................................... El control CLX Textviewer 240 
Seleccion de opciones ..................................................................................................... 240 
Los componentes CheckBox y RadioButton ........................................................... 241 
Los componentes GroupBox ..................................................................................... 241 
El componente RadioGroup ..................................................................................... 241 
Listas ................. ' ............................................................................................................... 242 
El componente ListBox ............................................................................................. 242 
El componente ComboBox ....................................................................................... 243 
El componente CheckListBox .................................................................................. 244 
Los cuadros combinados extendidos: ComboBoxEx y ColorBox ......................... 245 
Los componentes Listview y TreeView .................................................................. 246 
El componente ValueListEditor ............................................................................... 246 
Rangos .............................................................................................................................. 248 
El componente ScrollBar .......................................................................................... 248 
Los componentes TrackBar y ProgressBar ............................................................. 249 
El componente UpDown ........................................................................................... 249 
El componente PageScroller .................................................................................... 249 
El componente ScrollBox ......................................................................................... 250 
Comandos ......................................................................................................................... 250 
Comandos y acciones ................................................................................................ 251 
Menu Designer .......................................................................................................... 251 
Menus contextuales y el evento OncontextPopup .............................................. 252 
Tecnicas relacionadas con 10s controles ............................................................................ 254 
Gestion del foco de entrada ............................................................................................ 254 
Anclajes de control ......................................................................................................... 257 
Uso del componente Splitter .......................................................................................... 258 
Division en sentido horizontal ................................................................................. 260 
Teclas aceleradoras .........................................................................................................261 
Sugerencias flotantes ...................................................................................................... 262 
.......................................................................... Personalizacion de las sugerencias 263 
Estilos y controles dibujados por el propietario .......................................................... 264 
Elementos del menu dibujados por el usuario ........................................................ 265 
Una ListBox de colores ............................................................................................. 267 
Controles ListView y TreeView ........................................................................................... 270 
..................................................................................... Una lista de referencias grafica 270 
Un arb01 de datos ............................................................................................................ 275 
La version adaptada de DragTree ............................................................................ 278 
Nodos de arb01 personalizados ...................................................................................... 280 
. . 
6 . Creac~on de la interfaz de usuario .............................................................................. 283 
Formularios de varias paginas ............................................................................................ 284 
Pagecontrols y Tabsheets .............................................................................................. 285 
Un visor de imagenes con solapas dibujadas por el propietario ................................ 290 
La interfaz de usuario de un asistente .......................................................................... 294 
El control ToolBar ................................................................................................................ 297 
El ejemplo RichBar ......................................................................................................... 298 
Un menu y un cuadro combinado en una barra de herramientas .............................. 300 
Una barra de estado simple ............................................................................................ 301 
Temas y estilos ...................................................................................................................... 304 
Estilos CLX ..................................................................................................................... 305 
................................................................................................... Temas de Windows XP 305 
El Componente ActionList .................................................................................................. 308 
Acciones predefinidas en Delphi ................................................................................... 310 
Las acciones en la practica ............................................................................................ 312 
La barra de herramientas y la lista de acciones de un editor ..................................... 316 
Los contenedores de barra de herramientas ....................................................................... 318 
....................................................................................................................... ControlBar 320 
Un menu en una barra de control ............................................................................ 323 
Soporte de anclaje en Delphi ......................................................................................... 323 
Anclaje de barras de herramientas en barras de control ............................................ 324 
..................................................................... Control de las operaciones de anclaje 325 
Anclaje a un Pagecontrol .............................................................................................. 329 
..................................................................................... La arquitectura de ActionManager 331 
Construir una sencilla demostracion ............................................................................ 332 
..................................................... Objetos del menu utilizados con menos frecuencia 336 
Modificar un programa existente .................................................................................. 339 
Emplear las acciones de las listas ................................................................................. 340 
7 . Trabajo con formularios ................................................................................................ 345 
La clase TForm ..................................................................................................................... 346 
............................................................................................. Usar formularios normales 346 
El estilo del formulario .................................................................................................. 348 
El estilo del borde ........................................................................................................... 349 
....................................................................................................... Los iconos del borde 352 
Definicion de mas estilos de ventana ............................................................................ 354 
Entrada directa en un formulario ........................................................................................ 356 
Supervision de la entrada del teclado ........................................................................... 356 
Obtener una entrada de raton ........................................................................................ 358 
Los parametros de 10s eventos de raton ............................................................... 359 
Arrastrar y dibujar con el raton ..................................................................................... 359 
Pintar sobre formularios ...................................................................................................... 364 
Tecnicas inusuales: Canal Alpha, Color Key y la API Animate ..................................... 366 
Posicion, tamaiio, desplazamiento y ajuste de escala ....................................................... 367 . . ............................................................................................. La posicion del formulario 368 
................................................................................. Ajuste a la ventana (en Delphi 7) 368 
........................................................ El tamafio de un formulario y su zona de cliente 369 
Restricciones del formulario .......................................................................................... 370 
................................................................................................ Desplazar un formulario 370 
Un ejemplo de prueba de desplazamiento ............................................................... 371 
Desplazamiento automatico ..................................................................................... 373 
...................................................... Desplazamiento y coordenadas del formulario 374 
................................................................................................. Escalado de formularios 376 
Escalado manual del formulario .............................................................................. 377 
............................................................. Ajuste automatic0 de la escala del formulario 378 
Crear y cerrar formularios ................................................................................................... 379 
Eventos de creacion de formularios .............................................................................. 381 
......................................................................................................Cerrar un formulario 382 
........................................................ Cuadros de dialog0 y otros formularios secundarios 383 
Afiadir un formulario secundario a un programa ........................................................ 384 
Crear formularios secundarios en tiempo de ejecucion .............................................. 385 
........................................... Crear un unica instancia de formularios secundarios 386 
. . Creacion de un cuadro de d~alogo ....................................................................................... 387 
El cuadro de dialogo del ejemplo RefList .................................................................... 388 
..................................................................................... Un cuadro de dialog0 no modal 390 
. . Cuadros de dialog0 predefinidos ......................................................................................... 393 
Dialogos comunes de Windows ................................................................................... 394 
Un desfile de cuadros de mensaje ................................................................................. 395 
Cuadros "Acerca den y pantallas iniciales ......................................................................... 396 
. , Creacion de una pantalla inicial ................................................................................... 397 
Parte I1 . Arquitecturas orientadas a objetos en Delphi ............................................... 401 
............................................................... 8 . La arquitectura de las aplicaciones Delphi 403 
El objeto Application ............................................................................................................ 404 . . Mostrar la ventana de la aplicacion .............................................................................. 406 
Activacion de aplicaciones y formularios .................................................................... 407 
Seguimiento de formularios con el objeto Screen ..................................................... 407 
De eventos a hilos ................................................................................................................. 412 
Programacion guiada por eventos ................................................................................. 412 
Entrega de mensajes Windows ...................................................................................... 414 
.................................................................................... Proceso secundario y multitarea 414 
Multihilo en Delphi ........................................................................................................ 415 
Un ejemplo con hilos ................................................................................................ 416 
Verificando si existe una instancia previa de una aplicacion .......................................... 418 
................................................................ Buscando una copia de la ventana principal 418 
Uso de un mutex .............................................................................................................. 419 
Buscar en una lista de ventanas .................................................................................... 420 
Controlar mensajes de ventana definidos por el usuario ............................................ 421 
Creacion de aplicaciones MDI ............................................................................................ 422 
MDI en Windows: resumen tecnico ............................................................................. 422 
Ventanas marco y ventanas hijo en Delphi ........................................................................ 423 
Crear un menu Window completo ................................................................................. 424 
El ejemplo MdiDemo ...................................................................................................... 426 
Aplicaciones MDI con distintas ventanas hijo .................................................................. 428 
Formularios hijo y mezcla de menus ............................................................................ 428 
................................................................................................... El formulario principal 429 
Subclasificacion de la ventana MdiClient .................................................................... 430 
Herencia de formularios visuales ........................................................................................ 432 
Herencia de un formulario base .................................................................................... 4 3 3 
Formularios polimorficos ............................................................................................... 436 
Entender 10s marcos ............................................................................................................. 439 
Marcos y fichas ............................................................................................................... 442 
................................................................................................. Varios marcos sin fichas 444 
Formularios base e interfaces .............................................................................................. 446 
Uso de una clase de formulario base ............................................................................. 447 
............................................................ Un truco adicional: clases de interposition 450 
Uso de interfaces ............................................................................................................. 451 
El gestor de memoria de Delphi .......................................................................................... 452 
. . 9 . Creac~on de componentes Delphi ................................................................................. 455 
Ampliacion de la biblioteca de Delphi ............................................................................... 456 
.............................................................................................. Paquetes de componentes 4 5 6 
Normas para escribir componentes ............................................................................... 458 
Las clases basicas de componentes ............................................................................... 459 
. . Creacion de nuestro primer componente ........................................................................... 460 
............................................................................................ El cuadro combinado Fonts 460 
Creacion de un paquete .................................................................................................. 465 
............................................................................... ~QuC hay detras de un paquete? 466 
Uso del cuadro combinado Fonts ................................................................................... 469 
................................................................. Los mapas de bits de la Component Palette 469 
Creacion de componentes compuestos ............................................................................... 471 
.................................................................................................... Componentes internos 471 
Publicacion de subcomponentes .................................................................................... 472 
.................................................................................................... Componentes externos 475 
.......................................................... Referencias a componentes mediante interfaces 477 
Un componente grafico complejo ........................................................................................ 481 
......................................................................Definition de una propiedad enumerada 482 
Escritura del metodo Paint ............................................................................................. 484 
Adicion de las propiedades TPersistent ........................................................................ 486 
Definition de un nuevo evento personalizado ............................................................. 488 
..... Uso de llamadas de bajo nivel a la API de Windows : ....................................... 489 
La version CLX: Llamadas a funciones Qt nativas ............................................... 490 
Registro de las categorias de propiedades .................................................................... 490 
Personalizacion de 10s controles de Windows ................................................................... 492 
El cuadro de edicion numeric0 ...................................................................................... 494 
Un editor numeric0 con separador de millares ...................................................... 495 
El boton Sound ................................................................................................................ 496 
Control de mensaje internos: El boton Active ........................................................... 498 
Mensajes de componente y notificaciones .................................................................... 499 
Mensajes de componentes ........................................................................................ 499 
Notificaciones a componentes .................................................................................. 503 
................................................................. Un ejemplo de mensajes de componente 503 
Un cuadro de dialog0 en un componente ........................................................................... 504 
Uso del componente no visual ....................................................................................... 508 
Propiedades de coleccion ............................................................................................... 508 
Definicion de acciones personalizadas ........................................................................ 512 
Escritura de editores de propiedades .................................................................................. 516 
Un editor para las propiedades de sonido ................................................................ 517 
Instalacion del editor de propiedades ..................................................................... 520 
............................................................................... Creacion de un editor de componentes 521 
......................................................... Subclasificacion de la clase TComponentEditor 522 
.................................................................. Un editor de componentes para ListDialog 522 
Registro del editor de componentes ........................................................................ 524 
10 . Bibliotecas y paquetes ................................................................................................. 527 
La funcion de las DLL en Windows ............................................................................ 528 
El enlace dinamico .......................................................................................................... 528 
Uso de las DLL ................................................................................................................ 529 
Normas de creacion de DLL en Delphi ....................................................................... 530 
Uso de las DLL existentes .................................................................................................... 531 
.................................................................................................... Usar una DLL de C++ 532 
Creacion de una DLL en Delphi ......................................................................................... 534 
La primera DLL en Delphi ...................................................................................... 535 
Funciones sobrecargadas en las DLL de Delphi ................................................... 537 
Exportar cadenas de una DLL ................................................................................. 537 
Llamada a la DLL de Delphi ...................................................................................... 539 
Caracteristicas avanzadas de las DLL en Delphi ............................................................ 540 
............................................................. Cambiar nombres de proyecto y de biblioteca 540 
Llamada a una funcion DLL en tiempo de ejecucion .................................................. 542 
Un formulario de Delphi en una DLL .......................................................................... 544 
Bibliotecas en memoria: codigo y datos ............................................................................. 546 
Compartir datos con archivos proyectados en memoria ............................................. 548 
Uso de paquetes Delphi ........................................................................................................ 550 
Versiones de paquetes .................................................................................................... 551 
Formularios dentro de paquetes .......................................................................................... 553 
Carga de paquetes en tiempo de ejecucion ................................................................ 555 
Uso de interfaces en paquetes .................................................................................. 558 
Estructura de un paquete ..................................................................................................... 561 
11 . Modelado y programacih orientada a objetos (con ModelMaker) ................... 567 
Comprension del modelo interno de ModelMaker ............................................................ 568 
Modelado y UML .................................................................................................................. 569 
Diagramas de clase ........................................................................................................ 569 
Diagramas de secuencia ............................................................................................. 571 
Casos de uso y otros diagramas ..................................................................................... 572 
Diagramas no W ........................................................................................................ 574 
Elementos comunes de 10s diagramas ........................................................................... 575 
Caracteristicas de codification de ModelMaker .......................................................... 576 
................................................................................. Integracion Delphi / ModelMaker 576 
Gestion del modelo de codigo ........................................................................................ 578 
El editor Unit Code Editor ............................................................................................. 580 
........................................................... El editor Method Implementation Code Editor 582 
La vista de diferencias .................................................................................................... 582 
La vista Event Types View ............................................................................................. 584 
..................................................................................................... Documentacion y macros 585 
Documentacion frente a comentarios ............................................................................ 585 
Trabajo con macros .........................................................................................................587 
Reingenieria de codigo ......................................................................................................... 587 
. . Aplicacion de patrones de diseiio .................................................................................. 590 
Plantillas de codigo ......................................................................................................... 593 
Detallitos poco conocidos ................................................................................................... 595 
12 . De COM a COM+ ..................................................................................................... 597 
Una breve historia de OLE y COM ..................................................................................... 598 
Implementacion de IUnknow .............................................................................................. 599 
............................................................................... Identificadores globalmente unicos 601 
El papel de las fabricas de clases .................................................................................. 603 
Un primer sewidor COM ..................................................................................................... 604 
Interfaces y objetos COM ............................................................................................... 605 
Inicializacion del objeto COM ....................................................................................... 608 
Prueba del sewidor COM ............................................................................................... 609 
Uso de las propiedades de la interfaz ........................................................................... 610 
......................................................................................... Llamada a metodos virtuales 611 
..................................................................................................................... Automatization 612 
Envio de una llamada Automatizacion ......................................................................... 614 
Creacion de un sewidor de Automatizacion ...................................................................... 617 
.................................................................................... El editor de bibliotecas de tipos 618 
..................................................................................................... El codigo del sewidor 619 
Registro del sewidor de autornatizacion ...................................................................... 621 
Creacion de un cliente para el sewidor ........................................................................ 622 
................................................................ El alcance de 10s objetos de automatizacion 624 
El senidor en un componente ...................................................................................... 626 
Tipos de datos COM ....................................................................................................... 627 
Exponer listas de cadenas y fuentes ....................................................................... 627 
Us0 de programas Office ................................................................................................ 628 
Uso de documentos compuestos .......................................................................................... 629 
............................................................................................... El componente Container 630 
Uso del objeto interno .................................................................................................... 633 
Controles ActiveX ................................................................................................................. 633 
........................................................ Controles ActiveX frente a componentes Delphi 635 
Uso de controles ActiveX en Delphi ............................................................................. 636 
Uso del control WebBrowser .................................................................................... 636 
Creacion de controles ActiveX ............................................................................................ 638 
Creacion de una flecha ActiveX .................................................................................... 639 
Afiadir Nuevas Propiedades ........................................................................................... 640 
Adicibn de una ficha de propiedades ............................................................................ 642 
ActiveForms ..................................................................................................................... 644 
Interioridades de ActiveForm ................................................................................... 644 
El control ActiveX XClock ...................................................................................... 645 
ActiveX en paginas Web ................................................................................................ 646 
COM+ .................................................................................................................................... 648 
Creacion de un componente COM+ .............................................................................. 649 
Modulos de datos transaccionales ................................................................................. 651 
Eventos COM+ ................................................................................................................ 653 
COM y .NET en Delphi 7 .................................................................................................... 656 
................................ Parte I11 . Arquitecturas orientadas a bases de datos en Delphi 659 
13 . Arquitectura de bases de datos Delphi ..................................................................... 661 
Acceso a bases de datos: dbExpress. datos locales y otras alternativas .......................... 662 
La biblioteca dbExpress .................................................................................................. 662 
Borland Database Engine (BDE) .................................................................................. 664 
InterBase Express (IBX) ................................................................................................ 664 
MyBase y el componente ClientDataSet ....................................................................... 665 
dbGo para ADO ............................................................................................................... 665 
MyBase: ClientDataSet independiente ............................................................................... 666 
Conexion a una tabla local ya existente ....................................................................... 667 
De la DLL Midas a la unidad MidasLib ....................................................................... 669 
Formatos XML y CDS .................................................................................................... 669 
Definition de una tabla local nueva .............................................................................. 670 
Indexado ........................................................................................................................... 671 
Filtrado ............................................................................................................................. 672 
Busqueda de registros ..................................................................................................... 673 
Deshacer y Savepoint ................................................................................................ 674 
Activar y desactivar el registro ................................................................................ 675 
Usode controles data-aware ................................................................................................ 675 
Datos en una cuadricula ................................................................................................. 676 
DBNavigator y acciones sobre el conjunto de datos ................................................... 676 
Controles data-aware de texto ....................................................................................... 677 
Controles data-aware de lista ........................................................................................ 677 
El ejemplo DbAware ................................................................................................. 678 
Uso de controles de busqueda ........................................................................................ 679 
Controles grAficos data-aware ....................................................................................... 681 
El componente DataSet ........................................................................................................ 681 
El estado de un Dataset .................................................................................................. 686 
Los campos de un conjunto de datos .................................................................................. 687 
Uso de objetos de campo ................................................................................................ 690 
Una jerarquia de clases de campo ................................................................................. 692 
., Adicion de un campo calculado ..................................................................................... 695 
Campos de busqueda ....................................................................................................... 699 
Control de 10s valores nulos con eventos de campo .................................................... 701 
Navegacion por un conjunto de datos ................................................................................. 702 
El total de una columna de tabla ................................................................................... 703 
Uso de marcadores .......................................................................................................... 704 
Edicion de una columna de tabla ................................................................................. 707 
Personalizacion de la cuadricula de una base de datos .................................................... 707 
Pintar una DBGrid ...................................................................................................... 708 
Una cuadricula que permite la seleccion multiple ................................................. 710 
........................................................................................ Arrastre sobre una cuadricula 712 
Aplicaciones de bases de datos con controles estandar .................................................... 713 
Imitacion de 10s controles data-aware de Delphi ....................................................... 713 
Envio de solicitudes a la base de datos ......................................................................... 716 
....................................................................................................... Agrupacion y agregados 718 
...................................................................................................................... Agrupacion 718 
................................................................................................. Definicion de agregados 719 
Estructuras maestroldetalles ................................................................................................ 721 
Maestro/detalle con 10s ClientDataSet ..................................................................... 722 
Control de errores de la base de datos ............................................................................ 723 
14 . Clientelsemidor con dbExpress ............................................................................ 727 
La arquitectura clientelservidor .......................................................................................... 728 
Elementos del disefio de bases de datos .......................................................................... 730 
Entidades y relaciones .................................................................................................... 730 
Reglas de normalizacion ........................................................................................ 731 
De las claves primarias a 10s OID ................................................................................. 731 
................................................................. Claves externas e integridad referencial 733 
. . 
Mas restricciones ............................................................................................................ 734 
Cursores unidireccianales ....................................................................................... 734 
...................................................................................................... Introduccion a InterBase 736 
............................................................................................................ Uso de IBConsole 738 
Programacion de servidor en InterBase ........................................................................ 740 
Procedimientos almacenados ................................................................................. 740 
Disparadores (y generadores) ................................................................................... 741 
La biblioteca dbExpress ....................................................................................................... 743 
Trabajo con cursores unidireccionales ..................................................................... 743 
Plataformas y bases de datos ........................................................................................ 744 
.................... Problemas con las versiones de controladores e inclusion de unidades 745 
Los componentes dbExpress ................................................................................................ 746 
El componente SQLConnection .................................................................................... 747 
............................................... Los componentes de conjuntos de datos de dbExpress 751 
........................................................... El componente SimpleDataSet de Delphi 7 752 
El componente SQLMonitor .......................................................................................... 753 
Algunos ejemplos de dbExpress .................................................................................... 754 
Uso de un componente unico o de varios ..................................................................... 755 
Aplicacion de actualizaciones .................................................................................. 755 . . 
Seguimiento de la conexion ..................................................................................... 756 
Control del codigo SQL de actualizacion ............................................................... 757 
Acceso a metadatos de la base de datos con SetSchemaInfo ................................ 758 
............................................................................................... Una consulta parametrica 760 
....................................................... Cuando basta una sola direccion: imprimir datas 762 
Los paquetes y la cache ........................................................................................................ 765 
Manipulacion de actualizaciones .................................................................................. 766 
El estado de 10s registros .......................................................................................766 
Acceso a Delta ........................................................................................................... 767 
Actualizar 10s datos .................................................................................................... 768 
Uso de transacciones ....................................................................................................... 771 
Uso de InterBase Express ............................................................................................... 774 
Componentes de conjunto de datos IBX ..................................................................... 776 
Componentes administrativos IBX .......................................................................... 777 
Creacion de un ejemplo IBX ....................................................................................... 777 
Creacion de una consulta en vivo .................................................................................. 779 
Control en InterBase Express ........................................................................................ 783 
Obtencion de mas datos de sistema ............................................................................... 784 
Bloques del mundo real ....................................................................................................... 785 
Generadores e identificadores ........................................................................................ 786 
Busquedas sin distincion entre mayusculas y minusculas .......................................... 788 
Manejo de ubicaciones y personas ........................................................................... 790 
Creacion de una interfaz de usuario .......................................................................... 792 
Reserva de clases ............................................................................................................. 795 
Creacion de un dialogo de busqueda ............................................................................. 798 
Adicion de un formulario de consulta libre ................................................................ 800 
15 . Trabajo con ADO .......................................................................................................... 803 
Microsoft Data Access Componentes (MDAC) ............................................................. 805 
Proveedores de OLE DB ............................................................................................. 805 
Uso de componentes dbGo ................................................................................................... 807 
Un ejemplo practico ................................................................................................... 808 
El componente ADOConnection ............................................................................. 811 
Archivos de enlace de datos ......................................................................................... 811 
Propiedades dinamicas ....................................................................................................... 812 
Obtencion de information esquematica ............................................................................ 813 
Uso del motor Jet ............................................................................................................. 815 
Paradox a traves de Jet ................................................................................................... 816 
Excel a traves de Jet ....................................................................................................... 817 
Archivos de texto a traves de Jet ............................................................................. 819 . , Importaclon y exportation ............................................................................................ 821 
Trabajo con cursores ............................................................................................................. 822 
. . 
Ubicacion de cursor ................................................................................................... 822 
Tipo de cursor .................................................................................................................. 823 
Pedir y no recibir ............................................................................................................. 825 
................................................................................................ Sin recuento de registros 826 
Indices de cliente ............................................................................................................. 826 
. . . Repllcaclon ...................................................................................................................... 827 
Procesamiento de transacciones .................................................................................... 829 
Transacciones anidadas ........................................................................................... 830 
Atributos de ADOConnection ................................................................................... 830 
Tipos de bloqueo ............................................................................................................. 831 
. . 
El bloqueo peslmlsta ............................................................................................. 832 
Actualizacion de 10s datos ................................................................................................... 832 
............................................................................................... Actualizaciones por lotes 834 
Bloqueo optimists ........................................................................................................... 836 
Resolution de conflictos de actualizacion .................................................................... 839 
Conjuntos de registros desconectados ................................................................................ 840 
.......................................................................................................... Pooling de conexiones 841 
Conjuntos de registros permanentes ............................................................................. 843 
...................................................................................................... El modelo de maletin 844 
Unas palabras sobre ALIO.NET ........................................................................................... 845 
16 . Aplicaciones DataSnap multicapa ............................................................................. 847 
................................................................ Niveles uno. dos y tres en la historia de Delphi 848 
Fundamento tecnico de DataSnap ................................................................................. 850 
La interfaz AppSener .................................................................................................... 850 
Protocolo de conexion ..................................................................................................... 851 
Proporcionar paquetes de datos ..................................................................................... 853 
Componentes de soporte Delphi (entorno cliente) .................................................... 854 
.................................................... Componentes de soporte Delphi (entorno senidor) 856 
Construction de una aplicacion de ejemplo ...................................................................... 856 
El primer senidor de aplicacion ................................................................................... 856 
El primer cliente ligero .................................................................................................. 858 
Adicion de restricciones a1 senidor ....................................................................................860 
Restricciones de campo y conjuntos de datos .............................................................. 860 
Inclusion de propiedades de campo .............................................................................. 862 
Eventos de campo y tabla ............................................................................................... 862 
Adicion de caracteristicas a1 cliente ................................................................................... 863 
Secuencia de actualization ............................................................................................ 864 
Refresco de datos ............................................................................................................. 865 
Caracteristicas avanzadas de DataSnap ............................................................................. 867 
Consultas por parametros ............................................................................................... 868 
Llamadas a metodos personalizados ............................................................................. 868 
Relaciones maestroldetalle ............................................................................................. 870 
............................................................................................ Uso del agente de conexion 871 
Mas opciones de proveedor ............................................................................................ 872 
Agente simple de objetos ................................................................................................ 873 
Pooling de objetos ........................................................................................................... 874 
Personalizacion de paquetes de datos ........................................................................... 874 
17 . CreacMn de componentes de bases de datos ........................................................... 877 
El enlace de datos ................................................................................................................. 878 
La clase TDataLink ......................................................................................................... 878 
Clases de enlaces de datos derivadas ............................................................................ 879 
Creacion de controles data-aware orientados a campos .................................................. 880 
Una ProgressBar de solo lectura ................................................................................... 880 
Una TrackBar de lectura y escritura ............................................................................. 884 
Creacion de enlaces de datos personalizados .................................................................... 887 
Un componente visualizador de registros .................................................................... 888 
.......................................................................... Personalizacion del componente DBGrid 893 
.................................................................... Construir conjuntos de datos personalizados 897 
La definicion de las clases ............................................................................................. 898 
Apartado I: Inicio. apertura y cierre ............................................................................. 902 
..................................................... Apartado 11: Movimiento y gestion de marcadores 907 
............................................... Apartado 111: Buffers de registro y gestion de campos 911 
Apartado IV: De buffers a campos ................................................................................ 915 
.............................................. Comprobacion el conjunto de datos basado en streams 917 
Un directorio en un conjunto de datos ............................................................................... 918 
.................................................................................. Una lista como conjunto de datos 919 
......................................................................................................... Datos del directorio 920 
Un conjunto de datos de objetos .......................................................................................... 924 
. . 18 . Generation de informes con Rave ............................................................................. 931 
Presentation de Rave ............................................................................................................ 932 
Rave: el entorno visual de creacion de informes ......................................................... 933 
El Page Designer y el Event Editor ..................................................................... 934 
El panel Property .................................................................................................. 934 
El panel Project Tree ................................................................................................. 934 
Barras de herramientas y la Toolbar Palette .......................................................... 935 
La barra de estado ..................................................................................................... 936 
Uso del componente RvProject ...................................................................................... 936 
........................................................................................... Formatos de representacion 938 
Conexiones de datos ....................................................................................................... 939 
........................................................................................ Componentes del Rave Designer 941 
Componentes basicos ...................................................................................................... 942 
Componentes Text y Memo ...................................................................................... 942 
El componente Section ............................................................................................. 942 
Componentes grhficos ............................................................................................... 943 
El componente FontMaster ...................................................................................... 943 
.................................................................................................... Numeros de pagina 944 
Componentes de dibujo ............................................................................................. 944 
Componentes de codigo de barras ........................................................................... 944 
Objetos de acceso a datos ............................................................................................... 945 
Regiones y bandas ........................................................................................................... 946 
El Band Style Editor ................................................................................................. 947 
Componentes data-aware ............................................................................................... 949 
El Data Text Editor ................................................................................................... 949 
De Text a Memo ........................................................................................................ 950 
Calculo de totales ...................................................................................................... 951 
................................................................................ Repeticion de datos en paginas 951 
....................................................................................................................... Rave avanzado 951 
................................................................................................Informes maestro-detalle 952 
Guiones de informes ....................................................................................................... 953 
Espejos .............................................................................................................................. 954 
Calculos a tope ................................................................................................................ 955 
.................................................................................................................... CalcTotal 955 
Parte IV . Delphi e Internet .............................................................................................. 959 
19 . Programacidn para Internet: sockets e Indy ......................................................... 961 
Creacion de aplicaciones con sockets ................................................................................. 962 
Bases de la programacion de sockets ............................................................................ 963 
Configuracion de una red local: direcciones IP ................................................ 964 
Nombres de dominio local ........................................................................................ 964 
............................................................................................................... Puertos TCP 964 
Protocolos de alto nivel ............................................................................................ 965 
Conexiones de socket ................................................................................................ 965 
Uso de componentes TCP de Indy ................................................................................. 966 
Envio de datos de una base de datos a traves de una conexion de socket ................ 970 
Envio y recepcion de correo electronic0 ....................................................................... 973 
Correo recibido y enviado .............................................................................................. 975 
................................................................................................................ Trabajo con HTTP 977 
Obtencion de contenido HTTP ................................................................................. 978 
La M I WinInet .......................................................................................................... 982 
Un navegador propio ...................................................................................................... 983 
Un sencillo servidor HTTP ............................................................................................ 985 
Generacion de HTML ........................................................................................................... 987 
Los componentes productores de codigo HTML de Delphi ........................................ 987 
Generacion de paginas HTML ....................................................................................... 988 
Creacion de paginas de datos ................................................................................. 990 
Produccion de tablas HTML .......................................................................................... 991 
Uso de hojas de estilo ..................................................................................................... 993 
Paginas dinamicas de un servidor personalizado ........................................................ 994 
20 . Programacidn Web con WebBroker y WebSnap .................................................... 997 
Paginas Web dinarnicas .................................................................................................. 998 
........................................................................................................ Un resumen de CGI 999 
Uso de bibliotecas dinamicas ....................................................................................... 1000 
Tecnologia WebBroker de Delphi ..................................................................................... 1001 
Depuracion con Web App Debugger ...................................................................... 1004 
............................................................... Creacion de un WebModule multiproposito 1007 
Informes dinamicos de base de datos .......................................................................... 1009 
................................................................................................ Consultas y formularios 1010 
Trabajo con Apache ...................................................................................................... 1014 
Ejemplos practices .............................................................................................................. 1016 
............................................................................ Un contador Web grafico de visitas 1017 
.............................................................. Busquedas con un motor Web de busquedas 1019 
WebSnap ............................................................................................................................ 1021 
. , , . Gestion de varias paglnas ........................................................................................ 1025 
Guiones de servidor ...................................................................................................... 1027 
Adaptadores ................................................................................................................... 1030 
Campos de adaptadores .......................................................................................... 1030 
Componentes de adaptadores ................................................................................. 1031 
Uso del Adapterpageproducer ........................................................................... 1031 
Guiones en lugar de codigo .................................................................................... 1034 
........................................................................................................ Encontrar archivos 1035 
WebSnap y bases de datos .................................................................................................. 1036 
Un modulo de datos WebSnap ..................................................................................... 1036 
........................................................................................................ El DataSetAdapter 1036 
Edicion de 10s datos en un formulario ........................................................................ 1039 
Maestro/Detalle en WebSnap ................................................................................... 1041 
Sesiones, usuarios y permisos ........................................................................................... 1043 
Uso de sesiones .............................................................................................................. 1043 
Peticion de entrada en el sistema ............................................................................ 1045 
Derechos de acceso a una unica pagina .............................................................. 1047 
........................................................................... 21 . Programacibn Web con IntraWeb 1049 
Introduccion a IntraWeb ............................................................................................... 1050 
De sitios Web a aplicaciones Web ........................................................................... 1051 
Un primer vistazo interior ...................................................................................... 1054 
Arquitecturas IntraWeb .......................................................................................... 1057 
Creacion del aplicaciones IntraWeb ............................................................................1058 
Escritura de aplicaciones de varias paginas .......................................................... 1060 
Gestion de sesiones ................................................................................................. 1064 
Integracion con WebBroker (y WebSnap) .............................................................. 1066 
Control de la estructura ................................................................................................ 1068 
Aplicaciones Web de bases de datos ................................................................................. 1070 
Enlaces con detalles ...................................................................................................... 1072 
...................................................................................... Transporte de datos a1 cliente 1076 
22 . Uso de tecnologias XML ............................................................................................ 1079 
Presentacion de XML ......................................................................................................... 1080 
Sintaxis XML basica .................................................................................................. 1080 
XML bien formado ........................................................................................................ 1082 
.......................................................................................................... Trabajo con XML 1083 
Manejo de documentos XML en Delphi .............................................................. 1084 
Programacion con DOM .................................................................................................... 1085 
Un documento XML en una TreeView ................................................................... 1087 
................................................................. Creacion de documentos utilizando DOM 1090 
Interfaces de enlace de datos XML ......................................................................... 1094 
Validacion y esquemas ............................................................................................ 1098 
Uso de la API de SAX .................................................................................................. 1099 
Proyeccion de XML con transformaciones ................................................................. 1103 
XML e Internet Express ..................................................................................................... 1108 
......................................................................................... El componente XMLBroker 1109 
Soporte de JavaScript ................................................................................................... 1110 
Creacion de un ejemplo ........................................................................................... 1111 
Uso de XSLT ....................................................................................................................... 1116 
Uso de XPath ................................................................................................................. 11 17 
XSLT en la practica ...................................................................................................... 1118 
XSLT con WebSnap ...................................................................................................... 1119 
Transformaciones XSL directas con DOM ................................................................. 1121 
Procesamiento de grandes documentos XML ........................................................... 1123 
De un ClientDataSet a un documento XML ............................................................ 1123 
De un documento XML a un ClientDataSet ............................................................ 1125 
23 . Semicios Web y SOAP ............................................................................................... 1129 
Servicios Web ................................................................................................................... 1130 
SOAP y WSDL .............................................................................................................. 1130 
Traducciones BabelFish ........................................................................................ 1131 
Creacion de un servicio Web ....................................................................................... 1134 
Un servicio Web de conversion de divisas ............................................................... 1135 
Publicacion del WSDL ............................................................................................ 1136 
Creacion de un cliente personalizado ............................................................... 1137 
Peticion de datos de una base de datos ................................................................... 1139 
Acceso a 10s datos ................................................................................................... 1139 
Paso de documentos XML ...................................................................................... 1140 
El programa cliente (con proyeccion XML) ......................................................... 1142 
Depuracion de las cabeceras SOAP ............................................................................ 1143 
Exponer una clase ya existente como un servicio Web ............................................. 1144 
DataSnap sobre SOAP ........................................................................................................ 1145 
Creacion del semidor SOAP DataSnap ...................................................................... 1145 
Creacion del cliente SOAP DataSnap ......................................................................... 1148 
SOAP frente a otras conexion con DataSnap ............................................................. 1148 
Manejo de adjuntos ............................................................................................................. 1149 
Soporte de UDDI ................................................................................................................. 1151 
~QuC es UDDI? .............................................................................................................. 1151 
UDDI en Delphi 7 ......................................................................................................... 1153 
Parte V . ApCndices ............................................................................................................ 1157 
ApCndice A. Herramientas Delphi del autor ............................................................... 1159 
CanTools Wizards ............................................................................................................... 1159 
Programa de conversion VclToClx ................................................................................... 1162 
Object Debugger ................................................................................................................. 1162 
Memory Snap ...................................................................................................................... 1163 
Licencias y contribuciones ................................................................................................. 1164 
ApCndice B . Contenido del CD-ROM ........................................................................... 1165 
lntroduccion 
La primera vez que Zack Urlocker me enseiio un product0 aun sin publicar 
denominado Delphi, me di cuenta de que cambiaria mi trabajo (y el trabajo de 
muchos otros desarrolladores de software). Solia pelearme con bibliotecas de 
C++ para Windows y, Delphi era, y todavia es, la mejor combinacion de progra- 
macion orientada a objetos y programacion visual no solo para este sistema ope- 
rativo sino tambien para Linux y pronto para .NET. 
Delphi 7 simplementese suma a esta tradicion, sobre las solidas bases de la 
VCL, para proporcionar otra impresionante herramienta de desarrollo de soft- 
ware que lo coordina todo. iEsta buscando soluciones de bases de datos, clientel 
servidor, multicapa (multitier), Intranet o Internet? iBusca control y potencia? 
~ B U S C ~ una rapida productividad? Con Delphi y la multitud de tecnicas y trucos 
que se presentan en este libro, sera capaz de conseguir todo eso. 
Siete versiones y contando 
Algunas de las propiedades originales de Delphi que me atrajeron heron su 
enfoque orientado a objetos y basado en formularios, su compilador extremada- 
mente rapido, su gran soporte para bases de datos, su estrecha integracion con la 
programacion para Windows y su tecnologia de componentes. Pero el elemento 
mas importante era el lenguaje Pascal orientado a objetos, que es la base de todo 
lo demas. 
iDelphi 2 era incluso mejor! Entre sus propiedades aiiadidas mas importantes 
estaban las siguientes: El Multi Record Object y la cuadricula para bases de datos 
mejorada, el soporte para Automatizacion OLE y el tipo de datos variantes, el 
soporte e integracion totales de Windows 95, el tip0 de datos de cadena larga y la 
herencia de formulario visual. Delphi 3 aiiadio la tecnologia Code Insight, el 
soporte de depuracion DLL, las plantillas de componentes, el Teechart, el Decision 
Cube, la tecnologia WebBroker, 10s paquetes de componentes, 10s ActiveForms y 
una sorprendente integracion con COM, gracias a las interfaces. 
Delphi 4 nos trajo el editor AppBrowser, nuevas propiedades de Windows 98, 
mejor soporte OLE y COM, componentes de bases de datos ampliados y muchas 
mas clases principales de la VCL aiiadidas, como el soporte para acoplamiento, 
restriccion y anclaje de 10s controles. Delphi 5 aiiadio a este cuadro muchas 
mejoras en el IDE (demasiadas para enumerarlas aqui), soporte ampliado para 
bases de datos (con conjuntos de datos especificos de ADO e InterBase), una 
version mejorada de MIDAS con soporte para Internet, la herramienta de control 
de versiones Teamsource, capacidades de traduccion, el concept0 de marcos y 
nuevos componentes. 
Delphi 6 aiiadio a todas estas propiedades el soporte para el desarrollo 
multiplataforma con la nueva biblioteca de componentes para multiplataforma 
(CLX), una biblioteca en tiempo de ejecucion ampliada, el motor para base de 
datos dbExpress, un soporte excepcional de servicios Web y XML, un poderoso 
marco de trabajo de desarrollo Web, mas mejoras en el IDE y multitud de compo- 
nentes y clases, que siguen comentandose en las paginas siguientes. 
Delphi 7 proporciono mas robustez a estas nuevas tecnologias con mejoras y 
arreglos (el soporte de SOAP y DataSnap es lo primer0 en lo que puedo pensar) y 
ofrece soporte para tecnologias m h novedosas (como 10s temas de Windows XP 
o UDDI), per0 lo mas importante es que permite disponer rapidamente de un 
interesante conjunto de herramientas de terceras partes: el motor de generacion de 
informes RAVE, la tecnologia de desarrollo de aplicaciones Web IntraWeb y el 
entorno de diseiio ModelMaker. Finalmente, abre las puertas aun mundo nuevo a1 
ofrecer (aunque sea como prueba) el primer compilador de Borland para el len- 
guaje PascallDelphi no orientado a la CPU de Intel, si no a la plataforma CIL de 
.NET. 
Delphi es una gran herramienta, per0 es tambien un entorno de programacion 
completo en el que hay muchos elementos involucrados. Este libro le ayudara a 
dominar la programacion en Delphi, incluidos el lenguaje Delphi, 10s componen- 
tes (a usar 10s existentes y crear otros propios), el soporte de bases de datos y 
clientelservidor, 10s elementos clave de programacion en Windows y COM y el 
desarrollo para Web e Internet. 
No necesita tener un amplio conocimiento de estos temas para leer el libro, 
per0 es necesario que conozca las bases de la programacion. Le ayudara conside- 
rablemente el estar familiarizado con el lenguaje Delphi, sobre todo despues de 
10s capitulos introductorios. El libro comienza a tratar 10s temas con detenimiento 
de forma inmediata; se ha eliminado gran parte del material introductorio incluido 
en otros textos. 
La estructura del libro 
El libro se divide en cinco partes: 
Parte I: Bases. Introduce las nuevas propiedades del entorno de desarrollo 
integrado (IDE) de Delphi 7 en el capitulo 1, a continuacion pasa a1 len- 
guaje Delphi y a la biblioteca en tiempo de ejecucion (RTL) y la biblioteca 
de componentes visuales (VCL). Cuatro capitulos proporcionan las bases 
y explicaciones avanzadas sobre 10s controles mas usados, el desarrollo de 
interfaces de usuario avanzadas y el uso de formularies. 
Parte 11: Arquitecturas orientadas a objetos en Delphi. Trata las aplicacio- 
nes Delphi, el desarrollo de componentes personalizados, el uso de biblio- 
tecas y paquetes, el uso de ModelMaker y COM+. 
Parte 111: Arquitecturas orientadas a bases de datos en Delphi. Trata sobre 
el acceso simple a las bases de datos, la explicacion pormenorizada de 10s 
controles data-aware, la programacion clientelservidor, dbExpress, 
InterBase, ADO, Datasnap, el desarrollo de controles data-aware y con- 
juntos de datos personalizados y la generacion de informes. 
Parte IV: Delphi e Internet. Trata en primer lugar sobre 10s sockets TCPI 
IP, 10s protocolos de Internet e Indy, y despues pasa a areas especificas 
como las extensiones del lado del servidor Web (con WebBroker, WebSnap 
e IntraWeb) y acaba con XML y el desarrollo de servicios Web. 
Parte V: Apendices. Describe las herramientas extra de Delphi y el conte- 
nido del CD-ROM que acompaiia a1 libro. 
Tal como sugiere este breve resumen, el libro trata muchos temas de interes 
para 10s usuarios de Delphi con casi cualquier nivel de experiencia en programa- 
cion, desde "principiantes avanzados" a desarrolladores de componentes. 
En el libro, he intentado eludir el material de referencia casi por completo y me 
he centrado, en cambio, en las tecnicas para utilizar Delphi de forma efectiva. 
Dado que Delphi ofrece amplia documentacion electronica, incluir listas sobre 
metodos y propiedades de componentes en el libro resultaria superfluo y haria que 
la obra quedase obsoleta en cuanto el software sufriese pequeiios cambios. Para 
tener material de referencia disponible, le sugiero que lea el libro con 10s archivos 
de Ayuda de Delphi a mano. Sin embargo, he hecho todo lo posible para que el 
libro se pueda leer lejos del ordenador, si asi se prefiere. Las capturas de pantalla 
y 10s fragmentos clave de 10s listados deberian ayudarle en ese sentido. El libro 
utiliza unicamente unas cuantas convenciones para resultar mas legible. 
Normas usadas en este libro 
En este libro se usan las siguientes convenciones tipograficas: 
Las opciones de menus se indican en orden jerarquico, con cada instruc- 
cion de menu separada por el signo "mayor que" y en un tip0 de letra Arial. 
Por ejemplo, File>Open quiere decir hacer clic en el comando File en la 
barra de menu y luego seleccionar Open. 
Todos 10s elementos del codigo fuente, como las palabras clave, las pro- 
piedades, las clases y las funciones, aparecen en un tipo de l e t r a c o u r i e r 
y 10s fragmentos de codigo poseen el mismo formato que el utilizado en el 
editor Delphi, a saber, las palabras claves en negrita y 10s comentarios y 
cadenas en cursiva. 
Las combinaciones de teclas se indican de esta forma: Control-C. 
A lo largo del libro encontrara unos rectangulos sombreados que resaltan 
la informacion especial o importante, por ejemplo: 
ADVERTENCIA: Indica un procedimiento que, en teoriq podria causar 
dificultades o incluso la ptr&da de datos. 
- 
NOTA: Resalta la informacion interesante o erdicional y suele contener 
pequefios trozos extra de informaci6n tecnica sobrc dn terna. 
-- - -- - -- 
TRUCO: Llamm la atenci6n sobre habiles sugerencias, pistas recomenda- 
bles y consejos 6tiles. 
Bases 
Delphi 7 
En una herramienta de programacion visual como Delphi,el papel del Entorno 
de Desarrollo Integrado (IDE, Integrated Development Environment) resulta a 
veces mas importante que el lenguaje de programacion. Delphi 7 ofrece algunas 
nuevas caracteristicas muy interesantes sobre el maravilloso IDE de Delphi 6. En 
este capitulo examinaremos estas nuevas caracteristicas, a1 igual que las caracte- 
risticas aiiadidas en otras versiones recientes de Delphi. Tambien comentaremos 
unas cuantas caracteristicas tradicionales de Delphi que no son bien conocidas u 
obvias a 10s recien llegados. Este capitulo no es un tutorial completo sobre el 
IDE, que necesitaria mucho mas espacio; principalmente es un conjunto de conse- 
jos y sugerencias dirigidas a1 usuario medio de Delphi. Si se trata de un progra- 
mador novato, no se preocupe. El IDE de Delphi es bastante intuitivo. El propio 
Delphi incluye un manual (disponible en formato Acrobat en el CD Delphi 
Companion Tools) con un tutorial que presenta el desarrollo de aplicaciones en 
Delphi. Puede encontrar una introduccion mas sencilla a Delphi y su IDE en otros 
textos. Pero en este libro asumiremos que ya sabe como llevar a cab0 las opera- 
ciones basicas del IDE; todos 10s capitulos despues de este se centraran en cues- 
tiones y tecnicas de programacion. Este capitulo trata 10s siguientes temas: 
Navegacion del IDE. 
El editor. 
La tecnologia Code Insight. 
Diseiio de formularios. 
El Project Manager 
Archivos de Delphi. 
Ediciones de Delphi 
Antes de pasar a 10s pormenores del entorno de programacion de Delphi, resal- 
taremos dos ideas clave. En primer lugar, no hay una unica edicion de Delphi, 
sino muchas. En segundo lugar, cualquier entorno Delphi se puede personalizar. 
Por dichas razones, las pantallas de Delphi que aparecen en este capitulo pueden 
ser distintas a las que vea en su ordenador. Las ediciones de Delphi actuales son 
las siguientes: 
La edicion "Personal": Dirigida a quienes empiezan a utilizar Delphi y a 
programadores esporadicos. No soporta programacion de bases de datos ni 
ninguna de las caracteristicas avanzadas de Delphi. 
La edicion "Professional Studio": Dirigida a desarrolladores profesiona- 
les. Posee todas las caracteristicas basicas, mas soporte para programa- 
cion de bases de datos (corno soporte ADO), soporte basico para servidores 
Web (WebBroker) y algunas herramientas externas como ModelMaker e 
IntraWeb. En el libro se asume que el lector trabaja como minimo con la 
edicion Professional. 
La edici6n "Enterprise Studio": Esta dirigida a desarrolladores que crean 
aplicaciones para empresas. Incluye todas las tecnologias XML y de servi- 
cios Web avanzados, soporte de CORBA, internacionalizacion, arquitec- 
tura en tres niveles y muchas otras herramientas. Algunos capitulos del 
libro tratan sobre caracteristicas que solo posee esta version de Delphi y 
asi se ha especificado en esos casos. 
La edicihn "Architect Studio": Aiiade a la edicion Enterprise el soporte 
de Bold, un entorno para la creacion de aplicaciones dirigidas en tiempo de 
ejecucion por un modelo UML y capaces de proyectar sus objetos tanto 
sobre una base de datos como sobre una interfaz de usuarios, gracias a una 
gran cantidad de componentes avanzados. El soporte de Bold no se trata en 
este libro. 
Ademas de las distintas versiones disponibles, existen varias formas de perso- 
nalizar el entorno Delphi. En las capturas de pantalla presentadas a lo largo del 
libro, se ha intentado utilizar una interfaz estandar (corno la que resulta de la 
instalacion tal cual). Sin embargo, en ciertos ejemplos, pueden aparecer refleja- 
das algunas preferencias del autor como la instalacion de muchos aiiadidos, que 
pueden reflejarse en el aspect0 de las pantallas. La version Professional y supe- 
riores de Delphi 7 incluyen una copia funcional de Kylix 3, en la edicion de 
lenguaje Delphi. Ademas de referencias a la biblioteca CLX y a las caracteristi- 
cas multiplataforma de Delphi, este libro no trata Kylix ni el desarrollo sobre 
Linux. Puede buscar otras obras para conseguir mas informacion sobre este tema. 
(No hay muchas diferencias entre Kylix 2 y Kylix 3 en la version de lenguaje 
Delphi. La caracteristica nueva mas importante de Kylix 3 es su soporte del 
lenguaje C++.) 
Una vision global del IDE 
Cuando se trabaja con un entorno de desarrollo visual, el tiempo se emplea en 
dos partes distintas de la aplicacion: en 10s asistentes de disefio visual y en el 
editor de codigo. Los asistentes de diseiio permiten trabajar con componentes a un 
nivel visual (como cuando se coloca un boton sobre un formulario) o a un nivel no 
visual (como cuando se situa un componente DataSet sobre un modulo de datos). 
La figura 1.1 muestra un formulario y un modulo de datos en accion. En ambos 
casos, 10s asistentes de diseiio permiten escoger 10s componentes necesarios y 
fijar el valor inicial de las propiedades de 10s componentes. 
Figura 1.1. Un formulario y un modulo de datos en el IDE de Delphi 7. 
rn 
El editor de codigo es donde se escribe el codigo. El mod0 mas obvio de 
escribir codigo en un entorno visual implica responder a eventos, comenzando por 
10s eventos enlazados con las operaciones realizadas por 10s usuarios del progra- 
ma, como hacer clic sobre un boton o escoger un elemento de un cuadro de lista. 
Puede usarse el mismo enfoque para manejar eventos internos, como 10s eventos 
que implican cambios en bases de datos o notificaciones del sistema operativo. 
A medida que 10s programadores adquieren un mayor conocimiento sobre 
Delphi, suelen comenzar escribiendo basicamente codigo gestor de eventos y des- 
pues escriben sus propias clases y componentes y, normalmente, acaban invir- 
tiendo la mayor parte de su tiempo en el editor. Ya que este libro trata mas 
conceptos que la programacion visual e intenta ayudar a dominar toda la potencia 
de Delphi, a medida que el testo avance se vera mas codigo y menos formularios. 
Un IDE para dos bibliotecas 
Por primera vez en Delphi 6 aparecio un importante cambio. El IDE permite 
ahora utilizar dos bibliotecas de componentes distintas: la VCL (Visual Cornpo- 
nente Library, Biblioteca de componentes visuales) y la CLX (Component Library 
for Cross-Platform, Biblioteca de componentes para multiplataforma). Cuando 
creamos un nuevo proyecto, sencillamente escogemos cual de las dos bibliotecas 
queremos emplear, con las opciones de menu File>New>Application en el caso 
de un clasico programa Windows basado en la VCL y con las opciones 
File>New>CLX Application en el caso de una nueva aplicacion que se puede 
transportar basada en la CLX. 
blpbi w-pefliiik,~mmpi&p 91 cbdi& +g G& para, qv fwnicqk bajc 
Fioux. Re- ipte~eaante:vt&w CLS De& 7, ya que ip versi6n para 
lenguaje lM@i dc K y b se dkstribuye junto con el pv&tr;topam ~ind'ms, 
Al crear un nuevo proyecto o abrir uno que ya existe, la Component Palette 
se reorganiza para mostrar solo 10s controles relacionados con la biblioteca en 
uso (aunque en realidad la mayoria de 10s controles son compartidos). Cuando se 
traba con un diseiiador no visual (como un modulo de datos), las pestaiias de la 
Component Palette que muestran solo 10s componentes visuales se ocultan de 
la vista. 
Configuracion del escritorio 
Los programadores pueden personalizar el IDE de Delphi de varias maneras 
(tipicamente abriendo muchas ventanas, reordenandolas, y acoplandolas entre si). 
Sin embargo, normalmente sera necesario abrir un conjunto de ventanas en tiem- 
po de diseiio y un conjunto distinto en tiempo de depuracion. Del mismo modo, 
podria necesitarse una disposicion cuando se trabaje con formularios y otra com- 
pletamente diferente cuando se escriban componentes o codigo de bajo nivel me- 
diante el unico uso del editor. Reorganizar el IDE para cada una de estas 
necesidades es una tarea tediosa. 
Por este motivo, Delphi permite almacenar una determinada disposicion de las 
ventanas del IDE (llamada escritorio o escritorio global (Global Desktop) para 
distinguirlo de un escritorio deproyecto (Project Desktop) con un nombre y recu- 
perarla rapidamente. Tambien se puede convertir a una de estas agrupaciones en 
la configuracion predeterminada para la depuracion, de manera que se recuperara 
automaticamente cuando se inicie el depurador. Todas estas caracteristicas estan 
disponibles en la barra de herramientas Desktops. Tambien puede trabajar con las 
configuraciones de escritorio mediante el menu View>Desktops. 
La informacion de configuracion de escritorio se guarda en archivos DST 
(dentro del directorio b i n de Delphi), que en realidad son archivos INI. Los 
parametros guardados incluyen la posicion de la ventana principal, el Project 
Manager, la Alignment Palette, el Object Inspector (incluida su configura- 
cion de categorias de propiedades), el editor de ventanas (con el estado del Code 
Explorer y la Message View) y muchos otros, ademb del estado de anclaje de 
las diversas ventanas. Este es un pequeiio extract0 de un archivo DST, que debe- 
ria resultar facil de leer: 
[Main Window] 
Create=l 
Visible=l 
State=O 
Left=O 
Top=O 
Width=1024 
Height=105 
ClientWidth=1016 
ClientHeight=78 
[Alignmentpalette] 
Create=l 
Visible=O 
Las configuraciones de escritorio tienen mas fierza que las configuraciones de 
proyecto, que se guardan en un archivo DSK con una estructura similar. Las 
configuraciones de escritorio ayudan a eliminar problemas que pueden suceder 
cuando se traslada un proyecto de una maquina a otra (o de un desarrollador a 
otro) y es necesario reorganizar las ventanas a1 gusto. Delphi separa las configu- 
raciones de escritorio globales por usuario y las configuraciones de escritorio por 
proyecto, para ofrecer un mejor soporte a equipos de desarrollo. 
- -- -- 
7 ---- - 
TRUCO: Si se abre Delphi y no se puede ver el formulario u otras vent.- 
nas, es recornendable cornprobar (o borrar) las configuraciones dti 'escrito- 
rio (en el directorio bin de Delphi). Si se abre un proyecto recibido de un 
usuario clistinto y no se pueden ver algunas de las ventanas o no gusta la 
disposici6n del escritorio, lo mejor es volver a cargar las c o n f i s e i o n e s 
de 10s escritorios globales o borrar el archivo DSK del proyccto. . 
Environment Options 
Unas cuantas de las ultimas mejoras tienen que ver con el habitual cuadro de 
dialogo Environment Options. Las paginas de este cuadro de dialogo se reorga- 
nizaron en Delphi 6, desplazando las opciones del Form Designer de la pagina 
Preferences a la nueva pagina Designer. En Delphi 6 tambien existian unas 
cuantas opciones y paginas nuevas: 
La pagina Preferences del cuadro de dialogo: Time una casilla de veri- 
ficacion que impide que las ventanas de Delphi se acoplen automaticamente 
entre si. 
La pagina Environment Variables: Permite inspeccionar las variables 
del entorno del sistema (como las rutas predefinidas y parametros del SO) 
y establecer variables definidas por el usuario. Lo bueno es que se pueden 
utilizar ambos tipos de variable en cada uno de 10s cuadros de dialogo del 
IDE (por ejemplo, se puede evitar escribir explicitamente rutas usadas 
habitualmente, sustituyendolas por una variable). En otras palabras, las 
variables del entorno funcionan de manera similar a la variable $DELPHI, 
que hace referencia a1 directorio base de Delphi per0 puede ser definida 
por el usuario. 
L a pagina Internet: En ella se pueden escoger cuales son las extensiones 
de archivo predefinidas para 10s archivos HTML y SML (basicamente por 
el marco de trabajo WebSnap) y tambien asociar un editor externo con 
cada extension. 
Sobre 10s menus 
La principal barra de menu de Delphi (que en Delphi 7 tiene un aspect0 mas 
moderno) es un metodo importante de interaccion con el IDE, aunque probable- 
mcnte la mayoria de las tareas se realizaran mediante atajos de teclado y de menu. 
La barra de menu no cambia demasiado como reaccion a la operacion actual: se 
necesita hacer clic con el boton derecho del raton para conseguir una lista de las 
operaciones que se pueden realizar en la ventana o componente actual. 
La barra de menu cambia en gran medida segun las herramientas y asistentes 
de terceras partes que se hayan instalado. En Delphi 7, ModelMaker dispone de 
su propio menu. Si se instalan modulos adicionales como GExperts se pueden 
contemplar otros menus. 
Un importante menu afiadido a Delphi en las versiones mas recientes es el 
menu Window del IDE. Este menu muestra la lista de las ventanas abiertas; antes, 
se podia obtener esta lista mediante la combinacion de teclas Alt-0 o la opcion de 
menu View>Window List. El menu Window resulta realmente practico, ya que 
las ventanas suelen acabar detras de otras y son dificiles de encontrar. Puede 
controlarse el orden alfabetico de este menu mediante un parametro del Registro 
de Windows: hay que encontrar la subclave Main Window de Delphi (dentro de 
HKEY CURRENT USER\Software\Borland\Delphi\7.0). Esta c law 
del ~ e g i s t r o utiliz; una cadena (en lugar de valores booleanos), donde -1 y 
True indican verdadero y 0 y False indican falso. 
TRUCO: En Delphi 7, el menu Windows finaliza con un comando nuevo: 
Next Window. Este comando resulta particularmente util como atajo, 
ALGF6p. Se pueden recorrer las diversas ventanas del IDE de manera muy 
sencilla olediante este comando. 
El cuadro de dialogo Environment Options 
Como ya se ha comentado, algunos de 10s parametros del IDE necesitan que se 
edite directamente el Registro. Por supuesto, 10s parametros mas comunes pueden 
ajustarse simplemente mediante el cuadro de dialogo Environment Options, que 
esta disponible a traves del menu TOOIS junto con Editor Options y Debugger 
Options. La mayor parte de 10s parametros resultan bastante intuitivos y estan 
bien descritos en el archivo de ayuda de Delphi. La figura 1.2 muestra mis 
parametros estandar para la pagina Preferences de este cuadro de dialogo. 
TO-DO List 
Otra caracteristica aiiadida en Delphi 5 pero que aun sigue sin usarse como 
deberia es la lista de tareas pendientes. Se trata de una lista de tareas que aun se 
debe realizar para completar un proyecto (es un conjunto de notas para el progra- 
mador o programadores, que resulta una herramienta muy util en un equipo). 
Aunque la idea no es novedosa, el concept0 clave de la lista de tareas pendientes 
en Delphi es que funciona como una herramienta de dos vias. 
Figura 1.2. La pagina Preferences del cuadro de dialogo Environment Options. 
Se pueden aiiadir o modificar elementos pendientes a esta lista afiadiendo co- 
mentarios TODO al codigo fuente de cualquier archivo de un proyecto; se pueden 
ver las entradas correspondientes en la lista. Ademas, se pueden editar visualmente 
10s elementos de la lista para modificar el comentario correspondiente en el codi- 
go fuente. Por ejemplo, este es el aspect0 que mostraria un elemento de la lista de 
tareas pendientes en el codigo fuente: 
procedure TForml.FormCreate(Sender: TObject); 
begin 
/ / TODO - o M a r c o : A i i a d i r cddigo d e creacidn 
end; 
El mismo elemento puede editarse visualmente en la ventana que muestra la 
figura 1.3, dentro de la ventana To-Do List. 
La excepcion a esta regla de las dos vias es la definition de elementos pendien- 
tes en el ambito del proyecto. Debe aiiadir directamente estos elementos a la lista. 
Para hacer esto, puede utilizar la combinacion de teclas Control-A dentro de la 
ventana To-Do List o hacer clic con el boton derecho sobre la ventana y seleccio- 
nar la opcion Add en el menu desplegable. Estos elementos se guardan en un 
archivo especial con el mismo nombre raiz que el archivo del proyecto y una 
extension .TODO. 
Pueden utilizarse diversas opciones con un comentario TODO. Puede usarse 
-0 (como en el ejemplo anterior) para indicar el propietario (el programador que 
escribio el comentario), la opcion -c para indicar una categoria, o simplemente 
un numero de 1 a 5 para indicar la prioridad (0 , o ningun numero, indica que no 
se establece ningun nivel de prioridad).Por ejemplo, a1 usar el comando Add 
T o - D o I t e m del menu desplegable del editor (o la combinacion Control-Mayus- 
T ) se genero este comentario: 
TODO 2 -oMarco : B u t t o n p r e s s e d } 
Delphi trata todo lo que aparezca tras 10s dos puntos (hasta el final de la linea 
o hasta la Have de cierre, segun el tipo de comentario), como el texto del elemento 
de tarea pendiente. 
1 * _. ---. . - --' - A 
A c m llcm I ! I ~ o a ~ e 10- IWWY 
7 Check comp~ler felhngs 1 Marco 
Figura 1.3. La ventana Edit To-Do Item puede usarse para modificar un elemento de 
tarea pendiente, una operacion que tambien puede realizarse directamente en el 
codigo fuente. 
Finalmente, en la ventana TO-DO List se puede elirninar la marca de un ele- 
mento para indicar que se ha completado. El comentario del codigo fuente cam- 
biara de T O D O a DONE. Tambien se puede cambiar manualmente el comentario 
en el codigo fuente. 
Uno de 10s elementos mas potentes de esta arquitectura es la ventana principal 
TO-DO List, que puede recopilar automaticamente informacion de tareas pendien- 
tes a partir de archivos de codigo fuente a medida que se escribe, ordenarla, 
filtrarla y esportarla a1 Portapapeles como texto simple o una tabla HTML. To- 
das estas opciones estan disponibles en el menu de contesto. 
Mensajes ampliados del com pilador 
y resultados de busqueda en Delphi 7 
De manera predeterminada aparece una pequeiia ventana Messages bajo el 
editor, muestra tanto 10s mensajes del compilador como 10s resultados de las 
busquedas. Esta ventana se ha modificado de manera importante en Delphi 7. En 
primer lugar, 10s resultados de busqueda se muestran en una pestafia distinta para 
que no se mezclen con 10s mensajes del compilador como solia suceder. En segun- 
do lugar, cada vez que se realiza una busqueda distinta se puede pedir que Delphi 
muestre 10s resultados en una pagina diferente, para que 10s resultados de la 
operacion de busqueda anterior sigan disponibles: 
Se pueden utilizar las combinaciones Alt-Av Pag y Alt-Re Pag para recorrer 
de manera ciclica las pestaiias de esta ventana. (Los mismos comandos sirven 
para otras vistas con pestaiias.) 
Si suceden errores de compilador, puede activarse otra ventana nueva median- 
te el comando View>Additional Message Info. A medida que se compila un 
programa, esta ventana Message Hints proporcionara informacion adicional para 
algunos mcnsajes de error frecuentes, proporcionando sugerencias sobre como 
solucionar estos errores: 
Este tipo de ayuda esta destinada mas a programadores novatos, per0 podria 
ser practico tener presente esta ventana. Es importante darse cuenta de que esta 
informacion cs bastante facil de personalizar: un director de desarrollo de un 
proyccto pucdc introducir descripciones apropiadas de errores comunes en un 
formulario que signifiquen algo especifico para nuevos desarrolladores. Para ha- 
cer esto, siga las instrucciones del archivo que guarda los parametros de esta 
caracteristica, el archivo msginfo70,ini que se encuentra en la carpeta b i n de 
Delphi. 
El editor de Delphi 
Aparentemente el editor de Delphi no ha cambiado mucho en la version 7 del 
IDE. Sin embargo, en el fondo, se trata de una herramienta completamente nueva. 
Ademas de emplearlo para trabajar con archivo escritos en lenguaje Pascal orien- 
tad0 a objetos (o-en lenguaje Delphi, como prefiere llamarlo ahora Borland), se 
puede usar ahora para trabajar con otros archivos relacionados con el desarrollo 
en Delphi (como archivos SQL, XML, HTML y XSL), al igual que con archivos 
de otros lenguajes (entre 10s que se incluyen C++ y C#). La edicion de XML y 
HTML ya estaba disponible en Delphi 6, per0 10s cambios en esta version son 
importantes. Por ejemplo, durante la edicion de un archivo HTML se tiene sopor- 
te tanto para resaltado de sintaxis como para acabado de codigo. 
Las configuraciones el editor para cada archivo (incluido el comportamiento 
de teclas como Tab) dependen de la estension del archivo que se abra. Se pueden 
configurar estos parametros mediante la nueva pagina Source Options del cua- 
dro de dialogo Editor Properties, que muestra la figura 1.4. Esta caracteristica 
se ha ampliado y abierto aun mas para que incluso pueda configurarse el editor 
mediante un DTD para formatos de archivo basados en XML o mediante un 
asistente personalizado que proporcione el resaltado de sintaxis para otros len- 
guajes de programacion. Otra caracteristica del editor, las plantillas de codigo, 
son ahora especificas del lenguaje (las plantillas predefinidas para Delphi tendran 
poco sentido en HTML o C # ) . 
Figura 1.4. Los diversos lenguajes soportados por el IDE de Delphi se pueden 
asociar con varias extensiones de archivo mediante la pagina Source Options del 
cuadro de dialogo Editor Properties. 
NOTA: C# es el nuevo lenguaje que present6 Micmsofk junto con su arqui- 
tectura .NET. Borland espera soportar C# en su propio entorno .NET, que 
actualmente tiene el nombre en codigo de Galileo. 
Si solo se considera el lenguaje Delphi, el editor incluido en el IDE no ha 
cambiado mucho en las versiones recientes. Sin embargo, tiene unas cuantas ca- 
racteristicas que muchos programadores de Delphi desconocen y no utilizan, asi 
que se merece un poco de analisis. 
El editor de Delphi nos permite trabajar con varios archivos a la vez, usando 
una metafora de "bloc de notas con fichas". Se pasa de una ficha del editor a la 
siguiente pulsando Control-Tab (o Mayus-Control-Tab para movernos en la 
direccion opuesta). 
Podemos pasar de una ficha del editor a la siguiente pulsando Control-Tab (o 
Mayus-Control-Tab para movernos en la direccion opuesta). Se puede arrastrar y 
soltar las solapas con 10s nombres de unidad situadas en la parte superior del 
editor para cambiar su orden, para que se pueda usar un simple Control-Tab 
para moverse entre las unidades en que se trabaje en un momento dado. El menu 
local del editor posee tambien un comando Pages, que lista todas las fichas dispo- 
nibles en un submenu, muy util cuando se cargan muchas unidades. 
Tambien se pueden abrir varias ventanas del editor, cada una de ellas con 
multiples fichas o pestaiias. Hacer esto es la unica manera de inspeccionar el 
codigo fuente de dos unidas a la vez. (Realmente, cuando es necesario comparar 
dos unidades de Delphi, tambien se puede utilizar Beyond Compare, una herra- 
mienta de comparacion de archivos muy barata y maravillosa escrita en Delphi y 
disponible a traves de www.scootersoftware.com.) 
En el cuadro de dialogo Editor Properties, hay algunas opciones que afectan 
a1 editor. Sin embargo, para definir la propiedad AutoSave del editor, que guarda 
10s archivos del codigo fuente cada vez que se ejecuta el programa (y evita que se 
pierdan 10s datos en caso de que el programa sufra daiios importantes en el depu- 
rador), tenemos que ir a la ficha Preferences del cuadro de dialogo Environment 
Options. 
El editor de Delphi proporciona muchos comandos, incluyendo algunos que se 
remontan a sus ancestros de emulacion de WordStar (de 10s primeros compiladores 
Turbo Pascal). No vamos a comentar 10s distintos parametros del editor, ya que 
son bastante intuitivos y estan bien descritos en la ayuda disponible. Aun asi, 
fijese en que la pagina de ayuda que describe 10s atajos de teclado es accesible de 
una sola vez solo si se busca el elemento del indice shortcuts. 
I TRUCO: Un tmco que debemos recordar es que emplear ias 6rdenes Cut 
y paste no cs la &ca forma de mover el cb&o &to,, siop qqe fambi6n 
podemos s e l ~ i o n a r y pnastrar las palabras, expresicihes o lineas enteras 
de c6dig0, ademis de wpiar el texto en lugar de myerlo, mantmiendo 
pulsada Ia tecla Cpatrel tnbh-as iir~astnmas. 
El Code Explorer 
La ventana Code Explorer, que por lo general esta anclada en el lateral del 
editor, lista sencillamente todos 10s tipos, variables y rutinas definidas en una 
unidad, mas otras unidades que aparecen en sentencias u s e s .En el caso de tipos 
complejos, como las clases, el Code Explorer puede listar informacion 
pormenorizada, como una lista de campos, propiedades y metodos. Cuando co- 
menzamos a teclear en el editor, toda la informacion se actualizara. 
Podemos usar el Code Explorer para desplazarnos por el editor. A1 hacer 
doble clic sobre una de las entradas del Code Explorer, el editor pasa a la 
declaracion correspondiente. Tambien podemos modificar nombres de variables, 
propiedades y m6todos directamente en el Code Explorer. Sin embargo, si se 
desea utilizar una herramienta visual para trabajar con las clases, ModelMaker 
ofrece muchas mas caracteristicas. 
Aunque todo esto resulta bastante obvio a 10s cinco minutos de comenzar a 
usar Delphi, algunas caracteristicas del Code Explorer no se pueden utilizar de 
una forma tan intuitiva. Lo importante es que el usuario tiene control total sobre 
el mod0 en que aparece dispuesta la informacion y que se puede reducir la profun- 
didad del arbol que aparece en esta ventana cuando se personaliza el Code 
Explorer. Si reducimos el arbol, podremos realizar las elecciones con mayor 
rapidez. Podemos configurar el Code Explorer mediante la pagina de Environment 
Options correspondiente, como se muestra en la figura 1.5. 
Figura 1.5. Se puede configurar el Code Explorer mediante el cuadro de dialogo 
Environment Options. 
Fijese en que a1 eliminar la seleccion de uno de 10s elementos de Explorer 
Categories situados en la parte derecha de esta pagina del cuadro de dialogo, el 
Explorer no elimina 10s elementos correspondientes, simplemente aiiade el nodo 
a1 arbol. Por ejemplo, si se elimina la seleccion de la casilla Uses, Delphi no 
oculta la lista de unidades usadas; a1 contrario, las unidad usadas aparecen en la 
lista como nodos principales en lugar de permanecer en la carpeta Uses. Es una 
buena idea eliminar la seleccion de Types, Classes y VariablesIConstants. 
Dado que cada elemento del arbol Code Explorer tiene un icono que indica su 
tipo, la organizacion por campo y metodo parece menos importante que la organi- 
zacion por especificador de acceso. Es preferible mostrar todos 10s elementos en 
un grupo unico, puesto asi no es necesario pulsar el raton tantas veces para llegar 
a cada uno de 10s elementos. En realidad, la posibilidad de seleccionar elementos 
en el Code Explorer supone una forma muy comoda de desplazarnos por el 
codigo fuente de una unidad amplia. Cuando hacemos doble clic sobre un metodo 
en el Code Explorer, el foco se desplaza a la definicion de la declaracion de 
clase (en la parte de interfaz de la unidad). Se puede usar la combinacion Con- 
trol-Mayus junto con las teclas de cursor arriba y abajo para saltar de la defini- 
cion de un metodo o procedimiento en la parte de interfaz de una unidad a su 
definicion completa en la parte de implernentacion o volver hacia atras (es lo que 
se llaman Module Navigation). 
. - 
NOTA: Algunas de las categorias del explorador que aparecen en la figura 
1.5 son mas utilizadas por el Project Explorer que por el Code Explorer. 
Entre estas se encuentran las opciones de agrupamiento vi r t ua 1 s, 
!d e Introduced. 
Exploracion en el editor 
Otra caracteristica del editor es la Tooltip symbol insight (Ventanas de suge- 
rencia sobre simbolos). A1 mover el raton sobre un simbolo del editor, una venta- 
na de sugerencia nos mostrara el lugar en el que se declara el identificador. Esta 
caracteristica puede resultar especialmente importante para realizar el seguimien- 
to de identificadores, clases y funciones de una aplicacion que estamos escribien- 
do y tambien para consultar el codigo fuente de la biblioteca de componentes 
visuales (VCL). 
- 
ADVERTENCIA: Aunque pueda parecer buena idea en principio, no po- 
demos usar la ventana de sugerencia sobre simbolos para averiguar que 
unidad declara un identificador que queremos emplear. En realidad. la ven- 
tana de sugerencia no aparece, si no se ha incluido todavia la unidad corres- 
pondiente. 
Sin embargo, la autentica ventaja de esta funcion, es que el usuario puede 
transformarla en un instrumento auxiliar para desplazarse. Si mantenemos pulsa- 
da la tecla Control y movemos el raton sobre el identificador, Delphi creara un 
enlace activo con la definicion, en lugar de mostrar la ventana de sugerencia. 
Dichos enlaces aparecen en color azul y estan subrayados, estilo tipico de 10s 
exploradores Web, y el punter0 se transforma en una mano siempre que se situa 
sobre el enlace. 
Podemos, por ejemplo, pulsar Control y hacer clic sobre el identificador 
TLabel para abrir su definition en el codigo de la VCL. Cuando seleccionamos 
referencias, el editor conserva la pista de las diversas posiciones a las que se ha 
movido y gracias a ella podemos pasar de una referencia a otra (de nuevo como en 
un explorador Web mediante 10s botones Browse Back y Browse Forward que se 
encuentran en la esquina superior derecha de las ventanas o mediante las combi- 
naciones Alt-Flecha izda. o Alt-Flecha dcha.). Tambien podemos hacer clic so- 
bre las flechas desplegables proximas a los botones Back y Forward para ver 
una lista pormenorizada de las lineas de 10s archivos de codigo fuente a las que ya 
hemos accedido, para tener mayor control sobre 10s movimientos adelante y atras. 
Ahora cabe preguntarse como podemos saltar directamente al codigo fuente de 
la VCL si no forma parte de nuestro proyecto. El editor no solo puede encontrar 
las unidades de la ruta de busqueda (Search, que se compila como parte del 
proyecto), sino tambien aquellas que estan en las rutas Debug Source, Browsing 
y Library de Delphi. La busqueda se realiza en estos directorios en el mismo 
orden en que aparecen aqui enumerados y podemos definirlos en la ficha 
Directories/Conditionals del cuadro de dialogo Project Options y en la ficha 
Library del cuadro de dialogo Environment Options. Por defecto, Delphi aiiade 
10s directorios de codigo fuente de la VCL a la ruta Browsing del entorno. 
Class Completion 
El editor de Delphi tambien puede generar parte del codigo fuente, completan- 
do lo que ya se haya escrito. Esta caracteristica se llama Class Completion, y se 
activa a1 pulsar la combinacion de teclas Control-Mayus-C. Aiiadir un controla- 
dor de eventos a una aplicacion es una operacion rapida, porque Delphi aiiade 
automaticamente la declaracion de un nuevo metodo que controle el evento y nos 
proporciona el esquema del metodo en la seccion de implementacion de la unidad. 
Esto forma parte del soporte para programacion visual de Delphi. 
De un mod0 similar, las ultimas versiones de Delphi han conseguido facilitar 
el trabajo de 10s programadores que escriben codigo extra detras de 10s 
controladores de evento. De hecho, la nueva caracteristica de creacion de codigo 
afecta a 10s metodos generales, a 10s metodos de control de mensajes y a las 
propiedades. Por ejemplo, si tecleamos el siguiente codigo en la declaracion de 
clase: 
public 
procedure Hello (MessageText : string) ; 
y a continuacion, pulsamos Control-Mayus-C, Delphi nos ofrecera la defini- 
cion del metodo en la parte de implementacion de la unidad y crea las siguientes 
lineas de codigo: 
{ T F o r m l ) 
procedure TForml.Hello(MessageText: string); 
begin 
end; 
Esto resulta mas comodo que copiar y pegar una o mas declaraciones, aiiadir 
10s nombres de clase y por ultimo duplicar el codigo begin. . . end en cada 
metodo copiado. La funcion C 1 as s C omp 1 e t i o n tambien puede funcionar a 
la inversa: podemos escribir la implementacion del metodo directamente con su 
codigo y despues pulsar Control-Mayus-C para crear la entrada necesaria en la 
declaracion de clase. 
El ejemplo mas importante y util de esta funcion de completitud de clases es la 
generacion automatica de codigo para dar soporte a las propiedades declaradas en 
las clases. Por ejemplo, si en una clase se escribe 
p r o p e r t y Value: I n t e g e r ; 
y se pulsa Control-Mayus-C, Delphi convertira la linea enp r o p e r t y Value: I n t e g e r r ead fValue w r i t e Se tva lue ; 
Delphi aiiadira tambien el metodo setvalue a la declaracion de clase y 
proporcionara una implementacion predefinida para ese metodo. 
Code Insight 
Ademas del Code Explorer, la funcion de completitud de clases y las funcio- 
nes de desplazamiento, el editor de Delphi soporta la tecnologia Code Insight. En 
conjunto, las tecnicas Code Insight se basan en un analisis sintactico continuo en 
segundo plano, tanto del codigo fuente que escribimos como del codigo fuente de 
las unidades del sistema a las que se refiere nuestro codigo. 
La funcion Code Insight implica cinco capacidades: Code Completion, Code 
Templates, Code Parameters, Tooltip Expression Evaluation y Tooltip Symbol 
Insight. Esta ultima caracteristica se trato durante la seccion sobre la exploracion 
en el editor. Todas estas caracteristicas se pueden habilitar, inhabilitar y configu- 
rar en la pagina Code Insight del cuadro de dialog0 Editor Properties. 
Code Completion 
La funcion Code Completion permite escoger la propiedad o metodo de un 
objeto simplemente buscandolo en una lista o escribiendo sus letras iniciales. 
Para activar esta lista, solo hay que teclear el nombre de un objeto, como But tonl, 
aiiadir el punto y esperar. Para que forzar la aparicion de la lista, hay que pulsar 
Control-Barra espaciadora; para quitarla cuando no queramos verla, hay que 
pulsar Esc. La funcion Code Completion permite ademas buscar un valor adecua- 
do en una sentencia de asignacion. 
Cuando comenzamos a teclear, la lista va filtrando su contenido de acuerdo 
con la parte inicial del elemento que hemos escrito. La lista Code Completion 
emplea colores y muestra mas detalles para ayudarnos a distinguir elementos 
diferentes. En Delphi, se pueden personalizar estos colores mediante la pagina 
Code Insight del cuadro de dialogo Editor Properties. Otra caracteristica en el 
caso de funciones con parametros es la inclusion de parentesis en el codigo creado 
y la aparicion inmediata de la ventana de sugerencia de la lista de parametros. 
Cuando se escribe : = despues de una variable o propiedad, Delphi listara 
todas las demas variables u objetos del mismo tipo, ademas de 10s objetos que 
tengan propiedades de ese tipo. Mientras la lista permanece visible, podemos 
hacer clic con el boton derecho del raton sobre ella para modificar el orden de 10s 
elementos, clasificandolos por alcance o por nombre y tambien podemos adaptar 
el tamaiio de la ventana. 
Desde Delphi 6, Code Completion funciona ademas en la parte de interfaz de 
una unidad. Si pulsamos Control-Barra espaciadora mientras el cursor esta 
dentro de la definition de clase, obtendremos una lista de 10s metodos virtuales 
que se pueden sobrescribir (como por ejemplo, 10s metodos abstractos), 10s meto- 
dos de las interfaces implementadas, las propiedades de clase basica y, por ulti- 
mo, 10s mensajes del sistema que se pueden controlar. A1 seleccionar uno de ellos, 
aiiadiremos sencillamente el metodo adecuado a la declaracion de clase. En este 
caso concreto, la lista Code Completion permite la seleccion multiple. 
TRUCO: Si el c6digo que hemos escrito es incorrecto, Code Insight no 
funcionari y veremos un mensaje de error generic0 que nos indica dicha 
situation. Es posible hacer que aparezcan errores especificos de Code Insight 
1, porque no se abre 
ilacion). Para activar 
esta caracteristicas, es necesarlo estamecer una entrada del Registro no 
en el panel Message (que debera estar ya abiertc 
automaticamente para mostrar 10s errores de comp 
. , .. . .. 
- 
documentada, defhendo la clave de cadena \Delphi \ 7 . 0 \Cornpi 1 ing\ 
ShowCodeInsiteErrors con el valor 1. 
Hay algunas caracteristicas avanzadas de la funcion Code Completion que no 
resultan faciles de ver. Una particularmente util esta relacionada con el descubri- 
miento de 10s simbolos en unidades no utilizadas por nuestro proyecto. Cuando 
recurrimos a ella (con Control-Barra espaciadora) sobre una linea en blanco, la 
lista incluye tambien simbolos de unidades comunes (como Math, StrUtils y 
DateUtils) todavia no incluidas en la sentencia uses de la unidad en uso. A1 
seleccionar uno de estos simbolos externos, Delphi aiiade la unidad a la sentencia 
uses de forma automatics. 
Esta caracteristica (que no funciona dentro de expresiones) esta dirigida por 
una lista de unidades adicionales que puede ser personalizada, almacenada en la 
clave de registro \Delphi\7.0\CodeCompletion\ExtraUnits. 
TRgC(r:,l&fpG 7 b capaoidad de explorar la d e c h r w i h de ele- 
mentos de la fista.de campletitud de codigo a1 mantener pul'sadd la teela 
Control y'hacer chc sohre cualquier identificador de la Ikta. L . 
Code Templates 
Esta caracteristica permite insertar una de las plantillas de codigo predefinidas, 
como una declaracion compleja con un bloque interior b e g i n . . . . e n d . Las 
plantillas de codigo deben activarse de forma manual, usando Control-J para 
obtener una lista de todas ellas. Si tecleamos unas cuantas letras (como una pala- 
bra clave) antes de pulsar Control-J, Delphi listara solo las plantillas que 
comiencen por dichas letras. 
Tambien se pueden aiiadir plantillas de codigo personalizadas, para crear me- 
todos abreviados para 10s bloques de codigo que usemos normalmente. Por ejem- 
plo, si empleamos con frecuencia la funcion MessageDlg , podemos aiiadir una 
plantilla para la misma. 
Para modificar plantillas, mediante la pagina Source Options del cuadro de 
dialogo Editor Options, hay que seleccionar Pascal en la lista Source File Type 
y hacer clic sobre el boton Edit Code Templates. A1 hacer esto, aparecera el 
nuevo cuadro de dialogo Code Templates de Delphi 7. 
En este momento, si hacemos clic sobre el boton Add, escribimos un nuevo 
nombre de plantilla (por ejemplo, d e s o r d e n ) , escribimos tambien una descrip- 
cion y, a continuacion, aiiadimos el siguiente texto a1 cuerpo de la plantilla en el 
control memo Code: 
MessageDlg ( ' I ' , mtInformation, [mbOK] , 0 ) ; 
Ahora, cada vez que necesitemos crear un cuadro de dialogo de mensaje, sim- 
plemente escribiremos d e s o r d e n y, a continuacion, pulsaremos Control-J para 
obtener el texto completo. El caracter de linea vertical indica la posicion dentro 
del codigo fuente en la que estara el cursor en el editor despues de haber desplega- 
do la plantilla. Deberiamos escoger la posicion en la que queremos comenzar a 
teclear para completar el codigo producido por la plantilla. 
Aunque pueda parecer que las plantillas de codigo, a primera vista, se corres- 
ponden con palabras clave del lenguaje, estas son en realidad un mecanismo mas 
general. Se guardan en el archivo DELPHI32.DC1, un archivo de texto en un 
formato bastante simple que puede editarse con facilidad. Delphi 7 tambien per- 
mite exportar la configuracion para un lenguaje a un archivo e importarla, lo que 
facilita que 10s desarrolladores intercambien sus propias plantillas personalizadas. 
Code Parameters 
La funcion Code Parameters muestra, en una ventana de sugerencia, el tip0 de 
datos de 10s parametros de un metodo o funcion mientras 10s tecleamos. A1 escri- 
bir el nombre de la funcion o metodo y abrir el parentesis, apareceran inmediata- 
mente 10s nombres y tipos de parametro en una ventana de sugerencia contextual. 
Para que forzar a que aparezcan 10s parametros de codigo, podemos pulsar Con- 
trol-Maylis-Barra espaciadora. Ademas, el parametro en uso aparece resaltado 
en negrita. 
Tooltip Expression Evaluation 
La funcion Tooltip Expression Evaluation es una caracteristica en tiempo de 
depuracion. Muestra el valor del identificador, la propiedad o expresion que esta 
bajo el cursor del raton. En el caso de una expresion, normalmente necesitara 
seleccionarla en el editor y despues mover el cursor sobre el texto seleccionado. 
Mas teclas de metodo abreviado del editor 
El editor tiene muchas mas teclas de metodo abreviado que dependen del estilode editor escogido. A continuacion, aparece una lista de las menos conocidas: 
Control-Mayus mas una tecla numerica del 0 a1 9 activa un marcador, 
indicado en el margen "para encuadernacion" del lateral del editor. Para 
volver a1 marcador, pulsamos la tecla Control mas la tecla numerica. La 
utilidad de 10s marcadores en el editor esta limitada por el hecho de que un 
nuevo marcador puede sobrescribir a otro ya existente y porque 10s marca- 
dores no son permanentes (se pierden cuando se cierra el archivo). 
Control-E activa la busqueda incremental. Hay que pulsar Control-E y 
teclear directamente la palabra que queramos buscar, sin necesidad de 
pasar por un cuadro de dialogo especial ni de hacer clic sobre la tecla 
Enter para realizar la busqueda. 
Control-Mayus-I sangra diversas lineas de codigo a1 mismo tiempo. El 
numero de espacios utilizado es el establecido en la opcion Block Indent 
de la ficha Editor del cuadro de dialogo Environment Options. Control- 
Mayus-U es la combinacion correspondiente para deshacer el sangrado del 
codigo. 
Control-O-U cambia el codigo seleccionado a mayusculas o minusculas. 
Tambien se puede usar Control-K-E para cambiar a minuscula y Con- 
trol-K-F para pasar a mayuscula. 
Control-Mayus-R inicia la grabacion de una macro, que mas tarde se 
puede reproducir utilizando la combinacion de teclas Control-Mayus-P. 
La macro graba todas las operaciones de escritura, movimiento y borrado 
realizadas en el archivo del codigo fuente. A1 reproducir la macro simple- 
mente se repite la secuencia. Las macros del editor resultan bastante utiles 
para repetir operaciones que constan de varios pasos, como volver a dar 
formato a1 codigo fuente u organizar 10s datos de una manera mas legible 
en el mismo. 
Si se mantiene pulsada la tecla Alt, se puede arrastrar el raton para selec- 
cionar zonas rectangulares del editor, no solo lineas consecutivas y pala- 
bras. 
Vistas que se pueden cargar 
En la ventana del editor ha habido otra modificacion importante, presentada en 
Delphi 6. Para cada uno de 10s archivos que se cargan en el IDE, el editor puede 
mostrar ahora diversas vistas que podemos definir de forma programada y aiiadir 
a1 sistema, y despues cargar para unos archivos determinados. 
La vista mas utilizada es la pagina Diagram, que ya estaba disponible en 10s 
modulos de datos de Delphi 5, aunque era menos potente. Existe otro conjunto de 
vistas disponibles en las aplicaciones Web, entre las que se encuentra una vista 
HTML Script, una vista previa HTML Result y muchas mas. Se pueden utilizar 
las combinaciones Alt-Av Pag y Alt-Re PBg para recorrer las pestaiias inferiores 
de este editor; con Control-Tab se salta entre las paginas (o archivos) que se 
muestran en las pestaiias superiores. 
Diagram View 
La vista de diagrama muestra las dependencias entre componentes, como las 
relaciones padrelhijo, de posesion, las propiedades enlazadas y las relaciones 
genericas. En el caso de componentes de un conjunto de datos, tambien soporta 
relaciones maestroldetalle y conexiones de busqueda. Podemos incluso aiiadir 
comentarios en bloques de texto enlazados a componentes especificos. 
El diagrama no se crea de forma automatica. Debemos arrastrar 10s compo- 
nentes desde la vista en arb01 a1 diagrama, en el que automaticamente apareceran 
las relaciones entre 10s mismos. Podemos seleccionar diversos elementos desde la 
Object TreeView y arrastrarlos todos a la vez a la ficha Diagram. 
Lo agradable es que podemos definir propiedades simplemente dibujando fle- 
chas entre 10s componentes. Por ejemplo, despues de mover un control Edit y una 
etiqueta a1 diagrama, podemos seleccionar el icono Property Connector, hacer 
clic sobre la etiqueta y arrastrar el cursor del raton sobre el control Edit. Cuando 
soltemos el boton del raton, el diagrama establecera una relacion de posesion 
basada en la propiedad FocusCont r o 1, que es la unica propiedad de la etique- 
ta que se refiere a un control Edit. Esta situacion se muestra en la figura 1.6. 
Como se puede ver, la definicion de propiedades es direccional: si arrastramos 
la linea de relacion de propiedad desde el control Edit a la etiqueta, en realidad, 
estamos intentando usar la etiqueta como valor de una propiedad del cuadro de 
edicion. Dado que eso no es posible, veremos un mensaje de error que nos indica 
el problema y nos ofrece la posibilidad de conectar 10s componentes en la direc- 
cion opuesta. 
El Diagram View nos permite crear varios diagramas para cada unidad Delphi 
(es decir, para cada formulario o modulo de datos). Simplemente se proporciona 
un nombre a1 diagrama y se puede aiiadir tambien una descripcion, haciendo clic 
sobre el boton New Diagram, se prepara otro diagrama y se puede pasar de un 
diagrama a otro usando el cuadro combinado de la barra de herramientas de la 
vista en diagrama. 
-- 
ti- 
h e 
Q+fcrolim 
Ths IS a simple version 
J 
Figura 1.6. La vista Diagram rnuestra relaciones entre cornponentes (e incluso 
perrnite establecer esas relaciones). 
Aunque se pueda emplear la vista en diagrama para establecer relaciones, su 
funcion principal es documentar nuestro diseiio. Por esa razon: es importante que 
se pueda imprimir el contenido de dicha vista. Al usar la orden estandar File>Print 
mientras este activada la vista en diagrama, Delphi nos indica que seleccionemos 
las opciones para personalizar la impresion, como se puede ver en la figura 1.7. 
M base r- 
Figura 1.7. Las opciones de impresion de la vista en diagrama. 
La informacion de la vista Diagram se guarda en un archivo separado, no 
como parte del archivo DFM. Delphi 5 empleaba 10s archivos de informacion en 
tiempo de diseiio (DTI), que tenian una estructura similar a 10s archivos INI. 
Delphi 6 y 7 todavia pueden leer el antiguo formato .DTI, per0 usan el nuevo 
formato Delphi Diagram Portfolio (.DDP). 
Estos archivos utilizan aparentemente el formato binario DFM (o uno simi- 
lar), por lo que se pueden editar como texto. Obviamente todos estos archivos son 
inutiles en tiempo de ejecucion (no tiene sentido incluirlos en la compilacion del 
archivo ejecutable). 
NOTA: Si se desea experimentar con la vista en diagrama, se puede co- 
menzar abriendo el proyecto DiagramDemo. El formulario del programa 
+:,,, A,, A: ,,,, -,- ,,,,:,J,-. ..,, ,- ,I .I- 1, C ,.., , 1 L ...-,, ,..,I.- ,A, 
LIGIIG UW3 U l i l g l i U l l i l 3 i l?~UblilUWS. U l l U GI1 GI UG lil I l g U l i l l .V Y U l l U 1IIUC;llU IllilJ 
complejo con un menu desplegable y sus elementos. 
Form Designer 
Otra ventana de Delphi con la que vamos a interactuar muy a menudo es el 
Form Designer; una herramienta visual para colocar componentes en 10s formu- 
larios. En el Form Designer, se puede seleccionar directamente un componente 
con cl raton o a traves dcl Object Inspector o la Object Treeview, mttodos 
ultimos utiles en caso de quc un control quede oculto. Si un control cubre a otro 
por complete, se puedc emplear la tecla Esc para seleccionar el control padre del 
control actual. Se pucdc pulsar la tecla Esc una o mas veces para seleccionar el 
formulario o pulsar y mantener pulsada la tecla Mayus mientras sc hace clic 
sobre cl componcntc scleccionado. Esto desactivara la selection del componente 
en uso y seleccionara el formulario por defecto. 
Esisten dos alternativas al uso del raton para fijar la posicion de un compo- 
ncnte. Se pueden definir valores para las propiedades L e f t y TOP, o bien usar 
las teclas de cursor mientras se mantiene pulsada la tech Control. El uso de las 
teclas de cursor resulta util sobre todo para precisar la posicion de un elemento 
(cuando la opcion Snap To Grid se encuentra activada), a1 igual que mantener 
pulsada la tecla Alt y utilizar el raton para mover el control. Si se pulsa la 
combinacion Control-Mayus junto con una tecla de cursor, el componente se 
mover6 solo a intervalos de cuadricula. 
Del mismo modo, a1 pulsar las teclas de cursor mientras se mantiene pulsada 
la teclaMayus, podemos precisar el tamaiio de un componente, algo que tambien 
se puede hacer mediante la tecla Alt y el raton. 
Para alinear diversos componentes o hacer que tengan el mismo tamaiio, se 
pueden sclcccionar todos ellos y establecer las propiedades Top, L e f t , Width 
o H e i g h t de todos a1 mismo tiempo. Para seleccionar varios componentes, po- 
demos haccr clic sobre ellos con el raton mientras mantenemos pulsada la tecla 
Mayus o. si todos 10s componentes se encuentran en zonas rectangulares, se 
puede arrastrar el raton hasta "dibujar" un rectangulo que 10s rodee. Para selec- 
cionar 10s controles hijo (por ejemplo, 10s botones que se encuentran dentro de un 
panel), arrastraremos el raton dcntro del panel mientras que mantendremos pulsa- 
da la tecla Control, ya que de no ser asi desplazaremos el panel. Cuando ya esten 
seleccionados 10s diversos componentes, tambien se puede fijar su posicion rela- 
tiva utilizando el cuadro de dialog0 Alignment (con la ordcn A l i g n del menu de 
metodo abreviado del formulario) o Alignment Palette (a la que accedemos 
mediante la orden del menu View>Alignment Palette). 
Cuando este terminado el diseiio de un formulario, podemos emplear la orden 
Lock C o n t r o l s del menu Edit para evitar cambiar por equivocacion la posi- 
cion de una componente en un formulario. Esto resulta util, sobre todo teniendo 
en cuenta que las operaciones Undo en 10s formularios son limitadas (solo se 
puede recuperar elementos eliminados), per0 la definicion no es permanente. 
Entre otras de sus caracteristicas, el Form Designer ofrece diversas ventanas 
de sugerencia: 
A1 mover el punter0 sobre un componente, en la sugerencia aparece el 
nombre y el tipo del componente. Desde la version 6, Delphi ofrece suge- 
rencias extendidas, con datos sobre la posicion del control, el tamaiio, el 
orden de tabulacion y mas. Esta es una mejora de la configuracion del 
entorno Show Component Captions que se puede mantener activada. 
Cuando adaptamos el tamaiio de un control, en la sugerencia aparece el 
tamaiio actual (las propiedades Wid th y H e i g h t ) . Por supuesto, estas 
caracteristicas estan disponibles solo para controles, no para componentes 
no visuales (que estan indicados en el Form Designer mediante iconos). 
A1 mover un componente, la sugerencia indica la posicion actual (las pro- 
piedades L e f t y Top). 
Por ultimo, se pueden guardar 10s archivos DFM (Delphi Form Module, Mo- 
dulo de Formulario Delphi) en el formato de recurso binario tradicional, en lugar 
de hacerlo como texto normal que es el comportamiento predeterminado. Esta 
opcion se puede modificar en el caso de un formulario individual, con el menu de 
metodo abreviado del Form Designer o establecer un valor predefinido para 10s 
formularios nuevos que creemos en la ficha Designer del cuadro de dialogo 
Environment Options. En la misma ficha, podemos especificar tambien si 10s 
formularios secundarios de un programa se crearan automaticamente a1 arrancar, 
una decision que siempre se podra modificar en el caso de cada formulario indivi- 
dual (usando la ficha Forms del cuadro de dialogo Project Options). 
Disponer de archivos DFM almacenados como texto permite trabajar de mane- 
ra mas eficaz con sistemas de control de versiones. Los programadores no se 
aprovecharan mucho de esta caracteristica, ya que se podria simplemente abrir el 
archivo DFM binario en el editor de Delphi con un comando especifico desde el 
menu de metodo abreviado del diseiiador. Por otra parte, 10s sistemas de control 
de versiones necesitan guardar la version textual de 10s archivos DFM para ser 
capaz de compararlos y extraer las diferencias entre dos versiones del mismo 
archivo. En cualquier caso, si se utilizan archivos DFM como texto, Delphi 10s 
convertira a un formato de recurso binario antes de incluirlos en el archivo ejecu- 
table del programa. Los archivos DFM estan enlazados a su ejecutable en forma- 
to binario para reducir el tamaiio del archivo ejecutable (aunque no esten 
comprimidos) y para mejorar el rendimiento en tiempo de ejecucion (se pueden 
cargar mas rapido). 
NOTA: Los archivos de texto DPM resultan m b faciles de tramportar de 
una version a otra de Delphi que sus versiones binarias. Aunque una ver- 
sion mas antigua de Delphi puede no acevtar una nueva propiedad de un - 
control en un archivo DFM ireado por u& veni6n posterior be Delphi, la 1 
version anterior si sera capaz de leer el resto del archivo de texto DFM. Sin 
a,t...,,, A I, ..,,..:L.. ,A- c~.-.:~,+, A, r\-1-L: -Z.-.Ar. .... ....-.., +:,, A, A,+,.. GuIualgu, SI la YGIJIUU 111aa IGUGULG UG U G I ~ L U mau~ u u IIUGVU c~yu UG uacua, 
la version anterior no podra leer en absoluto 10s archivos binarios DFM 
mas recientes. hcluso aunque no suene probable, recuerde que 10s sistemas 
que funcionan con 64 bits e s t b a la vuelta de la esquina. Si tiene dudas, 
guarde 10s archivos en formato texto DFM. Fijese tarnbien en que todas las 
versiones de Delphi soportan DFM en formato texto, usando la herrarnienta 
en linea de comandos convert que se encuentra en el directorio bin. Por 
ultimo, tenga presente que la biblioteca CLS utiliza la extension XFM en 
lugar de la extension DFM, tanto en Delphi como en Kylix. 
Object lnspector 
Para visualizar y modificar las propiedades dc 10s componentes de un formula- 
rio (u otro disciiador) en tiempo de diseiio, se puede utilizar el Object Inspector. 
En comparacion con las primeras versiones de Delphi, el Object lnspector dis- 
pone de unas cuantas caracteristicas nuevas. La ultima, presentada en Delphi 7, 
es cl uso de una fuente en negrita para resaltar las propiedades que tienen un valor 
distinto dcl predefinido. Otro importante cambio (en Delphi 6) es la capacidad del 
Object lnspector de desplegar las referencias de 10s componentes emplazados. 
Las propiedades que se refieren a otros componentes aparecen en un color dife- 
rcntc y pueden desplegarse seleccionado el simbolo + de la izquierda, como ocu- 
rre con 10s subcomponentes internos. A continuacion, se pueden modificar las 
propiedades de ese otro componente sin tener que seleccionarlo. La siguiente 
figura muestra un componente conectado (un menil desplegable) expandido en el 
Object lnspector mientras que se trabaja con otro componente (un cuadro de 
lista): 
Esta caracteristica de ampliacion de la interfaz tambien soporta subcompo- 
nentes, tal y como demuestra el nuevo control LabeledEdit. Una caracteristi- 
ca relacionada del Object lnspector es que podemos seleccionar el componente 
a1 que hace referencia una propiedad. Para ello, hacemos doble clic sobre el valor 
de la propiedad con el boton izquierdo del raton mientras mantenemos pulsada la 
tecla Control. Por ejemplo, si tenemos un componenteMainMenu en un formu- 
lario y estamos echando un vistazo a las propiedades del formulario en el Object 
Inspector, podemos seleccionar el componente MainMenu moviendonos a la pro- 
piedad MainMenu del formulario y haciendo doble clic sobre el valor de dicha 
propiedad mientras mantenemos pulsada la tecla Control. Con esto se selecciona 
el menu principal indicado junto con el valor de la propiedad en el Object Ins- 
pector. A continuacion aparece una lista de algunos cambios recientes del Object 
Inspector: 
La lista situada en la parte superior del Object Inspector muestra el tip0 de 
objeto y permite escoger un componente. Puede eliminarse para ahorrar 
algo de espacio, ya que se puede seleccionar componentes en la Object 
Treeview. 
Las propiedades que hacen referencia a un objeto son ahora de un color 
diferente y pueden ampliarse sin cambiar la seleccion. 
Opcionalmente se pueden ver tambien las propiedades de solo lectura en el 
Object Inspector. Por supuesto, estan en gris. 
El Object lnspector posee un cuadro de dialog0 Properties, que permite 
personalizar 10s colores de diversos tipos de propiedades y el comporta- 
miento general de esta ventana. 
Desde Delphi 5, la lista desplegable de una propiedadpuede incluir ele- 
mentos graficos. Esta caracteristica la utilizan propiedades como color 
y Cursor, y es particularmente util para la propiedad Image Index de 
10s componentes conectados a una ImageLis t . 
NOTA: Las propiedades de la interfaz plleden coafigurarse ahora en tiem- 
po de diseKo utilimdo d meet ImpMor. Este n s a s l linodeloInterfaced 
Component Reference ('Rdeiencias de G~m~pobetrte por hterfaz) presenta- 
do en KyIix/Delpbi 6, en &qxk IT& c?mp&&nk$ pueden implemmtar y 
mantener referenciae* a b interfaces siempre qae Iw ihterfaces eat& 
impl&entadas por coapmenteJ, Este mbdelb hnciicma d igrlal qae h 
antiguas y s imp~es . referencb r componentes, p m IBS propidides de 
interfaz pueden enlazaise c m 4QUier componente que implemente la 
interfaz necesaria. Las prcjpiahdes #e i n t e e no egt4.11 lhfiitadas a mtip 
de componentes especjfico (ma elwe o so's clases derivadu). Cuands ha- 
cemos clic sobm la%&, despggableen el edihr de %& Y n s w i p a r a 
. - - - . - - - . - - - . . - 
I obtener una propiedad deinterfaz, aparecen todos 10s componentes de1 for-- 1 
mulario actual (y formularios relacionados) que irnpleme& la interfaz. 
Fuentes desplegables en el Object Inspector 
El Object Inspector de Delphl tiene una lista grafica desplegable para 
diversas propiedades. Si queremos aiiadir una que muestre la imagen real 
de la fuente seleccionada y se corresponda a la subpropiedad Name de la 
propiedad Fon t , hay que instalar en Delphi un paquete que habilite la 
variable global FontName PropertyDisplayFontNames de la nue- 
va unidad VCLEditors. Esta capacidad ya estaba disponible en Delphi, 
pero quedaba inhabilitada ya que la mayoria de 10s ordenadores tienen 
instalado un gran numero de fbentes y mostrarlas todas ralentizaria 
significativamente el ordenador. En el paquete Oi FontPk, que se puede 
encontrar entre 10s programas de ejemplo, se ha hecho esto. 
Una vez que se haya instalado dicho paquete. podemos desplazarnos a la 
propiedad F o n t de cualquier componente y emplear el menu desplegable 
grafico Name, como se ve a continuacion: 
B F d ITFant) 
j Charsel 'DEFAULT-CHARSET 
1 Cob ' W cWindowText I 
Existe una segunda forma, 
. P . Existe una segunda forma, miis compteja, de personalizar el Object Ins- pector: una fuente personalizada para todo el Object Inspector, para que 
su texto resulte mhs visible. Esta caracteristica resulta especialmente util 
en el caso de presentaciones publicas. 
Categorias propiedades 
Delphi incluye tambien el concept0 de categorias de propiedades, activadas 
mediante la opcion Arrange del mcnu local del Object Inspector. Si se activa 
csta opcion, las propiedades no se listaran alfabeticamente sino que se organiza- 
ran por grupos, con la posibilidad de que cada propiedad aparezca cn diversos 
grupos. 
Las categorias tienen la ventaja de reducir la complejidad del Object Inspec- 
tor. Se puede usar el submenu View presente en cl menu de metodo abreviado 
para ocultar propiedades de determinadas categorias. sea cual sea el mod0 en que 
aparezcan (es decir, incluso aunque se desee el tradicional orden por nombrc, aun 
asi se podran las propiedades de algunas categorias). 
Object TreeView 
Delphi 5 introdujo una vista en arbol para modulos de datos: en la que se 
podian ver las relaciones entre 10s componentes no visuales, como 10s conjuntos 
de datos, 10s campos, las acciones, etc. Delphi 6 amplio esta idea a1 proporcionar 
una Object TreeView para cada diseiiador, como en el caso de 10s formularios 
simples. La Object TreeView se situa por defecto sobre el Object Inspector. 
La Object TreeView muestra todos 10s componentes y objetos del formulario 
en un arbol en el que se representan sus relaciones. 
La relacion mas obvia es la relacion padrelhijo: si colocamos un panel sobre 
un formulario, un boton dentro de cste y uno fuera del panel, en el arbol aparece- 
ran 10s dos botones, uno bajo el formulario y el otro bajo el panel, tal como 
mucstra la figura: 
Fijcse en que la vista en arbol esta sincronizada con el Object Inspector y 
con el Form Designer, de tal mod0 que cuando escogemos un elemento y cam- 
biamos el foco en una de estas tres herramientas, tambien cambiara en las otras 
dos . 
Ademas de la relacion padrelhijo, la Object TreeView muestra tambien otras 
relaciones, como la de propietariolposeido, componentelsubobjeto, coleccion/ele- 
mento, y otras especificas como conjunto de datos/conexion y fuente de datosl 
relaciones del conjunto de datos. 
A continuacion, se puede ver un ejemplo de la estructura de un menu en forma 
de arbol: 
L d h l + + - -- - 
hn New (Newl) 
em, Open (Open11 
bM, Save (Save1 ) 
A veces, en la vista en arbol aparecen tambien nodos falsos, que no correspon- 
den a un objeto real sino a uno predefinido. Como ejemplo de este comportamien- 
to, si desplegamos un componente Table (desde la ficha BDE), veremos dos 
iconos en gris que corresponden a la sesion y a1 alias. Tecnicamente, la Object 
TreeView usa iconos en gris para 10s componentes que no permanecen en tiempo 
de diseiio. Son componentes reales (en tiempo de diseiio y en tiempo de ejecu- 
cion), per0 como son objetos predefinidos que estan construidos en tiempo de 
ejecucion y no contienen datos permanentes que se puedan editar en tiempo de 
diseiio, el Data Module Designer no nos permite editar sus propiedades. Si 
colocamos una Table en el formulario, veremos tambien elementos que tienen a 
su lado una interrogacion en rojo dentro de un circulo amarillo. Este simbolo 
indica elementos parcialmente definidos. 
La Object TreeView soporta varios tipos de arrastre: 
Podemos escoger un componente de la paleta (haciendo clic sobre el, no 
arrastrandolo), mover el raton sobre el arbol y hacer clic sobre un compo- 
nente para dejarlo ahi. Esto nos permite dejar un componente en el conte- 
nedor que corresponda (formulario, panel y otros), aunque su superficie 
este totalmente cubierta por otros componentes, algo que evita, a su vez, 
que dejemos el componente en el diseiiador sin reorganizar primer0 10s 
demas componentes. 
En la vista en arbol, podemos arrastrar componentes, Ilevandolos, por ejem- 
plo, de un contenedor a otro. Con el Form Designer, en cambio, solo 
podemos utilizar la tecnica de cortar y pegar. Mover, en lugar de cortar, 
nos ofrece la ventaja de conservar las conexiones entre 10s componentes, si 
las hubiera, y de que no se pierdan como ocurre al eliminar el componente 
durante la operacion de cortar. 
Podemos arrastrar 10s componentes desde la vista en arbol a la vista en 
diagrama. 
Al pulsar con el boton derecho del raton sobre cualquier elemento de la vista 
en arbol, aparece un menu de metodo abreviado, similar a1 menu de componentes 
que obtenemos cuando el componente esta en un formulario (y en ambos casos, en 
el menu de metodo abreviado pueden aparecer elementos relacionados con 10s 
editores personalizados de componentes). Podemos incluso eliminar elementos 
del arbol. La vista en arbol sirve tambien como editor de colecciones, como pode- 
mos ver a continuacion en el caso de la propiedad Columns de un control 
Listview. En esta ocasion, no solo podemos reorganizar y eliminar 10s elementos 
existentes, sin0 tambien aiiadir elementos nuevos a la coleccion. 
1 Folrnl 
0 Bullon2 
[-I IJ 
- ::, Columns 
4 o . r L ~ r c o l w m 
L: 1 TL~~tCalurnn 
2 . TL~stCalumn 
4 3 - T L~slCd.mm 
TRUCO: Se pueden imprimir 10s contenidos de la Object TreeView para 
documentarse. Sirnplemente hay que seleccionar la ventana y usar la orden 
File>Print (no existe una orden P r i n t en el menu de metodo abreviado). 
Secretos de la Component Palette 
La Component Palette se utiliza para seleccionar componentes que sc de- 
Sean aiiadir al diseiiador actual. Si movemos el raton sobre un componente, apare- 
ccra su nombre. En Delphi 7, la sugerencia muestra tambien el nombre de la 
unidad en que se define el componente. 
La Component Palette tiene demasiadas pestaiias. Se pueden ocultar laspestaiias que contienen 10s componentes que no se planea utilizar y reorganizar la 
ventana para que se adecue a las necesidades del momento. En Delphi 7, tambien 
se pueden arrastrar las pestaiias para reorganizarlas. Mediante la pagina Palette 
del cuadro de dialog0 Environment Options, se pueden reordenar completamen- 
te 10s componentes de las diversas paginas, afiadir elementos nuevos o llevarlos 
de una pagina a otra. Cuando hay demasiadas fichas en la Component Palette, 
sera necesario moverlas para alcanzar un componente. Esiste un truco muy senci- 
110 que se puede usar en este caso: dar un nuevo nombre mas corto a cada ficha, 
para que todas ellas encajen en la pantalla (es obvio, una vez que se piensa). 
Delphi 7 ofrece otra caracteristica nueva. Cuando hay demasiados componen- 
tes en una unica pagina, Delphi muestra una flecha abajo doble; si se hace clic 
sobre ella se mostrara el resto de 10s componentes sin tener que recorrer la pagina 
Palette. 
El menu contextual de la Component Palette tiene un submenu Tabs que 
muestra todas las paginas de la paleta en orden alfabetico. Se puede utilizar este 
subrncnu para modificar la pagina activa. en particular cuando la pagina que se 
neccsita no esta visible en pantalla. 
L 
TRUCO: Se puede establecer el orden de las entradas en el submenu Tabs 
para que tengan el misrno orden que la propia paleta, en lugas de un orden 
alfabetico. Para hacer esto, hay que ir a la seccion Main Window del 
Registroi para Delphi (dentro de \Sof tware\Borland\Delphi\7 . 0 
para el usuario actual) y dar a la clave Sort Palette Tabs Menu el 
valor de 0 (falso). 
Una importante caracteristica no documentada de la Component Palette es la 
posibilidad de activar un "seguimiento directo". Si configuramos claves especia- 
les del Registro. podemos seleccionar una ficha de la paleta a1 movernos sobre la 
solapa, sin tener que hacer clic con el raton. Se puede aplicar esta misma caracte- 
ristica a las barras de desplazamiento de 10s componentes situadas a ambos lados 
de la paleta, que aparecen cuando hay demasiados componentes en la ficha. Para 
activar csta caracteristica oculta, hay que aiiadir una clave Extras dentro de la 
seccion \HKEY CURRENT USER\Software\Borland\Delphi\7.0. 
Bajo esta clave ST introducen-dos valores de cadena, Auto Palet teselect y 
Auto Palette S c r o 11 y definimos cl valor de cada cadcna como '1' 
Copiar y pegar componentes 
Una caracteristica interesante del Form Designer es la posibilidad de copiar 
y pegar componentes de un formulario a otro o de duplicar el componente en el 
formulario. Durantc dicha operation, Delphi duplica todas las propiedades, man- 
tiene 10s controladorcs dc cvcntos conectados y, si es necesario, cambia el nombre 
dcl control (quc dcbc scr unico en cada formulario). Tambien es posible copiar 
componentes del Form Designer a1 editor y viccversa. Cuando se copia un com- 
ponente en cl Portapapelcs, Delphi coloca tambien en este su descripcion textual. 
Se puede incluso editar la version textual de un componente, copiar el texto a1 
Portapapeles y luego pegarlo de nuevo en el formulario como un componente 
nuevo. Por ejemplo, si se coloca un boton sobre un formulario, se copia y luego se 
pega en un editor (que puede ser el propio editor de codigo de Delphi o cualquier 
procesador de texto), se obtendra la siguiente descripcion: 
object Buttonl: TButton 
Left = 152 
Top = 1 0 4 
Width = 75 
Height = 25 
Caption = ' B u t t o n l 
TabOrder = 0 
end 
Ahora, si se modifica el nombre del objeto, su etiqueta o su posicion, por 
ejemplo, o se aiiade una nueva propiedad, estos cambios pueden copiarse y volver 
a pegarse en un formulario. Estos son algunos cambios de muestra: 
object B u t t o n l : TButton 
L e f t = 152 
Top = 1 0 4 
Width = 75 
Height = 25 
Capt ion = ' M i Bo ton ' 
TabOrder = 0 
Font .Name = ' Arial' 
end 
Copiar esta descripcion y pegarla en el formulario creara un boton en la posi- 
cion especificada con la etiqueta Mi Boton con una fuente Arial. 
Para utilizar esta tecnica, es necesario saber como editar la representacion 
textual de un componente, que propiedades son validas para ese componente en 
particular y como escribir 10s valores para las propiedades de cadena, de conjunto 
y otras propiedades especiales. 
Cuando Delphi interpreta la descripcion textual de un componente o formula- 
rio, tambien puede cambiar 10s valores de otras propiedades relacionadas con 
aquellas que se han modificado y podria cambiar la posicion del componente, de 
forma que no solape con una copia previa. Por supuesto, si escribimos algo total- 
mente incorrect0 e intentamos pegarlo en un formulario, Delphi mostrara un men- 
saje de error indicando lo que ha fallado. 
Se pueden seleccionar diversos componentes y copiarlos a otro formulario o 
bien a1 editor de textos a1 mismo tiempo. Puede que esto resulte util cuando 
necesitamos trabajar con una serie de componentes similares. Podemos copiar 
uno en el editor, reproducirlo una serie de veces, realizar las modificaciones apro- 
piadas y, a continuacion, pegar todo el grupo de nuevo en el formulario. 
De las plantillas de componentes a 10s marcos 
Cuando copiamos uno o mas componentes de un formulario a otro, sencilla- 
mente copiamos todas sus propiedades. Una tecnica mas potente consiste en crear 
una plantilla de componentes, que hace una copia de las propiedades y del codigo 
fuente de 10s controladores de eventos. A1 pegar la plantilla en un nuevo formula- 
rio, seleccionando el pseudocomponente desde la paleta, Delphi reproduce el co- 
dig0 fuente de 10s controladores de eventos en el nuevo formulario. 
Para crear una plantilla de componentes, seleccionamos uno o m b componen- 
tes y activamos la orden del menu Component>Create Component Template. 
Esta abre el cuadro de dialog0 Component Template Information, en el que 
hay que introducir el nombre de la plantilla, la ficha de la Component Palette 
en la que deberia aparecer y un icono: 
De manera predeterminada, el nombre de la plantilla es el nombre del primer 
componente seleccionado, seguido de la palabra Template. El icono predefinido 
de la plantilla es tambien el icono del primer componente seleccionado, per0 se 
puede sustituir con un archivo de icono. El nombre que se de a la plantilla del 
componente sera el utilizado para describirlo en la Component Palette (cuando 
Delphi muestre la sugerencia contextual). 
Toda la informacion sobre las plantillas de componentes se almacena en un 
unico archivo, D E L P H I 3 2 . DCT, per0 aparentemente no hay forma de recuperar 
dicha informacion y editar una plantilla. Sin embargo, lo que si se puede hacer es 
colocar la plantilla de componentes en un formulario completamente nuevo, edi- 
tarlo e instalarlo de nuevo como una plantilla de componentes utilizando el mismo 
nombre. De este mod0 se podra sobrescribir la definicion anterior. 
TRUCO: Un grupo de programadores en Delphi puede compartir planti- 
llas de componentes si las guarda en un directorio comb, W i e n d o a1 
Registro la entrada CCLibDir bajo la claw \SoftwareABorland\ 
Delphi\7.0\ComponentTemplates. 
La plantillas de componentes son muy comodas cuando hay distintos formula- 
rios que necesitan el mismo grupo de componentes y controladores de eventos 
asociados. El problema es que una vez que se ha colocado una instancia de la 
plantilla en el formulario, Delphi hace una copia de 10s componentes y de su 
codigo, que ya no se referira a la plantilla. No hay ninguna forma de modificar la 
definicion de la propia plantilla, ni tampoco es posible realizar el mismo cambio 
en todos 10s formularios que usan dicha plantilla. Pero si lo podemos hacer gra- 
cias a la tecnologia de marcos de Delphi. 
Un marco es una especie de panel con el que se puede trabajar en tiempo de 
diseiio de un mod0 similar a un formulario. Simplemente se crea un nuevo marco, 
se colocan algunos controles en el y se aiiade el codigo a 10s controladores de 
eventos. Cuando el marco estalisto, se abre un formulario, se selecciona el 
pseudocomponente Frame desde la ficha Standard de la Component Palette y 
se escoge uno de 10s marcos disponibles (del proyecto actual). Despues de colocar 
el marco en el formulario, lo veremos como si 10s componentes se hubieran copia- 
do en el. Si modificamos el marco original (en su propio diseiiador), las modifica- 
ciones apareceran reflejadas en cada una de las instancias del marco. 
Podemos ver un ejemplo sencillo, llamado Framesl, en la figura 1.8. Una 
imagen realmente no significa mucho, deberia abrir el programa o reconstruir uno 
similar si desea comenzar a utilizar frames. 
Framel T 
I1 
IS Smt Smi 
(@dad 
Framel 
All 
I 
Figura 1.8. El ejemplo Framesl demuestra el uso de marcos El marco (a la 
izquierda) y su instancia en un formulario (a la derecha) permanecen en sincronia. 
A1 igual que 10s formularios, 10s marcos definen clases, por lo que encajan 
dentro del modelo orientado a objetos de la VCL con mayor facilidad que las 
plantillas de componentes. Como cabe imaginar a partir de esta introduccion 
breve, 10s marcos son una tecnica nueva realmente potente. 
Gestionar proyectos 
El Project Manager de Delphi (View>Project Manager) funciona con un 
grupo de proyectos, que puede englobar a su vez uno o mas proyectos. Por ejem- 
plo, un grupo de proyectos puede incluir una DLL y un archivo ejecutable o 
varios archivos ejecutables. Todos 10s paquetes abiertos apareceran como pro- 
yectos en la vista del Project Manager, incluso aunque no se hayan aiiadido a1 
grupo de proyecto. 
En la figura 1.9, podemos ver el Project Manager con el grupo de proyecto 
del presente capitulo. Como se puede ver, el Project Manager se basa en una 
vista en arbol, que muestra la estructura jerarquica del grupo de proyectos, 10s 
proyectos y todos 10s formularios y unidades que lo componen. Podemos emplear 
la barra de herramientas y 10s menus de metodo abreviado mas complejos del 
Project Manager para trabajar con el. El menu de metodo abreviado funciona de 
acuerdo con el contexto: sus opciones dependen del elemento seleccionado. Hay 
elementos del menu para afiadir un nuevo proyecto o un proyecto esistente a1 
grupo de proyecto, para compilar o crear un proyecto especifico o para abrir una 
unidad. 
Fata P&h - - - - - - - - - 
C Wchnos de programa\Borland\Delph17\Prolecls 
- ! 3 w e r n ~ me D \ r n ~ c o d e \ ~ ~ \ ~ ~ a g r a m ~ e r n o 
d 9 OtagrarnForrn D Lnd7caJe\Ol\D1agramDemo 
ttl a ToDoTesl exe D \md7code\0l\ToDoTest 
n J Fiamesl .ere D \rnd7caJe\Ol\Fiarnesl 
,-' 3 Fum D hd7mde\Ol\Framesl 
5 Fnm pas D \md7wdeWl\Frametl a Form1 D \md7codeWl\Fiamesl 
13 @ Frame D \rnd7codeWl \Frames1 
@ Flame pas D \md7code\Ol \Frames1 
a Fianel D hd7mde\O1 \Flames1 
Figura 1.9. El Project Manager de Delphi. 
I TRUCO: d i r d e Belphi 6; e f e e c t Manager muestra tambih 1bs pa- 1 
qudes abiaitos, hdusoaunque no selfiayaediadido sl grupo de proyedos. 
Un paquete es'w ooleccion de componente Q & otras u n i d a h que se 
compila como un archim ejccuhble 3.p- M&o se vex&& a6elante. 
De todos 10s proyectos de un grupo, solo hay uno que esta activo y ese es el 
proyecto sobre el que trabajamos cuando seleccionamos una orden como 
Project>Compile. El menu desplegable Project posee dos ordenes para compi- 
lar o crear todos 10s proyectos del grupo. Cuando tengamos que crear diversos 
proyectos, podemos establecer un orden relativo usando las ordenes Build 
Sooner y Build Later. Estas dos ordenes basicamente reorganizan 10s pro- 
yectos de la lista. 
Entre las caracteristicas avanzadas del Project Manager, se encuentra la 
funcion de arrastre de archivos de codigo fuente desde carpetas de Windows o 
desde el Windows Explorer a un proyecto de la ventana del Project Manager 
para aiiadirlos a un proyecto (tambien se soporta este comportamiento para abrir 
archivos en el editor de codigo). Podemos ver facilmente que proyecto esta selec- 
cionado y cambiarlo utilizando el cuadro combinado de la parte superior de la 
ventana o utilizando la flecha hacia abajo que se encuentra junto a1 boton Run en 
la barra de herramientas de Delphi. 
Ademas de aiiadir archivos y proyectos de Pascal, se pueden aiiadir archivos 
de recurso de Windows a1 Project Manager; estos se compilan junto con el 
proyecto. Sencillamente, hay que desplazarse a un proyecto, seleccionar Add en 
el menu de metodo abreviado y escoger Resource File (*.rc) como tipo de 
archivo. Este archivo de recurso se unira automaticamente a1 proyecto, incluso 
aunque no haya una directiva $R correspondiente. 
Delphi guarda 10s grupos de proyectos con la extension .BPG (Borland Project 
Group). Esta caracteristica procede del C++ Builder y de 10s antiguos compiladores 
Borland C++, un historial que resulta claramente visible a1 abrir el codigo fuente 
de un grupo de proyectos, que basicamente corresponde a1 de un archivo makefile 
de un entorno de desarrollo C/C++. Veamos un ejemplo: 
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
MAKE = $ (ROOT) \bin\make.exe - $ (MAKEFLAGS) -f$** 
DCC = $ (ROOT) \bin\dcc32. exe $ * * 
BRCC = $ (ROOT) \bin\brcc32. exe $ * * 
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
PROJECTS = Project1 .exe 
Opciones de proyecto 
El Project Manager no ofrece una forma de definir las opciones para dos 
proyectos diferentes a la vez. Sin embargo, se puede recurrir a1 dialog0 Project 
Options desde el Project Manager en el caso de cada proyecto. La primera 
ficha de Project Options (Forms) muestra la lista de 10s formularios que se 
deberian crear automaticamente cuando arranca el programa y 10s formularios 
que crea el propio programa. La siguiente ficha (Application) se usa para esta- 
blecer el nombre de la aplicacion y el nombre de su archivo de ayuda y para 
escoger su icono. Otras posibilidades de Project Options estan relacionadas con 
el compilador y el editor de enlaces de Delphi, la informacion sobre la version y el 
uso de paquetes en tiempo de ejecucion. 
Existen dos formas de configurar las opciones del compilador. Una es utilizar 
la ficha Compiler del dialogo Project Options. La otra es definir o eliminar las 
opciones individuales del codigo fuente con las ordenes { $x+ } o { $x- } , en las 
que se reemplazaria la X por la opcion que queramos definir. Esta segunda tecni- 
ca resulta mas flexible, puesto que permite modificar una opcion solo para un 
archivo de codigo fuente concreto o incluso solarnente para unas cuantas lineas de 
codigo. Las opciones del nivel de fuente sobrescriben las opciones del nivel de 
compilacion. 
Todas las opciones de un proyecto se guardan automaticamente con el, per0 en 
un archivo a parte con una extension .DOF. Este es un archivo de texto que se 
puede editar facilmente. No se deberia eliminar dicho archivo si se ha modificado 
alguna de las opciones predefinidas. Delphi tambien guarda las opciones del 
compilador en otro formato, en un archivo CFG, para la compilacion desde la 
linea de comandos. Los dos archivos poseen un contenido similar per0 tienen un 
formato distinto: el compilador de la linea de comandos dcc no puede usar archi- 
vos .DOF, sino que necesita el formato .CFG. 
Tambien se pueden guardar las opciones del compilador pulsando Control-0- 
0 (pulsar la tecla 0 dos veces mientras se mantiene pulsada la tecla Control). 
Esto inserta, en la parte superior de la unidad actual, directivas de compilador 
que corresponden a las opciones de proyecto en uso, como en el siguiente listado: 
I $ A + , B - , C+,D+, E - , F - , G + , H t , I t , J t , K - , L t , M - , N t , O+, P t , Q - , R - , S - , T - 
, U - , v t , W - , X + , Y t , Z l ) 
{ $ M I N S T A C K S I Z E $ 0 0 0 0 4 0 0 0 ) 
{$MAYSTACKSIZE $ O O I O O O O O ) 
{ $ I M A G E B A S E $ 0 0 4 0 0 0 0 0 ) 
{ S A P P T Y P E G U I ) 
ISWARN SYMBOL-DEPRECATED O N ){$WARN SYMBOL-LIBRARY O N ) 
{$WARN SYMBOL-PLATFORM O N ) 
{$WARN U N I T - L I B R A R Y O N ) 
{$WARN UNIT-PLATFORM ON) 
{$WARN UNIT-DEPRECATED O N ) 
{$WARN HRESULT-COMPAT O N ) 
{$WARN HIDING-MEMBER O N ) 
{$WARN HIDDEN-VIRTUAL O N ) 
{$WARN GARBAGE O N ) 
{$WARN BOUNDS-ERROR O N ) 
{$WARN ZERO-NIL-COMPAT O N ) 
{$WARN STRING-CONST- TRUNCED O N ) 
{$WARN FOR-LOOP-VAR-VARPAR O N ) 
{$WARN TYPED-CONS T-VARPAR O N ) 
{$WARN ASG- TO- TYPED-CONST O N ) 
{$WARN CASE-LABEL-RANGE O N ) 
{$WARN FOR-VARIABLE O N ) 
{$WARN CONS TRUCTING-ABS TRACT ON) {$WARN COMPARISON-FALSE ON) 
{$WARN COMPARISON- TRUE ON) 
{$WARN COMPARING- S IGNED- UNSIGNED ON) 
$ WARN COMBINING- S I G N E D UNSIGNED ON) 
{$WARN UNSUPPORTED-CONS TRUCT ON) 
{$WARN FILE-OPEN ON) 
{$WARN FILE-OPEN-UNITSRC ON) 
{$WARN BAD-GLOBAL-SYWBOL ON) 
{$WARN DUPLICATE-CTOR-DTOR ON) 
{$WARN I N V A L I D - D I R E C T I V E ON) 
{$WARN PACKAGE-NO- L I N K ON) 
{$WARN PACKAGED- THREADVAR ON) 
{$WARN I M P L I C I T - IMPORT ON) 
{$WARN HPPEMI T- IGNORED ON) 
{$WARN NO-RETVAL ON) 
{$WARN USE-BEFORE-DEF ON) 
{$WARN FOR-LOOP-VAR-UNDEF ON) 
{$WARN UNIT--MISMATCH ON) 
{$WARN NO-CFG-FILE-FOUND ON) 
{$WARN MESSAGE-DIRECTIVE ON) 
{$WARN I M P L I C I T - V A R I A N T S ON) 
{$WARN UNICODE- TO-LOCALE ON) 
{$WARN LOCALE- TO- UNICODE ON) 
{$WARN IMAGEBASE-MULTIPLE ON) 
{$WARN SUSPICIOUS-TYPECAST ON) 
{$WARN PRIVATE-PROPACCESSOR ON) 
{$WARN UNSAFE- TYPE O F F ) 
{$WARN UNSAFE-CODE OFF) 
ISWARN UNSAFE-CAST OFF) 
Compilar y crear proyectos 
Existen diversas formas de compilar un prbyecto. Si se ejecuta (pulsando F9 o 
haciendo clic sobre el icono Run de la barra de herramientas), Delphi lo compila- 
ra primero. Cuando Delphi compila un proyecto, compila unicamente 10s archi- 
vos que han cambiado. En cambio, si seleccionamos Compile>Build>All, se 
compilan todos 10s archivos, aunque no hayan cambiado. Esta segunda orden 
deberia ser necesaria en raras ocasiones, puesto que Delphi puede decidir normal- 
mente que archivos han cambiado y compilarlos como sea necesario. La unica 
excepcion son 10s casos en 10s que se cambian algunas opciones de proyecto, en 
cuyo caso debemos emplear la orden B u i l d A l l para que las nuevas opciones 
Sean efectivas. 
Para crear un proyecto, Delphi compila primero cada archivo de codigo fuente 
y crea una unidad compilada de Delphi (DCU). (Este paso se realiza solo si el 
archivo DCU no se ha actualizado aun). El segundo paso, que realiza el editor de 
enlaces, consiste en mezclar todos 10s archivos DCU en un archivo ejecutable, 
opcionalmente con codigo compilado de la biblioteca VCL (si no hemos decidido 
utilizar paquetes en tiempo de ejecucion). El tercer paso consiste en unir a un 
archivo ejecutable cualquier archivo de recurso opcional, como el archivo RES 
del proyecto, que contiene su icono principal y 10s archivos DFM de 10s formula- 
rios. Se pueden entender mejor 10s pasos de la compilacion y seguir el hilo de lo 
que ocurre durante dicha operacion si activamos la opcion Show Compiler 
Progress (en la pagina Preferences del cuadro de dialog0 Environment 
Options). 
- - 
ADVERTENCIA: Del@ no siempre tiene claro cuhijo feconstruir las 
unidadcs basadas en ah.bs unidades que se han m o d i f i d . Esto s s sobre 
todo verdad en 10s casos (y son muchos) en que la i n t e r v W 4 n -deI usuario 
confunde la logica del wmpilador. Por ejemplo, r m m b n u adiivas, modi- 
#3catAcodigo.fuente desde el exterior del IDE. copiar archiui,s tk &.&go 
heate ~n&uos Q wchivos DCU a1 disco, o tmer multiples ~ o p i a s de un 
archiyo fuentc dc'oni~ en la ruta dc busqucda puede e s t r o p k el proceso 
dc compiIaclln. Ctqh vez que el compilador muestra &6n naensaje de 
error estraiio, 1~ primer0 que deberiamos hacer es utilizarla oFden Bui ld 
XLl pard sincrohizar de nuevo l a caracteristica make (dq @mdmcci6n) 
corilos uchivas acfuafes del disco. . - 
La orden Compile se puede usar solo cuando se ha cargado un proyccto en el 
cditor. Si no hay ningun proyecto activo y cargamos un archivo fuente Pascal, no 
se puede compilar. Sin embargo, si cargamos el archivo fuente como si fuera un 
proyecto, podremos compilar el archivo. Para ello, simplemente seleccionamos el 
boton de la barra de herramientas Open Project y cargamos un archivo PAS. 
Ahora podemos verificar su sintaxis o compilarlo, creando un DCU. 
Ya mencionamos que Delphi permite el uso de paquetes en tiempo de ejecu- 
cion, lo que afecta a la distribucion del programa mas que a1 proceso de compila- 
cion. Los paquetes Delphi son bibliotecas de cnlace dinamico (DLL) que contienen 
componentes Delphi. A1 emplear paquetes, se consigue que un archivo ejecutable 
sea mucho mas pequeiio. Sin embargo, el programa no se ejecutara a no ser que 
este disponible la biblioteca dinamica apropiada (corno vcl50. bpl, que es 
bastante amplia) en el ordenador en el que desea ejecutar el programa. 
Si sumamos el tamafio de esta biblioteca dinamica a1 del pequeiio archivo 
ejecutable, la cantidad total de espacio en disco necesaria por el aparentemente 
pcqueiio programa, que hemos creado con 10s paquetes en tiempo de ejecucion, es 
mucho mayor que el espacio necesario por el supuestamente gran archivo ejecuta- 
ble por si solo. Por supuesto, si tenemos diversas aplicaciones en un unico siste- 
ma, ahorraremos mucho, tanto en espacio de disco como en consumo de memoria 
en tiempo de ejecucion. El uso de paquetes suele ser recomendable, pero no siem- 
pre. 
En ambos casos, 10s ejecutables Delphi resultan extremadamente rapidos de 
compilar y la velocidad de la aplicacion que obtenemos es comparable a la de un 
programa en C o C++. El codigo compilado en Delphi se ejecuta al menos cinco 
vcccs mas rapido que el codigo equivalente de herramientas interpretadas o 
"scmicompiladas". 
Ayudante para mensajes del compilador y advertencias 
Ademas de 10s clasicos mensajes del compilador, Delphi 7 ofrece una nueva 
ventana con informacion adicional sobre algunos mensajes de error. Esta ventana 
se activa mediante el comando de menu View>Additional Message Info. Mues- 
tra informacion almacenada en un archivo local, que puede actualizarse descar- 
gando una version nueva desde el sitio Web de Borland. Otro cambio en Delphi 7 
esta rclacionado con el mayor control que se tiene sobre las advertencias del 
compilador. 
El cuado de dialogo Project Options incluye ahora una pagina Compiler 
Message en la que se pueden seleccionar muchas advertencias individuales. Esta 
posibilidad se aiiadio probablemente por el hecho de que Delphi 7 tiene un nuevo 
conjunto de advertencias relacionadas con la compatibilidad con la futura herra- 
mienta Delphi for .NET. 
Estas advertencias son bastante exhaustivas, y se pueden inhabilitar como se 
muestra en la figura 1.10. 
I 
yarn- - - - - - - - -. 
3 Unit idenlifier does m t match hle name ?. 
% Na sonl~gu~at~an files laund - 
,JJ User message 
B lmpl~ut use of Varlants unit 
Errol conveltrng Unicode cha~ to locale charsel 
@ Er~or converl~q locals s l i i ~ to Unicode 
,4 Imagebase e not a rmkiile d 64k 
M 1 
LI'.Unsafe typecast 
i 
1 - 
Figura 1.10. La nueva pagina Compiler Messages del cuadro de dialogo Project 
Options. 
TambiCn se pueden habilitar o inhabilitar algunas de estas advertencias me- 
diante opciones de compilador como estas: 
( $Warn UNSAFE-CODE OFF) 
{ $Warn UNSAFE-CAST OFF) 
($Warn UNSAFE-TYPE OFF) 
En general, es mejor mantener estas opciones fuera del codigo fuente del pro- 
grams, algo que finalmente permite Delphi 7. 
Exploracion de las clases de un proyecto 
Delphi siempre ha incluido una herramienta para explorar 10s simbolos de un 
programa compilado, aunque el nombre de csta herramienta haya carnbiado mu- 
chas veces (desde Object Browser a Project Explorer y ahora a Project 
Browser). En Delphi 7, se puede activar la ventana del Project Browser me- 
diante la opcion de menu View>Browser, que muestra la misma ventana que la 
figura1 . 1 1 . El explorador permite analizar la estructura jerarquica de las clases 
de un proyccto y buscar en ella 10s simbolos y lineas del codigo fuente en que se 
haga referencia a ellos. 
Figura 1.11. Project Browser 
Al contrario que el Code Explorer, el Project Browser so10 se actualiza 
cuando se vuelve a compilar el proyecto. Este explorador permite ver listas de 
clases, unidades y globales, y tambien escoger si buscar so10 simbolos definidos 
en el proyecto o tanto del proyecto como de la VCL. Se puede cambiar la configu- 
ration del Project Browser y la del Code Explorer en la pagina Explorer de 
Environment Options o mediante el comando P r o p e r t i e s del menu desple- 
gable del Project Browser. Algunas de las categorias que se pueden ver en esta 
ventana son especificas del Project Browser; otras estan relacionadas con am- 
bas herramientas. 
Herramientas Delphi adicionales y externas 
Ademas del IDE, a1 instalar Delphi se consiguen otras herramientas externas. 
Algunas de ellas, como el Database Desktop, el Package Collection Editor 
(PCE . e x e ) y el Image Editor (1magEdi t . e x e ) estan disponibles desde el 
menu Took del IDE. Ademas, la edicion Enterprise posee un enlace a1 SQL 
Monitor (S qlMon . exe ) . Otras herramientas a las que no se puede acceder di- 
rectamente desde el IDE son, por ejemplo, las herramientas de linea de comandos 
que se pueden encontrar en el directorio bin de Delphi. Por ejemplo, entre estas 
herramientas se incluye el compilador de Delphi en linea de comandos 
(DCC3 2 . e x e ) , un compilador de recursos de Borland (BRC3 2 . e x e y 
BRCC3 2 . e x e ) y un visor de ejecutables (TDump . exe) . 
Por ultimo, algunos de 10s programas de ejemplo que se incluyen con Delphi 
son en realidad utiles herramientas que el usuario puede compilar y tener siempre 
a mano. Aqui se presentan algunas de ellas, las de mas alto nivel, la mayoria 
disponibles en la carpeta \ D e l p h i 7 \ b i n y en el menu Tools: 
Web App Debugger (WebAppDbg . exe ) : Es el servidor de depuracion 
Web introducido en Delphi 6. Se utiliza para guardar la pista de segui- 
miento de las solicitudes que el usuario envia a sus aplicaciones y para 
depurarlas. Este depurador se rescribio en Delphi 7: ahora se trata de una 
aplicacion CLX y su conectividad se basa en sockets. 
XML Mapper (XmlMapper . exe ) : Es una herramienta para crear trans- 
formaciones XML aplicadas a1 formato producido por el componente 
ClientDataSet. 
External Translation Manager (e tm60. exe) : Es la version indepen- 
diente del Integrated Translation Manager. Esta herramienta externa pue- 
de ofrecerse a traductores externos y esta disponible desde Delphi 6. 
Borland Registry Cleanup Utility (D7RegClean. exe ) : Ayuda a eli- 
minar todas las entradas de Registro aiiadidas por Delphi 7 a un ordena- 
dor. 
TeamSource: Es un sistema de control de versiones avanzado proporcio- 
nado con Delphi, que comenzo con la version 5. La herramienta es muy 
similar a su antigua encarnacion y se instala separadamente de Delphi. 
Delphi 7 ofrece la version 1.0 1 de TeamSource, la misma version disponi- 
ble despues de aplicar un parche disponible para la version de Delphi 6. 
WinSight (Ws32 . exe ) : Es un programa Windows "espia de mensajes" 
disponible en el directorio b i n . 
Database Explorer: Puede activarse desde el IDE de Delphi o como herra- 
mienta independiente, usando el programa ~ B E x p l o r . e x e del directo- 
rio b i n . Ya que esta destinada a BDE, no se utiliza mucho actual- 
mente. 
OpenHelp (oh. exe) : Es la herramienta que podemos emplear para admi- 
nistrar la estructura de 10s propios archivos de ayuda de Delphi, integran- 
do archivos de otras personas en el sistema de ayuda. 
Convert ( C o n v e r t . e xe): Es una herramienta de linea de comandos que 
podemos usar para convertir 10s archivos DFM en su descripcion textual 
equivalente y viceversa. 
Turbo Grep (Grep . exe) : Es una utilidad de busqueda de lineas de orde- 
nes, mucho mas rapida que el arraigado mecanismo Find In Files, per0 no 
es facil de usar. 
Turbo Register Server (TRegSvr . exe ) : Es una herramienta que pode- 
mos emplear para registrar bibliotecas ActiveX y servidores COM. El co- 
dig0 fuente de esta herramienta esta disponible bajo \Demos \ A c t i veX\ 
TRegSvr . 
Resource Explorer: Es un poderoso visor de recursos (pero no un editor 
de recursos propiamente dicho) que se puede encontrar bajo \Demos \ 
R e s X p l o r . 
Resource Workshop: Es un editor de recursos de 16 bits que puede con- 
trolar archivos de recursos de Win32. El CD de instalacion de Delphi 
incluye una instalacion independiente para esta herramienta. Se ofrecia 
con 10s compiladores de Borland para C++ y Pascal para Windows y era 
mucho mejor que 10s editores de recursos de Microsoft disponibles enton- 
ces. Aunque su interfaz de usuario no se ha actualizado y no trabaja con 
nombres de archivos largos, esta herramienta todavia resulta muy util para 
construir recursos especiales o personalizados. Tambien le permite explo- 
rar 10s recursos de 10s archivos ejecutables existentes. 
Los archivos creados por el sistema 
Delphi produce diversos archivos para cada proyecto y seria conveniente sa- 
ber que son y como se denominan. Basicamente, hay dos elementos que influyen 
en la forma de denominacion de 10s archivos: 10s nombres que se dan a un proyec- 
to y a sus unidades, y las extensiones predefinidas de 10s archivos que utiliza 
Delphi. 
En la tabla 1.1 se listan las extensiones de 10s archivos que encontrara en el 
directorio en el que se guarda un proyecto Delphi. La tabla muestra tambien 
cuando o en que circunstancias se crean estos archivos y su importancia de cara a 
su posterior cornpilacion. 
Tabla 1.1. Extensiones de archivos de proyecto Delphi 
BMP, 
CUR 
BPG 
BPL 
CAB 
.CFG 
.DCP 
ICO, Archivos de mapas de bits, 
iconos y cursores: archivos 
estandar de Windows usa- 
dos para almacenar ima- 
genes de mapas. 
Borland Project Group 
(Grupo de proyectos 
Borland): archivos que usa 
el nuevo Project Manager. 
Es una especie de 
makefile. 
Borland Package Library 
(Biblioteca de paquetes 
Borland): una DLL que 
contiene, entre otros, com- 
ponentes VCL que usa el 
entorno Delphi en tiempo 
de disefio o las aplicacio- 
nes en tiempo de ejecu- 
cion. (Estos archivos 
usaban una extension 
.DPL en Delphi 3.) 
Formato de archivo com- 
primido Microsoft Cabinet 
usado por Delphi para el 
despliegue Web. Un archi- 
vo CAB puede contener 
diversos archivos compri- 
midos. 
Archivo de configuracion 
con las opciones de pro- 
yecto. Similar a 10s archi- 
vos DOF. 
Delphi Component Packa- 
ge (Paquete de componen- 
tes de Delphi): un archivo 
con informacion de simbo- 
Desarrollo: 
Image Editor 
Desarrollo 
Compilacion: 
Enlace 
Compilacion 
Desarrollo 
Compilacion 
Normalmente no, per0 
pueden ser necesarios 
en tiempo de ejecu- 
cion y para una poste- 
rior modificacion. 
Necesario para compi- 
lar de nuevo todos 10s 
proyectos del grupo a 
la vez. 
Se distribuiran a otros 
desarrolladores Delphi 
y opcionalmente a 
usuarios finales. 
Distribuido a usuarios 
Necesario 
han definido opciones 
especiales de compi- 
lacion. 
Necesario cuando 
usamos paquetes. 
Solo se distribuira a 
otros desarrolladores 
.DCU 
. DDP 
.DFM 
.-DF 
lo para el codigo compilado 
en el paquete. No incluye 
codigo compilador, que se 
guarda en archivos DCU. 
Delphi Compiled Unit (U ni- 
dad compilada Delphi): re- 
sultado de la compilacion 
de un archivo en Pascal. 
El n uevo Delphi Diagram 
Portfolio (Cartera de 
diagrama Delphi) usado por 
la vista en diagrarna del 
editor (era DTI en Delphi 
5 ) . 
Delphi Form File (Archivo 
de formulario de Delphi): 
un archivo binario con la 
descripcion de las propie- 
dades de un formulario (o 
un modulo de datos) y de 
10s componentes que con- 
tiene. 
Copia de seguridad de 
Delphi Form File (DFM) 
Com pilacion 
Desarrollo 
Desarrc 
Desarrollojunto con 10s archivos 
BDPL. Se puede 
compilar una aplica- 
cion con las unidades 
de un paquete simple- 
mente con el archivo 
DCP y el BPL (sin 
archivos DCU). 
Solo si el codigo 
fuente no esta dispo- 
nible. Los archivos 
DCU de las unidades 
que escribimos son un 
paso intermedio, por 
lo que favorecen una 
compilacion mas 
rapida. 
No. Este archivo 
almacena informacion 
"solo en tiempo de 
disefio" no necesaria 
para el programa 
resultante per0 muy 
importante para el 
programador. 
Si. Todos 10s formula- 
rios se almacenan 
tanto en un archivo 
PAS como en un 
DFM. 
No. Este archivo se 
crea al guardar una 
version de la unidad 
relacionada con el 
formulario y el archivo 
del formulario junto 
con ella. 
DFN Archivo de soporte para Desarrollo (ITE) Si (para el ITE). Estos 
Integrated Translation 
Environment (hay un archi- 
vo DFN para cada formula- 
rio y cada lenguaje 
o bjetivo). 
DLL Dinamic Link Library (Bi- Cornpilacion 
blioteca de enlace dinami- Enlace 
co): otra version de un 
archivo ejecutable. 
DOF Delphi Option File: archivo Desarrollo 
de texto con la configura- 
cion actual de las opciones 
actuales para las opciones 
del proyecto. 
DPK y 
~ h o r a tam- 
lien .DPKW 
r .DPKL 
DPR 
-DP 
DSK 
Delphi Package: el archivo Desarrollo 
de codigo fuente del pro- 
yecto de un paquete (o un 
archivo de proyecto espe- 
cifico para Windows o 
Linux). 
Archivo Delphi Project. Desarrollo 
(Este archivo contiene en 
realidad codigo fuente 
Pascal.) 
Copia de seguridad del ar- Desarrollo 
chivo Delphi Project 
(.DPR). 
Desktop file (Archivo de es- Desarrollo 
critorio): contiene infor- 
macion sobre la posicion 
de las ventanas Delphi, 10s 
archivos que se abren en 
el editor y otras configura- 
ciones del escritorio. 
archivos contienen 
cadenas traducidas 
para cada formulario 
que editarnos en el 
Translation Manager 
Vease .EXE 
Necesario solo si se 
han instalado opcio- 
nes especiales del 
compilador. 
Si. 
No. Este archivo se 
crea automaticarnente 
al guardar una nueva 
version de un archivo 
de proyecto. 
No. En realidad debe- 
rian eliminarse si se 
copia el proyecto en 
un nuevo directorio. 
DSM 
EXE 
HTM 
LIC 
OBJ 
. OCX 
.PAS 
Delphi Symbol Module (Mo- Cornpilacion 
dulo de simbolos Delphi): (pero solo si se 
Alrnacena toda la informa- ha activado la 
cion de sirnbolo del explora- opcion Save 
dor. Symbols) 
Executable file (Archivo eje- Compilacion: 
cutable): la aplicacion Enlace 
Windows creada. 
0 .HTML (Hypertext Despliegue Web 
Markup Language, Len- de un 
guaje de rnarcas con ActiveForrn 
hipertexto): el forrnato de 
archivo usado para pagi- 
nas Web. 
Los archivos de licencia Asistente 
relacionados con un archi- ActiveX y otras 
vo OCX. herrarnientas 
Object file (Archivo objeto) Paso intermedio 
(cornpilado), tipico del de compilacion, 
rnundo C/C++. generalmente no 
se usa en 
Delphi. 
OLE Control Extension (Ex- Compilacion: 
tension de control OLE): Enlace 
una version especial de una 
DLL, que contiene controles 
ActiveX o forrnularios. 
Pascal file (Archivo de Desarrollo 
Pascal): El codigo fuente 
de una unidad Pascal, una 
unidad relacionada con un 
forrnulario o una unidad 
independiente. 
No. El Object Browser 
usa este archivo, en 
lugar de 10s datos en 
memoria, cuando no 
puede volver a compi- 
lar un proyecto. 
No. Este archivo que 
se distribuira incluye 
todas las unidades 
compiladas, forrnula- 
rios y recursos. 
No. No participa en la 
cornpilacion del pro- 
yecto. 
No. Es necesario usar 
el control en otro 
entorno de desarrollo. 
Podria ser necesario 
para rnezclar Delphi 
con codigo cornpilado 
C++ en un tinico 
proyecto. 
Vease .EXE. 
-PA 
RES, .RC 
.RPS 
.TLB 
TODO 
.UDL 
Copia de seguridad de un Desarrollo 
archivo Pascal (.PAS). 
No. Este archivo lo 
crea Delphi autorna- 
ticamente al guardar 
una nueva version del 
codigo fuente. 
Resource file (Archivo de 
recurso): el archivo binario 
asociado con el proyecto 
de una aplicacion y que 
normalmente contiene su 
icono. Podernos afiadir 
otros archivos de este tip0 
a un proyecto. Cuando 
creamos archivos de recur- 
so personalizados pode- 
rnos usar tambien el 
forrnato textual .RC. 
Cuadro de dialo- 
go Development 
Options. El ITE 
(Integrated 
Translation 
Environment) 
crea archivos de 
recurso con 
comentarios 
especiales. 
Translation Repository Desarrollo (ITE) 
(parte de Integrated 
Translation Environment). 
Type Library (Biblioteca de Desarrollo 
tipos): un archivo creado 
de forrna autornatica o por 
el Type Library Editor para 
aplicaciones del servidor 
OLE. 
Archivo de lista To-do en Desarrollo 
el que se guardan elernen- 
tos relacionados con el 
proyecto entero. 
Microsoft Data Link (Enlace Desarrollo 
de datos Microsoft). 
Si. Delphi crea de 
nuevo el archivo RES 
principal de una apli- 
cacion en funcion de 
la inforrnacion de la 
ficha Application del 
cuadro de dialogo 
Project Options. 
No. Necesario para 
adrninistracion de las 
traducciones. 
Este es un archivo 
que pueden necesitar 
otros prograrnas OLE. 
No. Este archivo 
contiene notas para 
10s programadores. 
Usado por ADO para 
referirse a un provee- 
dor de datos. Similar 
a un alias en el entor- 
no BDE. 
Ademas de 10s archivos creados durante el desarrollo de un proyecto en Delphi, 
existen muchos otros creados y usados por el propio IDE. En la tabla 1.2, se 
rn 
presenta una breve lista de las extensiones que merece la pena conocer. La mayo- 
ria de estos archivos estan en formatos propietarios no documentados, por lo que 
poco se puede hacer con ellos. 
Tabla 1.2. Extensiones de archivo de personalizacion del IDE de Delphi 
seleccionadas. 
. DC I Delphi Code Templates (Plantillas de codigo Delphi). 
.DRO Delphi Object Repository (Object Repository de Delphi) (De- 
beria modificarse el Repository con la orden Tools> 
Repository.) 
. DMT Delphi Menu Templates (Plantillas de menu de Delphi). 
.DBI Database Explorer Information (Informacion del explorador 
de bases de datos). 
.DEM Delphi Edit Mask (Mascara de edicion de Delphi) (Archivos 
con formatos especificos seglin paises para mascaras de 
edicion). 
. DCT Delphi Component Template (Plantillas de componentes de 
Delphi). 
.DST Desktop Settings File (Archivo de configuracion del escrito- 
I rio): uno para cada configuracion de escritorio definida. 
Un vistazo a 10s archivos de codigo fuente 
Los archivos basicos de Delphi son 10s archivos de codigo fuente en Pascal, 
que son archivos de testo ASCII normales. El texto en negrita, cursiva y colorea- 
do que se ve en el editor depende de la forma en que se resalte la sintaxis, per0 no 
se guarda esa configuracion junto con el archivo. Merece la pena destacar que 
hay un unico archivo para todo el codigo del formulario, no solo pequeiios frag- 
mentos de codigo. 
- . . - - - - - - - - . - - - - - ----- 
TRUCO: En 10s listados de este libro, hemos asociado la fnrma de regaltar 
la sintaxis en negrita del editor a las palabras clave y la cnrsira p lrts 
cadenas y 10s comentarios. 
En el caso de un formulario, el archivo Pascal contiene la declaracion de clase 
del formulario y el codigo fuente de 10s controladores de eventos. Los valores de 
las propiedades que se definen en el Object Inspector se almacenan en un archi- 
vo a parte con la descripcion de formulario (con extension .DFM). La unica 
excepcion es la propiedad Name, que se usa en la declaracion de formulario para 
hacer referencia a 10s componentes del formulario. 
El archivo DFM es de manera predeterminada una representacion textual del 
formulario, pero se puede guardar en cl formato binario tradicional Resource de 
Windows. Podemos establecer el formato predefinido que queremos usar para 
proyectos nuevos en la ficha Preferences del cuadro de dialog0 Environment 
Options y cambiar el formato de formularios individuales con la orden Tcxt 
DFM del menu de metodo abreviado de un formulario. Un editor de texto normal 
puede leer solo la version de texto.Sin embargo, se pueden cargar 10s archivos 
DFM de ambos tipos en el editor Delphi, que 10s convertira primero, si cs neccsa- 
rioj en una descripcion textual. La forma mas sencilla de abrir la descripcion 
textual dc un formulario (sea en el formato que sea) es seleccionar la orden View 
A s Text del menu de metodo abreviado del Form Designer. Esta orden cierra 
el formulario, lo guarda si es necesario y abre el archivo DFM en el editor. Mas 
tarde sc puede volver a1 formulario usando la orden View A s Form del menu dc 
metodo abreviado de la ventana del editor. 
En realidad, se puede editar la descripcion textual de un formulario, aunquc 
esto deberia hacerse con extremo cuidado. Desde el momento en que se guarde el 
archivo, se convertira de nuevo en un archivo binario. Si se han hecho cambios 
incorrectos, se detendra la compilacion con un mensaje de error y habra que 
corregir el contenido del archivo DFM antes de volver a abrir el formulario. Por 
esa razonj no se deberia intentar cambiar la descripcion textual de un formulario 
manualmentc hasta disponcr de un solido conocimiento de programacion en Delphi. 
propiedades m k relevantes, por lo general, he elirninado las propiedades de 
posicion, 10s valores binarios y otra lineas que ofiecen poca informacion. 
- 
TRUCO: En el libro, aparecen normalmente extractos de archivos DFM. 
En l a mayoridde estos extractos, aparecen unicamente 10s componentes o 1 
Ademas de 10s dos archivos que describen el formulario (PAS y DFM), hay un 
tercer archivo que resulta vital para volver a construir la aplicacion. Este es el 
archivo de proyecto de Delphi (DPR), otro archivo de codigo f~iente en Pascal, 
que se crea automaticamente y que rara vez es necesario modificar manualmente. 
Puede verlo con la orden del menu View>Project Source. 
Algunos de 10s demas archivos menos relevantes creados por el IDE usan la 
estructura de archivos IN1 de Windows, en la que cada seccion se indica mediante 
un nombre que va entre corchetes. Por ejemplo, este es un fragment0 de un archi- 
vo de opciones (DOF). 
[Compiler] 
A= 1 
B=O 
[Linker] 
MinStackSize=16384 
MaxStackSize=1048576 
ImageBase=4194304 
[Parameters] 
Runparams= 
HostApplication= 
Los archivos de escritorio (DSK) utilizan la misma estructura, que contiene el 
estado del IDE de Delphi para un proyecto especifico, listando la posicion de cada 
ventana. 
[Mainwindow] 
Create=l 
Visible=l 
State=O 
Lef t=2 
Top=O 
Width=800 
Height=97 
El Object Repository 
Delphi tiene varias ordenes de menu que se pueden usar para crear un nuevo 
formulario, una nueva aplicacion, un nuevo modulo de datos, un nuevo compo- 
nente, etc. Dichas ordenes estan situadas en el menu File>New y en otros menus 
desplegables. Si seleccionamos sencillamente File>New>Other, Delphi abre el 
Object Repository, que se usa para crear nuevos elementos de cualquier tipo: 
formularios, aplicaciones, modulos de datos, objetos thread, bibliotecas, compo- 
nentes, objetos de automatizacion y muchos mas. 
El nuevo cuadro de dialogo (que se ve en la figura 1.12) posee varias fichas, 
contiene todos 10s elementos que puede crear, 10s formularios existentes y 10s 
proyectos almacenados en el Repository, asistentes Delphi y 10s formularios del 
proyecto actual. 
Las fichas y las entradas de este cuadro de dialogo con solapas dependen de la 
version especifica de Delphi, por lo que no las mencionaremos. 
por techa o por descnpcl6n) y mostrat dttim%&s ViMw (idol3 giqhks, 
iconos pequefios, listas y detalles). La vista Msib propo*ei& & hes- 
cripcion, autor y fecha de la herramienta, una informacion que resulta so- 
bre todo importante cuando se echa un vistazo a los asistentes, proyectos o 
formularios que hemos aiiadido a1 Repository. 
Cunlrol Panel 
Appbcalmn 
TI 
Flame 
1 - C 
Control Panel Dda Module 
Module 
Package Ploiect GI- 
Console 
Cwone* Applcat~on 
DCC W~zad Fam 
Resource DLL Service 
Wnald 
Figura 1.12. La primera pagina del cuadro de dialogo New Items, 
generalmente corno Object Repository. 
conocida 
El mod0 mas sencillo de personalizar el Object Repository es aiiadir nuevos 
proyectos, formularios y modulos de datos como plantillas. Tambien podemos 
aiiadir fichas nuevas y organizar 10s elementos de algunos de ellas (sin incluir las 
fichas New ni la del proyecto en uso). Cuando se tiene una aplicacion en funcio- 
namiento que se quiere emplear como punto de arranque para el desarrollo de 
programas similares, se puede guardar el estado actual en una plantilla para 
usarla mas tarde. Simplemente se usa la orden Project>Add To Repository y se 
, cubre su cuadro de dialogo. 
Tambien se pueden aiiadir nuwas plantillas de formulario. Sencillamente des- 
plazamos el formulario que se quiere aiiadir y seleccionamos la orden ~ d d T o 
R e p o s i t o r y del menu de metodo abreviado. A continuacion, indicamos el titu- 
lo, la descripcion, el autor, la ficha y el icono en su cuadro de dialogo. Hay que 
tener en cuenta que si se copia un proyecto o una plantilla de formulario a1 
Repository y se vuelve a copiar a otro directorio, simplemente se realiza una 
operacion de copiar y pegar; no es muy distinto de copiar 10s archivos manual- 
mente. 
I La plmWla de pmyecb en blanco I 
Cuando se inicia un nuevo proyecto, autodticamente se abre tambib un 
formulario en blgaco. Sin embargo, si queremos basar el nuevo proyecto en 
urn, de 10s objetos de fbmularios o asistentes, habra que afiadir una planti- 
hay que seguir para ello son: 
1. Crear un nuevo proyecto como de costumbre. 
2. Eliminar el unico formulario del proyecto. 
3. Aiiadir este proyecto a las plantillas y denominado Empty Project. 
Cuando seleccionamos este proyecto en el Object Repository, se obtienen 
dos ventajas: tener su proyecto sin un formulario y poder escoger un direc- 
torio en el que se copiaran 10s archivos de la plantilla de proyecto. Tambien 
hay una desventaja, habra que recordar usar la orden FileSave Project 
AS para dar un nuevo nombre a1 proyecto, porque si se guarda el proyecto 
de otro modo se utiliza automaticamente el nombre predefinido de la plan- 
tilla. 
Para personalizar aun mas el Repository se puede usar la orden Tools> 
Repository. Esta orden abre el cuadro de dialog0 del Object Repository, que se 
puede emplear para mover elementos a distintas fichas, aiiadir elementos nuevos 
o borrar 10s que ya existen. Incluso se pueden aiiadir fichas nuevas, darles un 
nombre nuevo o eliminarlas y cambiar su orden. Un elemento importantc de la 
instalacion del Object Repository es el uso de 10s valores predefinidos: 
Usar la casilla de verificacion New Form bajo la lista dc objetos para 
designar un formulario como el que se usara cuando se Cree un nuevo 
formulario (File>New Form). 
La casilla de verificacion del Main Form indica que tipo de formulario 
emplear cuando se crea el formulario principal de una nueva aplicacion 
(File>New Application), si no se selecciona un New Project especial. 
La casilla de verificacion New Project, disponible cuando se selecciona 
un proyecto, marca el proyecto por defecto que Delphi utilizara cuando se 
de la orden File>New Application. 
Solo un formulario y un proyecto del Object Repository pueden tener cada 
una de estas tres configuraciones marcadas con un simbolo especial situado sobre 
su icono. Si no se selecciona ningun proyecto como New Project, Delphi crea un 
proyecto por defecto basado en el formulario marcado como Main Form. Si no 
hay ningun formulario marcado como Main Form, Delphi crea un proyecto por 
defecto con un formulario en blanco. Cuando trabajamos con el Object 
Repository, trabajamos con formularios y modulos guardados en el subdirectorio 
OBJREPOS del directorio principal de Delphi. En este momento, si usamos un 
formulario u otro objeto directamente sin copiarlo, acabaremos teniendo algunos 
archivos de nuestro proyecto en este directorio. Es importante darse cuenta de 
como funciona cl Repository, porque si queremos modificar un proyecto o un 
objetoguardados en 61; la mejor tecnica es trabajar con 10s archivos originalcs, 
sin copiar 10s datos una y otra vez en el Repository. 
. 
lnstalar nuevos asistentes DLL 
Tecnicamente, 10s nuevos asistentes poseen dos formas diferentes: pueden 
formar parte de 10s componentes o de 10s paquetes o pueden distribuirse 
como archivos DLL independientes. En el primer caso, se instalaria del 
mismo mod0 que un componente o un paquete. Cuando se recibe una DLL 
independiente, hay que aiiadir el nombre de la DLL a1 Registro de Windows 
baio la clave \Sof tware\Borland\DelDhi\7.O\Ex~erts. Sirn- a . . 
plemente se aiiade una nueva clave de cadena bajo esta clave, se escoge un 
nombre (no importa realmente cual) y se utiliza como texto la ruta y nom- 
L - _ J - ---l-_.- 3 - 1 __:_*_-A_ n m T 0 . . 2 . _ - I - _ _..*---l-_ -..- _._ _ _ L Z _ _ ore a e arctuvo ael asmenre ULL. 3 e pueaen ver las enrraaas que ya estan 
presentes bajo la clave Experts para averiguar el mod0 en que se debe 
introducir la ruta. 
Actualizaciones del depurador en Delphi 7 
Cuando se ejecuta un programa en el IDE de Delphi, generalmente se arranca 
en el depurador integrado. Se pueden fijar puntos de ruptura, ejecutar el codigo 
linea a linea y explorar sus detalles internos, como el codigo ensamblador que se 
ejecuta y el uso de 10s registros de la CPU en la vista CPU. 
Para mencionar un par de las nuevas caracteristicas del depurador, en primer 
lugar el cuadro de dialog0 Run Parameters en Delphi 7 permite establecer un 
directorio de traba.jo para el programa que se va a depurar. Esto significa que el 
directorio actual sera el que se indique, no aquel en el que se haya compilado del 
programa. Otra modificacion importante tiene que ver con la Watch List. Ahora 
dispone de multiples pestaiias que permiten mantener un conjunto distinto de 
escuchas de variables activo para las distintas areas del programa que se esta 
depurando, sin amontonarse en una unica ventana. Puede aiiadirse un grupo nue- 
vo a la Watch List mediante su menu abreviado y tambien modificar la visibilidad 
de las cabeceras de las columnas y habilitar escuchas individuales con sus corres- 
pondientes casillas de activacion. 
-- 
Wc_hName ' V W - - _ - _ . . . - 
rn Controls ' ' expected but end of lde found 
rn TRad~oButton Symbol was el~mtnated by l~nker I 
El lenguaje 
de programaclon 
Delphi 
El entorno de desarrollo para Delphi se basa en una extension orientada a 
objetos del lenguaje de programacion Pascal conocida como Object Pascal o Pascal 
orientado a objetos. Recientemente, Borland declaro su intencion de referirse a1 
lenguaje como "el lenguaje Delphi", probablemente porque la empresa deseaba 
ser capaz de decir que Kylix usa el lenguaje Delphi y porque Borland ofrecera el 
lenguaje Delphi sobre la plataforma .NET de Microsoft. Debido a la costumbre 
de 10s aiios, es comun utilizar ambos nombres por igual. 
La mayoria de 10s lenguajes de programacion modernos soportan programa- 
cion orientada a objetos (OOP). Los lenguajes OOP se basan en tres conceptos 
fundamentales: la encapsulacion (normalmente implementada mediante clases), 
la herencia y el polimorfismo (o enlace tardio). Aunque se puede escribir codigo 
Delphi sin comprender las caracteristicas principales del lenguaje, no es posible 
dominar este entorno hasta que se comprende totalmente el lenguaje de programa- 
cion. Este capitulo trata 10s siguientes temas: 
Clases y objetos. 
Encapsulacion: p r i v a t e y pub1 ic. 
Uso de propiedades. 
Constructores. 
Objetos y memoria. 
Herencia. 
Metodos virtuales y polimorfismo. 
Conversion de tipos segura (informacion de tip0 en tiempo de ejecucion). 
Interfaces. 
Trabajo con excepciones. 
Referencias de clase. 
Caracteristicas centrales del lenguaje 
El lenguaje Delphi es una extension OOP del clasico lenguaje Pascal, que 
Borland ha liderado durante muchos aiios con sus compiladores Turbo Pascal. La 
sintaxis del lenguaje Pascal suele considerarse bastante explicita y mas legible 
que, por ejemplo, el lenguaje C. Su extension orientada a objetos sigue el mismo 
enfoque, ofreciendo la misma potencia de 10s recientes lenguajes OOP, desde Java 
a C#. 
Incluso el nucleo del lenguaje esta sujeto a cambios continuos, per0 algunos de 
ellos afectaran a las necesidades diarias de programacion. En Delphi 6, por ejem- 
plo, Borland aiiadio el soporte para varias caracteristicas mas o menos relaciona- 
das con el desarrollo de Kylix, la version para Linux de Delphi: 
Una directiva nueva para la compilacion condicional ($IF). 
Un conjunto de directivas de sugerencia ( p l a t f o r m , d e p r e c a t e y 
l i b r a r y , de las cuales solo se suele usar la primera) y la nueva directiva 
$WARN que se utiliza para inhabilitarlas. 
Una directiva $MESSAGE para emitir informacion personalizada entre 10s 
mensajes del compilador. 
Delphi 7 aiiade tres advertencias del compilador adicionales: tipo inseguro, 
codigo inseguro, y conversion insegura. Estas advertencias se emiten en caso de 
operaciones que no se puedan utilizar para generar codigo "gestionado" seguro 
sobre la plataforma Microsoft .NET. 
Otra modification se encuentra relacionada con 10s nombres de unidad, que 
ahora pueden formarse con multiples palabras separadas por puntos, como en la 
unidad m a r c o . t e s t , almacenada en el archivo m a r c o . t e s t . p a s . 
Esta caracteristica ayudara a ofrecer soporte para espacios de nombres y 
para referencias de unidad mas flexibles en Delphi para .NET y las futuras ver- 
siones del compilador Delphi para Windows, per0 en Delphi 7 tiene un uso limi- 
tado. 
Clases y objetos 
Delphi se basa en 10s conceptos de la orientacion a objeto y, en particular, en 
la definition de nuevos tipos de clase. 
El uso de OOP esta forzado en parte por el entorno de desarrollo visual, ya que 
para cada formulario nuevo definido en tiempo de disefio, Delphi define 
automaticam'ente una clase nueva. Ademas, cada componente situado visualmente 
en un formulario es un objeto de un tip0 de clase disponible en la biblioteca del 
sistema o afiadido a ella. 
NOTA: Los tkrminos clase y objeto se utdizan con mucha fiecuencia y a 
rnenudo se confunden, ssi que asegurbmonos de estar de acuerdo sobre sus 
definiciones. Una clase es un tip0 de dabs definido por el usuario, que 
posee un estado (su representacibn o sus datos internos) y algunas opera- 
ciones (su comportamiento o sus mbtodos). Un objeto es una instancia de 
una clase o una variable del tipo de datos demdo por la clase. Los objetos 
son entidades rcales. ~ u a n d ~ e l programa se ejeiuta, los objetos ocipan 
park de la memoria para su repreaentacilln intern. La relacih en- objeto 
y clase es la misma que entre variable y tipo. 
Como en la mayor parte del resto de 10s lenguajes orientados a objetos (como 
Java y C#), en Delphi una variable de tipo clase no proporciona el almacenamien- 
to para el objeto, sino solo un punter0 o referencia al objeto en la memoria. Antes 
de utilizar el objeto, se debe reservar memoria para 61 mediante la creacion de una 
nueva instancia o asignando una instancia ya existente a la variable: 
var 
Obj 1, Obj2 : TMyClass; 
begin 
// a s i g n a r un o b j e t o r e c i e n c r e a d o 
Objl := TMyClass.Create; 
// a s i g n a r un o b j e t o e x i s t e n t e 
Obi2 : = ExistingObject; 
La llamada a create invoca un constructor predefinido disponible para cada 
clase, a no ser que la clase lo vuelva a definir (como ya veremos). Para declarar 
un nuevo tipo de datos de clase en Delphi, con algunos campos de datos locales y 
algunos metodos, se puede utilizar la siguicnte sintaxis: 
type 
TDate = class 
Month, Day, Year: Integer; 
procedure SetValue (m, d, y: Integer); 
function Leapyear: Boolean; 
end; 
h~ GE JUlU U W W I l V G U b l U l l WWir GI W l l l ~ l i W l , 1 ES &UlW 1CL14 CiVUlV 
cualquier otra), per0 es tan frecuente que respetarla harfr' que el d g o 
resulte intis facil de entender. 
qOTA:La convenci6n en Delphi es usar la letra T mmo prefijo para el 
lombre de cada clase que se escribe y cualquier otro tipo (T significa Tipo). 
?,A, ,, ,'I, ..,, ,,--.,,, :*, I,,,, -1 ,,,:t,A,, 'Pa, ,'I ,,.,, I d , , ,,,, 
Un metodo se define con la palabra clave f u n c t i o n o p r o c e d u r e , segun 
si dispone de un valor de retorno o no. Dentro de la definicion de clase, solo se 
pueden definir 10s metodos; despues deben definirse en la seccion de implernentacion 
de la misma unidad. En este caso, se antepone a1 nombre de cada metodo el 
nombre de la clase a la que pertenece, mediante una notacion de puntos: 
procedure TDate.SetValue (m, d, y: Integer) ; 
begin 
Month : = m; 
Day := d; 
Year := y; 
end; 
function TDate.LeapYear: Boolean; 
begin 
// l l a m a I s L e a p Y e a r en S y s U t i l s . p a s 
Result : = IsLeapYear (Year) ; 
end; 
TRUCO: Si se pulsa Controi-Maylis-C mientras que el cursor se m'cw- 
tra sobre la definicion de clase, la ~aracteristiea Class Completion 
del editor de Delphi generara el esqueleto de la deWci6n d& 10s rn6bcbs 
declarados en una clase. 
Es asi como se puede usar un objeto de la clase definida anteriormente: 
var 
ADay: TDate; 
begin 
// c r e a u n o b j e t o 
ADay : = TDate.Create; 
t r~ 
// u s a e l o b j e t o 
ADay-SetValue ( 1 , 1 , 2000); 
if ADay-LeapYear then 
ShowMessage ( ' A d o b i s i e s t o : ' + IntToStr (ADay-Year)); 
finally 
// d e s t r u y e e l o b j e t o 
ADay. Free; 
end ; 
end : 
Fijese en que ADa y . LeapYear es una expresion similar a ADa y . Year, sin 
embargo, la primera es una llamada a una funcion y la segunda es un acceso 
direct0 a datos. Opcionalmente se pueden aiiadir parentesis tras la llamada a la 
funcion sin parametros. Se pueden encontrar 10s fragmentos de codigo anteriores 
en el codigo fuente del ejemplo Date 1, la unica diferencia es que el programa crea 
una fecha basada en el aiio que se introduce en un cuadro de edicion. 
Mas sobre metodos 
Hay mucho mas que comentar sobre 10s metodos. Estas son algunas breves 
notas sobre las caracteristicas disponibles en Delphi: 
Delphi soporta la sobrecarga de metodos. Esto significa que se pueden 
tener dos metodos con el mismo nombre, siempre que se marquen 10s meto- 
dos con la palabra clave o v e r l o a d y que las listas de parametros de 10s 
dos metodos Sean lo suficientemente diferentes. Mediante la comprobacion 
de 10s parametros. el compilador puede determinar que version se desea 
Ilamar. 
Los metodos pueden tener uno o mas parametros con valores predefinidos. 
Si estos parametros se omitiesen en la llamada a1 metodo, se asignaria el 
valor predefinido. 
Dentro de un metodo se puede usar la palabra clave self para acceder a1 
objeto actual. Cuando se hace referencia a 10s datos locales del objeto, la 
referencia a s e l f es implicita. Por ejemplo, en el metodo s e t v a l u e de 
la clase TDa t e comentada anteriormente, se usa Month para hacer refe- 
rencia a un campo del objeto y el compilador transforma Month en 
S e l f .Month. 
Se pueden definir metodos de clase, indicados por la palabra clave c l a s s . 
Un metodo de clase no tiene una instancia de objeto sobre la que actuar, ya 
que puede aplicarse a un objeto de la clase o a la clase en su totalidad. 
Actualmente Delphi no tiene un mod0 de definir datos de clase, per0 puede 
simularse esta prestacion aiiadiendo datos globales en la porcion de 
implementacion de la unidad en que se defina a la clase. 
De manera predeterminada, 10s metodos usan la convencion de llamada 
r e g i s t er : 10s parametros (simples) y 10s valores de retorno se pasan del 
codigo de llamada a la funcion y de vuelta mediante registros de la CPU, 
en lugar de en la pila. Este proceso hace que las llamadas a metodo resul- 
ten mucho mas rapidas. 
Creacion de componentes de forma dinamica 
Para hacer hincapie en el hecho de que 10s componentes de Delphi no son muy 
distintos de otros objetos (y para demostrar el uso de la palabra clave S e l f ) , 
existe el ejemplo CreateCompos. Este programa tiene un formulario sin compo- 
nentes y un manejador para su evento OnMouseDown, escogido porque recibe 
como uno de 10s parametros la posicion del clic de raton (no como el evento 
O n c l i c k ) . 
Esta informacion es necesaria para crear un componente boton en esa posi- 
cion. Veamos el codigo de este metodo: 
procedure TForml.FormMouseDown (Sender: TObject; 
Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
var 
Btn: TButton; 
begin 
Btn := TButton-Create (Self) ; 
Btn-Parent := Self; 
Btn-Left := X; 
Btn-Top : = Y; 
Btn-Width := Btn.Width + 50; 
Btn-Caption := Format ('Botdn en %d, % d l , [ X , Y]); 
end ; 
Con este codigo, se crean botones en las posiciones en las que se haga clic con 
el raton, como muestra la figura 2.1. En el codigo anterior, fijese en concreto en el 
uso de la palabra clave S e 1 f , tanto como parametro del metodo c r e a t e (para 
especificar el dueiio del componente), como valor de la propiedad P a r e n t . 
Figura 2.1. El resultado del ejernplo CreateCornps, que crea componentes boton en 
tiernpo de ejecucion. 
Cuando se escribe un procedimiento como el codigo que acabamos de ver, 
podriamos sentirnos tentados a utilizar la variable F o r m l en lugar de S e l f . En 
este ejemplo concreto, el cambio no tendria ninguna diferencia practica, per0 si 
existen diversas instancias de un formulario, usar F o r m l seria un error. De 
hecho, si la variable F o r m l se refiere a1 primer formulario de ese tipo que se ha 
creado, a1 pinchar sobre otro formulario del mismo tipo, el nuevo boton siempre 
aparecera en el primer formulario. Sus O w n e r y P a r e n t seran el F o r m l y no 
el formulario que ha pinchado el usuario. Por lo general, no conviene referirse a 
una instancia concreta de una clase cuando se necesita el objeto actual. 
Encapsulado 
Una clase puede tener cualquier cantidad de datos y cualquier numero de meto- 
dos. Sin embargo, para conseguir una buena tecnica orientada a objetos, 10s datos 
deberian estar ocultos o encapsulados dentro de la clase que 10s usa. Cuando se 
accede a una fecha, por ejemplo, no tiene sentido cambiar solo el valor del dia 
directamente. De hecho, si se cambia el valor del dia podria resultar una fecha no 
valida, como el 30 de febrero, por ejemplo. Si se usan metodos para acceder a la 
representacion interna de un objeto, se limita el riesgo de generar situaciones 
erroneas, puesto que 10s metodos pueden verificar si la fecha es valida y negarse 
a modificar el nuevo valor si no lo es. El encapsulado es importante porque permi- 
te que la persona que escribe las clases modifique la representacion interna en una 
version futura. 
El concepto de encapsulado se describe normalmente como una "caja negra", 
en la que no se conoce el interior: simplemente se sabe como interactuar con ella 
o como usarla, sin tener en cuenta su estructura. La parte "modo de empleo", 
denominada interfaz de clase, permite que otras partes de un programa tengan 
acceso y utilicen 10s objetos de dicha clase. Sin embargo, cuando se emplean 10s 
objetos, la mayor parte de su codigo esta oculto. Rara vez se conocen 10s datos 
internos que contiene el objeto y normalmente no hay manera de acceder directa- 
mente a 10s datos. Por supuesto, se supone que utilizamos 10s metodos para acce- 
der a 10s datos, que estan protegidos contra accesos no autorizados. Esta es la 
tecnica orientada a objetos del concepto de programacion clasico conocido como 
ocultacion de informacion. Sin embargo, en Delphi existe un nivel adicional de 
ocultacion, mediante propiedades. 
Delphi implementa este encapsulado basado en clases per0 todavia soporta el 
encapsulado clasico basado en modulos, que usa la estructura de unidades. Todo 
identificador que se declare en la seccion de interfaz de una unidad resulta visible 
a otras unidades del programa, siempre que se utilice una sentencia u s e s que se 
refiere a launidad que define el identificador. Por otro lado, 10s identificadores 
declarados en la seccion de implernentacion de la unidad seran locales a esa uni- 
dad. 
Privado, protegido y public0 
En el caso de un encapsulado basado en clases, el lenguaje Pascal orientado a 
objetos tiene tres especificadores de acccso: p r i v a t e , p r o t e c t e d y p u b l i c . 
Un cuarto; p u b l i s h e d , controla la RTTI (informacion de tipo en tiempo de 
e.jecucion) y la informacion en tiempo de diseiio, proporcionando la misma dispo- 
nibilidad de cara a la programacion que si fuera p u b l i c . A continuacion se 
enumeran 10s tres especificadores de acceso clisi'cos: 
La directiva private: Denota campos y metodos de clase no accesiblcs 
fuera de la unidad (el archivo dc codigo fuente) que declara la clasc. 
La directiva protected: Se utiliza para indicar metodos y campos con 
visibilidad limitada. Solo la clase actual y sus clases heredadas pueden 
acceder a 10s elementos protegidos. Para ser mas precisos, solo la clase. 
las subclases y cualquier codigo presente en la misma unidad que la clase 
pueden acceder a 10s miembros protegidos. 
La directiva public: Denota campos y metodos a 10s que se puede acceder 
libremente desdc cualquier otra parte de un programa asi como en la uni- 
dad en la que se definen. 
Por lo general, 10s campos dc una clase deberian ser privados. Los metodos 
son normalmente publicos. Aunque esto no siempre es asi, 10s metodos pueden ser 
privados o protegidos si son necesarios internamente solo para realizar parte de 
un calculo. Los campos pueden ser protegidos para que se puedan manipular en 
subclases, aunque no se considera una buena practica de la orientation a objetos. 
ADVERTENCIA: Los especificadores de acceso solo restringen el acceso 
por parte del codigo que est i fuera de la unidad a ciertos miembros de 
clases declaradas en la parte de interfaz de la misma. Esto significa que si 
dos clases estAn en la misma unidad, sus campos privados no e s t h protegi- 
dos. 
Como e.jemplo, consideremos esta nueva version de la clase TDate: 
type 
TDate = class 
private 
Month, Day, Year: Integer; 
public 
procedure SetValue (y, m, d: Integer) ; overload; 
procedure SetValue (NewDate: TDateTime); overload; 
function Leapyear: Boolean; 
function GetText: string; 
procedure Increase; 
end; 
Se podria pensar en aiiadir otras funciones, como G e t D a y , G e t M o n t h y 
G e t Y ear, que simplemente devuelvan 10s datos privados correspondientes, per0 
no siempre se necesitan funciones similares directas de acceso a datos. Si se 
conceden funciones de acceso para cada uno de 10s campos, se podria reducir el 
encapsulado y dificultar la modificacion de la implementacion interna de una 
clase. Las funciones de acceso deberian de definirse unicamente si forman parte 
de la interfaz logica de la clase que esta implementando. 
Otro nuevo metodo es el procedimiento Increase, que suma un dia a la 
fecha. Este calculo no es nada sencillo, porque hay que considerar las distintas 
longitudes de 10s meses asi como 10s 6 0 s bisiestos o no bisiestos. Lo que hare- 
mos, para que resulte mas sencillo escribir el codigo, sera cambiar la 
implementacion interna de la clase a1 tipo T D a t e T i m e de Delphi para la 
implernentacion interna. La definicion de clase cambiara a lo siguiente (el codigo 
completo aparece en el proximo ejemplo, D a t e p r o p ) : 
type 
TDate = class 
private 
fDate: TDateTime; 
public 
procedure SetValue (y, m, d: Integer); overload; 
procedure SetValue (NewDate: TDateTime); overload; 
function Leapyear: Boolean; 
function GetText: string; 
procedure Increase; 
end ; 
Fijese en que debido a que la unica modificacion se realiza en la seccion priva- 
daj no habra que modificar ninguno de 10s programas existents que usen la clase. 
Esa es la ventaja del encapsulado. 
NOTA: El tipo TDateTime es en realidad un numero de coma flotante. 
La parte entera del numero indica la fecha desde el 3O/l2/1899, la misma 
fecha basica usada por las aplicaciones OLE Automation y Win32. (Para 
exDresar 10s afios anteriores se usan valores ne~ativos.) La t>arte decimal - . 
indica la hora en forma de fiacci6n. Por ejemplo, un valor de 3,75 correspon- 
de a1 dos de enero de 1900, a las 6:00 de la tarde (tres cuartos de un dia). 
n--- _- - ---L-- r_ _L _ - -- J- ____--- - ---A_- -1 --1_- --- 2- _I-- ---- rara sumar o resrar recnas, se pueue sumar o restar el numero ue mas, que 
resulta d s sencillo que aiiadir &as con una representacih de dia/mes/aito. 
Encapsulado con propiedades 
Las propiedades son un mecanismo de orientacion a objetos muy sensato o una 
aplicacion practica muy bien pensada de la idea de encapsulado. Basicamente, se 
tiene un nombre que oculta por completo 10s datos de implernentacion. Esto per- 
mite modificar la clase ampliamente sin que afecte a1 codigo que la utiliza. Una 
buena definicion de propiedades es la de campos virtuales. Desde la perspectiva 
del usuario de la clase que las define, las propiedades poseen m a apariencia 
exactamente igual a la de 10s campos, ya que, por lo general se puede leer o 
escribir su valor. Por ejemplo, se puede leer el valor de la propiedad C a p t i o n de 
un boton y asignarla a la propiedad T e x t de un cuadro de edicion con el siguiente 
codigo: 
Parece que estuvidramos leyendo y escribiendo campos. Sin embargo, las pro- 
piedades pueden proyectarse directamente a datos, asi como a metodos de acceso, 
para leer y escribir el valor. Cuando las propiedades se proyectan a metodos, 10s 
datos a 10s que acceden pueden formar parte del objeto o estar fuera de el y 
pueden producir efectos secundarios, como volver a pintar un control tras haber 
cambiado sus valores. Tecnicamente, una propiedad es un identificador que esta 
proyectado a datos o metodos que usan una clausula r e a d y otra w r i t e . Por 
ejemplo, aqui tenemos la definicion de una propiedad M o n t h para una clase de 
fecha: 
property Month: I n t e g e r read FMonth write SetMonth; 
Para acceder a1 valor de la propiedad Month, el programa lee el valor del 
campo privado FMonth, mientras que para cambiar el valor de la propiedad 
llama a1 metodo S e t M o n t h (que ha de estar definido dentro de la clase, por 
supuesto). Son posibles diversas combinaciones (por ejemplo, un metodo para 
leer el valor o cambiar directamente un campo en la directiva w r i t e ) , per0 el 
uso de un metodo para cambiar el valor de una propiedad es muy comun. Estas 
son dos definiciones alternativas para la propiedad, proyectada sobre dos meto- 
dos de acceso o directamente sobre 10s datos en ambas direcciones: 
property Month: I n t e g e r read GetMonth write SetMonth; 
property Month: I n t e g e r read m o n t h write m o n t h ; 
Normalmente, 10s datos reales y 10s metodos de acceso son privados (o prote- 
gidos) mientras que la propiedad es publica. Esto significa que hay que usar la 
propiedad para tener acceso a aquellos metodos o datos, una tecnica que ofrece 
tanto la version simplificada como la extendida del encapsulado. Se trata de un 
encapsulado ampliado, porque no solo se puede cambiar la representacion de 10s 
datos y sus funciones de acceso, sino tambien aiiadir o eliminar funciones de 
acceso sin cambiar el codigo de llamada en absoluto. Un usuario solo necesita 
volver a compilar el programa usando la propiedad. 
TRUCO: Cuando se definen propiedades, se puede aprovechar la funcion 
Class C o m p l e t i o n del editor de Delphi. que se activa con la combina- . 
popiedad y el punto y coma, a1 pulsar Control-Mayus-C, Delphi propor- 
cionara una definicion completa y el esqueleto del mttodo de escritura. Si 
se escribe G e t delante del nombre del identificador despues de la pala- 
bta clave read tambitn se conseguira un m e t o d ~ de lectura sin apenas 
escribir. 
Propiedades de la clase TDate 
Como ejemplo, hemos aiiadido propiedades para acceder al aiio, el mes y el dia 
de un objeto de laclase T D a t e . Dichas propiedades no eskin proyectadas a 
campos especificos, sino al campo unico f D a t e que almacena toda la informa- 
cion de la fecha. Esta es la nueva definicion de la clase, con mejores metodos de 
lectura y escritura: 
t y p e 
TDate = c l a s s 
p u b l i c 
p r o p e r t y Year: In t ege r r e a d GetYear w r i t e SetYear: 
p r o p e r t y Month: I n t e g e r r e a d GetMonth w r i t e SetMonth; 
p r o p e r t y Day: In t ege r r e a d GetDay w r i t e SetDay; 
Cada uno de estos metodos se implementa facilmente utilizando funciones 
disponibles en la nueva unidad DateUtils. Veamos el codigo de dos de ellos (10s 
otros son muy similares): 
f u n c t i o n TDate.GetYear: In t ege r ; 
b e g i n 
Resul t := YearOf ( fDate) ; 
end; 
procedure TDate.SetYear(const Value: I n t e g e r ) ; 
b e g i n 
fDate : = Recodeyear ( fDate , Value) ; 
end ; 
El codigo de esta clase esta disponible en el ejemplo Dateprop. El programa 
utiliza una unidad secundaria para que la definicion de la clase T D a t e active el 
encapsulado y Cree un objeto de fecha simple guardado en una variable de formu- 
lario y almacenado en memoria durante toda la ejecucion del programa. Si se usa 
una tecnica estandar, el objeto se crea en el controlador de eventos oncreate 
del formulario y se destruye en el controlador de eventos OnDes t roy del formu- 
lario. 
El formulario del programa (vease figura 2.2) tiene tres cuadros de edicion y 
botones para copiar 10s valores de estos cuadros de edicion en las propiedades del 
objeto de fecha: 
Figura 2.2. El formulario del ejemplo Dateprop. 
ADVERTENCIA: Cuando se escribefi 10s valm; d $pn>&'ama utiliza el 
metodo setvalue en lugar & &£ink cada una de las pfopiedades. De 
hecho, asignar e1 mes y el &a por separado puede cam& pLoblemati cuando 
el mes no es valid0 para el dia en uso. Pongam~s por &&plo que la fecha 
actual es el 3 1 de enero jr qgxemos twignark el 20 de fe'bkro. Si asignamos 
primero el mes, esa pa& darsr error, puesto que el 3 1 d;e febrero no existe. 
Si asignamos primero el &a, el problem slirgilpr al hacer 1a asignstci6n 
inversa. Debido a las rm&m de validmikt para fixkttd, ss enejor.wigm.r 
todo a1 mismo ~~. 
Caracteristicas avanzadas de las propiedades 
Las propiedades tienen varias caracteristicas avanzadas. Este es un breve re- 
sumen de ellas: 
La directiva write de una propiedad se puede omitir, convirtiendola asi 
en una propiedad de solo lectura. El compilador dara error si intentamos 
cambiarla. Tambien se puede omitir la directiva read y definir una pro- 
piedad de solo escritura, per0 ese enfoque no tiene mucho sentido y no se 
suele emplear. 
El IDE de Delphi da un trato especial a las propiedades en tiempo de 
diseiio, que se declaran con el especificador de acceso pub1 i s hed y que 
por lo general aparecen en el Object Inspector para el componente selec- 
cionado. 
Las otras propiedades, normalmente denominadas propiedades solo de tiem- 
po de ejecucion, son las declaradas con el especificador de acceso public. 
Dichas propiedades pueden usarse en el codigo del programa. 
Se pueden definir propiedades basadas en matrices, que usan la notacion 
tipica con corchetes para acceder a un elemento de la lista. Las propieda- 
des basadas en la lista de cadenas, como Lines en un cuadro de lista, son 
un ejemplo tipico de este grupo. 
Las propiedades tienen directivas especiales, como stored y default, 
que controlan el sistema de streaming de componentes. 
incluso se pueden usar propiedades en expresiones, pero no siempre se 
puede pasar una propiedad como parimetro a un procedimiento o metodo. 
I Esto se debe a que una propiedad no es una posicion de memoria, por lo que 
no se puede utilizar como parimetro var u o u t : no se puede pasar por .' 
referencia. 
Encapsulado y forrnularios 
Una de las ideas clave del encapsulado es reducir el numero de variables globales 
cmpleadas por el programa. Se puede acceder a una variable global desde todas 
las partes de un programa. Por esa razon, un cambio en la variable global afecta 
al programa entero. Por otra parte, cuando se cambia la representacion de un 
campo de clase, solo hay que cambiar el codigo de algunos metodos de dicha clase 
y nada mas. Por lo tanto, podemos decir que la ocultacion de informacion se 
refiere a 10s cambios de encapsulado. 
Cuando tengamos un programa con diversos forrnularios, podemos hacer que 
algunos datos estkn disponibles para todos 10s formularios, si 10s declaramos 
como variable global en la parte de interfaz de la unidad de uno de 10s formula- 
rios: 
var 
F o r m 1 : T F o r m l ; 
n C l i c k s : I n t e g e r ; 
Esto funciona pero tiene dos inconvenientes. En primer lugar, 10s datos no 
estan conectados a un caso especifico del formulario, sino a1 programa entero. Si 
creamos dos formularios del mismo tipo, compartiran 10s datos. Si queremos que 
cada formulario del mismo tip0 tenga su propia copia de 10s datos, la unica 
solucion es aiiadirlos a la clase de formulario: 
type 
T F o r m l = class ( T F o r m ) 
public 
nClicks: Integer; 
end; 
Afiadir propiedades a formularios 
La clase anterior utiliza datos publicos, asi que por el bien del encapsulado, se 
la deberia modificar para que use datos privados y funciones de acceso a 10s 
datos. Una solucion aun mejor es aiiadir una propiedad a1 formulario Cuando sea 
necesario que alguna informacion del formulario este disponible en otros formu- 
larios, se deberia utilizar una propiedad. Simplemente hay que cambiar la decla- 
ration de campo del formulario, como se indica en el listado anterior, aiiadir la 
palabra clave p r o p e r t y delante de ella y a continuacion, pulsar Control-Mayus- 
C para activar la funcion Code Comple t ion. Delphi generara automaticamente 
todo el codigo adicional necesario. 
El codigo completo para esta clase de formulario esta disponible en el ejemplo 
FormProp y la figura 2.3 muestra el resultado. El programa puede crear multiples 
instancias del formulario (es decir, multiples objetos basados en la misma clase 
de formulario), cada una con su propia cuenta de clic. 
Figura 2.3. Dos forrnularios del ejemplo ForrnProp en tiernpo de ejecucion. 
4 
NOTA: ~ i ~ c s e eg quo el a & d ~ p & i ~ d d a d pun f o n d ario, no 3. Mia& -~4' 
a'la M a de ~ ~ ~ e s del f a h d ! del Qbject Bpector . 
Conviene usar las propiedades tambien en las clases de formulario para 
encapsular el acceso a 10s componentes de un formulario. Por ejemplo, si hay un 
formulario principal con una barra de estado en la que se muestre cierta informa- 
cion (y con la propiedad s i m p l e p a n e l definida como T r u e ) y hay que modi- 
ficar el texto de un formulario secundario, podriamos sentir la tentacion de escribir: 
Form1 .StatusBarl .SimpleText : = ' n u e v o texto' ; 
Esta es una costumbre muy comun en Delphi, pero no es una buena costumbre, 
porque no ofrece encapsulado de la estructura de formulario ni de sus componen- 
tes. Si hay un codigo similar en una aplicacion y mas tarde se decide modificar la 
interfaz de usuario del formulario (y reemplazar S t a t u s B a r por otro control o 
activar diversos paneles), habra que adaptar el codigo en muchos sitios. La alter- 
nativa es utilizar un metodo o, incluso mejor, una propiedad para ocultar un 
control concreto. Esta propiedad puede definirse como: 
property StatusText: string read GetText write SetText; 
siendo G e t T e x t y S e t T e x t metodos que leen de y escriben en la propiedad 
S i m p l e T e x t de la barra de estado (o la etiqueta de uno de sus paneles). En 10s 
demas formularios del programa simplemente se puede hacer referencia a la pro- 
piedad StatusText del formulario y si la interfaz de usuario cambia, solo se 
veran afectados 10s metodos de lectura y escritura. 
Constructores 
Para asignar la memoria a1 objeto, podemos llamar a1 metodo Create. Este 
es un constructor, un metodo especial que podemos aplicara una clase para 
asignar memoria a una instancia de dicha clase. El constructor devuelve la instan- 
cia, que puede asignarse a una variable para almacenar el objeto y usarlo mas 
tarde. El constructor por defecto TObj e c t . Create inicializa todos 10s datos 
del nuevo caso a cero. Para que 10s datos de dicho caso comiencen con un valor 
diferente a cero, hay que escribir un constructor personalizado. 
El nuevo constructor se puede denominar c r e a t e o tener otro nombre, y hay 
que usar la palabra clave constructor delante de el. Fijese en que no es 
necesario llamar a TOb j e c t . Create: es Delphi el que asigna memoria para el 
nuevo objeto, no el constructor de clase. Todo lo que hay que hacer es iniciar la 
base de clase. 
Aunque se puede usar cualquier nombre para el constructor, deberia ajustarse 
a1 nombre estandar, c r ea t e . Si se usa otro nombre distinto de c rea te , el 
constructor Create de la clase basica TOb j e c t aun estara disponible, per0 un 
programador que llame a1 constructor por defecto podria pasar por alto el codigo 
de inicializacion ofrecido porque no reconoce el nombre. 
A1 definir un constructor c r e a t e con algunos pa rhe t ros , reemplazamos la 
definicion predeterminada por una nueva y hacemos que su uso resulte obligato- 
rio. Por ejemplo, despues de haber definido: 
type 
TDate = class 
public 
constructor Create (y, m, d: Integer); 
solo podremos llamar a este constructor y no a1 c r ea t e estandar: 
var 
ADay: TDate; 
begin 
// Error, no conpila: 
ADay := TDate.Create; 
// OK: 
ADay : = TDate.Create (1, 1, 2000); 
Las normas de escritura de constructores para componentes personalizados 
son diferentes. La razon es que en este caso hay que sobrescribir un constructor 
virtual. La sobrecarga resulta particularmente importante para 10s constructores 
ya que se pueden aiiadir multiples constructores a una clase y llamarlos a todos 
ellos create. Este enfoque hace que 10s constructores resulten faciles de recor- 
dar y sigan una via estandar proporcionada por otros lenguajes de orientacion a 
objetos en 10s que 10s constructores deben de tener todos el mismo nombre. Como 
ejemplo, podemos aiiadir a la clase dos constructores create distintos; uno sin 
parametros, que oculta el constructor predeterminado; y otro con valores de 
inicializacion. El constructor sin parametros usa el valor predefinido de la fecha 
de hoy (como se puede ver el codigo completo del ejemplo Dataview): 
'=we 
TDate = c l a s s 
p u b l i c 
c o n s t r u c t o r Crea te ; overload; 
c o n s t r u c t o r Create (y , m, d : I n t e g e r ) ; overload; 
Destructores y el metodo Free 
Del mismo mod0 que una clase puede tener un constructor personalizado, 
tambien puede tener un destructor personalizado, un mCtodo declarado con la 
palabra clave destructor y llamado Destroy. A1 igual que una llamada a1 
constructor asigna memoria para el objeto, un destructor libera la memoria. Los 
destructores son necesarios solo para objetos que adquieren recursos externos en 
sus constructores o durante su vida util. Se puede escribir codigo personalizado 
para un destructor, en general sobrescribiendo el destructor Destroy predeter- 
minado, para permitir que un objeto ejecute algo de codigo de limpieza antes de su 
destruccion. Destroy es un destructor virtual de la clase TObj ect. Jamas 
deberia definirse un destructor distinto, ya que 10s objetos suelen destruirse me- 
diante una llamada al metodo Free y este metodo llama al destructor virtual 
Destroy de la clase especifica. Free es un metodo de la clase TOb j ect, 
heredado por todas las demas clases. El metodo Free verifica basicamente si el 
objeto actual (Self) no es nil antes de llamar a1 destructor virtual Destroy. 
Free no cambia el objeto a nil automaticamente, sino que es algo que se debe- 
ria hacer personalmente. La razon es que el objeto no sabe que variables pueden 
referirse a el, por lo que no hay mod0 de cambiarlas todas a nil. 
Delphi 5 present6 un procedimiento FreeAndNil que se puede usar para 
liberar un objeto y dar el valor nil a su referencia a1 mismo tiempo. Se puede 
llamar a FreeAndNil (Ob j 1 ) en lugar de escribir lo siguiente: 
0 b j l . F r e e ; 
Objl := n i l ; 
El modelo de referencia a objetos de Delphi 
En algunos lenguajes orientados a objetos, a1 declarar una variable de un tipo 
de clase, se crea una instancia de dicha clase. Delphi, en cambio, se basa en un 
modelo de referencia a objetos. La idea es que una variable de un tipo de clase, 
como la variable TheDay en el ejemplo anterior ViewDate, no mantiene el 
valor del objeto. En lugar de eso, contiene una referencia, o un puntero, para 
indicar la posicion de mernoria en la que se ha almacenado el objeto. Se puede ver 
la estructura en la figura 2.4. 
TheDay objeto TDay 
Figura 2.4. Una representacion de la estructura de un objeto en memoria, con una 
variable que se refiere a el. 
El unico problema de esta tecnica es que cuando se declara una variable, no se 
crea un objeto en memoria (lo que es inconsistente con el resto de variables, 
confundiendo a 10s nuevos usuarios de Delphi); solo se reserva la posicion de 
memoria para una referencia al objeto. Las instancias de objetos h a b r h de crear- 
se manualmente, a1 menos para 10s objetos de las clases que se definan. Las 
instancias de 10s componentes que se coloquen en un formulario son creadas 
automaticamente por la biblioteca de Delphi. 
Hemos visto como crear una instancia de un objeto, aplicando un constructor a 
su clase. Cuando hayamos creado un objeto y hayamos terminado de usarlo, es 
necesario eliminarlo (para evitar llenar la rnemoria que ya no necesita, lo cual 
origina lo que se conoce como "goteo de memoria"). Esto se puede hacer mediante 
una llamada a1 metodo Free. Siernpre que se creen objetos cuando Sean necesa- 
rios y se liberen cuando ya no lo Sean, el modelo de referencia a objetos funciona- 
ra perfectamente. El modelo de referencia a objetos tiene una gran influencia en la 
asignacion de objetos y en la administracion de memoria. 
Asignacion de objetos 
Podemos preguntarnos que ocurriria si una variable que mantiene un objeto 
solo contiene una referencia a1 objeto en memoria y se copia el valor de dicha 
variable. Supongamos que escribimos el metodo Bt nToda yCli c k del ejemplo 
ViewDa te del siguiente modo: 
procedure TDateForm.BtnTodayClick(Sender: TObject); 
var 
NewDay: TDate; 
begin 
NewDay := TDate-Create; 
TheDay := NewDay; 
LabelDate.Caption := TheDay-GetText; 
end; 
Este codigo copia la direccion de memoria del objeto NewDay a la variable 
TheDay (corno muestra la figura 2.5); no copia 10s datos de un objeto en el otro. 
En esta circunstancia concreta, esta tecnica no es muy adecuada, puesto que cada 
vez que se pulsa el boton, se asigna memoria para un nuevo objeto y nunca se 
libera la memoria del objeto a la que anteriormente apuntaba la variable TheDay. 
NewDay objeto TDate 
TheDay 
Figura 2.5. Una representacion de la operacion de asignacion de una referencia de 
objeto a otro objeto. Esto es distinto de copiar el contenido real de un objeto en otro. 
Esta cuestion especifica puede resolverse liberando el objeto antiguo, como en 
el siguiente codigo (que tambien esta simplificado, sin el uso de una variable 
explicita para el objeto de nueva creacion): 
procedure TDateForm.BtnTodayClick(Sender: TObject); 
begin 
TheDay-Free; 
TheDay : = TDate.Create; 
Lo importante es que cuando se asigna un objeto a otro objeto, Delphi copia la 
referencia a1 objeto en memoria en la nueva referencia a objeto. No deberia consi- 
derarse esto como algo negativo: en muchos casos, ser capaz de definir una varia- 
ble que se refiera a un objeto ya existente puede ser una ventaja. Por ejemplo, se 
puede almacenar el objeto devuelto a1 acceder a una propiedad y usarla en las 
sentencias siguientes, como se indica en este fragment0 de codigo: 
var 
ADay: TDate; 
begin 
ADay: User1nformation.GetBirthDate;// usar un ADay 
Lo mismo ocurre si se pasa un objeto como parametro a una funcion: no se 
crea un nuevo objeto, sino que se hace referencia a1 mismo en dos lugares diferen- 
tes del codigo. Por ejemplo, a1 escribir este procedimiento y llamarlo como se 
indica a continuacion, se modificara la propiedad C a p t i o n del objeto B u t t o n l , 
no de una copia de sus datos en memoria (algo que seria completamente inutil): 
procedure Captionplus (Button: TButton); 
begin 
Button.Caption := Button.Caption + ' + I ; 
end; 
// llamar.. . 
CaptionPlus (Buttonl) 
Esto significa que el objeto se pasa por referencia sin el uso de la palabra clave 
var y sin ninguna otra indicacion obvia de la semantica de paso por referencia, 
lo que confunde a 10s novatos. Cabria preguntarse lo que sucede si realmente se 
quieren cambiar 10s datos de un objeto existente, para que se corresponda con 10s 
datos de otro objeto. En este caso, hay que copiar cada campo del objeto, lo cual 
es posible solo si son todos publicos, u ofrecer un metodo especifico para copiar 
10s datos internos. Algunas clases de la VCL tienen un metodo Assign, que 
realiza esta operacion de copia. Para ser mas precisos, la mayoria de las clases de 
la VCL que heredan de TPers is tent, per0 no de TComponent, tienen el 
metodo Ass ign. Otras clases derivadas de TComponent tienen este metodo 
per0 lanzaran una excepcion cuando se llama. 
En el ejemplo Da t eCopy, se ha aiiadido un metodo Assign a la clase TDa te 
y se le ha llamado desde el boton Today, con el siguiente codigo: 
procedure TDate .Assign (Source: TDate) ; 
begin 
fDate := Source.fDate; 
end ; 
procedure TDateForm.BtnTodayClick(Sender: TObject); 
var 
NewDay: TDate; 
begin 
NewDay : = TDate-Create; 
TheDay .Assign (NewDay) ; 
LabelDate.Caption := TheDay.GetText; 
NewDay.Free; 
end ; 
Objetos y memoria 
La administracion de memoria en Delphi esta sujeta a tres normas, a1 menos si 
se permite que el sistema trabaje en armonia sin violaciones de acceso y sin 
consumir memoria innecesaria: 
Todo objeto ha de ser creado antes de que pueda usarse 
Todo objeto ha de ser destruido tras haberlo utilizado. 
Todo objeto ha de ser destruido solo una vez. 
El tener que realizar estas operaciones en el codigo o dejar que Delphi controle 
la administracion de memoria, dependera del modelo que escojamos entre las 
distintas tecnicas que ofrece Delphi. 
Delphi soporta tres tipos de administration de memoria para elementos dinamicos: 
Cada vez que creamos un objeto explicitamente en el codigo de una aplica- 
cion, tambien debemos liberarlo (con la sola excepcion de un puiiado de 
objetos del sistema y de objetos que se utilizan a traves de referencias de 
interfaz). Si no se hace asi, la memoria utilizada por dicho objeto no se 
libera hasta que finaliza el programa. 
Cuando creamos un componente, podemos especificar un componente pro- 
pietario, pasando el propietario a1 constructor del componente. El compo- 
nente propietario (normalmente un formulario) se transforma en el 
responsable de destruir todos 10s objetos que posee. Asi, si creamos un 
componente y le damos un propietario, no es necesario que nos acordemos 
dc destruirlo. Este es el comportamiento estandar de 10s componentes que 
se crean en tiempo de diseiio a1 colocarlos sobre un formulario o modulo de 
datos. Sin embargo, es imperativo que se escoja un propietario cuya des- 
truccion quede garantizada; por ejemplo, 10s formularios suelen pertenecer 
a 10s objetos globales A p p l i c a t i o n , que son destruidos por la bibliote- 
ca cuando acaba el programa. 
Cuando la RTL de Delphi reserva memoria para las cadenas y matrices 
dinamicas, libera automaticamente la memoria cuando la referencia resul- 
ta inalcanzable. No es necesario liberar una cadena: cuando resulta inacce- 
sible, se libera su memoria. 
Destruir objetos una sola vez 
Otro problema es que si se llama a1 metodo F r e e (o a1 destructor D e s t r o y ) 
de un objeto dos veces, dara error. Sin embargo, si recordamos cambiar el objeto 
a n i l , se puede llamar a F r e e dos veces sin ningun problema. 
b - 
NOTA: Podriamos preguntarnos por que se puede llamar a Free con total 
seguridad si la referencia del objeto es n i l , pero no se pue& llamar a 
D e s t r o y . La razon es que F r e e es un mbodo conocido en una posicibn 
de memoria dada, rnientras que la funcion virtual Destroy se defrne en 
tiempo de ejecucion a1 ver el tip0 de objeto, una operacibn muy peligrosa si 
el objeto ya no existe. 
Para resumir todo esto, hemos elaborado una lista de directrices: 
Llamar siempre a F r e e para destruir objetos, en lugar de llamar a1 des- 
tructor D e s t r o y . 
Utilizar F r e e A n d N i 1 o cambiar las referencias de objeto a n i 1 despues 
de haber llamado a F r e e , a no ser que la referencia quede inmediatamente 
despues fuera de alcance. 
En general, tambien se puede verificar si un objeto es nil usando la funcion 
signed. Por lo que las dos sentencias siguientes son equivalentes, a1 menos 
la mayor parte de 10s casos: 
i f Assigned (ADate) then . . . 
i f ADate <> nil then . . . 
Fijese en que estas sentencias solo verifican si el puntero no es nil, no verifi- 
can si se trata de un puntero valido. Si se escribe el siguiente codigo, se realizara 
la verificacion, per0 se obtendra un error en la linea de llamada a1 metodo del 
objeto: 
ToDestroy.Free; 
i f ToDestroy <> n i l then 
ToDestroy.DoSomething; 
Es importante darse cuenta de que llamar a F r e e no cambia el objeto a nil. 
Herencia de 10s tipos existentes 
Normalmente es necesario usar una version ligeramente diferente de una clase 
existente. Por ejemplo, se podria necesitar aiiadir un metodo nuevo o modificar 
ligeramente uno dado. Si se copia y se pega la clase original y se modifica (una 
alternativa terrible, a no ser que exista una razon especifica para hacer esto), se 
duplicara el codigo, 10s errores y 10s dolores de cabeza. En lugar de esto, se 
deberia utilizar una caracteristica clave de la programacion orientada a objetos: 
la herencia. Para heredar de una clase existente en Delphi, solo hay que indicar 
esa clase a1 principio de la declaracion de la nueva clase. Por ejemplo, esto se 
hace cada vez que se crea un formulario: 
tYPe 
TForml = c l a s s (TForm) 
end; 
Esta definicion indica que la clase T F o r m l hereda todos 10s metodos, cam- 
pos, propiedades y eventos de la clase TForm. Se puede llamar a cualquier meto- 
do public0 de la clase T F o r m para un objeto del tipo T F o r m l . TForm, a su vez, 
hereda algunos de sus metodos de otra clase, y asi sucesivamente hasta la clase 
basica TOb j ec t . Como ejemplo de herencia, podemos cambiar una nueva clase 
a partir de T D a t e y modificar su funcion G e t T e x t . Se puede encontrar este 
codigo en la unidad Date del ejemplo NewDate: 
tYPe 
TNewDate = c l a s s (TDate) 
pub1 i c 
function GetText: string; 
end : 
Para implementar la nueva version de la funcion GetText, utilizamos la 
funcion Format DateTime, que emplea (entre otras caracteristicas) 10s nom- 
bres de mes predefinidos disponibles en Windows, estos nombres dependen de la 
configuracion regional del usuario y de la configuracion del lenguaje. Muchas de 
estas configuraciones las copia Delphi en constantes definidas en la biblioteca, 
como LongMonthNames, ShortMonthNames y muchas otras que puede 
encontrar bajo el tema "Currency and datehime formatting variables" (Variables 
para formatear la moneda y la fecha/hora) en el archivo de ayuda de Delphi. 
Veamos el metodo GetText, en el que 'dddddd' corresponde a1 formato de fecha 
largo: 
function TNewDate.GetText: string; 
begin 
GetText : = FormatDateTime ( ' d d d d d d ' , fDate); 
end : 
TRUCO: Cuando usamos la information regional, el programa NewDate 
se adapta automaticamente% las diferentes codi@r&i~nes & u~arici de 
Windows. Si ejecuta este mismo programa en un ordenador con una confi- 
guracion regi~nal en ,espaiiol, 10s nombresde 10s m e s a agsuecerh 
automaticamente en eqpat(o1 
Cuando tengamos la definicion de la nueva clase, hay que usar este nuevo tipo 
de datos en el codigo del formulario del ejemplo NewDate. Simplemente hay que 
definir el objeto TheDay de tipo TNewDate y crear un objeto de la nueva clase 
mediante en el metodo Formcreate. No es necesario modificar el codigo con 
llamadas de metodo, ya que 10s metodos heredados seguiran funcionando del 
mismo modo; sin embargo, se modifica su efecto, como muestra la nueva salida 
(vease figura 2.6) 
jueves, 25 de dlclembre de 2003 
Figura 2.6. El resultado del programa NewDate, con el nombre del mes y del dia de 
acuerdo con la configuracion regional de Windows. 
CCI;I 
Campos protegidos y encapsulado 
El codigo del mktodo GetText de la clase TNewDate compila solo si esta 
escrito en la misma unidad que la clase TDate. De hecho, accede a1 campo 
privado f Date de la clase ascendiente. Si queremos colocar una clase descen- 
diente en una unidad nueva, debemos declarar el campo fDate como protegido o 
aiiadir un metodo de acceso protegido en la clase ascendiente para leer el valor del 
campo privado. 
Muchos desarrolladores creen que la primera solucion es siempre la mejor, ya 
que declarar la mayor parte de 10s campos como protegidos permitira que una 
clase resulte mas extensible y hara mas sencillo escribir clases heredadas. Sin 
embargo, este enfoque se enfrenta con la idea del encapsulado. En una gran jerar- 
quia de clases, modificar la definicion de algunos campos protegidos de las clases 
base resulta tan dificil como modificar algunas estructuras globales de datos. Si 
diez clases derivadas acceden a estos datos, modificar su definicion significa 
modificar potencialmente el codigo de cada una de estas 10 clases. 
La flexibilidad, extension y encapsulado normalmente son objetivos conflicti- 
vos, por lo que deberiamos favorecer el encapsulado, sin sacrificar la flexibili- 
dad. Normalmente eso se puede conseguir usando un metodo virtual. Si se decide 
no utilizar el encapsulado para que la codification de las subclases sea mas rapi- 
da, el disefio podria no ajustarse a 10s principios de la orientacion a objetos. 
Acceder a datos protegidos de ottas clases 
Hemos vim que en Delphi, 10s datos privados y p r i P t e ~ 1 3 ~ de una elase 
son accesibles para cualquier funcib o rnM~ que aparezca ed fa rnismti 
unidad qae l a dase. Por ejemplo. ~ ~ ~ i d e r e r n i j ~ esta'clase f ~ & del ejem 
plo Protec&~): 
t Y P 9 
TTest = ex-s 
ptotec ted 
~ r o t e k t e d ~ I k B ? Integer; 
d; 
Cued0 hayarnos'co~ocado esta clase qn Ia unidad, no se podra accedet absu 
park protegida directamente desde otras unidades. Segiin esto, si escribi- 
mm el kipiente cbdigo. 
p~ocecbre TForrnl. B u t C o n l C & i c R (Sender : T O b j e c t ) ; 
VaE 
Ob'j: TTest; 
.begin 
Obj : = TTest . C r e a t e : 
O b ] . ProtectedData := 20; // no va a compiler 
'ProtectedDatan' (Identificador no declarado: Datos Protegidos). En este 
momento, se podria pensar que no hay manera de acceder a 10s datos prote- 
gidos de una clase defmida en una unidad diferente. Sin embargo, en cierto 
mod0 si se puede. Tengarnos en cuenta lo que ocurre si se crea una clase 
aparentemente derivada inutil, corno: 
type 
TTestHack = alaas (TTest); 
Ahora, si realizamos una conversion directa del objeto a la nueva clase y 
accedemos a 10s datos protegidos a traves de ella, el codigo sera: 
var 
Obj: TTest; 
begin 
Ob j : = TTest. Create; 
TTestHack (Obj) .ProtectedData := 20; // ;conpila! 
csre coaigo compua y runciona correctamenre, como se pueae ver si se 
ejecuta el programa Protection. La raz6n es que la clase TTestHack 
hereda autornstticamente 10s campos protegidos de la clase birsica TTest 
y, como est4 en la misma unidad que el ckligo que intenta acceder a 10s 
datos de 10s campos heredados, 10s datos protegidos resultan accesibles. 
Como seria de esperar, si se mueve la declaracibn de la clase TTes t Hac k 
a una unidad secundaria, el programa ya no cornpilad. 
Ahora que ya hemos visto d m o se hace, hay que Wet en cuenta que viola 
el mecanismo de proteccibn de c lam de este m o b pbdrfir Brigbar errores 
en el programa (a1 acceder a datos a 10s que no deberimw tener acceso) y 
no respeta las tbcnicas de orientacih a objetos. Sin embargd, en muchas 
ocasiones usar esta thnica es la mejor solucibn, como veremos a1 analizar 
el codigo fuente de Ia VCL y el ddigo fuente de mucbos wmponentes 
Delphi. Dos ejemplos de ello son el acceso a la propiedad Text de la clase 
TControl y las posicio&s Row y G o 1 del control DBGrid. EQtas dos 
ideas aparecen en-10s ejemplos Text Prop y DBGridCol, respectiva- 
mente. (Son ejemplos bastante avanzados, asi que es mejor no enfientarse a 
ellos hasta tener un buen conocimiento de Delphi.) Aunque el primer0 es un 
:̂--I- ---a --L 1 - 1-1 ---- A- 1- ----.---:I- 3- A:--- ---A LA- -i -:---la ~jcruylo r ~ ~ u ~ e u c ~ WQ UG IU z;onvwsrun oe upus wwX;sr, cl qcmplu 
DBGrid de Row y Col es en &dad un ejemplo de w o opuesto. que 
ilustplos riwgm de a c d r a bits que la persona que escribib las clases 
prefifio s o exgoner. La fib y colbima de una clase DB-id no significan 
lo mismo gw en u& ~ r p w ~ r i d Q una StringGrid &q clpses bhi- 
cas). En pjmer h p r , ll5Gxld ao cuenta las w b @as oomo cedas 
rcakr ( & t i a d i s eelda? dehatos dc 10s c l ~ ~ d e ~ b r a t i l i q ] , ~ P ~ r lo 
que sys indices ,de fils. y aoluraaa. €idrib qua aj$#arse a los,efemento# 
biar sin que nos demos cuenta). En segundo lugar, la DBGrid es una vista 
virtual de 10s datos. Cuando nos desplazamos hacia arriba en una DBGrid, 
10s dabs pueden moverse bajo ella, bero la fila seleccionada en ese momen- 
to podria no cambiar. 
protegidos miembros de una clase) se describe normalmente como un hack 
o apaKo y deberia evitarse siempre que sea posible. El problema no esth en 
acceder a datos protegidos de una cIase en la misma unidad sino en declarar . , . - . .. . . . 
una clase con el unico tin de acceder a datos protegldos de un ObJetO exls- 
tente de una clase distinta. El peligro de esta tecnica esth en la conversion 
de tipos codificada directamente de un objeto de una clase a otra diferente. 
Herencia y compatibilidad de tipos 
Pascal es un lenguaje con tipos estrictos. Esto significa que no se puede, por 
ejemplo, asignar un valor entero a una variable booleana, a no ser que se aplique 
una conversion de tipos explicita. La regla es que dos valores son compatibles en 
tip0 so10 si son del mismo tipo de datos o (para ser mas precisos) si su tipo de dato 
se rcfiere a una unica definicion de tipo. Para simplificarlo todo, Delphi hace que 
algunas asignaciones de tipos predefinidas Sean compatibles: se puede asignar un 
Extended a un Double y viceversa: con promocion o degradacion automatica 
(y una potencial perdida de precision). 
- - - - - - - 
ADVERTENCIA: Si se redefine el mismo tip0 de datos en dos unidades 
diferentes, no s e r h compatibles, incluso aunque sus nombres Sean identi- 
cos. SerA muy dificil compilar y depurar un programa que use dos tipos con 
el mismo nombre de dos unidades diferentes. 
Existe una importante excepcion a esta norma en el caso de 10s tipos de clase. 
Si se declara una clase, como TAnimaL, y se deriva de ella una nueva clase, 
como por cjemplo TDog, se puede asignar un objeto de tipo TDog a una variable 
de tipo TAnimal. Esto se debe a que un perro (dog) es un animal. Como regla 
general, se puede usar un objeto de una clase descendente cada vez que se espere 
un objeto de la clase ascendente. Sin embargo, lo opuesto no resulta legal; no se 
puede usar un objeto de una clase antecesora cuando se espera un objeto de una 
clase que desciende de la anterior. Para simplificar la esplicacion, veamos este 
codigo: 
var 
MyAnimal : TAnimal; 
MyDog: TDog; 
begin 
MyAnimal : = MyDog; // Esto es correcto 
MyDog : = MyAnimal; // ;Esto es u n error! 
Enlace posterior y polimorfismo 
Las funciones yprocedimientos de Pascal se basan normalmente en el enlace 
estatico o anterior. Esto significa que el compilador y el enlazador resuelven una 
llamada a un metodo, que reemplazan la peticion por una llamada a la posicion de 
memoria especifica en la que se encuentra la funcion o el procedimiento (esto se 
conoce como la direccion de la funcion). Los lenguajes de orientacion a objetos 
permiten el uso de otra forma de enlace, conocida como enlace dinamico o poste- 
rior. En este caso, la direccion real del metodo a llamar se establece en tiempo de 
ejecucion, segun el tipo de instancia utilizada para hacer la llamada. 
Esta tecnica se conoce como polimorfismo (que en griego significa muchas 
formas). Polimorfismo significa que se puede llamar a un metodo, aplicarlo a una 
variable, per0 que el metodo a1 que realmente llama Delphi depende del tipo de 
objeto con el que este relacionada la variable. Delphi no puede decidir la clase 
real del objeto a1 que se refiere la variable hasta estar en tiempo de ejecucion, 
debido a la norma de la compatibilidad de tipos. La ventaja del polimorfismo es 
que permite escribir codigo mas simple, tratar tipos de objetos distintos como si 
se tratara del mismo y conseguir el comportamiento correcto en tiempo de ejecu- 
cion. 
Por ejemplo, supongamos que una clase y una clase heredada (las clases 
TAnimal y TDog) definen ambas un nuevo metodo y que este metodo tiene 
enlace posterior o tardio. Se puede aplicar este metodo a una variable generica 
como MyAnimal que en tiempo de ejecucion puede referirse a un objeto de la 
clase TAnimal o a un objeto de la clase TDog. El metodo real a llamar se 
determina en tiempo de ejecucion, segun la clase del objeto real. 
El ejemplo PolyAnimals muestra esta tecnica. Las clases TAnimal y TDog 
tienen un metodo Voice, que pretende reproducir el sonido que realiza el animal 
seleccionado, como texto y como sonido (mediante una llamada a la funcion 
Playsound de la API definida en la unidad MMSystem). Este metodo se define 
como virtual en la clase TAnimal y mas tarde se sobrescribe cuando se define la 
clase TDog, mediante el uso de las palabras clave virtual y override: 
type 
TAnimal = class 
public 
function Voice: string; virtual; 
TDog = class (TAnimal) 
public 
function Voice: string; override; 
El efecto de la llamada M yAnimal . Voice puede variar. Si la variable 
MyAnimal se refiere en un momento dado a un objeto de la clase TAnimal, 
llamara a1 metodo TAnimal . Voice. Si se refiere a un objeto de la clase TDog, 
llamara en cambio a1 metodo TDog . Voice. Esto ocurre solo porque la funcion 
es virtual (como veremos si se elimina esta palabra clave y se vuelve a compilar). 
La llamada a MyAnima1. Voice funcionara en el caso de un objeto que sea 
una instancia de cualquier descendiente de la clase TAnimal, aunque las clases 
esten definidas en otras unidades, o aunque todavia no se hayan escrito. El 
compilador no necesita conocer todos 10s descendientes para hacer que la llamada 
sea compatible con ellos, solo se necesita la clase ascendiente. En otras palabras, 
esta llamada a MyAnima 1 . Voice es compatible con todas las futuras clases 
que hereden de TAnimal. 
- - - . - . - . . . . . - - - - - . - . .- - - -. . - . 
I NOTA: Esta es la raz6n clave por la que 10s lenguajes de programa&n I 
orientada a obietos favorecen la reutilizacion. Se vuede escribir un cbdiqo 
i- 
[Y 
GI prugriu~laj iuuavla sc yucuc iulrpllar, aunquc sc n a y u GSGIILU IIIIICS de 
lineas de c d i g o que la usan. Por supuesto, existe una condicion: las clases 
ascendientes de la jerarquia ban de disekrse con mucho cuidado. 
En la figura 2.7 se puede ver un ejemplo dc la salida del programa PolyAnimals. 
A1 ejecutarlo, se oiran 10s sonidos correspondientes producidos por la llamada a 
Playsound. 
- 
Figura 2.7. El resultado del ejemplo PolyAnimals. 
Sobrescribir y redefinir metodos 
Como acabamos de ver, para sobrescribir un metodo con enlace posterior en 
una clase descendiente, hay que usar la palabra clave override. Fijese en que 
esta solo puede utilizarse si se definio el metodo comovirtual (o dinamico) en 
la clase ascendiente. 
Las normas son sencillas: un metodo definido como estatico sigue siendo esta- 
tico en todas sus subclases, a no ser que se oculte con un nuevo metodo virtual 
que tenga el mismo nombre. Un metodo definido como virtual, sigue manteniendo 
el enlace posterior de cada subclase (a menos que se oculte con un metodo estati- 
co, que resulta algo bastante alocado). No hay ningun mod0 de cambiar este 
comportamiento, debido a la forma en que el compilador genera un codigo dife- 
rente para 10s metodos con enlace posterior. 
Para redefinir un metodo estatico, hay que aiiadir un metodo a una subclase 
que tenga 10s mismos parametros o parametros diferentes que el original, sin 
ninguna otra especificacion. 
Para sobrescribir un metodo virtual, habra que especificar 10s mismos 
parametros y usar la palabra clave o v e r r i d e : 
type 
TMyClass = class 
procedure One; virtual; 
procedure Two; (metodo estdtico) 
end; 
TMyDerivedClass = class (TMyClass) 
procedure One; override; 
procedure Two; 
end; 
Hay dos formas muy comunes de sobrescribir un metodo. Una consiste en 
reemplazar el metodo de la clase ascendiente por una nueva version. La otra, en 
aiiadir mas codigo a1 metodo existente. Para ello se utiliza la palabra clave 
i n h e r i t e d que llama a1 mismo metodo de la clase ascendiente. Por ejemplo, se 
puede escribir: 
procedure TMyDerivedClass.0ne; 
begin 
/ / codigo nuevo 
. . . 
/ / llamada a 1 procedimiento MyClass.One 
inherited One ; 
end; 
Cuando se sobrescribe un metodo virtual existente de una clase basica, hay 
que usar 10s mismos parametros. Cuando se presenta una nueva version de un 
metodo en una clase descendiente, se puede declarar con cualquier parametro. De 
hecho, este sera un nuevo metodo independiente del metodo ascendiente del mis- 
mo nombre, solo que tendra el mismo nombre. Veamos un ejemplo: 
type 
TMyClass = class 
procedure One; 
end; 
TMyDerivedClass = class (TMyClass) 
procedure One ( S : string) ; 
end; 
NOTA: Si se usan las definiciones de clase anteriores, cuando se crea un 
objeto de la clase TMyDer ivedClas s, se puede usar su m&odo One con 
3 3 . . . . 4 _ _ 1 L ! I A . , 1 I - el parametro ae cauena, pero no la version sm parametros aeImaa en la 
clam bit8iaa. Qi se necesita esto, se puede marcar el metodo redeclarado (el 
de h c h derivada) con la palabra clave overload. Si el &todo time 
pariimetros diferentes a 10s de la versibn de la clase bbica, se cunvierte 
cfedtivamente en un mktodo sobrecargado. Si no es asi, reemplaza a1 rnkto- 
do ck la olase bbsica. Ffjese en que el m&odo no necesita estar marcado con 
overload en la c h e bkica. Sin embargo, si el m h d o de la chse bhica 
es virtual, el compihd~r emite la advertencia "Method 'One'hfdes virtual 
method of base type "~yClass" '(E1 m&odo 'One'oculta el metodo virtual 
del tip bbico "TMyClassW). Para evitar este mensaje e instruir a1 compilador 
de forma m h precisa sobre nuestras intenciones, se puede usar la directiva 
reintroduce. El c6digo sobre este tema se puede encontrar en el ejem- 
plo Reintr. 
Metodos virtuales frente a metodos dinamicos 
En Delphi, hay dos formas distintas de activar el enlace posterior. Se puede 
declarar el metodo como virtual, como hemos visto antes, o como dinamico. La 
sintaxis de estas dos palabras clave (virtual y dynamic) es exactamente la 
misma y el resultado de su uso tambien. Lo que cambia es el mecanismo interno 
usado por el compilador para implementar el enlace posterior. 
Los metodos virtuales se basan en una tabla de metodos virtuales (VMT, tam- 
bien conocida como vtable), que es una matriz de direcciones de metodo. Para una 
llamada a un metodo virtual, el compilador genera codigo para saltar a una direc- 
cion almacenada en la enesima ranura de la tabla de metodos virtuales del objeto. 
Las tablas de metodo virtualpermiten que las llamadas a metodo se ejecuten 
rapidamente, pero se necesita una entrada para cada metodo virtual de cada clase 
descendiente, aunque el metodo no se sobrescriba en la subclase. 
Las llamadas a un metodo dinamico, por otra parte, se realizan usando un 
numero unico que indica el metodo, el cual se guarda en una clase solo si la clase 
lo define o sobrescribe. La busqueda de la funcion correspondiente es, por lo 
general, mas lenta que la busqueda de 10s metodos virtuales en la tabla, que 
consta de un solo paso. La ventaja es que las entradas del metodo dinamico solo 
se propagan a descendientes cuando estos sobrescriben el metodo. 
Manejadores de mensajes 
Tambien se puede usar un metodo de enlace posterior para manejar un mensaje 
de Windows, aunque la tecnica es algo distinta. Con este proposito, Delphi ofrece 
otra directiva, message, para definir 10s metodos de control de 10s mensajes, 
que habran de ser procedimientos con un unico parametro var. La directiva 
message va seguida del numero del mensaje de Windows que el metodo quiere 
controlar. 
ADVERTENCIA;- La direct in i e s sage tambien ,est& dispodble ,en 
Kylix y el bguaja y lsr RTL la soportan por cornpleto. 8ir1 embargo, par& 
visual del mars de hbajo de la apiicacion-CLX nd WJQY m b t o b del 
mensaje para enviar las natificacioneg a Basqontrolm. Por esq ra26a, impre 
que sea posible, se deberia usar un mitach virtual: propomionado por la 
biblioteca en lugar de manejar un m@hscLje de Winhws dlrectamente. Por 
supuesto, esto importa s61o si queremoa qiie el &go se pueda tramportar. 
Por ejemplo, la siguiente porcion de codigo permite manejar un mensaje defi- 
nido por el usuario, con el valor numirico indicado por la constante vm - User de 
Windows. 
type 
TForml = class (TForm) 
... 
procedure WMUser (var Msg: TMessage) ; 
message vm-User; 
end ; 
El nombre del procedimiento y el tip0 de 10s parametros dependen del progra- 
mador, aunque esisten varios tipos de registros predefinidos para 10s diversos 
mensajes de Windows. Podria generarse mas adelante este mensaje, invocando a1 
metodo correspondiente, como en: 
PostMessage (Form1 .Handle, vm-User, 0, 0) ; 
Esta tecnica puede resultar extremadamente util para un programador vetera- 
no de Windows, que lo sepa todo sobre 10s mensajes y las funciones de la API de 
Windows. Tambien se puede enviar inmediatamente un mensaje mediante la lla- 
mada a la API de SendMessage o a1 metodo Perform de la VCL. 
Metodos abstractos 
La palabra clave abstract se usa para declarar metodos que se van a defi- 
nir solo en subclases de la clase actual. La directiva abstract define por com- 
pleto el metodo, no es una declaracion que se completara mas adelante. Si se 
intenta definir el metodo, el compilador protestara. En Delphi se pueden crear 
instancias de clases que tengan metodos abstractos. Sin embargo, a1 intentarlo, el 
compilador de 32 bits de Delphi emite un mensaje de advertencia "Constrtrcting 
instance of <class name> containing abstract methods" (Creando caso de +om- 
bre de clase> que contiene metodos abstractos). Si se llama a un metodo abstract0 
en tiempo de ejecucion, Delphi creara una escepcion, como muestra el ejemplo 
AbstractAnimals (una ampliacion del ejemplo PolyAnimals), que usa la siguiente 
clase: 
type 
TAnimal = c lass 
public 
function Voice: s t r i n g ; virtual; abstract; 
NOTA: La rnayoria de 10s lenguajes orientados a objetos usan un enfo 
m h estricto: generalmente no se pueden crear instancias de cIases que c 
tengan m6todos abstractos. 
Podriamos preguntarnos por la razon del uso de 10s metodos abstractos. Esta 
razon es el polimorfismo. Si la clase TAnimal tiene el metodo virtual Voice, 
toda clase heredada puede volver a definirlo. Si se trata de un metodo abstracto 
Voice, cada clase heredada debe volver a definirlo. 
En las primeras versiones de Delphi, si un metodo sobrescribia un metodo 
abstracto llamado inherited, el resultado era una llamada a1 metodo abstrac- 
to. A partir de Delphi 6; el compilador se ha mejorado para detectar la presencia 
dcl metodo abstracto y evitar la llamada inherited. Esto significa que se 
puede usar con seguridad inherited en todo metodo sobrescrito, a no ser que 
se desee inhabilitar esplicitamente la ejecucion de parte del codigo de la clase 
basica. 
Conversion descendiente con seguridad 
de tipos 
La norma sobre compatibilidad de tipos de Delphi para las clases descendien- 
tes permite usar una clase descendiente donde se espera una clase ascendiente. Sin 
embargo, el caso contrario nunca es posible. Ahora supongarnos que la clase 
TDog posee un metodo Eat, que no esta presente en la clase TAnimal. Si la 
variable MyAnimal se refiere a un perro, se podra llamar a la funcion. Pero si lo 
intenta y la variable se refiere a otra clase, el resultado le dara un error. A1 
realizar una conversion de tipos explicita, podemos originar un fastidioso error en 
tiempo de ejecucion (o peor, un problema de sobrescritura de la memoria subya- 
cente), porque el compilador no puede establecer si el tip0 del objeto es correct0 
ni si 10s metodos a 10s que se llama existen realmente. Para solucionar el proble- 
ma, podemos usar tecnicas basadas en informacion de tip0 en tiempo de ejecucion 
(abreviado RTTI). Basicamente, dado que cada objeto "conoce" su tip0 y su clase 
padre y podemos pedir informacion con el operador is o utilizar el metodo 
InheritsFrom de la clase TObject. 
Los parametros del operador is son un objeto y un tipo de clase y el valor de 
retorno es un booleano: 
if MyAnimal is TDog then . . . 
La expresion is evalua como True si se el objeto MyAnimal se refiere 
realmente a un objeto de clase T D O ~ o de un tipo descendiente de T D O ~ . Esto 
significa que si se comprueba si un objeto TDog es de tipo TAnimal, la compro- 
bacion tendra exito. En otras palabras, esta sentencia evalua como True si se 
puede asignar con seguridad el objeto (MyAnimal) a una variable del tipo de 
datos (TDO~). 
Ahora que sabemos con seguridad que el animal es un perro (dog), se puede 
realizar una conversion de tipos segura. Se puede realizar dicha conversion direc- 
ta escribiendo el siguiente codigo: 
var 
MyDog: TDog; 
begin 
if MyAnimal is TDog then 
begin 
MyDog : = TDog (MyAnimal) ; 
Text := MyDog.Eat; 
end; 
Esta misma operacion se puede realizar directarnente mediante el segundo ope- 
rador RTTI, as, que convierte el objeto solo si la clase solicitada es compatible 
con la real. Los parametros del operador as son un objeto y un tip0 de clase, y el 
resultado es un objeto convertido a1 nuevo tipo de clase. Podemos escribir el 
siguiente fragment0 de codigo: 
MyDog := MyAnimal as TDog; 
Text := MyDog. Eat; 
Si solo queremos llamar a la funcion E a t , tambien podemos usar una notacion 
incluso mas corta: 
(MyAnimal as TDog) .Eat; 
El resultado de esta expresion es un objeto del tip0 de datos de clase TDog, 
por lo que se le puede aplicar cualquier metodo de dicha clase. La diferencia entre 
la conversion tradicional y el uso de as es que el segundo enfoque crea una 
excepcion si el tip0 del objeto es incompatible con el tipo a1 que estamos intentan- 
do convertirlo. La excepcion creada es E I nva 1 idCa s t . 
Para evitar esta excepcion, hay que usar el operador is y, si funciona, realizar 
una conversion de tipos normal (en realidad, no hay ninguna razon para usar is 
y as de manera secuencial y hacer la verificacion de tipos dos veces): 
if MyAnirnal is TDog then 
TDog (MyAnimal) . Eat ; 
Ambos operadores RTTI resultan muy utiles en Delphi para escribir codigo 
generico que se pueda usar con diversos componentes del mismo tipo o incluso de 
distintos tipos. Cuando un componente se pasa como parametro a un metodo de 
respuesta a un evento, se usa un tipo de datos generico (TOb j ect), por lo que 
normalmente es necesario convertirlo de nuevo a1 tip0 de componente original: 
procedure TForml.ButtonlClick(Sender: TObject); 
begin 
if Sender is TButton then 
. . .end; 
Se trata de una tecnica habitual en Delphi. Los dos operadores RTTI, i s y 
as, son realmente potentes y podriamos sentirnos tentados a considerarlos como 
construcciones de programacion estandar. Sin embargo, probablemente se debe- 
ria limitar su uso para casos especiales. Cuando sea necesario resolver un proble- 
ma complejo relacionado con diversas clases, hay que intentar utilizar primer0 el 
polimorfismo. Solo en casos especiales, en 10s que el polimorfismo solo no se 
pueda aplicar, deberiamos intentar usar 10s operadores RTTI para complementar- 
lo. No hay que usar RTTI en lugar del polimorfismo, puesto que daria lugar a 
programas mas lentos. La RTTI, de hecho, tiene un impact0 negativo en el rendi- 
miento, porque debe pasar por la jerarquia de clases para ver si la conversion dc 
tipos es correcta. Como hemos visto, las llamadas de metodo virtual solo necesi- 
tan una busqueda en memoria, lo cual es mucho mas rapido. 
I 
NOTA: En realidad hay m i s informaci6n de tipo en tiempo de ejecuei6o 
(RTTI) que 10s operadores is y as. Se puede acceder a clases detalladas e 
information de tipos en tiempo de ejecucion, sobre todo para propiedades 
eventos y mCtodos pub1 i s hed. 
Uso de interfaces 
Cuando se define una clase abstracta para representar la clase basica de una 
jerarquia, se puede llegar a un punto en el que la clase abstracta sea tan abstracta 
que so10 liste una serie de funciones virtuales, sin proporcionar ningtin tip0 de 
implernentacion real. Este tip0 de clase puramente abstracta puede definirse tam- 
bien mediante una tecnica concreta, una interfaz. Por esta razon, nos referimos a 
dichas clases como interfaces. 
Tecnicamente, una interfaz no es una clase, aunque puede parecerlo, porque se 
considera un elemento totalmente a parte con caracteristicas distintivas: 
Los objetos de tipo interfaz dependen de un recuento de referencias y se 
destruyen automaticamente cuando no hay mas referencias al objeto. Este 
mecanismo es similar a la forma en que Delphi maneja cadenas largas y 
administra la memoria casi de forma automatica. 
Una clase puede heredar de una clase basica simple, per0 puede implementar 
varias interfaces. 
A1 igual que todas las clases descienden de T O b j ect, todas las interfaces 
descienden de 1 Interface y forman una jerarquia totalmente indepen- 
diente. 
m z E d i a s e r IUnknown has@ ~ e l ~ h i 5, per0 ~ e l ~ h i 7 
6 le otorgo un nuevo nombre, I I n t er f ace, para paarcar de un modo rnk 
claro el hecho de que de esta func ih del lenguaje es independiente del 
COM de Microsoft (que usa IUnknown como su iaterfaz base). De hecho, 
las interfaces Delphi tambikn e s t h disponibles en Kylix. 
Es importante fijarse en que las interfaces soportan un modelo de programa- 
cion orientada a objetos ligeramente distinto a1 que soportan las clases. Las 
interfaces ofrecen una implernentacion del polimorfismo menos restringida. El 
polimorfismo de las referencias de objetos se basa en una rama especifica de una 
jerarquia. El polimorfismo de interfaces funciona en toda una jerarquia. Ademas, 
el modelo basado en interfaces es bastante potente. Las interfaces favorecen el 
encapsulado y proporcionan una conexion mas flexible entre las clases que la 
herencia. Hay que resaltar que 10s lenguajes orientados a objetos mas recientes, 
de Java a C#, poseen el concept0 de interfaces. Veamos la sintaxis de la declara- 
cion de una interfaz (que, por convencion, comienza con el caracter I): 
type 
ICanFly = interface 
['{EAD9C4B4-ElC5-4CF4-9FAO-3B812C880A21]'] 
function Fly: string; 
end; 
La interfaz anterior posee un GUID, un identificador numeric0 que sigue a su 
declaracion y se basa en las convenciones Windows. Estos identificadores (llama- 
dos generalmente GUID) se pueden generar pulsando la combinacion de teclas 
Control-Mayus-G en el editor de Delphi. 
- - - - - - - . - - - - - - - - - - - - - 
NClTkt Awqne se $udden coMilar y usar interfaces sin:especificar un 
4&RD para ellas For la general conviene generar uno, puesto que es nece- 
sari0 t a r s realizar consbltas & interfaz o la conversibn dinamica de tipos 
mediante as c y ese tipo de interfaz. Dado que todo el inter& de las interfaces 
coslsiste'(nomalmentefin aprovechar la flexibilidad mejorada en tiernpo 
I& ejecuci'6ir,'si Ta compaqmos cob 10s tipos de clase, las interfaces sin 10s 
GUIH no resultan muy utiles. 
Cuando hayamos declarado una interfaz, se puede definir una clase que la 
implemente, como en: 
type 
TAirplane = class (TInterfacedObj ect, ICanFly) 
function Fly: string; 
end; 
La RTL ya ofrece unas cuantas clases basicas para implementar el comporta- 
miento fundamental que necesita la interfaz I I n t e r f ace. Para 10s objetos in- 
ternos, se usa la clase T I n t e r f acedOb j ect , utilizada en el codigo anterior. 
Se pueden implementar mktodos de interfaz con metodos estiticos (como en el 
codigo anterior) o con metodos virtuales. Se pueden sobrescribir mktodos virtuales 
en subclases utilizando la directiva overr ide . Si no se usan metodos virtuales, 
aun asi se puede ofrecer una nueva implementacion en la subclase, volviendo a 
declarar el tipo de interfaz en la subclase y a enlazar 10s metodos de interfaz con 
nuevas versiones de 10s metodos estaticos. A primera vista, el uso de metodos 
virtuales para implementar interfaces parece permitir un codigo mas limpio en las 
subclases, per0 ambos enfoques son igual de potentes y flexibles. Sin embargo, el 
uso de metodos virtuales afecta a1 tamaiio del codigo y de la memoria necesaria. 
I 
NQTA: coolpiladm ha de garerar mtinas de d e w p ~ r q ajustar lm 
puntos b entrada & la llatnada dq infe&gaI r n b cmespgndiente de hi 
olase de impletneq@ci&y adaptar el punter0 self ~ s t c t-$o de mi- & 
m6todo de interfaz para m w a p ~ 4 t i c o s es muy sencillo: a j u m r ' s s i f y 
p&r al &&#o real de la clase. 'tas mtinas de mCtodo de interfaz para 
m&'&s virtuales son mucho mas complejas y requieren unas cuatro veces 
has' codigtj (20 a 30 bytes) en cada una que en el caso esthtico. Ademas, 
aiiadir mas- metodos virtuales a la clase de implementacion contribuye a 
inflat la tabla.de rn6todos virtuaIes (VMT) en la clase y en todas sus 
subdases. Una interfaz ya dispone de su propia VMT y volver a declarar 
una interfaz en las subclases para volver a enlazar la interfaz con 10s nue- 
vos metodos supone tanto polimorfismo como usar metodos virtuales, pet0 
requiere un codigo menor, 
Ahora que hemos definido una implementacion de las interfaces, podemos es- 
cribir algo de codigo para usar un objeto de esa clase, mediante una variable de 
tipo interfaz: 
var 
Flyerl: ICanFly; 
begin 
Flyerl := TAirplane.Create; 
Flyerl.Fly; 
end; 
En el momento en que se asigna un objeto a una variable de tipo interfaz, 
Delphi comprueba automaticamente si el objeto implementa esa interfaz, median- 
te el operador as. Se puedc espresar csplicitamente esta operacion de este modo: 
Flyerl := TAirplane-Create as ICanFly; 
-- 
NOTA: El cornpilador genera diferente cbdigo para el operador as cuamlo 
se usa con intefices que cuando se usa con clases. Con clases, introduce 
verificaciones en tiempo de ejecuci6n para cornprobar que el objeto es efec- 
tivamente "compatible en tipo" con la clase dada. Con las interfaces, com- 
prueba en tiempo de compilaci6n que puede extraer la interfaz necesaria del 
tipo de clase disponible y asi lo hace. Esta operacih es como un "as en 
tiempo de compilation", no algo que exista en tiempo de ejecucibn. 
Usemos la asignacion directa o bien la sentencia as, Delphi realiza una accion 
extra: llama a1 metodo AddRef del objeto (definido por I Interf ace). La 
implementacion estand& de este mktodo, como la que ofrece TI nt er f a - 
cedOb j ect, es aumentar el recuento de referencias. Al mismo tiempo, desde el 
momento en que la variable Flyerl esta fuera de alcance, Delphi llama al meto- 
do Release (de nuevo parte de IInterface). La irnplementacion de 
~1;ter f aced~bj ect de - Release decrementa el recuento de referencias, 
verifica si este es cero y, si es necesario, destruye el objeto. Por esa razon en el 
ejemplo anterior, no hay codigo para liberar el objeto que hemos creado. 
ADVERTENCIA: Cuando se usan &j&~ b& en intediuxs, por lo 
general deberiamos acceder a ellos s6io w n las variables da objeto o sblo 
con las variables de interfaz. Si se m&+zlsa hs dw ~~, el s h a de 
recuenta de referencias de Del* se interrump y pue&.ariginar errores de 
memoria que sean extre-entc diff ciles de 1-ar: J3i la piktim, si 
hemos decidido usar interfa~eer . probabkmeot~ deberiamosi usa r f i w e n - 
te variables basadas en inte&e$.' $i &d asi debcanps m e z w las vdrh- 
bles, lo msls aconsejable es inhev6ilitar d reopanto de-re-fer&as-esd&do 
m a clase base propia en lugar de usar T 1 n t er f aced~b j d ct . 
Trabajar con excepciones 
Otra caracteristica clave de Delphi es el soporte de excepciones. Las excepcio- 
nes hacen que 10s programas Sean mas robustos ya que proporcionan un mod0 
estandar de notificar y gestionar errores y situaciones inesperadas. Las excepcio- 
nes hacen que 10s programas Sean mas faciles de escribir, leer y depurar porque 
permiten separar el codigo de gestion de errores de codigo normal, en lugar de 
entremezclar ambos. A1 obligar a mantener una division logica entre el codigo y 
la gestion de errores y a1 conmutar al manejador de errores automaticamente, se 
consigue que la logica real resulte mas limpia y clara. Nos permiten escribir un 
codigo mas compacto y menos inundado por 10s habituales metodos de manteni- 
miento no relacionados con el objetivo real de programacion. En tiempo de ejecu- 
cion, las bibliotecas de Delphi crean excepciones cuando algo va ma1 (en el codigo 
de tiempo de ejecucion, en un componente, en el sistema operativo). Desde el 
punto del codigo en el que se crea, la escepcion se pasa a su codigo de llamada, y 
asi sucesivamente. Por ultimo, si ninguna parte del codigo controla la excepcion, 
la VCL se encarga de ella, mostrando un mensaje estandar de error y tratando de 
continuar el programa proporcionando el siguiente mensaje del sistema o peticion 
a1 usuario. Todo este mecanismo se basa en cuatro palabras clave: 
try: Delimita el comienzo de un bloque protegido de codigo. 
except: Delimita el final de un bloque protegido de codigo e introduce las 
sentencias de control de excepciones. 
finally: Se usa para especificar bloques de codigo que han de ejecutarse 
siempre, incluso cuando se dan excepciones. Este bloque se usa general- 
mente para realizar operaciones de limpieza que siempre se deberian ejecu- 
tar, como cerrar archivos o tablas de bases de datos, liberar objetos y 
liberar memoria y otros recursos adquiridos en el mismo bloque de progra- 
ma. 
raise: Es la sentencia usada para generar la excepcion. La mayoria de las 
excepciones que encontramos en programacion en Delphi las genera el 
sistema, per0 tambien'se pueden crear excepciones propias en el codigo, 
cuando se descubren datos no validos o incoherentes en tiempo de ejecu- 
cion. La palabra clave r a i s e tambien puede usarse dentro de un contro- 
lador para volver a crear una excepcion, es decir, para propagarla a1 
siguiente controlador 
TRUCO: La gestibn de excepciones no supone un reemplazo aI adecuado 
control de flujo en un progami. Es rcmmendabfe mmtener el uso de sen- 
*._ _ - _ . C _ n _ I d 3 . I L- , I 1- >.:_ rencias para co~nproopr m cqmaa aei usuano y ouas posmres concucio- 
nes de error. S61o d&erf& asarse ex.cepcianes para eituaciones a n o d e s 
o inesperadas . 
Flujo de programa y el bloque finally 
La potencia de las excepciones en Delphi tiene que ver con el hecho de que se 
"pasan" de una rutina o metodo del llamador, hasta un manejador global (si el 
programa ofrece uno, como suele suceder con las aplicaciones de Delphi), en 
lugar de seguir la ruta estandar de ejecucion del programa. Asi que el autentico 
problema no consiste en saber como detener una excepcion sin0 como ejecutar 
codigo incluso aunque se lance una excepcion. 
Consideremos esta seccion de codigo (parte del ejemplo TryFinally), que rea- 
liza algunas operaciones para las que emplea bastante tiempo y usa el cursor en 
forma de reloj de arena para mostrar a1 usuario que esta haciendo algo: 
Screen.Cursor := crHourglass; 
// gran a l g o r i t m o . . . 
Screen.Cursor : = crDefault; 
En caso de que se produzca un error en el algoritmo (corno el que se ha inclui- 
do a proposito en el ejemplo TryFinally), el programa se detendra, per0 no volve- 
ra a establecer el cursor predefinido. Es para esto para lo que sirve un bloque 
t r y / f i n a l l y : 
Screen.Cursor := crHourglass; 
try 
// gran a l g o r i tmo . . . 
finally 
Screen.Cursor : = crDefault; 
end ; 
Cuando el programa ejecuta esta funcion, siempre reinicia el cursor, haya una 
excepcion (de cualquier tipo) o no. Este codigo no controla la excepcion, simple- 
mente hace que el programa sea robusto en caso de que se Cree un una excepcion. 
Un bloque t r y puede ir seguido de una sentencia e x c e p t o f i n a l l y , per0 no 
por ambas a1 mismo tiempo. La solucion mas comun para controlar tambien la 
excepcion consiste en usar dos bloques t r y anidados. En ese caso, hay que 
asociar el interno con una sentencia f i n a 11 y y el externo con una sentencia 
e x c e p t o viceversa, segun lo requiera la situacion. Aqui tiene el esquema del 
codigo para el tercer boton del ejemplo T r y F i n a l l y : 
Screen.Cursor : = crHourglass; 
try try 
// gran a l g o r i tmo . . . 
finally 
Screen.Cursor : = crDefault; 
end; 
except 
on E: EDivByZero do . . . 
end; 
Cada vez que haya algun codigo de finalizacion a1 concluir un metodo, hay que 
situar dicho codigo en un bloque f i n a l l y . Siempre se deberia, invariablemente 
y de forma continuada proteger el codigo con sentencias f i n a l l y , para evitar 
problemas de recursos o de goteos de memoria en caso de que se Cree una excep- 
cion. 
- . - - - - - - - - - --- - - - - - - - 
TRUCO: Controlar la excepcion es generalmente mucho menos importan- 
te que utilizar 10s bloques f i n a l l y , puesto que Delphi puede sobrevivir a 
la mayoria de ellas. Ademas, dernasiados bloques para controlar excepcio- r 
nes en el c6digo probablernente indicarh errores en el flujo del programa y 
una mala comprension de la funcion de las excepciones en el lenguaje. .-.. . . . . . ... . .. . - . - - 
mtre 10s ejemplos ae este llbr0 ser veran mucaos bloques t r y / r l n a l l y , 
unas cuantas sentencias raise, y casi ningin bloque t r y / e x c e p t . 
Clases de excepciones 
En las sentencias de control de escepciones mostradas anteriormente, capta- 
mos la excepcion EDivBy Zero, que define el RTL de Delphi. Otras excepcio- 
nes como esta se refieren a problemas en tiempo de ejecucion (como una conversion 
dinamica erronea), problemas de recursos de Windows (como 10s errores por falta 
de memoria), o errores de componentes (como un indexado erroneo). Los progra- 
madores pueden definir tambien sus propias excepciones. Se puede crear una 
nueva subclase de escepciones predefinidas o de una de sus subclases: 
type 
EArrayFull = c lass (Exception) ; 
Cuando se aiiade un nuevo elemento a una matriz que ya esta llena (probable- 
mente por un error en la Iogica del programa), se puede establecer la excepcion 
correspondiente, creando un objeto de esa clase: 
if MyArray.Ful1 then 
ra ise EArrayFull .Create ( 'Ma t r i z l l e n a ' ) ; 
Este metodo c r e a t e (heredado de la clase E x c e p t i o n ) tiene un parametro 
de cadena para describir la excepcion a1 usuario. No es necesario preocuparse de 
destruir el objeto creado para la excepcion, porque se borrara automaticamente 
gracias a1 mecanismo de control de excepciones. 
El codigo presentado en 10s extractos anteriores forma parte de un programa 
ejemplo, denominado Exception 1. Algunas de las rutinas se han modificado lige-ramente, como en la siguiente funcion Div ideTwiceP lusOne : 
function DivideTwicePlusOne (A, B: Integer) : Integer; 
begin 
try 
// e r r o r s i B e s i g u a l a 0 
Result : = A div B; 
// h a c e o t r a c o s a . . . o b v i a r s i s e c r e a una e x c e p c i o n 
Result : = Result div B; 
Result := Result + 1; 
except 
on EDivByZero do 
begin 
Result := 0; 
MessageDlg ('Dividir por cero corregido.', mtError, 
[ m b O K l , 0); 
end ; 
on E : Exception do 
begin 
Result := 0 ; 
MessageDlg (E.Message, mtError, [mbOK] , 0) ; 
end; 
end; // finaliza except 
end; 
En el codigo de Esceptionl hay dos excepciones diferentes despues del mismo 
bloque t r y . Puede haber un numero cualquiera de controladores de este tipo, 
evaluados consecutivamente. 
Si se usa una jerarquia de excepciones, tambien se llama a un controlador para 
las subclases del tip0 a las que se refiere, como haria cualquier procedimiento. 
Por csta razon es necesario colocar 10s controladores de excepciones de mayor 
ambito (10s de la clase E x c e p t i o n ) a1 final. Pero hay que tener presente que 
utilizar un controlador para cada excepcion, como el anterior, no suele ser una 
buena opcion. Es mejor dejar las excepciones desconocidas para Delphi. El con- 
trolador de excepciones por defecto de la VCL muestra el mensaje de error de la 
clase de escepcion en un cuadro de mensaje y, a continuacion, reanuda el funcio- 
namiento normal del programa. En realidad se puede modificar el controlador de 
escepciones normales con el evento A p p l i c a t i o n . OnExcept ion o el even- 
to OnExcep t ion del componente A p p l i c a t i o n E v e n t s , como se demues- 
tra en el ejemplo ErrorLog posterior. Otro importante elemento mas del codigo 
anterior es el uso del objeto de excepcion en el controlador (vease en E: 
E x c e p t i o n do). La referencia E de la clase E x c e p t i o n se refiere a1 objeto 
de excepcion pasado por la sentencia r a i s e . Cuando se trabaja con escepcio- 
nes, hay que recordar esta norma: se lanza una excepcion mediante la creacion de 
un objeto y se controla mediante la indicacion de su tipo. Esto nos ofrece una 
importante ventaja, porque como hemos visto, cuando se controla un tipo de 
excepcion, en realidad se controlan excepciones del tip0 que se especifica asi 
como de cualquier otro tip0 descendiente. 
A1 arrancar un programa en el entorno Delphi (por ejemplo, a1 pulsar la 
tecla F9), por lo general se ejecuta en el depurador. Cuanda se encuentra 
una excepcion, el depurador detendrb por defecto el programa. Asi, sabre- 
mos donde tuvo lugar la excepcion y podremo~ ver la llamada del controla- 
dor paso a paso. Tambih se puede usar la cafacteristica Stack Tmce de 
Delphi para ver la secuencia de la funci6n y las llamadas de d o d o que 
dieron lugar a que el programa crease una ex&pci6n. 
portamiento confundira a un programador que no sepa bien c6mo funciona 
el depurador de Delphi. Aunque se prepare el dd igo para controlar de 
f o m a adecuada la excepcih, el depurador detendni la ejecucib del pro- 
grama en la linea de c6digo fuente m& cercana a1 lvgar m ~l qw se cfeb la 
excepcion. Asi, a1 moverse paso a paso por el cMgo, puede verse se 
controla. Si sirnplemente queremos dejar que el program se ejtcutt mamb 
la excepci6n se controla correctamente, hay que ejecutar el pr0gms.m des& 
el Explorador de Windows o desactivar temporalme& la deteaqhh $top en 
las opcioncs de Delphi Extxptions de la ficha ~&guage b c d p f h s 
del cuadro de diirlogo Debugger Options (activada mediaate la wden 
Tools> Debugger Options), que aparece en la ficha Language 
Exceptions del cuadro de diilogo Debugger Options que se muestra a 
continuation. Tambien se puede detener el depurador. 
Sin X r G , e x caso del progrim & ejemp1o dxceptioni este cirn---~ 
'VCL EAbort Exceptions 
lndy EIDConnCbsedG~acelul?y Enceplm 
' Mtc~osoR DAD Excepl~ons 
' V~s~Broke~ lntelnal Except~ons 
't CORBA Syslem Exceplans 
CORBA User Excepl~onr 
Registro de errores 
La mayor parte del tiempo, no se sabe que operacion va a crear una excepcion 
y no se puede (ni se debe) envolver cada una de las partes del codigo en un bloque 
try/except. La tecnica general consiste en dejar que Delphi controle todas las 
escepciones y finalmente pasarselas todas a1 usuario, mediante el control del 
evento OnException del objeto global Application. Esto se puede hacer 
de un mod0 mas sencillo con el componente ApplicationEvents. En el 
ejemplo ErrorLog, se ha aiiadido a1 formulario principal una copia del componen- 
te Appl icat ionEvent s y un controlador para su evento OnExcept ion: 
procedure TForrnLog. LogException (Sender: TObj ect; E: Exception) ; 
var 
Filename: string; 
LogFile : TextFile; 
begin 
// prepara un archivo de r e g i s t r o 
Filename := ChangeFileExt (Application.Exename, ' . l o g 1 ) ; 
AssignFile (LogFile, Filename) ; 
if FileExists (FileName) then 
Append (LogFile) // abre un archivo e x i s t e n t e 
e l s e 
Rewrite (LogFile); // crear uno nuevo 
t r~ 
// e s c r i b e en un archivo y mostrar e r r o r 
Writeln (LogFile, DateTimeToStr (Now) + ' : ' + E-Message) ; 
if not CheckBoxSi1ent.Checked then 
Application. ShowException (E) ; 
finally 
// c i e r ra e l archivo 
CloseFile (LogFile) ; 
end: 
- - -- - - - - - . . . - - . . . - - . . - - . - . . - . - . . - - -- ~~ - - - - - - - . - 
NOTA: El ejemplo Er ro rhg usa el soporte de archivos de texto que pro- 
porciona el tradicional t i p de datos Turbo Pascal TextFile. Se puede asig- 
nar una variable de archivo de texto a un archivo real y despues leerlo o 
escribirlo. 
En el controlador de excepciones global, se puede escribir en el registro, por 
ejemplo, la fecha y hora del evento y tambien decidir si mostrar la excepcion 
como suele hacer Delphi (ejecutando el metodo ShowException de la clase 
TApplicat ion). De hecho, Delphi ejecuta ShowExcept ion de manera pre- 
determinada solo si no hay instalado un controlador OnException. La figura 
2.8 muestra el programa ErrorLog en ejecucion y una excepcion de muestra abierta 
en ConTEXT (una practico editor para programadores incluido con Delphi y 
disponible en w~vw.fixedsys.com/context). 
Referencias de clase 
La ultima caracteristica del lenguaje que trataremos en este capitulo son las 
referencias de clase, lo cual implica la idea de manipular las propias clases dentro 
del codigo. El primer punto que hemos de tener en cuenta es que la referencia de 
clase no es un objeto; es sencillamente una referencia a un tipo de clase. Un tipo 
de referencia de clase establece el tip0 de una variable de referencia de clase. 
Aunque esto suene confuso, con unas cuantas lineas de codigo quedara un poco 
mas claro. 
. - .- - . - 119 
. . . . . . . . . . . . . . ...................... 
1 17/05/2003 ll:37:48:Divisiun bv zero 
- -- I 
1 17/05/2003 ll:37:53: raise button pressed I 
Div by 0 1 
........ ....... 
7/05/2003 11:37:56:Divislon by zero 
7/05/2003 ll:37:58:raise button pressed 
7/05/2003 ll:37:59:raise button pressed 
7/05/2003 11:38:00:raise button pressed 
Figura 2.8. El ejemplo ErrorLog y el registro que produce. 
Supongamos que hemos definido la clase T M y C l a s s . Ahora, se puede definir 
un nucvo tipo de referencia de clase relacionado con dicha clase: 
type 
TMyClassRef = class of TMyClass; 
Ahora se pueden declarar variables de ambos tipos. La primera variable se 
reficre a un objeto, la segunda a una clase: 
var 
AnOb j ect : TMyClass; 
AClassRef: TMyClassRef; 
begin 
AnObject : = TMyClass.Create; 
AClassRef : = TMyClass; 
Podriamos preguntarnos para que se usan las referencias de clase. En general, 
las referencias de clase permiten manipular un tipo de datos de clase en tiempo de 
ejecucion. Se puede usar una referencia de clase en cualquier espresion en la que 
sea valido el uso de un tipo de datos. En realidad, no hay muchas expresiones de 
este tipo, per0 10s pocos casos que esisten son interesantes, comola creacion de 
un objeto. Podemos rescribir las dos lineas anteriores del siguiente modo: 
AnObject : = AC1assRef.Create; 
Esta vez hemos aplicado el constructor create a la referencia de clase en 
lugar de a una clase real. Hemos utilizado una referencia de clase para crear un 
objeto de dicha clase. 
Los tipos de referencia de clase no serian tan utiles si no soportasen la misma 
norma de compatibilidad de tipos que se aplica a 10s tipos de clase. Cuando se 
declara una variable de referencia de clase, como MyClas s Ref, se le puede 
asignar esa clase especifica y cualquier subclase. Por lo tanto, si TMyNewClas s 
es una subclase de nuestra clase, tambien se puede escribir 
AClassRef := TMyNewClass; "uno" 
Delphi declara una larga lista de referencias de clase en la biblioteca de tiempo 
de ejecucion y en la VCL, como por ejemplo las siguientes: 
TClass = class of TObject; 
TComponentClass = class of TComponent; 
TFormClass = class of TForm; 
En concreto, el tipo de referencia de clase TC la s s se puede usar para almace- 
nar una referencia de cualquier clase que se escriba en Delphi, porque toda clase 
se deriva en ultimo termino de TOb j ec t . La referencia T FormClas s, en cam- 
bio, se usa en el codigo fuente de la mayoria de 10s proyectos Delphi. El metodo 
Create Form del objeto Appl i cat ion, en realidad, requiere como parametro 
la clase del formulario que va a crear: 
Application. CreateForm(TForm1, Forml) ; 
El primer parametro es una referencia de clase, el segundo es una variable que 
almacena una referencia a la instancia de objeto creada. 
Por ultimo, cuando se tiene una referencia de clase, se le pueden aplicar 10s 
metodos de clase de la clase relacionada. Si tenemos en cuenta que cada clase 
hereda de TOb j ec t, se pueden aplicar a cada referencia de clase algunos de 10s 
metodos de TObject. 
Crear componentes usando referencias de clase 
El uso practico de las referencias de clase en Delphi consiste en poder manipu- 
lar un tip0 de datos en tiempo de ejecucion, lo cual es un elemento fundamental 
del entorno Delphi. Cuando se aiiade un componente nuevo a un formulario, se- 
leccionandolo de la Component Palette, se selecciona un tip0 de datos y se crea un 
objeto de dicho tipo de datos. (En realidad, eso es lo que Delphi hace sin que 
podamos verlo.) En otras palabras, las referencias de clase aportan polimorfismo 
para la construction de objetos. Para que pueda hacerse una idea de como funcio- 
nan las referencias de clase, hemos creado un ejemplo llamado ClassRef. El for- 
mulario que aparece en este ejemplo es bastante sencillo. Tiene tres botones de 
radio, situados dentro de un panel en la parte superior del formulario. Cuando 
seleccionamos uno de estos botones de radio y hacemos clic sobre el formulario, 
podremos crear nuevos componentes de estos tres tipos indicados por las etique- 
tas del boton: botones de radio, botones de pulsador y cuadros de edicion. 
Para que este programa se ejecute correctamente, es necesario modificar 10s 
nombres de 10s tres componentes. El formulario tambien tendra un campo de 
referencia de clase, declarado como C l a s s R e f : T C o n t rolclass. Almace- 
na un nuevo tipo de datos cada vez que el usuario hace clic sobre uno de 10s tres 
botones de radio, con asignaciones como C l a s s R e f : = T E d i t . La parte 
interesante del codigo se ejecuta cuando el usuario hace clic sobre el formulario. 
Hemos escogido de nuevo el evento OnMouseDown del formulario para tener 
acceso a la posicion del cursor del raton: 
procedure TForml.FormMouseDown(Sender: TObject; Button: 
TMouseButton; 
Shift: TShiftState; X, Y: Integer) ; 
var 
NewCtrl: TControl; 
MyName: String; 
begin 
/ / c r e a e l c o n t r o l 
NewCtrl := ClassRef-Create (Self); 
/ / l o o c u l t a t e m p o r a l m e n t e , para e v i t a r e l p a r p a d e o 
NewCtrl.Visible : = False; 
/ / d e f i n e p a d r e y p o s i c i d n 
NewCtrl . Parent : = Self; 
NewCtrl-Left := X; 
NewCtrl.Top : = Y; 
/ / c a l c u l a e l nombre u n i c o ( y e l t i t u l o ) 
Inc (Counter) ; 
MyName := ClassRef .ClassName + IntToStr (Counter) ; 
Delete (MyName, 1, 1); 
NewCtrl.Name : = MyName; 
/ / l o r n u e s t r a a h o r a 
NewCtrl.Visible := True; 
end ; 
La primera linea del codigo de este metodo es la clave. Crea un nuevo objeto 
del tipo de datos de clase almacenados en el campo C l a s s R e f . Esto se consigue 
simplemente aplicando el constructor create a la referencia de clase. Ahora se 
puede establecer el valor de la propiedad P a r e n t , fijar la posicion del nuevo 
componente, darle un nombre (que se usa tambien automaticamente como 
C a p t i o n o T e x t ) y hacerlo visible. 
I NOTA: Para que fkncione la construccion polimorfica. el tipo de la clase 
I basica de la referencia de clase habd dc tener un constructor virtual. Si re maw constructor virtual (corno en el ejemplo), la llamada dcl constructor 
apljcgda la referencia de clase llamara at constructor del tip0 al que 
realmente sc refiere la variable de referencia de clase. Pero sin un construc- 
tax virtual, el cbrfigQ llamara a1 constructor del tipo dc clase fijo indicado 
exi k~&clwa&:de Ia referencia de clase. Los constructores son nccesarios 
para la construccion,~olimorf~ca del mismo modo que 10s mktodos virtuales 
son nccesariba para ei poIimorfismo. 
biblioteca 
en tiempo 
El lenguaje de programacion Delphi favorece un enfoque orientado a objetos, 
junto con un estilo visual de desarrollo. Es aqui donde sobresale Delphi y tratare- 
mos acerca del desarrollo visual y basado en componentes a lo largo de este libro; 
sin embargo, deseo subrayar el hecho de que muchas de las caracteristicas listas 
para ser utilizadas de Delphi proceden de su biblioteca en tiempo de ejecucion 
(RTL). Se trata de un gran conjunto de funciones que puede utilizar para realizar 
tareas sencillas, a1 igual que algunas complejas, dentro de su propio codigo Pascal. 
(Utilizo aqui "Pascal" porque la biblioteca en tiempo de ejecucion contiene princi- 
palmente procedimientos y funciones escritas con 10s mecanismos tradicionales 
del lenguaje y no con las extensiones de orientacion a objetos aiiadidas al lenguaje 
por Borland.) 
Existe un segundo motivo para dedicar este capitulo del libro a la biblioteca en 
tiempo de ejecucion: Delphi 6 supuso un gran numero de mejoras en este campo, 
y Delphi 7 aporta algunas mejoras mas. Estan disponibles nuevos grupos de fun- 
ciones, se han desplazado funciones a nuevas unidades y han cambiado otros 
elementos, lo que crea unas pocas incompatibilidades con el codigo antiguo a 
partir del cual podria adaptar sus proyectos. Por eso, incluso aunque haya utiliza- 
do las versiones antiguas de Delphi y se sienta comodo con la RTL, aun asi 
deberia leer a1 menos parte de este capitulo. Este capitulo comenta 10s siguientes 
temas: 
Nociones generales de la RTL. 
Funciones de la RTL de Delphi. 
El motor de conversion 
Fechas, cadenas de caracteres y otras nuevas unidades de la RTL. 
Informacion de clase en tiempo de ejecucion. 
Las unidades de la RTL 
En las versiones mas recientes de Delphi, la RTL (biblioteca en tiempo de 
ejecucion) posee una nueva estructura y varias unidades nuevas. Borland aiiadio 
nuevas unidades ya que tambien aiiadio numerosas funciones nuevas. En la mayo- 
ria de 10s casos, las funciones existentes se encuentran en las unidades en las que 
solian estar, pero las nuevas funciones aparecen ahora en unidades especificas. 
Por ejemplo, las nuevas funciones relacionadas con fechas estan en la unidad 
DatcUtils, per0 las funciones de fecha que ya existian no se han movido de SysUtils, 
para evitar incompatibilidades con el codigo existente. 
La excepcion a esta norma tiene que ver con algunas de las funciones de 
soporte de variantes, que se han extraido de la unidad System para evitar enlaces 
no deseados de bibliotecas especificas de Windows, incluso en programas que no 
utilizaban dichas caracteristicas.Estas funciones variantes son ahora parte de la 
nucva unidad Variants. 
AD D 
Dephi 5 necesite ntilizar esta nueva unidad Variants para volver a compi- 
lar. Delphi es lo suficientemente listo como para darse cuenta de ello e 
incluir automiticamente la unidad Variants en proyectos que usan el tipo 
Variant , emitiendo unicarnente UM advertencia. 
TambiCn se han aplicado ciertos ajustes para reducir el tamaiio m i n i m ~ de un 
archivo ejecutable, a veces ampliado por inclusiones no deseadas de variables 
globales o codigo de inicializacion. 
I nucmn a e ~ ramano mumno ae programa en unos cuantos ha parece algo El tamafio emutable bajo el microscopio 
ncnte, pero suponc una gran ayuda para 10s 
desarrolladoTes. En aQpgtbs casos. incfuso anos cuantos KB (rttuItiplicados 
pur muchas apliCaciones) puedcn reducir cl tam-iio y, cn ultima instancia. 
el tiempa de descarga. 
Como pcqueiia prueba, h a s ercado el programa Minisiic, que n o e s a n 
I 
en una cadena y no incluir sysufjls, ,que definc toc 
mas complejas e implicaria un pequcfia numcntb I 
Si este prograrna se compila con Delphi 5. s e ~ w i . - - .--. - . . . - . i. . - 
scr y muesua el resulraao en mymensajc. cr p g a m a nomme vauanas 
de alto nivel. A b m i x se utilka la funcibn s k r ~ p a r a cu&ertir un edero- 
4-f 
@ 
cf: 
de 18.452 bytes. Uelphi b reduce dicho tamano a mh 1 5 . 3 6 ~ ~ b y t e . recor- 
le 
I- 
tando unos 3 KB. Con Delphi 7. qFtama5o o~.solg Iigeranl,en& mayor. c 
15.872 bytes. A1 reemplazar laiWena larg&.por m a caden? colta y mod 
7- --o-- ------ Y -- r-- 
ta menos de 10 KB. Esto es debido a r 
de scmarte deedenas v tamhih el se 
que se acabath eliminando las rutinas 
-- - - r ---- - , -- ,:stor de memoria, lo cud es hicamen- 
te posible en programas que utilizan exclusivamente llamadas de bajo ni- 
vel. Se pueden enwntrar ambas versiones en el c6digo fuente del archivo de 
ejemplo. 
Fijese, de todos modos, en que las decisiones de este tip^ siempre implican 
una sene de concesiones. A1 eliminar el encabezamiento de variantes de las 
aplicaciones Delphi qure no las usan, por ejemplo, Borland ha aiiadido una 
carga extra a ias aplicaciones que si lo ham. La ventaja real de esta opera- 
cibn, sin embargo, estA en el reducido tamafio en memoria que necesitan las 
aplicaciones Delphi que no usan variantes, como consecuencia de no tener 
que introducir varios megabytes debido a las bibliotecas de sistema Ole2. 
Lo realmente importante, en mi opini&n, es el tamaiio de las grandes aplica- 
ciones Delphi basadas en paquetes en tiempo de ejecuci6n. Una sencilla 
prueba con un programa que no hace nada, el ejemplo Minipack, muestra 
un ejecutable de 17.408 bytes. 
En 10s siguientes apartados encontrara una lista de las unidades de la RTL en 
Delphi, asi como de todas las unidades disponibles (con el codigo fuente comple- 
to) que se encuentran en el subdirectorio Source\Rtl\Sys del directorio Delphi 
y algunas de las disponibles en el subdirectorio Source\Rtl\Common. Este 
segundo directorio contiene el codigo fuente de las unidades que conforman el 
nuevo paquete de la RTL, que engloba tanto la biblioteca basada en funciones 
como las clases centrales comentadas m h adelante. 
Comentare de forma breve el papel de cada unidad y tambien 10s grupos de 
funciones incluidas. Ademas dedicare mas espacio a las unidades mas nuevas. No 
se trata de ofrecer una lista detallada de las funciones incluidas, ya que la ayuda 
electronica incluye un material de referencia similar. 
Sin embargo, la intencion es fijarse en algunas funciones interesantes o poco 
conocidas. 
Las unidades System y Syslnit 
System es la unidad principal de la RTL y se incluye automaticamente en 
cualquier compilacion (siempre que haya una sentencia uses automatica e im- 
plicita que se refiera a ella). En realidad, si intentamos aiiadir la unidad a la 
sentencia uses de un programa, obtendremos el siguiente error en tiempo de 
compilacion: 
[Error] Identifier redeclared: System 
La unidad System se compone entre otras cosas de: 
La clase TO^ j ect, que es la clase basica de toda clase definida en el 
lenguaje Pascal orientado a objetos, como todas las clases de la VCL. 
Las interfaces IInterf ace, IInvokable, IUnknown y IDispatch, 
asi como la clase de implementation simple T Int er f acedOb j ec t . 
I ~nterface se aiiadio en Delphi 6 para recalcar el hecho de que el tip0 
de interfaz en la definicion del lenguaje Delphi, no depende en mod0 algu- 
no del sistema operativo Windows. I~nvokable se aiiadio en Delphi 6 
para soportar las llamadas basadas en SOAP. 
Codigo de soporte de variantes, como las constantes de tip0 variante, el 
tip0 de registro TVarData y el nuevo tipo TVariantManager, un 
amplio numero de rutinas de conversion de variantes y tambien registros 
variantes y soporte de matrices dinamicas. En este ambito ha habido un 
monton de cambios en comparacion con Delphi 5. 
Muchos tipos de datos basicos, como 10s tipos de punteros y de matrices y 
el tipo TDateTime. 
Rutinas de asignacion de memoria, como GetMem y FreeMem y el pro- 
pio administrador de memoria, definido por el registro TMemoryManager 
y a1 que se accede mediante las funciones GetMemoryManager y 
SetMemoryManager. Para mas informacion, la funcion GetHeap- 
St a tus devuelve una estructura de datos THeapS t a t us. Dos nuevas 
variables globales (A1 1ocMemCount y A1 locMemSi ze) guardan el 
numero y tamaiio total de 10s bloques de memoria asignados. En el capitulo 
sobre la arquitectura de las aplicaciones Delphi encontrara mas informa- 
cion sobre la memoria y estas funciones. 
El codigo de soporte de modulos y paquetes, como el tip0 de punter0 
PackageInf o, la funcion global GetPackageInf oTable y el pro- 
cedimiento EnumModules. 
Una lista bastante larga de las variables globales, como el caso de aplica- 
cion Windows MainInstance; IsLibrary, que indica si el archivo 
ejecutable es una biblioteca o un programa independiente; Isconsole, 
que indica aplicaciones de consola; I s M u l t i T h r e a d , que indica si esis- 
ten hilos de proceso secundarios; y la cadena de la linea de comandos 
CmdLine. (La unidad incluye tambien P a r a m c o u n t y ParamS t r para 
poder acceder mas facilmente a 10s parametros de la linea de comandos.) 
Algunas de estas variables son especificas de la plataforma Windows, otras 
estan tambien disponibles en Linux, mientras que otras son especificas de 
Linux. 
El codigo de soporte de hilos de proceso (threads), con las funciones 
B e g i n T h r e a d y E n d T h r e a d ; registros de soporte de archivos y ruti- 
nas relacionadas con archivos; rutinas de conversion de cadenas anchas y 
cadenas OLE; asi como muchas otras rutinas de sistema y de bajo nivel 
(junto con una serie de funciones de conversion automaticas). 
La unidad que acompaiia a System, denominada SysInit, incluye el codigo de 
inicializacion, con funciones que rara vez se utilizaran directamente. Esta es otra 
unidad que siempre se incluye de forma implicita, puesto que la unidad System 
hace uso de ella. 
Cambios recientes en la unidad System 
Ya se han mencionado algunas caracteristicas interesantes de la unidad System. 
La mayoria de 10s cambios estan relacionados con el objetivo de conseguir que la 
RTL de Delphi sea mas facil de transportar entre distintas plataformas, reempla- 
zando caracteristicas especificas de Windows por implementaciones genericas 
que ahora comparten Delphi y Kylix. De acuerdo con esta tendencia, existen 
nombres nuevos para tipos de interfaz, soporte para variantes totalmente revisa- 
do, nuevos tipos de punteros, soporte de matrices dinamicas y funciones para 
personalizar la adrninistracion de 10s objetos de excepcion. 
uso que se hace de la c&qdacibn condicio& con muchas referencias a 
($IFDEF L M ) p ($WDEF MSTKMDOWS), que se usan para diferen- 
ciar entre 10s dos sistemas o~erativos. Fiiese en me aara Windows. Borland 
utiliza MSWINDOWS &a indicar 1; plataf&r& a1 complete, ya q eWINDOWS se utilizaba en las versiones de 16 bits del sistema operativo 
(en contraste con el simboIo WIN32). 
Por ejemplo, otro aiiadido para la compatibilidad entre Linux y Windows esta 
relacionado con 10s saltos de linea en 10s archivos de testo. La variable 
DefaultTextLineBreakStyle, afecta a1 comportamiento de las rutinas 
que leen y escriben en archivos, como la mayoria de las rutinas de flujos de texto. 
Los valores posibles para esta variable global son t l b s L F (valor predetermina- 
do en Kylix) y t l b s C R L F (valor predeterminado en Delphi). El estilo de salto de 
linea tambien se puede configurar archivo por archivo mediante la funcion 
S e t T e x t L i n e B r e a k S t y l e . Del mismo modo, la constante global de cadena 
s L i n e B r e a k tiene el valor #13#10 en la version Windows del entorno de 
desarrollo y el valor # 1 0 en la version para Linux. Otro cambio es que la unidad 
System incluye ahora las estructuras T F i leRec y TTex t Rec, que en versiones 
anteriores de Delphi estaban definidas dentro de la unidad S y s u t i l s . 
Las unidades SysUtils y SysConst 
La unidad SysConst define una serie de cadenas de constantes utilizadas por 
otras unidades RTL para mostrar mensajes. Estas cadenas se declaran con la 
palabra clave r e s o u r c e s t r i n g y se guardan en 10s recursos de programa. A1 
igual que otros recursos, se pueden traducir mediante el Integrated Translation 
Manager o el External Translation Manager. 
La unidad SysUtils es un conjunto de utilidades del sistema de varios tipos. A 
diferencia de otras unidades RTL, es en gran parte una unidad dependiente del 
sistema operativo. La unidad SysUtils no posee un enfoque especifico, sino que 
engloba una pequeiia parte de todo, desde la gestion de cadenas a1 soporte de 
caracteres multibyte y locales, desde la clase Excep t i o n y muchas otras clases 
de excepcion derivadas a una multitud de constantes y rutinas de formato de 
cadena. Algunas de las caracteristicas de SysUtils las utilizan todos 10s progra- 
madores a diario, como las funciones de formato de cadena I n t T o S t r o Format. 
Otras caracteristicas son menos conocidas, como el caso de las variables globales 
de informacion sobre la version de Windows. st as indican la plataforma Windows 
(Window 9x o NT/2000/XP), la version del sistema operativo y el numero de 
creacion, asi como el paquete de servicio instalado. Se pueden usar del mismo 
mod0 que en el siguiente codigo, extraido del ejemplo Winversion: 
case Win32Platform of 
VER-PLATFORM-WIN32-WINDOWS: ShowMessage ('Windows 9x'); 
VER-PLATFORM-WIN32-NT: ShowMessage ( 'Windows NT ' ) ; 
end: 
ShowMessage ( 'Ejecutando en Windows: ' + IntToStr 
(Win32MajorVersion) + ' . ' + IntToStr (Win32MinorVersion) + ' 
(Creaci6n ' + IntToStr (Win32BuildNumber) + ' ) ' + #10#13 + 
' Actualizacidn: ' + Win32CSDVersion) ; 
El segundo fragment0 de codigo crea un mensa-je como el que muestra en la 
siguiente figura, dependiendo, claro esta, de la version del sistema operativo que 
se hava instalado. 
Otra caracteristica poco conocida de esta unidad es la clase TMul t iRead- 
ExclusiveWriteSynchronizer (probablemente la clase VCL de nombre 
mas largo). Borland ha definido un alias para la clase, que es mucho mas corto: 
TMREWSync (ambas clases son identicas). Esta clase soporta multithreading: 
permite trabajar con recursos que pueden usar diversos threads a1 mismo tiempo 
para leer (multilectura), pero que a1 escribir han de utilizar un unico thread (es- 
critura exclusiva). Esto significa que no se puede comenzar a escribir hasta que 
todos 10s threads de lectura hayan terminado su labor. 
La implementation de la clase TMultiReadExclusiveWriteSyn- 
c h r o n i z e r se ha actualizado en Delphi 7, pero mejoras similares estan dispo- 
nibles en forma de un parche que aparecio tras la segunda actualizacion de Delphi 
6. La nueva version de la clase esta mas optimizada y menos sujeta a bloqueos, 
que suelen ser un problema habitual del codigo de sincronizacion. 
- - 
NOTA: El sincronizador multilectura es linico porque soporta bloqueos 
recursivos y conversi6n de 10s bloqueos de lectura en bloqueos de escritura. 
El objetivo principal de la clase es permitir un acceso rapid0 y facil a 
diversos threads de lectura a1 recurso compartido, per0 a h asi pennitir 
que un thread obtenga el control exclusive del recurs; para reali&r actua- 
lizaciones relativamente poco frecuentes. Hay otras clases de sincronizacion - . - . - . . .. . . . --. .a - - . 
en Delphi, declaradas en la unidad SyncOb j s (disporuble baj0 Source / 
Rt 1 /Common) y con correspondencia directa con 10s objetos de 
sincronizaci6n del sistema operativo'(como eventos y secciones criticas en 
Windows). 
Nuevas funciones de SysUtils 
Durante las ultimas versiones, Delphi ha aiiadido algunas funciones nuevas 
dentro de la unidad SysUtils. Uno de 10s nuevos campos esta relacionado con la 
conversion de booleano a cadena. La funcion Boo lToSt r por lo general devuel- 
ve -1 y 0 como valores verdadero o falso. Si se especifica el segundo parametro 
optional, la funcion devuelve la primera cadena de las matrices T r u e BoolS t rs 
y F a l s e B o o l S t r s (por defecto T R U E y FALSE): 
BoolToStr (True) / / devuelve '-1 ' 
BoolToStr (False, True) / / devuelve 'FALSE' por de fec to 
La funcion inversa es S t r T o B o o l , que puede convertir una cadena que con- 
tenga uno de 10s valores de las dos matrices booleanas mencionadas anteriormen- 
te o un valor numerico. En este ultimo caso, el resultado sera verdadero si el valor 
numerico es distinto de cero. Se puede ver una sencilla demostracion del uso de 
las funciones de conversion booleanas en el ejemplo StrDemo. Otras funciones 
aiiadidas a SysUtils estan relacionadas con las conversiones de coma flotante en 
tipos divisa y fecha-hora: FloatToCurr y FloatToDateTime se pueden 
usar para evitar una conversion de tipos explicita. Las funciones TryStrTo- 
Float y Tr yS t rToCur r intentan convertir una cadena en un valor de coma 
flotante o de divisa, y, en caso de error, devuelven el valor False en lugar de 
generar una excepcion (corno hacen las clasicas funciones St rTo Float y 
StrToCurr). 
La Ans i Dequot edS t r, que elimina comillas de una cadena, se correspon- 
de con la funcion Ans iQuot est r aiiadida en Delphi 5. Con respecto a las 
cadenas, desde Delphi 6 existe un soporte muy mejorado de cadenas anchas, con 
una serie de rutinas como Wideuppercase, WideLowerCase, 
WideCompareStr,WideSameStr,WideCompareText,WideSameText 
y WideFormat. Todas estas funciones se utilizan como sus homologos 
AnsiString. 
Existen tres funciones (TryStrToDate, TryEncodeDate y 
Tr yEncodeTime) que intentan convertir una cadena en una fecha o codificar 
una fecha u hora, sin crear una excepcion, de un mod0 similar a las funciones 
Try antes mencionadas. Ademas, la funcion Decode Da t e Full y devuelve in- 
formation mas pormenorizada, como el dia de la semana y la funcion 
Current Y ear devuelve el aiio de la fecha actual. 
Hay una version que se puede transportar, sobrecargada de la funcion 
Get E nvironmentvar i ab le . Esta nueva version usa parametros de cadena 
en lugar de parametros PChar y es, en definitiva, m b facil de utilizar: 
function GetEnvironmentVariable(Name: string): string; 
Otras funciones nuevas estan relacionadas con el soporte de interfaz. Dos 
nuevas versiones sobrecargadas de la poco conocida funcion support permiten 
verificar si un objeto o una clase soporta una interfaz dada. La funcion se corres- 
ponde con el comportamiento del operador is para clases y se proyecta a1 metodo 
QueryInterf ace. Veamos un ejemplo: 
var 
W1: IWalker; 
J1: IJumper; 
begin 
W1 : = TAthlete.Create; 
// mds codigo. . . 
if Supports (wl, IJumper) then 
begin 
J1 := W1 as IJumper; 
Log (J1.Walk) ; 
end; 
SysUtils incluye tambien una funcion Is EqualGUID y dos funciones de 
conversion de cadenas a GUID y viceversa. La funcion Crea t eGUI D hasido 
desplazada a sysutils para que este disponible tambien en Linux (con una 
implernentacion personalizada, por supuesto). 
Por ultimo, en las ultimas versiones se han aiiadido algunas funciones mas de 
soporte para varias plataformas. La funcion Ad j us t LineBrea ks puede reah- 
zar ahora diferentes tipos de ajustes en las secuencias de retorno de carro y de 
avance de linea, y se han introducido nuevas variables globales para archivos de 
texto en la unidad System. La funcion Fi 1 eCre a t e tiene una version sobrecar- 
gada en la que se pueden especificar derechos de acceso a archivos a la manera 
Unix. La funcion ExpandFi 1 eName puede localizar archivos (en sistemas de 
archivos que distinguen entre mayusculas y minusculas), incluso cuando su tipo- 
grafia no se corresponde exactamente. Las funciones relacionadas con 10s 
delimitadores de ruta (barra inversa o barra oblicua) son ahora mas genericas que 
en las versiones precedentes de Delphi, por lo que se les han asignado nombres 
nuevos de acuerdo con ello. (Por ejemplo, la vieja funcion I ncludeTraling- 
Backslash ahora es mas conocida como IncludingTrailingPathDe- 
limiter). 
Ya que hablamos de archivos, Delphi 7 aiiade a la unidad SysUtils la funcion 
Get Fi levers ion, que lee el numero de version a partir de la informacion de 
version que se aiiade opcionalmente a un archivo ejecutable de Windows (que es 
por lo que esta funcion no funcionara sobre Linux). 
Rutinas extendidas de formato de cadenas en Delphi 7 
La mayor parte de las rutinas de formato de cadenas de Delphi utilizan varia- 
bles globales para determinar 10s separadores de decimales y miles, 10s formatos 
de fecha y hora, etc. Los valores de estas variables se leen en primer lugar desde 
el sistema (la configuracion local de Windows) cuando arranca un programa, y se 
puede sobreescribir cualquiera de ellas. Sin embargo, si el usuario modifica las 
opciones regionales en el Panel de control mientras que el programa se esta ejecu- 
tado, el programa respondera a1 mensaje radiado actualizando las variables, con 
lo que probablemente se perderan 10s cambios introducidos directamente en el 
codigo. Si necesita distintos formatos de salida en diferentes partes de un mismo 
programa, puede aprovecharse del nuevo conjunto de rutinas sobrecargadas de 
formato de cadenas; admiten un parametro adicional de tipo T Format Set t ings, 
que incluye todas las opciones relevantes. Por ejemplo, ahora hay dos versiones 
de Format: 
function Format (const. Format : string; 
const Args: array of const) : string; overload; 
function Format (const Format: string; const Args: array of 
cons t ; 
const FormatSettings: TFormatSettings) : string; overload; 
Decenas de funciones disponen de este nuevo parametro adicional, que se usa 
en lugar de las opciones globales. Sin embargo, puede inicializarlo con las opcio- 
nes predeterminadas del ordenador en el que se ejecutar su programa mediante la 
invocation de la nueva funcion Get Locale Format Settings (solo disponi- 
ble en Windows, no en Linux). 
La unidad Math 
La unidad Math (matematica) csta compuesta por un conjunto de funciones 
matcmaticas: unas cuarenta funciones trigonomdtricas, funciones logaritmicas y 
esponenciales, funciones de redondeo, evaluaciones polinomicas; casi treinta fun- 
ciones estadisticas y una doccna dc funciones economicas. 
Describir todas estas funcioncs seria bastante aburrido, aunquc algunos lecto- 
res probablementc se cncuentren muy intcresados en las capacidadcs matematicas 
dc Delphi. Es por esto, que hemos decidido centrarnos en las funciones matcmati- 
cas prescntadas en las illtimas vcrsiones de Delphi (en particular Delphi 6) y 
tratar dcspues un tema espccifico que suele confundir a 10s programadorcs dc 
Delphi, el redondeo. 
Veamos algunas dc las funcioncs matematicas mas nuevas. 
Nuevas funciones matematicas 
Las vcrsioncs recicntes de Delphi ahaden a la unidad Math un numero considc- 
rable dc caractcristicas nuevas. Esiste soporte para constantes infinitas 
( I n f i n i t y y Neg I n f i n i t y) y funciones de comparacion relac~onadas 
( I s I n f i n i t e y I sNan) . junto con las nuevas funciones trigonomdtricas para 
cosecantcs y cotangcntes. y nuevas funciones dc conversion de angulos. 
Una caracteristica nluy comoda es la disponibilidad de una funcion sobrecar- 
gada I f Then . que devuelvc uno de dos valores posiblcs, con dependencia de una 
expresion booleana. (Ahora tambien hay una funcion similar disponiblc para ca- 
denas.) Puede usarse, por ejcmplo. para calcular el minimo dc dos valorcs: 
nMin := IfThen (nA < nB, na, nB) ; 
NOTA: La hncion IfThen es similar a1 operador ?: del lenguaje C/ 
C++, que es muy util porque permite reemplazar una sentencia completa 
i f /t h e n / e l s e por una expresion mucho mas breve, escribiendo menos 
codigo y declarando normalmente menos variables temporales. 
RandomRange y RandomFrom se pueden usar en lugar dc la traditional 
funcion Random para tener un mayor control de 10s valores aleatorios produci- 
dos por la RTL. 
La primera funcion devuelve un numero comprendido cntrc dos cstremos que 
se especifican, mientras que el segundo escoge un valor aleatorio de una matriz de 
numeros posiblcs quc sc pasa como un parametro. 
La funcion booleana I n R a n g e se puede usar para comprobar si un numero sc 
encuentra entrc otros dos valores. La funcion E n s u r e R a n g e , en cambio, obliga 
a que el valor cstd dentro del rango especificado. El valor dc retorno es el propio 
numero o el limite mas bajo o limite mas alto, en el caso de quc el numero sc 
encuentrc fuera del rango. Veamos un cjcmplo: 
// a c t u a s o l o s i e l v a l o r e s t d e n t r e e l m i n y e l max 
if InRange (value, min, max) then 
// s e a s e g u r a q u e e l v a l o r e s t d e n t r e min y m x 
value : = EnsureRange (value, min, max); 
Otro grupo muy util de funciones esta relacionado con las comparaciones. Los 
numeros de coma flotante son basicamente inexactos. Un numero de coma flotan- 
tc cs una aproximacion de un valor real teorico. Cuando realizamos operaciones 
matematicas con numeros de coma flotante, la inesactitud de 10s valores origina- 
les se acumula en 10s resultados. Si multiplicamos y dividimos por el mismo 
numero puede que no consigamos exactamente el numero original, sino uno muy 
proximo a 121. La funcion samevalue permite verificar si dos valores se aproxi- 
man lo suficiente como para ser considerados iguales. Se puede especificar el 
grado de aproximacion que deberian tener dos numeros o dejar que Delphi calcule 
un rango de error razonable para la representacion que estamos utilizando. (Por 
csta razon se sobrecarga la funcion.) 
Del mismo modo, la funcion Iszero compara un numero con cero, mediante 
esta misma "logica borrosa". 
La funcion Comparevalue usa la misma norma para 10s numeros de coma 
flotante per0 esta disponible tambien para enteros. Devuelve una de las tres cons- 
tantes LessThanValue, EqualsValue y GreaterThanValue (que se 
corresponden con -1,O y 1). Del mismo modo, la nueva funcion sign devuelve 
-1, 0 y 1 para indicar un valor negativo, cero o un valor positivo. 
La funcion D i v M o d es equivalente a las operaciones de division y resto, de- 
volviendo el resultado de la division del entero y del resto al mismo tiempo La 
funcion RoundTo nos permite especificar el digito de redondeo (permite, por 
ejemplo, redondear hasta el millar mas proximo o hasta dos decimales): 
RoundTo (123827 , 3 ) ; // e l r e s u l t a d o e s 1 2 4 . 0 0 0 
RoundTo (12 .3827 , - 2 ) ; // e l r e s u l t a d o es 1 2 , 3 8 
. . 
ADVERTENCIA: Fijese en que la funci6n RoundTo usa un nhnero po- 
sitivo para indicar la potencia de diez hash la que hay que redondear (por 
ejemplo, 2 para centenas) o un n6mero negativo para el numero de cifras 
decimales. Esto es exactamente lo contrario de la funci6n Round utilizada 
por hojas de calculo como Excel. 
TambiCn ha habido algunoscambios en las operaciones de redondeo estandar 
de la funcion Round: ahora, se puede controlar el mod0 en que la FPU (la Unidad 
de Coma Flotante de la CPU) realiza el redondeo llamando a la funcion 
SetRoundMode. Existen tambien funciones de control del mod0 de precision de 
la FPU y sus excepciones. 
Redondeo y dolores de cabeza 
La clasica funcion Round de Delphi y las mas recientes funciones RoundTo 
se proyectan sobre algoritmos de redondeo de la CPU y la FPU. De manera 
predeterminada, las CPU de Intel utilizan el redondeo bancario, que es tambidn el 
tipo de redondeo que se suele encontrar en aplicaciones de hojas de calculo. 
El redondeo bancario se basa en la suposicion de que cuando se redondean 
numeros que residen exactamente entre dos valores (10s numeros ,5) , a1 redon- 
dearlos arriba o abajo se aumenta o reduce estadisticarnente la cantidad total (en 
general de capital). Por este motivo, la regla del redondeo bancario indica que 10s 
numeros ,5 deberian redondearse arriba o abajo dependiendo de que el numero 
(sin decimales) sea impar o par. De esta manera, el redondeo se equilibrara, a1 
menos estadisticamente. La figura 3.1 muestra un ejemplo del resultado del re- 
dondeo bancario. Se trata de un ejemplo diseAado para demostrar distintos tipos 
de redondeo. 
Figura 3.1. El ejernplo de redondeo, dernuestra el redondeo bancario y el aritmetico. 
El programa tambidn utiliza otro tipo de redondeo proporcionado por la uni- 
dad Math mediante la funcion SimpleRoundTo, que utiliza un redondeo arit- 
mktico asimetrico. 
En este caso, todos 10s numeros ,5 se redondean a1 valor superior. Sin embar- 
go, tal y como se recalca en el ejemplo de redondeo, la funcion no actua como se 
esperaria cuando se redondea hasta un digito decimal (es decir, cuando se pasa un 
segundo parametro negativo). En este caso, debido a 10s errores de representacion 
de 10s numeros de coma flotante, el redondeo recorta 10s valores; por ejemplo 
convierte 1,15 en 1,l en lugar del esperado 1.2. 
La solucion es multiplicar el valor por diez antes de redondear, redondearlos 
hasta cero digitos decimales, y despues dividirlo, como se muestra a continua- 
cion: 
(SimpleRoundTo ( d *10 , 0) / 10 ) 
Las unidades ConvUtils y StdConvs 
En la unidad ConvUtils se encuentra el nucleo del motor de conversion presen- 
tad0 en Delphi 6. Utiliza las constantes de conversion definidas por una segunda 
unidad, StdConvs. 
I NOTA: De 1 
a 14 lib&). LII C . U I U ~ U L G I baa", 3 1 LIGUG ~ U G I l m l G j a I U u I u a u G a UG LIIGUIUU 6 1 1 
su codigo, apreciara las caracteristicas disponibles en este motor. 
Jphi 7 supone solo una mejora en esta unidad de coaversi6n: 
-te parastones (la unidad britiinica de medida que es equivalente 
c.. ,.. "I"..:,, ,,", ..: c:,,* ,.., ,,,,;,, ..,:.a,,a*, ,a, ,, .I;..a... a, 
La unidad DateUtils 
La unidad DateUtils es una nueva coleccion de funciones relacionadas con la 
fecha y la hora. Engloba nuevas funciones para seleccionar valores de una varia- 
ble TDa t e T i m e o contar valores de un intervalo dado como: 
// e s c o g e r v a l o r 
function DayOf (const AValue : TDateTime) : Word; 
function HourOf (cons t AValue : TDateTime) : Word; 
// v a l o r en rango 
function WeekOf Year (const AValue : TDateTime) : Integer; 
function HourOfWeek (const AValue: TDateTime) : Integer; 
function SecondOfHour (const AValue: TDateTime) : Integer; 
Algunas de estas funciones son bastante extraiias, c o m o M i l l i S e c o n d O f - 
M o n t h o S e c o n d o f w e e k , pero 10s desarrolladores de Borland han decidido 
suministrar un con.junto de funciones complete, sin importar lo poco practicas 
que parezcan. (Realmente he utilizado algunas de estas funciones en mis e.jem- 
plos.) 
Existen funciones para calcular el valor final o inicial de un intervalo de tiem- 
po dado (dia, semana, mes, aiio) como la fecha actual y para verificacion del 
rango y consultas. Por e.jemplo: 
function DaysBetween (cons t ANow, AThen: TDateTime) : Integer; 
function WithinPastDays(const ANow, AThen: TDateTime; 
const ADays: Integer) : Boolean; 
Otras funciones abarcan el increment0 y decrement0 por parte de cada interva- 
lo de tiempo posible, codificando y "recodificando" (reemplazando un elemento 
del valor T D a t e T i m e , como el dia, por uno nuevo) y realizando comparaciones 
"borrosas" (comparaciones aproximadas en las que una diferencia de una milesi- 
ma de segundo haria que dos fechas fuesen iguales). 
En general, DateUtils resulta bastante interesante y no es excesivamente dificil 
de utilizar. 
La unidad StrUtils 
La unidad StrUtils es una nucva unidad presentada en Delphi 6 con algunas 
nucvas funciones relacionadas con cadenas. Una de las caractcristicas clave dc 
csta unidad es la existencia de muchas funcioncs de comparacion de cadenas. Hay 
funciones basadas en un algoritmo "soundex" (Ans iResembleText ) ; y algu- 
nas que ofrecen la capacidad de realizar busquedas en matrices de cadenas 
(Ans iMat c h T e x t y Ans i IndexTex t ) , localizar y sustituir subcadenas (como 
NOTA: Soundex es un algoritmo para comparar nombres basados en el 
mod0 en que suenan y no en el modo en que se deletrean. El algoritmo 
calcula un numero para cada sonido de la palabra, de modo que comparan- 
do dos de esos numeros se puede decidir si dos nombres suenan igual. El 
sistema lo aplic6 por pimerzi vez en 1880 la U.S. Bureau of the census (La 
Oficina del Censo de EEUU); se patent6 en 1918 y en la actualidad es de 
dominio publico. El codigo soundex es un sistema de indexado que traduce 
1 ---- - .... -:I:__ 3 - - . . -L -_ - - - _ _ L _ - - _ L- 3 - ..-A l - L - _ A _ - _ nomores a un coalgo ae cuatro caracteres Iormaao por una m r a y rres 
numeros. Puede encontrar mas information a1 respecto en www.nara.gov/ 
genealogylcoding . html . 
Mas a116 de las comparaciones, otras funciones proporcionan una prueba en 
dos direcciones (la simpatica funcion I f T h e n , similar a la que ya hemos visto 
para 10s numeros), duplican e invierten cadenas y sustituyen subcadenas. La ma- 
yoria de estas funciones de cadena se aiiadieron por comodidad para 10s progra- 
madores en Visual Basic que se pasaban a Delphi. Hemos utilizado algunas de 
dichas funciones en el ejemplo StrDemo, que usa tambien algunas conversiones 
de booleano a cadena definidas dentro de la unidad SysUtils. El programa en 
realidad es algo mas que una prueba para unas cuantas funciones. Por ejemplo, se 
usa la comparacion "soundex" entre las cadenas introducidas en dos cuadros de 
edicion. convierte el booleano resultante en una cadena y lo muestra: 
ShowMessage (BoolToStr (AnsiResemblesText 
(EditResemblel-Text, EditResemble.2 .Text) , True) ) ; 
El programa tambien utiliza las funciones An s iMa t c h T e x t y 
Ans i I ndexTex t , tras haber rellenado una matriz dinamica de cadenas (deno- 
minada s t r A r r a y ) con 10s valores de las cadenas del interior del cuadro de 
lista. Se podria haber utilizado el metodo I n d e x o f de la clase T S t r i n g s , que 
es mas sencillo, pero esto habria anulado el proposito del ejemplo. Las dos com- 
paraciones de lista se realizan del siguiente modo: 
procedure TForml.ButtonMatchesClick(Sender: TObject); 
begin 
ShowMessage (BoolToStr (AnsiMatchText(EditMatch.Text, 
strArray) , True) ) ; 
end; 
procedure TForml.ButtonIndexClick(Sender: TObject); 
var 
m a t c h : Integer; 
begin 
m a t c h := AnsiIndexText (EditMatch.Text, strArray) : 
ShowMessage ( IfThen ( m a t c h >= 0, ' C o r r e s p o n d e a 1 n u r n e r o d e 
c a d e n a ' + IntToStr ( m a t c h ) , ' N o c o r r e s p o n d e ' ) ) ; 
end; 
Fijese en el uso de la funcion I f Then en las ultimas lineas de codigo; tiene 
dos cadenas de salida alternativas, que dependen del resultado del test inicial 
(nMatch >= 0). 
Tres botones adicionales realizan llamadas sencillas a otras tres funciones 
nuevas, con las siguientes lineas de codigo (una para cada una):// r e p i t e ( 3 veces) u n a c a d e n a 
ShowMessage (Dupestring (EditSample.Text, 3) ) ; 
// i n v i e r t e l a c a d e n a 
ShowMessage (Reversestring (EditSample.Text)); 
// e s c o g e u n a c a d e n a a l e a t o r i a 
ShowMessage (RandomFrom (strArray)); 
De Pos a PosEx 
Delphi 7 aporta su granito de arena a la unidad StrUtils. La nueva funcion 
PO s E X resultara muy practica para muchos desarrolladores y merece que hable- 
mos de ella. Cuando se buscan multiples apariciones de una cadena dentro de 
otra, una solucion clasica de Delphi era utilizar la funcion Pos y repetir la bus- 
queda sobre la parte restante de la cadena. Por ejemplo, podria contar el numero 
de apariciones de una cadena dentro de otra con un codigo como este: 
function CountSubstr (text, sub: string) : Integer; 
var 
nPos: Integer; 
begin 
Result := 0; 
nPos := Pos (sub, text) ; 
while nPos > 0 do 
begin 
Inc (Result) ; 
text : = Copy (text, nPos + Length (sub) , MaxInt) ; 
nPos : = Pos (sub, text) ; 
end; 
end; 
La nueva funcion Po SEX permite especificar la posicion de comienzo de la 
busqueda dentro de una cadena, de manera que no se necesita modificar la cadena 
original (que supone una ligera perdida de tiempo). Por eso. el codigo anterior 
puedc simplificarsc como: 
function C o u n t S u b s t r ( t e x t , s u b : s t r i n g ) : I n t e g e r ; 
var 
nPos : I n t e g e r ; 
begin 
R e s u l t : = 0: 
npos : = PosEx ( s u b , t e x t , 1 ) ; // predeterminado 
while nPos > 0 do 
begin 
Inc ( R e s u l t ) ; 
npos : = PosEx ( s u b , t e x t , nPos + Length ( s u b ) ) ; 
end ; 
end ; 
Ambas porciones de codigo se utilizan de una manera trivial en el ejemplo 
S t r Demo comentado anteriormente. 
La unidad Types 
La unidad Types (de tipos) almacena tipos de datos comunes a diversos siste- 
mas operativos. En las anteriores versiones de Delphi, la unidad de Windows 
definia 10s mismos tipos; ahora se han desplazado a esta unidad comun, compar- 
tida por Delphi y Kylix. Los tipos definidos aqui son sencillos y engloban, entre 
otros. las estructuras de registro TPoint, T R e c t y TSmallPoint mas sus 
tipos de punter0 relacionados. 
ERTENCIA: Fijese en que tendri que actualizar 10s programas Delphi 
uos que hagan referencia a T R e c t o TPo i n t , dadiendo la unidad 
s en la sentencia uses: de no ser asi- 10s Droeramas no se comoilarh. 
La unidad Variants y VarUtils 
Las unidades Variants (de variantes) y VarUtils son dos nuevas unidades pre- 
sentadas en Delphi 6 que agrupan las partes de la biblioteca relacionadas con 
variantes. La unidad Variants contiene codigo generico para variantes. Algunas 
rutinas de esta unidad han sido desplazadas aqui desde la unidad System. Las 
funciones abarcan soporte generico de variantes, matrices variantes, copiado de 
variantes y convcrsiones de matriz dinarnica a matriz variante. Tambien esta la 
clase T C u s t omVa r i an t T y p e , que define 10s tipos de datos variantes 
personalizables. 
La unidad Variants es totalmente independiente de la plataforma y utiliza la 
unidad VarUtils, que contiene codigo dependiente del SO. En Delphi, esta unidad 
usa las API dcl sistcma para manipular datos de variantcs: cn Kylis usa codigo 
particularizado quc Ic proporciona la biblioteca RTL. 
NOTA: En Dclphi 7, estas unidades se han arnpliado y se han solucionado 
algunos problcmas. La impiementacion de variantes ha sido remodelada a 
conciencia para mejorar la velocidad de esta tecnologia y reducir la ocupa- 
cion en memoria de su codigo. 
Un arca cspccifica quc ha visto una me-jora significativa en Dclphi 7 es la 
capacidad de controlar cl comportamicnto de las implemcntacioncs dc variantes, 
en particular las rcglas dc comparacion. Delphi 6 supuso un cambio en el codigo 
dc variantes de mancra quc 10s valores null no podian compararsc con otros 
valores. Estc comportamiento es correct0 desde un punto de vista formal, de 
manera cspccifica para 10s campos de un conjunto dc datos (un area en que se 
usan mucho variantcs). pcro cste cambio tuvo cl cfccto colateral de romper el 
codigo csistcntc. Ahora sc puede controlar cstc comportamiento mediante el uso 
dc las variablcs globales Nu1 lEqual it yRule y Nu1 lMagni tudeRule; 
cada una dc las cualcs toma uno de 10s siguicntcs valorcs: 
ncrError : Cualquicr tipo de comparacion provoca quc sc levante una es- 
cepcionj \,a quc no pucdc compararse un valor indcfinido: cste cra cl com- 
portamicnto prcdctcrminado (nuevo) en Dclphi 6 . 
ncrstr ict : Cualquier tipo de comparacion falla siempre (devuelvc False), 
sin importar 10s valores. 
ncrLoose: Las comprobaciones de igualdad solo tienen cxito cntrc valores 
nulos (un valor nulo es distinto de cualquicr otro valor). En las compara- 
cioncsi 10s valorcs nulos se consideran como valorcs vacios o cero. 
Otras opcioncs con10 NullStrictConvert y NullAsStringValue 
controlan cl mod0 cn quc sc rcalizan las comparaciones en caso dc valorcs nulos. 
Un buen consejo cs cspcrimcntar con el e.jcmplo VariantComp quc se cncuentra 
disponiblc mas adelantc. Como mucstra la figura 3.2. este programa dispone de 
un formulario con un RadioGroup que se puede utilizar para modificar 10s \ d o - 
res de las variablcs globales NullEqualityRule y NullMagnitudeRule 
y unos cuantos botoncs para rcalizar diversas comparacioncs. 
Variantes personalizadas y numeros complejos 
La posibilidad dc ampliar el sistema dc tipos con variantes personalizadas es 
una extension rcciente del concept0 dc variantcs. Nos permite definir un nuevo 
tipo de datos quc, cn oposicion a la clase; sobrccarga 10s operadores aritmiticos 
estandar. Una variantc es un tipo que manticnc tanto la especificacion de tipo 
como el valor real. Una variante puedc contener una cadcna. otra pucde contener 
un numero. El sistema define conversiones automaticas entre tipos dc variantes 
(como variantes personalizadas), lo que le permite mezclarlas en las opcraciones. 
Esta flexibilidad tiene un coste muy alto: las operaciones con variantes son mu- 
cho mas lentas que las rcalizadas con tipos originales y las variantcs utilizan 
memoria adicional. 
Figura 3.2. El forrnulario del ejernplo VariantCornp en tiempo de diseiio. 
Como ejemplo dc un tip0 de variante personalizada, Delphi aporta una intere- 
sante definicion para 10s numeros complejos en la unidad VarCmplx (disponi- 
bles en formato de codigo fuente en el directorio Rtl\Common). Se pueden crear 
variantes complejas utilizando una de las funciones sobrecargadas Varcomplex- 
Create y usarlas en cualquier espresion, como se demuestra en el siguiente 
fragment0 de codigo: 
var 
vl, v2: Variant; 
begin 
vl : = VarComplexCreate (10, 12); 
v2 := VarComplexCreate (10, 1) ; 
ShowMessage (vl + v2 + 5) ; 
Los numeros complejos se definen en realidad utilizando clases, per0 la super- 
ficie quc adoptan es la de variantes, mediante la herencia de una nueva clase de la 
clase TCus tomVar iantT ype (definida en la unidad Variants), sobrescritura 
de una serie de funciones abstractas virtuales y creacion de un objeto global que 
se encarga del registro dentro del sistema. 
Ademas de estas definiciones internas, la unidad incluye una larga lista de 
rutinas para operar con variantes, como las operaciones matematicas y 
trigonometricas. 
ADVERTENCIA: Construir una variante personalizada no es una tarea 
nada sencilla y apenas se pueden encontrar razones para usarlas en lugar de 
objetos y clases. De hecho, con una variante personalizada se tiene la ven- 
. . I I . I I I . . l r raja ae usar la soorecarga ae operaaores en las esrrucruras ae aaros, per0 se 
pierde la verification en tiempo de cornpilacion, se hace que el codigo sea 
z l e n t o v i s t i c a s be orlentaci6n a 04et.o~ y se 
ha de escribir un codigo bastante mas complejo. 
Las unidades DelphiMM y ShareMem 
Las unidades DelphiMM y ShareMem estan relacionadas con la gestion de 
memoria. El administrador de memoria estandar de Delphi se declara en launidad 
S y s tern. 
La unidad DelphiMM define una bibliotcca de administrador de mcmoria al- 
tcrnativa para utilizarla a1 pasar cadenas de un ejecutable a una DLL (una biblio- 
tcca de enlace dinamico de Windows), ambas construidas en Delphi. Esta biblioteca 
dc administrador de memoria se encuentra compilada de manera predeterminada 
cn el archivo de biblioteca Borlndmrn. dl1 que habra que distribuirjunto con el 
programa. 
La interfaz de este administrador de memoria se define en la unidad ShareMem. 
Esta es la unidad que se habra de incluir (es obligatoria como primera unidad) en 
10s proyectos del Gecutablc y de la biblioteca (bbibliotecas). 
_LC--- - 
NOTA: Al contrario que Delphi, Kylix no dispone de unidades DelphiMM 
y ShareMem, ya que la gestion de memoria se proporciona en las bibliote- 
cas nativas de Linux (en particular, Kylix utiliza malloc de glibc) y por 
eso se comparte efectivamente entre distintos modulos. Sin embargo, en 
Kylix, las aplicaciones con multiples modulos deben utilizar la unidad 
ShareExcept, que permite que las excepciones lanzadas en un modulo se 
reflejen en otro. 
Unidades relacionadas con COM 
ComConst, ComObj y ComServ proporcionan soporte COM a bajo nivel. Es- 
tas unidades no son realmente parte de la RTL, desde un cierto punto de vista, asi 
que no se comentaran aqui. Mas adelante encontrara informacion detallada, per0 
baste aiiadir que estas unidades no han cambiado mucho en las mas recientes 
versiones de Delphi. 
Convertir datos 
Delphi incluye un nuevo motor de conversion, definido en la unidad ConvUtils. 
El motor por si mismo no incluye definicion alguna de las unidades de medida 
reales; en cambio, posee una serie de funciones principales para 10s usuarios 
finales. La funcion clave es la llamada de conversion, la funcion Convert. 
Sencillamente, nosotros proporcionamos la cantidad, las unidades en las que se 
expresa y las unidades a las que queremos que se conviertan. 
Lo siguiente convertiria una temperatura de 3 1 grados centigrados a Fahren- 
heit: 
Convert (31, tucelsius, tuFahrenheit) 
Una version sobrecargada de la funcion convert permite convertir valores 
que poseen dos unidades, como la velocidad (que tiene una unidad de longitud y 
una unidad de tiempo). Por ejemplo, se pueden convertir kilometros por hora en 
metros por segundo con esta llamada: 
Convert (20, duKilometre, tuHours, duMeters, tuseconds) 
Otras funciones de la unidad permiten convertir el resultado de una suma o una 
resta, verificar si las conversiones se pueden aplicar e incluso listar las familias y 
unidades de conversion disponibles. 
En la unidad StdConvs, se proporciona un conjunto predefinido de unidades de 
medida. Esta unidad tiene familias de conversion y un impresionante numero de 
valores, como en el siguiente extracto: 
// U n i d a d e s d e c o n v e r s i o n d e d i s t a n c i a s 
// l a u n i d a d b d s i c a d e m e d i d a es e l m e t r o 
cbDistanke: TConvFamily; 
duAngstroms : TConvType; 
dulrlicrons: TConvType; 
dulrlillimeters: TConvType; 
duMeters : TConvType; 
duKilometers: TConvType; 
duInches: TConvType; 
duMiles: TConvType; 
duLightYears: TConvType; 
duFurlongs: TConvType; 
duHands : TConvType ; 
duPicas: TConvType; 
Esta familia y las diversas unidades se registran en el motor de conversion en 
la parte de inicializacion de la unidad y proporcionan ratios de conversion (guar- 
dados como una serie de constantes, como MetersPerInch en el siguiente 
codigo): 
cbDistance : = RegisterConversionFamily('Distancia'); 
duAngstroms : = RegisterConversionType(cbDistance, ' A n g s t r o m s ' , 
1E-10) ; 
dmillimeters : = RegisterConversionType(cbDistance, ' M i l i m e t r o s ' , 
0.001) ; 
duInches : = RegisterConversionType(cbDistance, ' P u l g a d a s ' , 
MetersPerInch) ; 
Para probar el motor de conversion, creamos un e.jemplo generic0 (ConvDemo) 
quc permite traba.jar con todo el conjunto de conversiones disponibles. El progra- 
ma rellena un cuadro combinado con las familias de conversion disponibles y un 
cuadro de lista con las unidades disponibles de la familia activa. Este es el codigo: 
procedure TForml. Formcreate (Sender: TObject) ; 
var 
i: Integer; 
begin 
GetConvFamilies (aFamilies) ; 
for i : = Low (aFamilies) to High (aFamilies) do 
ComboFamilies.1tems.Add (ConvFamilyToDescription 
(aFamilies [i] ) ) ; 
// obtiene el primer0 y lanza el evento 
ComboFamilies.Item1ndex : = 0; 
ChangeFamily (self) ; 
end ; 
procedure TForml.ChangeFamily(Sender: TObject); 
var 
aTypes : TConvTypeArray; 
1: Integer; 
begin 
ListTypes .Clear; 
CurrFamily : = aFamilies [ComboFamilies.ItemIndex]; 
GetConvTypes (CurrFamily, aTypes) ; 
for i : = Low(aTypes) to High(aTypes) do 
ListTypes.Items.Add (ConvTypeToDescription (aTypes[i])); 
end; 
Las variables aFamilies y CurrFamily se declaran en la parte privada 
del formulario dcl siguiente modo: 
aFamilies: TConvFamilyArray; 
CurrFamily: TConvFamily; 
En este punto, un usuario puede introducir dos unidades de medida y una 
cantidad en 10s cuadros de edicion correspondientes del formulario, como se pue- 
de ver en la figura 3 3. Para que la operacion sea mas rapida, es posible seleccio- 
nar un valor de la lista y arrastrarlo hasta uno de 10s dos cuadros de edicion de 
tipo. 
pulsado el boton lzquierdo del raton mientras se arrastra el elemento sobre 
una de las cajas de edicion que se encuentran en el centro del formulario. 
-- 
- para c o i k g z c & p a z , hay q z - ~ a propiedad 
DragMode de la caja de lista (el componente fuente) con el valor 
dmAutomatic e implementar 10s eventos OnDragOver y OnDragDrop 
de las cajas de edicion objetivo (las dos cajas de edicion se encuentran 
conectadas a 10s mismos manejadores de eventos, compartiendo el mismo 
codigo). En el primer mktodo, el programa indica que las cajas de edicion 
siempre aceptan la operaci6n de arrastre, sin importar la fuente. En el se- 
gundo mktodo, el programa copia el texto seleccionado en la caja de lista 
(el control source para la operation de arrastre) a la caja de edicion que 
haya disparado el evento (el objeto Sender). Este es el cd igo para 10s 
dos metodos: 
procedure TForml.EditTypeDragOver(Sender, Source: TObject; 
X I Y: Integer; State: TDragState; var Accept: Boolean); 
begin 
Accept := True; 
end; 
procedure TForml.EditTypeDragDrop(Sender, Source: TObject; 
X I Y: Integer) ; 
begin ; 
(Sender ar TEdit) .Text := (Source as TListBox) . Items 
[ (Source as TListBox) . ItemIndexl; 
end ; 
Eamiks 
Inslruciimr hap types 
D~stance Snnple Ted I lrorn lM to dl boxes. 
enlm am* 
lvper Base lype: &&: 
LghlYeats Cmlirnetus 1100 
Parsecs 
Fathom 
Furbngs Qerlinalica Type Cmvwted Am& 
Hands 
Paces 
Cham 
I 1 
Figura 3.3. El ejemplo ConvDemo en tiempo de ejecucion. 
Las unidades habran de corresponderse con aquellas disponibles en la familia 
activa. En caso de error, el texto de 10s cuadros de edicion de tipo aparecc en rojo. 
Este es el efecto de la primera parte del metodo DoConver t del forinulario, que 
se activa desde el momento en que el valor de uno de 10s cuadros de edicion para 
las unidades o la cantidad cambian. Despues de verificar 10s tipos de 10s cuadros 
de edicion, el metodo DoConver t realiza la conversion real y muestra el resul- 
tad0 en el cuarto cuadro de edicion, que esta en gris. En caso de errores, aparece- 
ra el mensaje correspondiente en el mismo cuadro. Veamos el codigo: 
procedure TForml.DoConvert(Sender: TObject); 
var 
BaseType, DestType: TConvType; 
begin 
// o b t i e n e y v e r i f i c a e l t i p o b d s i c o 
i f not DescriptionToConvType(CurrFamily, EditType-Text, 
BaseType) then 
EditType.Font.Color : = clRed 
else 
EditType.Font.Color : = clBlack; 
// o b t i e n e y v e r i f i c a e l t i p o d e d e s t i n o 
i f not DescriptionToConvType (CurrFamily, 
EditDestination-Text, 
DestType) then 
EditDestination.Font.Color := clRed 
e l s e 
EditDestination.Font.Co1or : = clBlack;i f (DestType = 0) or (BaseType = 0) then 
EditConverted.Text : = ' T i p o n o v d l i d o ' 
else 
EditConverted.Text : = FloatToStr (Convert ( 
StrToFloat (EditAmount-Text), BaseType, DestType)); 
end; 
Si todo esto no resulta interesante, hay que tener en cuenta que todos 10s tipos 
de conversion proporcionados en el ejemplo son solo una muestra: se puede perso- 
nalizar completamente el motor para que proporcione las unidades de medida en 
que se este interesado, como se comentara a continuacion. 
iConversiones de divisas? 
La conversion de divisas no es exactamente lo mismo que la conversion de 
unidades de medida, ya que 10s valores de las divisas cambian constantemente. En 
teoria, se puede registrar un valor de cambio en el motor de conversion de Delphi. 
De vez en cuando, se comprobara el nuevo indice de cambio, se desregistrara la 
conversion ya existente y se registrara la nueva. Sin embargo, mantener la tasa de 
cambio real implica modificar la conversion tan a menudo que la operacion po- 
dria no tener mucho sentido. Ademas, habra que triangular conversiones: hay que 
definir una unidad base (probablemente el euro, si vive en Europa) y convertir a/ 
y desde esta divisa incluso si la conversion se realiza entre dos divisas distintas. 
Por ejemplo, antes de la adopcion del euro como divisa de la Union Europea, lo 
mejor era utilizar esta divisa como base para las conversiones entre las divisas de 
10s estados miembros, por dos motivos. En primer lugar, 10s tipos de cambio eran 
fijos. En segundo lugar, la conversion entre las divisas euro se rcalizaban legal- 
mente convirtiendo una cantidad a euros y convirtiendo dcspues esa cantidad en 
euros a la otra divisa. el comportamiento exacto del motor de conversion de Delphi. 
Existe un pequeiio problema: debcria aplicarse un algoritmo de redondco en cada 
paso de la conversion. 
Considerarcmos este problema mas adelante, tras ofrccer el codigo base para 
integrar las divisas euro con cl motor de conversion de Delphi. 
NOTA: El ejemplo Conver I t disponible entre 10s ejemplos Delphi ofre- 
ce soporte para las conversiones a1 euro, utilizando un enfoque de redondeo 
ligeramente distintos, aunque no tan precis0 como el requerido por las re- 
glas de conversion de divisas europeas. Aun asi, resulta aconsejable mante- 
ner este ejemplo porque es bastante instructive en relacion con la creaci6n 
de un nuevo sistema de medida. 
El ejemplo, llamado EuroConv, muestra como registrar cualquier nueva uni- 
dad de medida con el motor. Siguiendo la plantilla que proporciona la unidad 
S tdConvs creamos una nueva unidad (llamada EuroConvCons t). En la sec- 
cion de la interfaz, declaramos las variables para la familia y las unidades especi- 
ficas: 
interface 
var 
// U n i d a d e s d e C o n v e r s i o n d e D i v i s a s E u r o p e a s 
c b E u r o C u r r e n c y : TConvFamily; 
cuEUR: TConvType; 
cuDEM: TConvType; // Alemania 
cuESP: TConvType; // Espafia 
cuFRF: TConvType; // P r a n c i a 
// y e l r e s t o . . . 
La seccion de implementation de la unidad define constantes para diversas 
tasas de conversion oficiales: 
implementation 
cons t 
DEMPerEuros = 1 , 9 5 5 8 3 ; 
ESPPerEuros = 166 ,386 ; 
FRFPerEuros = 6 ,55957 ; 
// y e l r e s t o . . . 
Finalmente, el codigo de inicializacion de la unidad registra la familia y las 
diversas divisas, cada una con su propio tip0 de cambio y un nombre legible: 
i n i t i a l i z a t i o n 
/ / Tipo de la familia de divisas europeas 
cbEuroCurrency : = RegisterConversionFamily ( ' D i v i s d s E u r o ) ; 
cuEUR := RegisterConversionType( 
cbEuroCurrency, 'EUR', 1) ; 
cuDEM : = RegisterConversionType( 
cbEuroCurrency, IDEM', 1 / DEMPerEuros) ; 
cuESP : = RegisterConversionType( 
cbEuroCurrency, 'ESP', 1 / ESPPerEuros); 
cuFRF : = RegisterConversionType( 
cbEuroCurrency, 'FRF' , I / FRFPerEuros) ; 
NOTA: El motor utiliza como factor de conversion la cantidad de la unidad 
base necesaria para obtener las unidades secundarias, con una constante 
como Meters P e r Inch, por ejemplo. El tipo es thdar de las divisas euro 
se define al rev&. Por este motivo, se han mantenido las constantes de 
conversion con 10s valores oficiales (como DEMPerEuros) y se han pasa- 
do a1 motor como fracciones ( I / DEMPerEuros). 
Tras registrar esta unidad, se pueden convertir 120 marcos alemanes en liras 
italianas de esta manera: 
Convert (120, cuDEM, cuITL) 
El programa de ejemplo hace algo mas: ofrece dos cajas de lista con las divisas 
disponibles, extraidas como en el ejemplo anterior, y cajas de edicion para el 
valor de entrada y el resultado final. La figura 3.4 muestra el formulario. 
Belg~an Francs [BEF) 1 Cmml 
Dutch Gu~lders [NLG] 
Austrian Sch~ll~ngi [ATS] 
Poituguese Escudos [PTE) 
F~nn~sh Marks [FIM] 
G~eek Drachms [GRD] 
Luembou'g F'-f [LUFI 
I labn L#e [ITLJ ' 
Belgian Francs [BEF) 
Dutch Gulders [NLG) 
Auslnan Sch~nlngs (ATS] 
Porluwese Escudos lPTEl 
~ m n & ~ a r k o [FIM] ' 
Greek Drachmas (GRDI 
Luxembourg Francs [LUF) 
Figura 3.4. La salida del ejemplo EuroConv, que muestra el uso del motor de 
conversion de Delphi con una unidad de medida personalizada. 
El programa funciona bien per0 no perfectamente, ya que no se aplica el re- 
dondeo correcto; deberia redondearsc no solo el resultado final de la conversion 
sin0 tambien el valor intermedio. Mediante el motor de conversion no se puede 
realizar este redondeo directamente de manera sencilla. El motor permite ofrecer 
una funcion de conversion o una tasa de conversion particularizadas. Pero escri- 
bir funciones de conversion identicas para todas las divisas parece una mala idea, 
asi que hemos escogido un camino diferente. (Puede ver ejemplos de funciones de 
conversion personalizadas en la unidad St dCo nvs, en la seccion relacionada 
con las temperaturas.) 
En el ejemplo EuroConv, aiiadimos a la unidad con las tasas de conversion 
una funcion EuroConv personalizada que realiza la conversion correcta. Lla- 
mando simplemente esta funcion en lugar de la funcion Convert estandar con- 
seguiremos el efecto deseado (y no parece existir ningun inconveniente, ya que en 
este tip0 de programas es extraiio mezclar divisas con distancias o temperaturas). 
De manera alternativa, podriamos haber heredado una nueva clase a partir de 
TCo nvT ype Fact o r, proporcionando una nueva version de 10s metodos 
FromCommon y Tocommon; o haber utilizado la version sobrecargada de 
Regi sterconvers ionType que acepta estas dos funciones como parametros. 
Sin embargo, ninguna de estas tecnicas habria permitido enfrentarse a casos espe- 
ciales, como la conversion de una divisa a si misma. 
Este es el codigo de la funcion EuroConv, que utiliza la funcion inter- 
na EuroRound para redondear a1 numero de digitos especificado en el pa- 
rametro Decimals (que debe estar entre 3 y 6, de acuerdo con las reglas oficia- 
les): 
type 
TEuroDecimals = 3. . 6 ; 
function EuroConvert (const AValue: Double; 
const AFrom, ATo: TConvType; 
const Decimals: TEuroDecimals = 3): Double; 
function EuroRound (const AValue: Double): Double; 
begin 
Result :=AValue * Power (10, Decimals) ; 
Result : = Round (Result) ; 
Result : = Result / Power (10, Decimals) ; 
end ; 
begin 
// comprobacion d e l caso e s p e c i a l : s i n convers ion 
if AFrom = ATo then 
Result := AValue; 
else 
begin 
/ / conversion a1 euro y redondeo 
Result := ConvertFrom (AFrom, AValue) ; 
Result := EuroRound (Result) ; 
/ / conversion a la divisa y nuevo redondeo 
Result : = ConvertTo (Result, ATo) ; 
Result : = EuroRound (Result) ; 
end ; 
end ; 
Por supuesto, podria desearse ampliar el ejemplo para ofrecer conversion a 
otras divisas no europeas, tal vez tomando 10s valores automaticamente desde un 
sitio Web. 
Gestion de archivos con SysUtils 
Para acceder a archivos y a la informacion de archivos, generalmente puede 
confiarse en las funciones estandar disponibles en la unidad SysUtils. Confiar en 
estas tradicionalesbibliotecas de Pascal hace que el codigo sea mas transportable 
entre diferentes sistemas operativos (aunque deberian considerarse con mucho 
cuidado las diferencias en las arquitecturas del sistema de archivos, en particular 
la cuestion de las mayusculas y las minusculas en la plataforma Linux). 
Por ejemplo, el ejemplo FilesList utiliza la combinacion F i n d F i r s t , 
F i n d N e x t y F i n d C l o s e para obtener a partir de una carpeta una lista de 
archivos que se corresponden con un filtro, con el mismo codigo que se podria 
utilizar en Kylis y Linux. La figura 3.5 muestra el aspect0 de este ejemplo. 
I D \md7code\O2\ClassRel\ClassRel dpr D \md7cude\02\C1ealeComps\CreateComps dp~ 
~ : \ r n d 7 c o d e \ 0 2 \ ~ a l e ~ r d p \ ~ a l e ~ r d ~ d ~ 
D:W7code\U2\Dalesl\Datesl dpr 
D-\md7code\OZ\DBGridCol\DBG11dCol,dpr 
D \rnd7coJe\02\Erro1Log\ErrorLog dpf 
D \md7code\02\Excepbun1\Excepbornl.dpr 
D.\md7wde\O2\F~mPfopU01mProp.dp 
D:\md7code\02\1IDrecl1veUID~ecl1ve.dp1 
D:Lnd7code\02\lnllDerno\lnllDemo dpr 
D hd7code\02\NewDale\NewDale dp~ 
D \md7c~de\02\Polu4n1mals\Polu9nmals.&r 
Figura 3.5. Un ejernplo de la salida de la aplicacion FilesList. 
El codigo siguiente aiiade 10s nombres de archivo a la caja de lista llamada 
1 b F i l e s : 
procedure TForml.AddFilesToList(Filter, Folder: string; 
Recurse : Boolean) ; 
var 
sr: TSearchRec; 
begin 
if FindFirst (Folder + Filter, faAnyFile, sr) = 0 then 
repeat 
1bFiles. Items .Add (Folder + sr .Name) ; 
until FindNext (sr) <> 0; 
FindClose (sr) ; 
Si el parametro Re c u r s e se activa, el procedimiento A d d F i l e s T o L i s t 
obtiene una lista de subcarpetas inspeccionando 10s archivos locales de nuevo y 
autoinvocandose para cada una de las subcarpetas. La lista de carpetas se coloca 
en un objeto de lista de cadenas, con el codigo siguiente: 
procedure GetSubDirs (Folder: string; sList: TStringList); 
var 
sr: TSearchRec; 
begin 
i f FindFirst (Folder + ' * . * I , faDirectory, sr) = 0 then 
try 
repeat 
i f ( sr.Attr and faDirectory) = faDirectory then 
sList .Add (sr .Name) ; 
u n t i l FindNext (sr) <> 0; 
f i n a l l y 
Findclose (sr) ; 
end ; 
end ; 
Finalmente, el programa utiliza una interesante tecnica para solicitar a1 usua- 
rio que seleccione el directorio inicial para la busqueda de archivos, mediante una 
llamada a1 procedimiento S e l e c t D i r e c t o r y . (Vease la figura 3.6.) 
i f SelectDirectory ('Seleccione una carpeta' , I , , CurrentDir) 
then . . . 
Figura 3.6. El cuadro de dialog0 del procedimiento select ~ i r e c t o r y , utilizado por 
la aplicacion FilesList. 
La clase TObject 
La definicion de la clase T O b j e c t es un elemento clave de la unidad System, 
"la madre de todas las clases Delphi". Cada clase del sistema es una subclase de la 
clase TObj e c t , directa (si se especifica TOb j e c t como la clase base), impli- 
citamente (a1 no indicarse la clase base), o indirectamente (cuando se especifica 
otra clase como antecesor). Toda la jerarquia de las clases de un programa en 
Pascal orientado a objetos posee una raiz unica. Esta permite usar el tipo de datos 
TOb j e c t como substituto del tipo de datos de cualquier tipo de clase del siste- 
ma. 
Por ejemplo, 10s controladores de eventos de componentes normalmente tienen 
un parametro Sender de tipo TObj e c t . Esto significa sencillamente que el 
objeto Sender puede pertenecer a cualquier clase, puesto que cada clase se 
deriva en ultima instancia de Tob j e c t . El inconveniente mas habitual de esta 
tecnica es que para trabajar sobre el objeto, es necesario conocer su tipo de datos. 
De hecho, cuando se tiene una variable o un parametro del tipo TObj e c t , se le 
pueden aplicar solo 10s metodos y propiedades definidas por la propia clase 
TOb j e c t . Si esta variable o parametro se refiere por casualidad a un objeto del 
tipo TButton, por ejemplo, no se puede acceder directamente a su propiedad 
Caption. La solucion a este problema recae en el uso de 10s operadores de 
conversion segura de tipos siguientes o en 10s operadores de informacion de tip0 
en tiempo de ejecucion (RTTI) (10s operadores i s y as). 
Existe otra tecnica. Para cualquier objeto, se puede llamar a 10s metodos defi- 
nidos en la misma clase TObj e c t . Por ejemplo, el metodo ClassName devuel- 
ve una cadena con el nombre de la clase. Debido a que es un metodo de clase, se 
puede aplicar tanto a un objeto como a una clase. Supongamos que hemos defini- 
do una clase TButton y un objeto Button1 de dicha clase. En ese caso, las 
siguientes sentencias tendran el mismo efecto: 
Text : = Button1.ClassName; 
Text := TButton.ClassName; 
Hay ocasiones en las que es necesario usar el nombre de una clase, per0 tam- 
bien puede ser util recuperar una referencia de clase a la propia clase o a su clase 
basica. La referencia de clase, de hecho, permite trabajar en la clase en tiempo de 
ejecucion, mientras quc cl nombre de clase es simplemente una cadena. Podemos 
obtener estas referencias de clase con 10s metodos Clas sType y Class Parent. 
El primer0 devuelve una referencia de clase a la clase del objeto, el segundo a su 
clase basica. Cuando tengamos una referencia de clase, podemos aplicarle cual- 
quier metodo de clase TOb j ec t , por ejemplo, para llamar a1 metodo ClassName. 
Otro metodo que podria resultar util es Ins t a n c e s i z e , que devuelve el 
tamaiio en tiempo de ejecucion de un objeto. Aunque se podria pensar que la 
funcion global Sizeof ofrece dicha informacion, esa funcion en realidad de- 
vuelve el tamaiio de una referencia al objeto (un punter0 que siempre tiene cuatro 
bytes), en lugar del tamaiio del objeto en si. 
En el listado 3.1, se puede encontrar la definicion completa de la clase 
TOb j e c t , extraida de la unidad System. Ademas de 10s metodos mencionados, 
fijese en que I n h e r i t s From proporciona una comprobacion muy similar a la 
del operador is, pero que se puede aplicar tambien a clases y referencias de clase 
(mientras el primer argument0 dc i s habra dc ser un objeto). 
Listado 3.1. La definicion de la clase TObject (en la unidad System de la RTL). 
type 
TObject = class 
constructor Create; 
procedure Free; 
class function Init Instance (Instance: Pointer) : TOb j ect; 
procedure CleanupInstance; 
function ClassType: TClass; 
class function ClassName: ShortString; 
class function ClassNameIs( 
const Name: string): Boolean; 
class function Classparent: TClass; 
class function ClassInfo: Pointer; 
class function Instancesize: Longint; 
class function InheritsFrom(AC1ass: TClass) : Boolean; 
class function MethodAddress (const Name : ShortString) : 
Pointer; 
class function MethodName(Address: Pointer): ShortString; 
function FieldAddress (const Name: ShortString) : Pointer; 
function GetInterf ace (const IID: TGU1D;out Obj) : Boolean; 
class function GetInterfaceEntry( 
const IID: TGUID): PInterfaceEntry; 
class function GetInterfaceTable: PInterfaceTable; 
function SafeCallException(ExceptObject: TObject; 
ExceptAddr: Pointer) : HResult; virtual; 
procedure Afterconstruction; virtual; 
procedure BeforeDestruction; virtual; 
procedure Dispatch(var Message); virtual; 
procedure DefaultHandler(var Message); virtual; 
class function NewInstance: TObject; virtual; 
procedure FreeInstance; virtual; 
destructor Destroy; virtual; 
end; 
I tipo en tiempo de ejecucib (RTTI) dc h clase 
Estos metodos de TOb j ect estan disponibles para 10s objetos de cada clase, 
puesto que TOb j ect es el antcccdente comun de cada clase. Veamos como pode- 
mos usar estos metodos para acceder a informacion de clase: 
procedure TSenderForm.ShowSender(Sender: TObject); 
begin 
Memo1 .Lines .Add ( 'Nombre de clase:' ' + Sender .ClassName) ; 
if Sender.ClassParent <> nil then 
Memol. Lines .Add ( ' Clase p a d r e : ' + 
Sender.ClassParent.ClassName); 
Memol .Lines .Add ( ' T a m d o de la instancia : ' + IntToStr 
(Sender-Instancesize)); 
end; 
El codigoverifica si la Classparent es nil, en caso de que se este utili- 
zando realmente una instancia del tipo TOb ject, que no tiene tipo basico. 
Este metodo Showsender es parte del ejemplo I f Sender del CD. El me- 
todo esta conectado con el evento OnClic k de diversos controles: tres botones, 
una casilla de verificacion y un cuadro de edicion. Cuando hacemos clic sobre 
cada control, se recurre a1 metodo Showsender con el control correspondiente 
como remitente. Uno de 10s botones es en realidad un boton Bitmap, un objeto de 
una subclase TButton. Se puede ver un ejemplo de este programa en tiempo de 
ejecucion en la figura 3.7 
Class Name TButton 
Parent Chss: TBultonConlrd 
Instance Sin: 536 
TButton ClassType 
Sender inherits Lom TButton 
Sender is a TButlm 
Class Name. TBitBtn 
Palent Class TBulton 
Instance Size: 560 
Sender &its from TButton 
Sendm is a TBulton 
Class Name TCheckBox 
Parent Class TCustornCheckBon 
Indance Size. 536 
Class Nam: TEB 
Paent Class: TCustomEdit 
lnstace Size: 544 
Figura 3.7. El resultado del ejemplo Ifsender 
Se pueden usar otros metodos para realizar pruebas. Por ejemplo, se puede 
verificar si el objeto Sender es de un tipo especifico con el siguiente codigo: 
if Sender-ClassType = TButton then . . . 
Tambien se puede verificar si el parametro Sender se corresponde a un obje- 
to dado, con este test: 
if Sender = Button1 then.. . 
En lugar de verificar una clase o objeto concreto, sera necesario, por lo gene- 
ral, comprobar la compatibilidad de tip0 de un objeto con una clase dada, es 
decir, sera necesario verificar si la clase del objeto es una clase determinada o una 
clase de sus subclases. Esto permite saber mejor si se puede trabajar sobre el 
objeto con 10s metodos definidos para dicha clase. Esta comprobacion se puede 
realizar utilizando el metodo InheritsFrom, a1 que tambien se llama cuando 
se usa el operador is. Las siguientes pruebas son equivalentes: 
if Sender. InheritsFrom (TButton) then . . . 
if Sender is TButton then . . . 
Mostrar informacion de clase 
Hemos ampliado el ejemplo If Sender para mostrar una lista completa de 
clases basicas de un objeto o clase dados. De hecho, cuando tengamos una refe- 
rencia de clase, se pueden aiiadir todas sus clases basicas a1 cuadro de lista 
List Parent mediante el codigo siguiente: 
with ListParent.Items do 
begin 
Clear; 
while MyClass.ClassParent <> nil do 
begin 
MyClass := MyClass.ClassParent; 
Add (MyClass .ClassName) ; 
end; 
end ; 
Se usa una referencia de clase en la parte principal del bucle while, que 
comprueba la ausencia de una clase padre (de mod0 que la clase actual es 
TOb j ect). Como alternativa, podiamos haber escrito la sentencia while de 
una de las siguientes formas: 
while not MyClass.ClassNameIs ('TObject') d o ... 
while MyClass <> TObject do... 
El codigo de la sentencia with que se refiere a la lista Listparent es parte 
del ejemplo class Inf o, que muestra la lista de clases padres y alguna otra 
informacion sobre una serie de componentes de la VCL (basicamente aquellos de 
la pagina Standard de la Component Palette). Dichos componentes se aiiaden de 
forma manual a la matriz dinamica que mantiene las clases y que se declara como: 
private 
ClassArray: array of TClass; 
Cuando se inicia el programa, se usa la matriz para mostrar todos 10s nombres 
de clase en un cuadro de lista. A1 seleccionar un elemento del cuadro de lista se 
desencadena la presentacion visual de sus datos y sus clases basicas. 
- 7 
N6%?& Comq extension adicional a este ejemplo. es posible crear un arb01 
con todas las tlases basicas de diversos componentes en una jerarquia. i 
La biblioteca 
de clases 
principales 
Ya vimos que Delphi incluye una gran cantidad de funciones y procedimien- 
tos, per0 la autentica potencia de la programacion visual en Delphi reside en la 
gigantesca biblioteca de clases que proporciona. 
La biblioteca de clases estandar de Delphi contiene cientos de clases, con miles 
de metodos, y es tan inmensa que no se puede proporcionar una referencia detalla- 
da en este libro. En su lugar, exploraremos diversas areas de esta biblioteca a 
partir de este punto. 
Este capitulo esta dedicado a las clases principales de la biblioteca a1 igual que 
a algunas tecnicas estandar de programacion, como la definicion de eventos. Ex- 
ploraremos las clases mas habitualmente utilizadas, como las listas, listas de 
cadenas, colecciones y streams o flujos. La mayor parte del tiempo exploraremos 
10s contenidos de la unidad c 1 a s se s, per0 tambien examinaremos otras unida- 
des principales de la biblioteca. 
Las clases de Delphi pueden utilizarse completamente desde el codigo o desde 
el diseiiador visual de formularios. Algunas de ellas son clases componentes, que 
apareceran en la paleta de componentes, y otras son de proposito mas general. 
Los terminos clase y componente puede usarse casi como sinonimos en Delphi. 
Los componentes son 10s elementos centrales de las aplicaciones Delphi. Cuando 
se escribe un programa, basicamente se escoge un cierto numero de componentes 
y se definen sus interacciones, y ya esta. 
Antes de comenzar con este capitulo, seria necesario disponer de una buena 
compresion del lenguaje, en temas como la herencia, las propiedades, 10s metodos 
virtuales, las referencias de clases y demas. Este capitulo trata 10s siguientes 
temas: 
El paquete RTL, CLX y VCL. 
TPersistent y published. 
La clase basica TComponent y sus propiedades 
Componentes y propiedad 
Eventos. 
Listas, clases contenedoras y colecciones. 
Streaming . 
Las unidades del paquete RTL. 
El paquete RTL, VCL y CLX 
Hasta la version 5, la biblioteca de clases de Delphi era conocida como VCL, 
que significa Biblioteca de Componentes Visuales (Visual Components Library). 
Se trata de una biblioteca de componentes que se proyecta sobre la API de Windows. 
Kylix, la version Delphi para Linux, introdujo una nueva biblioteca de compo- 
nentes, denominada CLX, pronunciado "clics", y que significa Biblioteca de Com- 
ponentes para Plataforma X o Multiplataforma (Component Library forX-Platform 
or Cross Platform). Delphi 6 fue la primera version en incluir ambas bibliotecas, 
la VCL y la CLX. Para 10s componentes visuales, las dos bibliotecas resultan 
alternativas. Sin embargo, las clases principales y las partes de la base de datos e 
Internet de las dos bibliotecas son basicamente compartidas. 
La VCL estaba considerada como una gran biblioteca unica, aunque 10s pro- 
gramadores solian referirse a diferentes partes de ella (componentes, controles, 
componentes no visuales, conjuntos de datos, controles data-aware, componentes 
de Internet, etc). CLX presenta una division en cuatro partes: BaseCLX, 
VisualCLX, DataCLX y NetCLX. La biblioteca utiliza un enfoque totalmente 
diferente entre Windows y Linux solo en VisualCLX, puesto que el resto del 
codigo puede transportarse de forma inherente a Linux. 
En las versiones mas recientes de Delphi, esta distincion se ve resaltada por el 
hecho de que 10s componentes y las clases centrales no visuales de la biblioteca 
forman parte del nuevo paquete RTL, que utilizan tanto la VCL como la CLX. 
Aun mas, utilizar este paquete en aplicaciones no visuales (por ejemplo, en pro- 
gramas de servidor Web) permite reducir considerablemente el tamaiio de 10s 
archivos que se van a desplegar y cargar en memoria. 
Partes tradicionales de la VCL 
Los programadores de Delphi se solian referir a distintas partes de la VCL con 
10s nombres que Borland sugirio originalmente en su documentacion y que se 
hicieron comunes posteriormente para diferentes grupos de componentes. Tecni- 
camente, 10s componentes son subclases de la clase TComponent, que es una de 
las clases raiz de la jerarquia, como muestra la figura 4.1. En realidad, la clase 
TComponent hereda de la clase TPersistent. 
ventana 
Controles 
(subclases de 
(oomponentes visuales) 
TWinControl) 
Controles no 
de ventana 
(TComponent) (subclases de 
TGraphicControl)I 
Componentes no visuales I 
(otras subclases de 
TComponent) 
Figura 4.1. Una representacion grafica de 10s principales grupos de componentes 
de la VCL. 
Ademas de 10s componentes, la biblioteca incluye clases que heredan directa- 
mente de TOb j ect j1 de TPers is tent. Estas clases se conocen de mod0 
colectivo como Objects en parte de la documentacion, un nombre bastante confu- 
so. Estas clases no componentes se utilizan normalmente para valores de propie- 
dades o como clases de utilidad empleadas en el c6digo; a1 no heredar de 
TComponent , no se pueden utilizar directamente en programacion visual. 
-- -- - 
NOTA: Para ser mb precisos, las clases no componentes no pueden estar 
disponibles en la Component Palette ni se pueden dejar eaer ditectamente 
en un formulario, pero se pueden, administtar visu.almeste con el Object 
Inspector, como subpropiedades de otras propiedadis o elemmtos de varios 
tipos. Por lo que, incluso las clases no componentes son n o ~ a h m t e faci- 
les de usar, gracias a la interfaz con el Form Designer. . 
Las clases componentes pueden dividirse ademas en dos grupos principales: 
controles y componentes no visuales. 
Controles: Todas las clases que descienden de TControl. Tienen una 
posicion y tamafio en pantalla y aparecen en el formulario en tiempo de 
diseiio en la misma posicion que tendrian en tiempo de ejecucion. Los 
controles tienen dos subespecificaciones diferentes, basados en ventanas o 
graficos. 
Componentes no visuales: Son todos 10s componentes que no son contro- 
les, todas las clases que descienden de T C o m p o n e n t pero no de 
T C o n t r o l . En tiempo de diseiio, un componente no visual aparece en el 
formulario o modulo de datos como un icono (con un titulo debajo opcional 
en 10s formularios). En tiempo de ejecucion, algunos de estos componentes 
pueden resultar visibles (por ejemplo, 10s cuadros de dialogo estandar) y 
otros estan visibles siempre (por ejemplo, el componente de tabla de la 
base de datos). 
01 o componente en 
el Form Designer, se puede ver una sugerencia sobre herramientas con su 
nombre y tip0 de clase (y alguna information ampliada). Se puede utilizar 
tambien una opcion del entorno, show Component Captions, parai 
vet el nombre del componente no visual bajo su icono. 
Esta es la subdivision tradicional de VCL, muy comun para 10s programadores 
Delphi. A pesar de la introduccion de CLX y de algunas estructuras de denomina- 
cion nuevas, 10s nombres tradicionales sobreviviran probablemente y sc mezcla- 
ran en la jerga de 10s programadores en Delphi. 
La estructura de CLX 
Borland se refiere ahora a distintas secciones de la biblioteca CLX empleando 
una terminologia para Linux y una estructura de nombrado ligeramente distinta 
(y menos clara) en Delphi. 
Esta nueva subdivision de la biblioteca multiplataforma representa areas mas 
logicas que la estructura de la jerarquia de clases: 
BaseCLX: Forma el nucleo principal de la biblioteca de clases: las clases 
mas altas (corno TComponen t ) y diversas clases de utilidades generales 
(corno listas, contenedores, colecciones y streams). En comparacion con 
las clases correspondientes de la VCL, BaseCLX ha cambiado poco y 
resulta muy facil de transportar entre las plataformas Windows y Linux. 
Este capitulo se dedica en gran medida a explorar BaseCLS y las clases 
principales comunes de VCL. 
VisualCLX: Es la coleccion de componentes visuales, por lo general lla- 
mados controles. Esta es la parte de la biblioteca que esta relacionada mas 
estrechamente con el sistema operativo: VisualCLX se implementa en la 
parte superior de la biblioteca Qt, disponible tanto en Windows como en 
Linux. Utilizar VisualCLX permite una capacidad de transporte total de la 
parte visual de una aplicacion entre Delphi en Windows y Kylix en Linux. 
Sin embargo, la mayoria dc 10s componentes VisualCLX poscen sus co- 
rrespondientes controles VCL, por lo que podemos adaptar facilmente el 
codigo de una biblioteca a otra. 
DataCLX: Engloba todos 10s componentes relacionados con bases de da- 
tos de la biblioteca. En realidad, DataCLX es la fachada del nuevo motor 
de base de datos dbExpress incluido tanto en Delphi como Kylix. Delphi 
incluye tambien la tradicional interfaz BDE, dbGo e InterBase Express 
(IBX). Si consideramos todos estos componentes como parte de DataCLX, 
solo la interfaz dbExpress e IBX resultan transportables entre Windows y 
Linux. DataCLX incluye tambien el componente C l i e n t Data S e t, aho- 
ra llamado MyBa s e y otras clases relacionadas. 
NetCLX: Incluye 10s componentes relacionados con Internet, desde el marco 
de trabajo WebBroker, a 10s componentes del productor HTML, desde 
Indy (Internet Direct) a Internet Express, de WebSnap a1 soporte XML. 
Esta parte de la biblioteca es, una vez mas, muy facil de transportar entre 
Windows y Linux. 
Partes especificas de VCL de la biblioteca 
Las anteriores partes de la biblioteca estan disponibles, con las diferencias 
mencionadas, tanto en Delphi como en Kylix. Sin embargo, en Delphi existen 
otras secciones de la VCL, que por una razon u otra son solo especificas para 
Windows: 
El marco de trabajo Delphi ActiveX (DAX) proporciona soporte para COM, 
Automatizacion OLE, ActiveX y otras tecnologias relacionadas con COM. 
Los componentes Decision Cube ofrecen soporte OLAP, per0 tienen lazos 
con el BDE y no se han actualizado recientemente. No comentaremos estos 
componentes en el libro. 
Por ultimo, la instalacion predefinida de Delphi incluye algunos componentes 
creados por terceros, como el TeeChart para graficos empresariales, RAVE para 
generacion de informes e impresion e IntraWeb para desarrollo para Internet. 
Algunos de estos componentes se comentaran en el libro, per0 no forman estricta- 
mente parte de la VCL. RAVE e IntraWeb tambien se encuentran disponibles 
para Kylix. 
La clase TPersistent 
La primera clase principal de la biblioteca de Delphi que veremos es su clase 
T Pe r s i s t e n t , que es bastante atipica: tiene poco codigo y casi no tiene uso 
directo, per0 ofrece la base para la idea global de la programacion visual. Se 
puede ver la definicion de la clase en el listado 4.1. 
Listado 4.1. La definicion de la clase TPersistent, desde la unidad Classes. 
I S M + ) 
TPersistent = class (TObject) 
private 
procedure AssignError(Source: TPersistent); 
protected 
procedure AssignTo (Dest: TPersistent) ; virtual; 
procedure Defineproperties (Filer: TFiler) ; virtual; 
function Getowner: TPersistent; dynamic; 
public 
destructor Destroy; override; 
procedure Assign (Source: TPersistent) ; virtual; 
function GetNamePath: string; dynamic; 
end; 
Como su nombre indica, esta clase controla la permanencia (es decir, el hecho 
de guardar el valor de un objeto en un archivo para usarlo mas tarde y volver a 
crear el objeto en el mismo estado y con 10s mismos datos). La permanencia es un 
elemento clave de la programacion visual. De hecho, en tiempo de diseiio en 
Delphi manipulamos objetos reales, que se guardan en archivos DFM y se vuel- 
ven a crear en tiempo de ejecucion a1 mismo tiempo que el contenedor especifico 
(formulario o modulo de datos) del componente. 
El formato es idCntico. La diferencia en la exte 
Delphi la utiliza para detenninar si el formula 
Vf'T AUinrlnrtre En U x r l i v tnrln Fnrmn.lnAm mm 
- - - - - - - - - . .- 
NOTA: ~ ~ d o 1 re aplica tarnbien a 
10s archivos XF M, el ~ o m r o ae arcolvo que u u ~ m ras t@xwiones CLX. 
ns&n ts 2@Mante porque 
rib se h a en CLS/Qt o en . v u r .. rrruwrru. uu x r j u n , wuv r w l u r u x u l v vu ~n f~rmulfwrip CLXIQt, sin 
importar la extension que se emplee; por eso, la extensi~n XF'IWDFM no 
tiene importancia en Kylix. 
Sin embargo, el soporte de streaming no es ta incluido en la clase 
TPersistent, aunque nos lo ofrecen otra clases, que tienen como objetivo 
T P e r s i s t ent y sus descendientes. En otras palabras, con el streaming 
predefinido de Delphi se puede hacer que

Mais conteúdos dessa disciplina