III Tabla de contenidos Sobre el libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 El autor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 El equipo de revisores del libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Dedicatoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 ¡Díganos lo que Piensa! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 0 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 A quién va dirigido este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Cómo está organizado este libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Componentes desarrollados en este libro . . . . . . . . . . . . . . . . . . . . 7 Aplicaciones de ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1 Las interfaces en Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Definiendo interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 La interfaz como un contrato . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Diferencias entre una interfaz y una clase . . . . . . . . . . . . . . . . . . . . . 11 Una interfaz es inalterable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Declarando una interfaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Definiendo GUIDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Implementando una interfaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Implementando IUnknown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Implementando IUnknown manualmente . . . . . . . . . . . . . . . . . . 17 Creando, usando y destruyendo interfaces . . . . . . . . . . . . . . . . . . 20 Las referencias a una interfaz se cuentan . . . . . . . . . . . . . . . . . . . 21 Obteniendo un puntero a una interfaz . . . . . . . . . . . . . . . . . . . . . 23 Ejemplo: IntfDemo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Programando con interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Ejemplo: SortDemo - Algoritmos con interfaces . . . . . . . . . . . . . 33 Tópicos avanzados sobre interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Implementando múltiples interfaces en una clase . . . . . . . . . . . . 43 Propiedades en las interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Ejemplo: Demostración gráfica . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 IV Tabla de contenidos 2 Las interfaces y COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Los GUIDs y COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Objetos COM y Fábricas de Clase . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Objetos COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Fábricas de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Servidores COM internos al proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Soporte de múltiples hilos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Registrando el servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Constructores a medida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Creando una instancia de un objeto COM interno al proceso. . . . . . 68 Ejemplo: Distribución unidimensional óptima . . . . . . . . . . . . . . . . . 71 Servidores COM externos al proceso . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Instanciación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Creando una instancia de un objeto COM externo al proceso . . . . . 98 Serialización de datos (marshaling) . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Arrays variantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Creando arrays variantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Accediendo a un array variante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Mejorando el rendimiento de los arrays variantes . . . . . . . . . . . . . . . 104 Ejemplo: A rray variante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Usando objetos COM con otros lenguajes . . . . . . . . . . . . . . . . . . . . . 109 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 3 Bibliotecas de tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Definición de Biblioteca de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Razones para Usar Bibliotecas de Tipos . . . . . . . . . . . . . . . . . . . . . 112 TTypedComObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Creando una biblioteca de tipos en Delphi . . . . . . . . . . . . . . . . . . . . . 115 Usando el Editor de Bibliotecas de Tipos . . . . . . . . . . . . . . . . . . . . 117 Creando un Visor de Bibliotecas de tipos . . . . . . . . . . . . . . . . . . . . . . 127 Interpretando enumeraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Interpretando interfaces y disp-interfaces . . . . . . . . . . . . . . . . . . . . 137 Interpretando co-clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 Extendiendo TIViewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Tabla de contenidos V 4 Automatización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Definiendo la automatización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Variantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Disp- interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Interfaces Duales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Servidores de automatización internos al proceso . . . . . . . . . . . . . . 144 Ejemplo: Servidor de conversión de unidades de medida . . . . . 144 CreateOleObject y GetActiveOleObject . . . . . . . . . . . . . . . . . . 148 Ejemplo: Cliente del servidor de conversión de unidades . . . . . 149 Servidores de automatización externos al proceso . . . . . . . . . . . . . 154 HResult y Safecall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Automatizando una aplicación existente . . . . . . . . . . . . . . . . . . . 156 Eventos y funciones de respuesta . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Disp- interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 Interfaces de respuesta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Microsoft ADO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 La filosofía de ADO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Obteniendo ADO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Instalando ADO en Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Conectando a una base de datos . . . . . . . . . . . . . . . . . . . . . . . . . 201 Abriendo un conjunto de datos . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Ejecutando un comando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 Accediendo a los valores de los campos . . . . . . . . . . . . . . . . . . . 205 Manejando errores de bases de datos . . . . . . . . . . . . . . . . . . . . . 205 Ejemplo: aplicación Microsoft ADO . . . . . . . . . . . . . . . . . . . . . 206 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 5 Controles ActiveX y ActiveForms . . . . . . . . . . . . . . . . . . . . . 211 Usando controles ActiveX existentes en Delphi . . . . . . . . . . . . . . . 211 Microsoft Agent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Ejemplo de aplicación Microsoft Agent. . . . . . . . . . . . . . . . . . . 222 Creación de controles ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Razones para crear controles ActiveX . . . . . . . . . . . . . . . . . . . . 228 Convirtiendo un componente VCL a un Control ActiveX . . . . 229 Registrando un control ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . 247 Probando el control ActiveX en Visual Basic . . . . . . . . . . . . . . 247 VI Tabla de contenidos Añadiendo una página de propiedades a un control ActiveX . . . . . 247 Distribuyendo controles ActiveX . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 ActiveForms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Creando un ActiveForm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Probando un ActiveForm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 6 DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Bases de DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Programación con DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Creando un Servidor DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 Instalación de un servidor DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . 272 Creando un cliente DCOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Implementación de conjuntos de datos remotos con DCOM . . . . . . 278 Definiendo la aplicación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Creando el servidor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Creando el cliente administrativo . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Creando el cliente punto de venta . . . . . . . . . . . . . . . . . . . . . . . . . . 300 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 7 Almacenamiento E s tructurado . . . . . . . . . . . . . . . . . . . . . . . 307 Definiendo el almacenamiento estructurado . . . . . . . . . . . . . . . . . . . . 307 Programación con almacenamiento estructurado . . . . . . . . . . . . . . . . 309 Creando un fichero de almacenamiento estructurado . . . . . . . . . . . 309 Abriendo un fichero de almacenamiento estructurado existente . . 312 Trabajando con flujos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 Creando y utilizando almacenes adicionales . . . . . . . . . . . . . . . . . . . 316 Iterando a través de un fichero de almacenamiento estructurado . . 316 Comprimiendo un fichero de almacenamiento estructurado . . . . . 318 Ejemplo: Uso de ficheros de almacenamiento estructurado . . . . . . . 319 Ejemplo: V isualizar un fichero de almacenamiento estructurado . . 337 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 8 Almacenamiento E s tructurado y OL E . . . . . . . . . . . . . . . . . 343 Conjuntos de Propiedades OLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 Convenios de los conjuntos de propiedades OLE . . . . . . . . . . . . . 344 Las interfaces IPropertySetStorage e IPropertyStorage . . . . . . . . . . 344 Un componente para leer y escribir conjuntos de propiedades . . . 356 Tabla de contenidos VII Ejemplo: Accediendo a propiedades definidas por el usuario . . 361 Ejemplo: E ncontrando ficheros por sus propiedades . . . . . . . . 364 Documentos compuestos y contenedores OLE . . . . . . . . . . . . . . . 369 Activando y desactivando servidores OLE . . . . . . . . . . . . . . . . . 371 Guardando y cargando objetos en ficheros y flujos . . . . . . . . . . 371 Mezcla de menús . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 Usando el Portapapeles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 Ejemplo: Un contenedor OLE sencillo . . . . . . . . . . . . . . . . . . . 373 Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 9 P rog ramación del shell de Windows . . . . . . . . . . . . . . . . . . . 377 Manejadores de menús contextuales . . . . . . . . . . . . . . . . . . . . . . . . 377 La interfaz IShellE xtInit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 La interfaz IContextMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Registrando el manejador de menú contextual . . . . . . . . . . . . . . 385 Manejadores de ganchos de copia . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 La interfaz ICopyHook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Registrando un manejador de gancho de copia . . . . . . . . . . . . . 396 Accesos directos del shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Interfaces de los enlaces del shell . . . . . . . . . . . . . . . . . . . . . . . . 402 Creando un enlace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Iconos de la bandeja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Mensajes de iconos de bandeja . . . . . . . . . . . . . . . . . . . . . . . . . . 414 El componente TDCPTrayIcon . . . . . . . . . . . . . . . . . . . . . . . . . . 414 Un ejemplo de aplicación de bandeja . . . . . . . . . . . . . . . . . . . . . 419 Manejadores de páginas de propiedades . . . . . . . . . . . . . . . . . . . . . . 421 Creando una plantilla de diálogo . . . . . . . . . . . . . . . . . . . . . . . . . 423 Interfaces de un manejador de página de propiedades . . . . . . . 424 Implementando el procedimiento de diálogo . . . . . . . . . . . . . . . 431 Implementando la función de respuesta . . . . . . . . . . . . . . . . . . . 432 Dónde ir desde aquí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433 Apéndices A - Lecturas y recursos recomendados . . . . . . . . . . . . . . . . . 435 Programación en Delphi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435 Programación COM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436 Indice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437