P. 1
C++ Builder

C++ Builder

|Views: 1.306|Likes:
Publicado porRafael Arciga

More info:

Published by: Rafael Arciga on Dec 02, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

07/10/2013

pdf

text

original

Programación visual de aplicaciones con C++ Builder

Curso de C++ Builder

Introducción El IDE Componentes La VCL Programación orientada a objetos en C++ Tratamiento de excepciones Programación con hebras Acceso a bases de datos Enlaces interesantes Todo en un ZIP

file:///D|/Manuales/index.html (1 of 2) [27/02/2003 16:23:49]

Programación visual de aplicaciones con C++ Builder

Índice

Ejercicios

Apéndices

© Francisco José Cortijo Bon & Fernando Berzal Galiano
Todos los derechos reservados por los autores sobre el contenido de este documento electrónico. Queda prohibido su uso comercial sin el consentimiento escrito de los autores. Cualquier uso de este material debe ser comunicado a los autores.

IDE | Componentes | VCL | OOP | Excepciones | Hebras | Bases de datos | Enlaces

file:///D|/Manuales/index.html (2 of 2) [27/02/2003 16:23:49]

Introducción

Curso de C++ Builder Introducción

Para ser un buen programador en C++ Builder existen distintos aspectos que se deben conocer:
q

q

q

q

El Entorno de desarrollo integrado de C++ Builder (el IDE). En la sección 2 se estudia el IDE de C++ Builder. Los componentes disponibles para crear aplicaciones Windows, y sobre éstos, sus propiedades más importantes, los métodos asociados y los eventos a los que pueden responder (sección 3). Un conocimiento genérico acerca de la biblioteca de clases visuales de Borland (la VCL), en definitiva, conocer a grandes rasgos la jerarquía de clases de la que forman parte los componentes (sección 4). Los conceptos fundamentales de la metodología de programación orientada a objetos (POO), el lenguaje C++ y cómo se debe usar bajo el estilo de C++ Builder (sección 5). Ciertas técnicas avanzadas de programación, como pueden ser el tratamiento de excepciones, la programación con hebras, la construcción de componentes personalizados, la interacción con bases de datos, la programación de aplicaciones para Internet...

q

En el transcurso del curso se pretende introducir al alumno en la programación de aplicaciones para Windows utilizando C++ Builder. Aunque se supone que éste ya posee cierta experiencia en la programación de C, y conocimientos muy básicos de programación orientada a objetos.

Página principal

file:///D|/Manuales/intro/1.html (1 of 2) [27/02/2003 16:23:49]

Introducción

© Francisco Cortijo Bon

file:///D|/Manuales/intro/1.html (2 of 2) [27/02/2003 16:23:49]

IDE

Curso de C++ Builder El IDE (Entorno de Desarrollo Integrado)

q q q q q q

2.1. Una visión general del IDE de C++ Builder.. 2.2. Un estudio detallado del IDE de C++ Builder.. 2.3. El sistema de ayuda. 2.4. Compilación, ejecución y depuración de programas. 2.5. El almacén de objetos. 2.6. Ejercicios: Ejemplos de aplicaciones simples y de consola .

IDE es el acrónimo de Integrated Development Environment o entorno de desarrollo integrado. C++ Builder es una aplicación Windows que proporciona un entorno de trabajo visual para construir aplicaciones Windows que integra distintos aspectos de la programación en un entorno unificado o integrado. La integración y facilidad de manejo hace que sea una herramienta indispensable para el desarrollo rápido de aplicaciones o RAD (Rapid Application Development). Guarda una gran similitud con el IDE de Visual Basic, aunque existen ciertas diferencias que veremos. El IDE de C++ Builder es una aplicación Windows 95 y como tal cumple con los estándares de aspecto, diseño y comportamiento que aconseja Microsoft a los desarrolladores de aplicaciones. En consecuencia, cualquiera que esté familiarizado con el manejo a nivel de usuario de Windows 95 no le supondrá ningún esfuerzo manejarlo con soltura.

2.1. Una visión general del IDE de C++ Builder.
El entorno de desarrollo se divide, básicamente, en tres partes. Una serie de ventanas, que pueden estar visibles u ocultas, constituyen la base de C++ Builder. El aspecto de la aplicación al inicio de una sesión de trabajo es el mostrado en la figura 2.1. Figura 2.1. Aspecto del C++ Builder al inicio de una sesión.

file:///D|/Manuales/intro/2.html (1 of 26) [27/02/2003 16:23:53]

IDE

En la parte superior se coloca la ventana principal, que contiene el menú principal, la barra de herramientas (a la izquierda) y la paleta de componentes (a la derecha). Debajo de la ventana principal, y a la izquierda se coloca el inspector de objetos. A la dercha del inspector de objetos está el área de trabajo de C++ Builder, que inicialmente muestra el diseñador de formularios, y escondido u oculto parcialmente tras éste
file:///D|/Manuales/intro/2.html (2 of 26) [27/02/2003 16:23:53]

IDE

aparece el editor de código. Veamos a grandes rasgos la misión de cada uno de ellos.

1. Ventana principal. En la ventana principal se ubican el menu principal, la barra de herramientas y la paleta de componentes (figura 2.2). Figura 2.2. Ventana principal de C++ Builder.

Menú principal. Permite el acceso a todas las operaciones y posibilita la configuración del programa. Barra de herramientas. Permite un acceso rápido a las operaciones que se realizan más frecuentemente. Paleta de componentes. Agrupa a los componentes que pueden incluirse en las aplicaciones.

file:///D|/Manuales/intro/2.html (3 of 26) [27/02/2003 16:23:53]

Diseñador de formularios. El inspector de objetos. Figura 2.html (4 of 26) [27/02/2003 16:23:53] .4. Para cambiar las propiedades de los objetos que forman la aplicación y seleccionar los eventos a los que debe responder la aplicación. 3. file:///D|/Manuales/intro/2. Figura 2. Es una ventana cuadriculada sobre el que se disponen los componentes para diseñar las ventanas que formarán la aplicación.IDE 2. El diseñador de formularios.3. Inspector de objetos.

IDE 4.html (5 of 26) [27/02/2003 16:23:53] . Está perfectamente integrado con el inspector de objetos y el diseñador de formularios. file:///D|/Manuales/intro/2. Un típico editor de texto multiventana para ver y editar el código de la aplicación.5. El editor de código. Figura 2. Editor de código.

2. que ya iremos comentando conforme vayamos profundizando en el curso.2. Un estudio detallado del IDE de C++ Builder.html (6 of 26) [27/02/2003 16:23:53] .IDE Existen otras partes del entorno. A continuación trataremos con más detalle las partes que hemos enumerado anteriormente. Menú Principal file:///D|/Manuales/intro/2. 1.

además de otros que ya iremos estudiando a lo largo del curso. etc. Barra de Herramientas La barra de herramientas tiene como objeto acelerar las operaciones más comunes del menú principal. Edit. Como veremos.7.7.html (7 of 26) [27/02/2003 16:23:53] . Por defecto.6. Figura 2. informándonos de cual es la funcionalidad de cada uno de ellos. En el título del menú principal aparece el nombre de la aplicación (C++ Builder) y el nombre del proyecto/grupo de proyectos con el que actualmente se está trabajando. Help. Figura 2. file:///D|/Manuales/intro/2. Si nos acostumbramos a utilizarla agilizaremos el uso del entorno significativamente. aunque éste deberá cambiarse. lógicamente. recursos.. 2. Para más detalles acerca de los menús. La barra de herramientas se puede personalizar (al igual que casi todas las partes del entorno) pulsando con el botón derecho y seleccionando Properties. La barra de herramientas. Search. Si pasamos el ratón sobre los iconos nos aparecerán unos globos o cuadros de ayuda.. Tiene los menús comunes a cualquier aplicación Windows: File. El menú principal. el concepto de proyecto es fundamental en C++ Builder ya que es el mecanismo de organizar sensatamente todos los ficheros (formularios. En él podemos encontrar todas las operaciones disponibles.IDE Se puede decir que es la ventana principal del IDE de C++ Builder y siempre está visible. asigan el nombre Project1 al proyecto con el que se va a trabajar. consultar la lista completa de menús.) asociados a una aplicación. código fuente. Su aspecto habitual es el que mostramos en la figura 2..

Una estrategia alternativa (y menos utilizada) es seleccionar el componente en la ventana Components. por lo que el usuario no puede elegir la ubicación de los componentes disponibles por defecto en la paleta de componentes. pinchar sobre el formulario donde se desea colocalo. Su aspecto es el que mostramos en la figura 2. Conocer los componentes y su filosofía de trabajo (propiedades. todos los componentes de C++ Builder se encuentran cargados por defecto. Todos los componentes (visuales y no visuales) están accesible rápida y cómodamente gracias a la paleta de componentes. seleccionándolo y colocándolo en un formulario.html (8 of 26) [27/02/2003 16:23:53] . Por conveniencia.8. Cada pestaña de la paleta de componentes da acceso a un conjunto de iconos que representan a componentes que pueden usarse para diseñar la aplicación. todos los componentes disponibles se encuentran organizados en distintas páginas o carpetas según su funcionalidad. En la sección 3 discutimos con más profundidad sobre los componentes disponibles en C++ Builder y en la sección 4 discutimos acerca de la estructura de la VCL.IDE 3. aunque se le pueden añadir más mediante las opciones del menú de componentes (opción Component del menú principal). Podemos decir que es un gran almacén de componentes listos para ser incorporados a una aplicación. que se abre seleccionando View | Component List. Figura 2. Cada componente tiene asignada una página. A diferencia con Visual Basic. métodos y eventos) es fundamental para un programador. La paleta de componentes. Paleta de Componentes Los componentes constituyen los bloques básicos sobre la que se construyen aplicaciones Windows con C++ Builder basadas en la VCL (Visual Component Library) y son la base de la VCL.8. Enlaces adicionales: file:///D|/Manuales/intro/2. aunque puede modificar la disposición de las páginas y añadir nuevas páginas o componentes ( Tools | Environment Options) Para colocar un componente en un formulario se debe seleccionar en la paleta de componentes el botón que representa al componente y a continuación.

4. Visualmente se sabe cuál es porque aparece enmarcado con trazos discontínuos en el diseñador de formularios. consultar la relación de propiedades. Pichar en el formulario: el componente ha quedado asociado al formulario. Es una herramienta visual destinada a diseñar y presentar la interfaz de usuario (la apariencia externa) de una aplicación. Siempre hay un componente (o en su defecto. 4. Diseñador de Formularios Como hemos indicado anteriormente. 3. Lo único que tenemos que hacer es: 1. Arrastrarlo hasta su posición final. La opciones relacionadas con la rejilla pueden modificarse en Tools | Environment Options. métodos y eventos de componentes.html (9 of 26) [27/02/2003 16:23:53] . Buscar el componente en la paleta de componentes.IDE Para más detalles acerca de los componentes disponibles. Si se pincha dos veces en lugar de una. Pinchar sobre el componente para seleccionarlo. Para más detalles acerca de cómo configurar y manipular los componentes. el propio formulario) activo. consultar la lista completa de componentes. es una ventana cuadriculada quer sirve para diseñar las ventanas (o formularios) que formarán la aplicación (ver figura 2. 2.4). En ningún caso se borrará manualmente lo que C++ Builder ha insertado automáticamente: podría provocar una inconsistencia interna y hacer inaprovechable el trabajo realizado. el código que C++ Builder ha insertado automáticamente desaparecerá porque no hemos introducido ningún código para ese gestor. Un formulario puede ser la ventana principal de un programa. file:///D|/Manuales/intro/2. Cuando se guarde el proyecto. La posición de un componente siempre se ajusta al punto más próximo de la rejilla para facilitar su ajuste (su alineación). se activa el editor de código para escribir el gestor del evento OnClick asociado a ese componente. Mediante el uso del ratón podemos colocar componentes de la paleta de componentes en el área de diseño. Si ésto no es lo que queremos basta con volver a activar el diseñador de formularios y continuar con la fase de diseño. agrupados por páginas. un cuadro de diálogo o cualquier otra ventana. Se puede activar cualquier componente pinchando (un sólo click) sobre él.

Figura 2. Su aspecto es el que mostramos anteriormente en la figura 2.html (10 of 26) [27/02/2003 16:23:53] . Las dos páginas (Properties y Events) del inspector de objetos. Inspector de Objetos Se trata. 5.IDE EJERCICIO 1: Diseño de un formulario. sin duda. file:///D|/Manuales/intro/2.3. Se trata de una ventana que contiene dos páginas: Properties y Events.9.9 mostramos el aspecto de las dos páginas en cuestión para el formulario que aparece por defecto al iniciar C++ Builder. de una de las herramientas más potentes y atractivas de C++ Builder. En la figura 2.

podemos modificar las propiedades de los componentes y construir los gestores de eventos a los que éstos pueden responder. Para seleccionar un objeto desde el inspector de objetos se despliega la lista de objetos y se selecciona el objeto en la lista. file:///D|/Manuales/intro/2. En definitiva. En la parte superior se especifica el objeto activo (en la figura 2.html (11 of 26) [27/02/2003 16:23:53] . También se puede seleccionar desde el diseñador de formularios pinchando (un solo click) sobre el objeto.IDE Cada componente tiene asociado un conjunto de propiedades y métodos y un conjunto de eventos a los que puede responder. Con el inspector de objetos podremos moldear los componentes de una aplicación según nuestras necesidades.9. llamado Form1). Las propiedades del objeto activo aparecen en la página con la pestaña Properties y los eventos a los que puede responder en la página con la pestaña Events. el formulario. en cuanto a su apariencia (propiedades) y funcionalidad (eventos a los que puede responder).

10. El editor de código. podríamos poner el texto Escuchar saludo en un botón colocado sobre un formulario (modificando la propiedad Caption) y escribir un código para reprodicir un fichero .WAV que contiene una grabación (escribiendo un gestor para el evento OnClick) EJERCICIO 2: Uso del inspector de objetos para modificar propiedades. No aparece por defecto. Más información en este enlace. en la parte superior izquierda. 6. Por ejemplo. Para abrir esta ventana: View | ClassExplorer.IDE Si lo que se desea es modificar sus propiedades. En la ventana del editor pueden "pegarse" el gestor de proyectos y el inspector de clases (véase en la figura 2. Admite coloreo simple de la sintaxis y distintos archivos abiertos simultáneamente. Si lo que se desea es asociarle un gestor de eventos. objetos y métodos asociados a la aplicación. se abre la carpeta de gestores de eventos seleccionando la pestaña Events. se abre la carpeta de propiedades pinchando sobre la pestaña Properties. Figura 2. Aparece por defecto asociada al editor (en la figura 2.html (12 of 26) [27/02/2003 16:23:53] .10) aunque estas dos herramientas pueden aparecer también como ventanas separadas. r r Inspector de clases: Es un navegador que muestra las clases. y cuando se abre (View | Project Manager) se muestra como una ventana independiente. Editor de Código Permite editar el código de una aplicación de una forma cómoda. file:///D|/Manuales/intro/2. En la figura 2.10. en la parte inferior izquierda).10 se muestra asociada al editor. Administrador de proyectos: Es básicamente un navegador entre los diferentes ficheros que forman la aplicación.

11) con algunas opciones bastante útiles. El menú contextual del editor de código. file:///D|/Manuales/intro/2.IDE Pulsando con el botón derecho aparece un menú contextual (figura 2.11. Figura 2.html (13 of 26) [27/02/2003 16:23:53] .

html (14 of 26) [27/02/2003 16:23:53] . EJERCICIO 3: Uso del inspector de objetos para escribir gestores de eventos con el editor de código. Por esto es importante saber qué partes de ese código está mantenido automáticamente. Lo mejor es borrar "el cuerpo" de dicha función (lo que el programador escribe) y dejar que el resto lo elimine C++ Builder (lo que ocurrirá cuando se guarde el archivo).IDE A diferencia con Visual Basic. y sobre todo ¡¡¡evitar modificarlo!!!. ya que este se generará correctamente en la unidad de código asociada al Form actual. C++ Builder nos permite el acceso a la totalidad del código fuente de la aplicación. Cuando queramos eliminar un manejador de evento que ha sido generado automáticamente es conveniente no borrar "a mano" la función. El editor de código está relacionado muy estrechamente con el inspector de objetos. 7. el IDE genera automáticamente el código para la función manejadora para tal evento. Administrador de Proyectos file:///D|/Manuales/intro/2. No tenemos que preocuparnos de cuál es exactamente el prototipo que debemos de usar para la función que maneje el evento. Al hacer doble click en un evento.

El administrador de proyectos. es lo que presenta. seleccionar View | Project Manager.12.IDE Un proyecto es un conjunto de archivos que trabajan en equipo para crear un archivo ejecutable independiente o una DLL. file:///D|/Manuales/intro/2. Un grupo de proyectos es un conjunto de proyectos. arrastrándolo hasta colocarlo sobre éste último (ver figura 2.10). Para visualizar el gestor de proyectos. El gestor de proyectos puede "pegarse" al editor de código. y será este el que se ejecute si elegimos la opción Run|Run. Figura 2.12. Los proyectos que componen un grupo de proyectos. el administrador de proyectos. en forma de árbol. En todo momento existe un único proyecto activo (en la figura 2. y los archivos que componen cada uno de esos proyectos. Project1). Puede emplearse como navegador para seleccionar el módulo con el que se va a trabajar.html (15 of 26) [27/02/2003 16:23:53] .

bpr y el ejecutable que se genera tiene el mismo nombre que el proyecto y la extensión .exe. A un grupo de proyectos se le pueden añadir proyectos. Para cada ventana (en la figura 2.) que se necesitan para la construcción del ejecutable. Veamos brevemente qué tipos de archivos pueden formar parte de un proyecto/grupo de proyectos.cpp (en la figura 2. Archivos fuente de C++. habitualmente. Cada uno de estos módulos estará formado por una pareja de ficheros: un . y que cuál es su cometido: EXT BPR CPP H OBJ EXE Descripción Es el archivo makefile del proyecto.cpp (en la figura 2.h. etc. formado por una pareja de ficheros: un .html (16 of 26) [27/02/2003 16:23:53] . Todo proyecto en C++ Builder se compone.cpp y su correspondiente . file:///D|/Manuales/intro/2. .cpp. Este fichero no está. al menos. con la extensión . Su nombre es el nombre del proyecto.IDE Los ficheros de proyecto especifican todos los recursos necesarios (ficheros . nuevos o que ya existan. visible. lógicamente.h. formularios.. Además del fichero que contiene la función principal. ficheros de descripción de formularios. archivos. Archivos de cabecera de C++. módulos.. Puede abrirse en el editor de código con la opción Project|View Source.h (que no se modificará. Unit1. de un archivo de código que contiene la función principal (WinMain()). normalmente) estará la declaración de los componentes de esa ventana. en definitiva. Define qué y cómo se debe compilar.cpp estarán los gestores de los eventos asociados a los componentes de esa ventana y en el . Archivos objeto resultado de la compilación. un proyecto puede tener asociados una serie de módulos adicionales en los cuales pueden incluirse funciones y clases de objetos. Cualquier aplicación típica tendrá al menos una ventana.cpp).12.12. ya que no es necesario modificarlo. el administrador de proyectos es únicamente un organizador de archivos.h: en el fichero . Form1) habrá un módulo. Los ficheros de proyecto tienen extensión .12. Más información sobre proyectos en C++ Builder y configuración de aplicaciones. Es el programa ejecutable resultante. como en cualquier aplicación C++. Hemos dicho que. Project1.cpp) y su correspondiente .

Aunque está en formato binario. en el caso de hacerlo en el editor de código. Figura 2. 2. se nos ofrecerá la ayuda correspondiente a la palabra que se encuentre bajo el cursor (figuras 2. Archivos de descripción de formulario.3. Es un archivo de grupo de proyectos. y los detalles concretos ya los buscaremos en la Ayuda cuando nos sean necesarios. Ventana de ayuda que se despliega al pulsar F1 sobre la palabra clave Application file:///D|/Manuales/intro/2. sino que más bien es conocer los principios en los que éste se basa. Describe qué proyectos conforman el grupo de proyectos. Contiene los valores de las propiedades de cada componente. Así. El sistema de ayuda El sistema de ayuda será una de las herramientas que más útiles nos resultará en nuestro trabajo con C++ Builder.14 y 2. por ejemplo. Especialmente la documentación de los componentes y clases predefinidas.13. Saber programar con C++ Builder no significa dominar todos y cada uno de los aspectos del entorno.IDE TDS DFM Archivos temporales para la compilación incremental. 2. RES DSK BPG HPP Un archivo de recursos.15). puede verse como texto seleccionando View as text en el menú contextual que aparece al pulsar con el botón derecho del ratón cuando se está situado sobre el formulario. sólo comentar que pulsando F1 obtendremos una ayuda contextual. La ayuda es una ayuda estándar de Windows por lo que no entraremos en más detalles.13. Es el archivo que contiene la configuración del escritorio para un proyecto. Archivos de cabecera creados automáticamente por C++ Builder.html (17 of 26) [27/02/2003 16:23:53] .

Ayuda detallada sobre Application variable (for standard applications).html (18 of 26) [27/02/2003 16:23:53] .14.IDE Figura 2. file:///D|/Manuales/intro/2.

file:///D|/Manuales/intro/2.IDE Figura 2. Ejemplo proporcionado en la ayuda sobre Application variable (VCL Reference).15.html (19 of 26) [27/02/2003 16:23:53] .

Ventana de ayuda mostrada al pulsar F1 estando seleccionada la opción View | Project Manager file:///D|/Manuales/intro/2. Figura 2.html (20 of 26) [27/02/2003 16:23:53] .IDE Pulsando F1 sobre cualquier opción de un menú se mostrará la ayuda asociada a esa opción (figura 2.16.16).

Al escribir el nombre de una clase seguido del operador de acceso punto (.17). file:///D|/Manuales/intro/2. métodos y eventos asociados a la clase TApplication.) o el nombre de un puntero que referencia a un objeto seguido del operador de acceso flecha (->) se muestra la lista de propiedades. Figura 2.html (21 of 26) [27/02/2003 16:23:53] .IDE C++ Builder proporciona algunas facilidades muy útiles a la hora de escribir código. Las más importantes son: q Completar código.17. métodos y eventos asociados a esa clase (figura 2. Ayuda para completar código: Propiedades.

Al pulsar Ctrl+J se muestran los patrones de código (también llamados "esqueletos") que pueden insertarse en el código de nuestro programa.4.html (22 of 26) [27/02/2003 16:23:53] . Submenús Project y Run del menú principal. El ejecutable se construye tomando como referencia los ficheros que forman el proyecto activo. file:///D|/Manuales/intro/2.18). Pueden crearse y guardarse nuevos patrones. Es posible configurar estas utilidades seleccionando Tools | Environment Options | Code Insight.18. Compilación.IDE q Patrones de código. Figura 2. 2. El objetivo final es la creación de un programa ejecutable correcto que funcione bajo Windows. ejecución y depuración de programas. Para esta tarea se utilizan los menús Project y Run (figura 2.

html (23 of 26) [27/02/2003 16:23:53] .18). aunque no se hayan modificado desde la última vez que se compilaron.IDE Project Run En la compilación se trata de la obtención del programa ejecutable (extensión . Compila el modulo fuente activo (extensión . sin mostrar la ejecución de las instrucciones de las funciones. file:///D|/Manuales/intro/2. y las más importantes son: q q Compile Unit.OBJ). Genera el fichero ejecutable a partir de los ficheros objeto asociados al proyecto recompilando todos los módulos fuente.18). Ejecuta instrucción a instrucción el programa. Las operaciones asociadas a este objetivo se encuentran en el menú que se despliega al seleccionar la opción Project del menú principal (figura 2. seleccionables al desplegar el menú Run (figura 2. Genera el fichero ejecutable a partir de los ficheros objeto asociados al proyecto recompilando únicamente los módulos fuente que se q hayan modificado desde la última vez que se compilaron. C++ Builder proporciona facilidades para la depuración de programas. Si durante la compilación se detectaran errores. Para ejecutar el programa basta con pinchar sobre el botón correspondiente de la barra de herramientas o seleccionar la opción Run | Run.EXE). se mostraran en el editor de código y se puede acceder directamente a las líneas de código en las que se han detectado para facilitar su corrección. pero ejecuta las llamadas a funciones como una instrucción más. Make.CPP) generando un fichero objeto (extensión . Las más importantes son: q Step Over F8. Build.

El almacén de objetos.19. Run to Cursor F4. módulos de datos. El almacén de objetos Se accede al almacén seleccionando File | New. Visualizar el contenido de una variable permanentemente.IDE q q Trace Into F7. DLLs. Todos ellos están prediseñados y pueden servirnos como punto de partida para nuestros propios diseños. Contiene formularios. Ejecuta instrucción a instrucción el programa. Ejecuta desde el principio del programa hasta la línea en la que está situada el cursor. Para que la depuración sea más completa y versátil se incorporan las siguientes opciones en el mismo menú: q q q Evaluate/Modify Ctrl+F7. Figura 2. 2. consiguiendo de esta forma reutilizar nuestros diseños. que podemos utilizar para simplificar el desarrollo de aplicaciones. etc.html (24 of 26) [27/02/2003 16:23:53] . Añade un punto de ruptura en la línea en la que está situado el cursor. asistentes. de modo que cuando se ejecute el programa se detendrá su ejecución al llegar al siguiente punto de ruptura. Add Watch Ctrl+F5. incluidas las instrucciones de las funciones llamadas. Además se pueden incorporar nuevos elementos que nosotros desarrollemos. Evaluar expresiones que involucren a las variables y modificar los valores de las variables. file:///D|/Manuales/intro/2.5. Add Breakpoint. cuadros de diálogo.

para añadir nuevos formularios (File | New | Form) o ficheros de código (File | New | Unit). 2.IDE En este curso utilizaremos con frecuencia el almacén para crear nuevos proyectos (File | New | Application). para crear módulos de datos (File | New | Data Module). Ejercicios Ejemplos de aplicaciones simples y de consola. file:///D|/Manuales/intro/2. para crear aplicaciones de consola (File | New | Console Wizard). etc.6.html (25 of 26) [27/02/2003 16:23:53] .

IDE Página principal © Francisco Cortijo Bon file:///D|/Manuales/intro/2.html (26 of 26) [27/02/2003 16:23:53] .

Menús Curso de C++ Builder Lista completa de menús Sobre el menú principal y sus submenús. File file:///D|/Manuales/appendix/menu/index..html (1 of 4) [27/02/2003 16:23:53] ..

html (2 of 4) [27/02/2003 16:23:53] .Menús Edit Search View file:///D|/Manuales/appendix/menu/index.

html (3 of 4) [27/02/2003 16:23:53] .Menús Project Run Component file:///D|/Manuales/appendix/menu/index.

html (4 of 4) [27/02/2003 16:23:53] .Menús Database Tools Workgroups Help Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/menu/index.

cuya única finalidad es la reutilización.Componentes Curso de C++ Builder Componentes q q q 3.html (1 of 5) [27/02/2003 16:23:54] . Páginas de componentes. La filosofía de los componentes en C++ Builder es exactamente la misma que en Visual Basic. a saber: q q q q q q Standard: Incluye los componentes comunes y más habituales de los programas Windows. 3. Propiedades. métodos y gestores de eventos. métodos y gestores de eventos a cada control. 3.1. Data Access y Data Controls: Componentes especializados para acceso a bases file:///D|/Manuales/intro/3. System: Esta página incluye controles muy especializados para interacción con el sistema. Un componente de la VCL es una clase que caracteriza a un control de Windows agregando propiedades. 3. propios de C++ Builder. Los componentes son unos elementos genéricos con una funcionalidad muy concreta.2. Componentes visuales y no visuales. Additional: Los componentes de esta página son controles especializados. Internet: Componentes para distintos protocolos de acceso a Internet.1. Esto es tanto así que algunos componentes pueden utilizarse en ambos entornos (los componentes ActiveX). Win32: Componentes de cuadros de diálogo propios de Windows 95/NT.3. Páginas de componentes Como ya hemos comentado anteriormente los componentes se agrupan en la paleta de componentes en distintas páginas. Cada uno de ellos está destinado a realizar una tarea típica en una aplicación.

1: Componentes propios de Windows 3. los métodos que puede ejecutar y los eventos a los que puede responder. Active X: Los componentes de esta página son objetos Active X. Las propiedades tienen. Muchos componentes tienen propiedades en común. Para más detalles. QReport: Componentes para diseñar rápidamente informes y resúmenes. Decision Cube: Incluye componentes para realizar análisis multidimensionales de datos con objeto de tomar decisiones. tanto en tiempo de diseño como en tiempo de ejecución. Para modificar una propiedad file:///D|/Manuales/intro/3. normalmente. Hemos visto como pueden establecerse y modificarse las propiedades de los componentes en tiempo de diseño utilizando el inspector de objetos. métodos y gestores de eventos De un componente podemos destacar tres aspectos: sus propiedades. creados por otros desarrolladores puede que utilizando otros lenguajes de programación. agrupados por páginas.html (2 of 5) [27/02/2003 16:23:54] . Samples: Componentes de demostración (cómo hacer componentes personalizados). Midas: Esta página incluye componentes que permiten el desarrollo de aplicaciones multicapa con MIDAS. 3.2. todos los componentes visuales tienen las propiedades Top y Left que controlan la posición del componente en el formulario. consultar la lista completa de componentes. Dialogs: Contiene cuadros de diálogo comunes en aplicaciones Windows listos para usar. un método de acceso asociado que se ejecuta al modificar la propiedad en tiempo de ejecución. Las propiedades son los elementos del componente que configuran su aspecto y controlan su comportamiento. la mayoría de ellos se mantienen en C++ Builder sólo por compatibilidad con versiones anteriores.Componentes q q q q q q q de datos. Por ejemplo.1. Propiedades. Win 3. Propiedades.

Los métodos son funciones asociadas al componente que pueden invocarse para que el componente realice distintas acciones. la VCL dibuja de nuevo todo el formulario en la nueva ubicación. La VCL comprueba si existe un método de acceso asociado al especificador de escritura y si es así. En la mayoría de los casos el especificador de lectura no hace más que devolver el valor de la propiedad. Los especificadores de acceso asocian métodos de lectura o de escritura (funciones. lo ejecuta. hay un especificador de lectura y un especificador de escritura.html (3 of 5) [27/02/2003 16:23:54] . Por ejemplo. simplemente asigna el nuevo valor a la propiedad. las propiedades tienen dos especificadores de acceso que se emplean al consultar o modificar el valor de una propiedad en tiempo de ejecución. A modo de resumen. Al realizar un cambio. Al consultar el valor de una propiedad se está accediendo al especificador de lectura. Métodos. Al consultar o modificar el valor de una propiedad se invocan. automáticamente. En el caso concreto de la propiedad Left. En el ejemplo 3 invocamos al método Terminate() asociado a la aplicación que se estaba file:///D|/Manuales/intro/3. En definitiva. las funciones respectivas asociadas: r Al asignar un nuevo valor a una propiedad se está accediendo al especificador de escritura. la VCL invoca el método de acceso a la propiedad. r EJERCICIO 4: Modificación y consulta de propiedades en tiempo de ejecución. todos los componentes visuales tienen un método llamado Show() para mostralos y otro llamado Hide() para ocultarlos. en definitiva) con las propiedades. Si no existe.Componentes basta (generalmente) con asignarle el nuevo valor.

En C++ los métodos son miembros de una clase. Cada componente poseerá una serie de eventos que puede recibir o generar. pulsación de algún botón del ratón. se escribe el código asociado al gestor del evento. Eventos. y dejar que los demás sean tratados por defecto. pulsación de una tecla del teclado. Un programa Windows está ocioso la mayor parte del tiempo esperando a que ocurra algún evento.Componentes ejecutando (Objeto Application) para terminar su ejecución como respuesta a la pulsación del botón. al igual que las propiedades. La forma de tratar un evento asociado a un componente en C++ Builder es sencilla: se activa el componente que va a responder al evento y utilizando el Inspector de Objetos (pestaña Events) se selecciona el evento al que debe responder y. file:///D|/Manuales/intro/3. Los eventos se manejan mediante los gestores o manipuladores de eventos. EJERCICIO 5: Métodos asociados a componentes. Un programa Windows está continuamente sondeando al sistema ante la ocurrencia de cualquier evento y de ocurrir. Se pueden tratar los eventos de un componente que necesitemos. cuando se active el editor de código. Cuando se responde a un evento se dice que se está manipulando el evento. Un evento es cualquier suceso que puede ocurrirle a un componente (movimiento del ratón. etc. desplazamiento o redimensionamiento de una ventana.html (4 of 5) [27/02/2003 16:23:54] . Esto significa que cualquier programa está condicionado por lo eventos que ocurren en el entorno Windows. Windows avisa al programa enviándole un mensaje. Se dice que Windows está orientado a eventos.) que pueden condicionar el comportamiento y apariencia del programa.

html (5 of 5) [27/02/2003 16:23:54] .). y se dice no visual en caso contrario (temporizadores. excepto. Los componentes no visuales se pueden colocar en los formularios de la misma manera que los controles. Componentes visuales y no visuales Se pueden establecer muchas clasificaciones para los componentes. Una de ellas es la de visuales o controles. Por lo demás no existen más diferencias entre ellos.Componentes EJERCICIO 6: Gestores de eventos. 3. etc. Un componente es visual cuando tiene una representación gráfica en tiempo de diseño y ejecución (botones.3. cuadros de diálogo -no visibles en la fase de dieño-. las derivadas de la visualización del componente. cuadros de edición. etc). Página principal © Francisco Cortijo Bon file:///D|/Manuales/intro/3. barras de scroll. aunque en este caso su posición es irrelevante. frente a no visuales. claro está.

Paleta de componentes . Para configurar el menú desplegable. o incluso para mostrar resultados. file:///D|/Manuales/appendix/components/Standard. añadir el componente MainMenu al formulario y hacer doble click sobre él para acceder al diseñador de menús. Se usa para mostrar textos de título. Muestra un área de edición de texto en la que el usuario puede introducir y modificar múltiples líneas de texto. Muestra texto que el usuario no puede seleccionar ni manipular. Para añadir opciones al menú y a los submenús. Crea menús desplegables (también llamados menús contextuales) que aparecen cuando se pincha con el botón PopupMenu derecho del ratón.Standard Curso de C++ Builder La paleta de componentes Página Standard Iconos de los componentes agrupados en la página Standard Esta página incluye los componentes comunes y más habituales de los programas Windows: Crea una barra de menú (que actúa como menú principal). ya que puede establecerse su valor (propiedad Caption) en tiempo de ejecución. proceder como con el componente MainMenu.html (1 of 2) [27/02/2003 16:23:55] . Label encabezamientos. MainMenu Edit Memo Muestra un área de edición de texto en la que el usuario puede introducir y modificar una única línea de texto.

Crea grupos de acciones que centralizan las respuestas de la plicación ante las acciones del usuario.Verdad/Falso) de manera que cuando se selecciona este control. Muestra una lista de eleciones. RadioGroup Contenedor que crea un grupo de componentes RadioButton en un formulario.Paleta de componentes .Verdad/Falso) de manera que cuando se selecciona este control. Es un control que combina aspectos de un componente ListBox y de un componente Edit: el usuario puede introducir datos en el área de edición o seleccionar en el área de lista.Standard Button Crea un botón que el usuario puede pulsar para efectuar acciones. Contenedor para agrupar opciones relacionadas en un formulario. Este control puede emplearse para crear un grupo de estos controles que representen elecciones mutuamente exclusivas (al contrario que los CheckBox. Presenta una opción binaria (Si/No . se permuta entre RadioButton ambos valores.html (2 of 2) [27/02/2003 16:23:55] . Este control puede emplearse para crear un grupo de estos controles que representen elecciones que no CheckBox sean mutuamente exclusivas (al contrario que los RadioButton. Se usa para crear barras de herramientas y líneas de estado. También puede usarse para "desplazarse" en un rango -amplio. se permuta entre ambos valores. ListBox ComboBox ScrollBar GroupBox Muestra una lista de eleciones que está acompañada de una barra de scroll. por lo que el usuario puede seleccionar más de una opción en un grupo.de valores por incrementos prefijados. Los componentes que contiene están asociados al panel. Panel ActionList Contenedor que puede contener otros componentes en un formulario. file:///D|/Manuales/appendix/components/Standard. por lo que el usuario puede seleccionar sólo una en un grupo. Presenta una opción binaria (Si/No . Prociona una forma cómoda de modificar el área visible de un formulario o de una lista.

file:///D|/Manuales/appendix/components/Additional. salvo que proporciona la posibilidad de especificar formatos particulares. normalmente. Crea un botón que puede contener un gráfico pero no contiene texto. Estos botones se agrupan. como lo hace el componente Edit.Paleta de componentes .html (1 of 2) [27/02/2003 16:23:55] . Crea una rejilla que puede usarse para mostrar datos en filas y columnas.Additional Curso de C++ Builder La paleta de componentes Página Additional Iconos de los componentes agrupados en la página Additional Los componentes de esta página son controles especializados: BitBtn SpeedButton MaskEdit StringGrid DrawGrid Crea un botón que puede contener un gráfico (tipo "bitmap"). Permite la introducción y edición de datos. como códigos postales o números de teléfono. dentro de un panel para crear una barra de herramientas. Crea una rejilla que puede usarse para mostrar cadenas en filas y columnas.

Un visualizador equivalene a TTable. Es muy parecido al componente ListBox salvo que cada elemento de la lista tiene asociado un CheckBox. sólo que StaticText tiene su propio gestor de ventana. Añade un divisor a un formulario entre dos componentes alineados que permite al usuario redimensionar los controles en tiempo de ejecución pinchando y arrastrando la línea de división. círculos. como elipses. cuadrados o rectángulos y cuadrados con bordes redondeados. como el componente Label.Paleta de componentes . Dibuja figuras geométricas. Es un componente de texto no editable. Un gestor para acompañar a barras de herramientas que se usa para poder mover este tipo de barras. rectángulos. file:///D|/Manuales/appendix/components/Additional. Crea líneas o cuadros con apariencia tridimensional y como si estuviera esculpida (alto o bajorrelieve). Muestra una lista de eleciones que está acompañada de una barra de scroll.Additional Image Shape Bevel ScrollBox CheckListBox Splitter StaticText ControlBar Chart Muestra un "bitmap" o un icono.html (2 of 2) [27/02/2003 16:23:55] . Crea un contenedor redimensionable que muestra barras de scroll cuando sea necesario.

Win32 Curso de C++ Builder La paleta de componentes Página Win32 Iconos de los componentes agrupados en la página Win32 Esta página incluye componentes comunes de aplicaciones para 32 bits. color. Se emplea para construir cuadros de diálodo con múltiples páginas dentro de la misma ventana. Es una barra que muestra un rango y un indicador que muestra el valor actual y que permite modificarlo. Es una especialización del componente Memo: proporciona la posibilidad de 1) modificar propiedades acrerca de la fuente de letra (familia. negrita o itálica). 2) modificar propiedades de formato (alineamiento. TabControl PageControl ImageList Divisor de páginas mutuamente exclusivas accesibles por pestañas.html (1 of 2) [27/02/2003 16:23:56] . RichEdit TrackBar file:///D|/Manuales/appendix/components/Win32. tamaño. tabulaciones. y 3) marcación de texto y arrastre del mismo.Paleta de componentes . añadir un componente ImageList al formulario y hacer doble click sobre él para acceder al editor de listas de imágenes. Paracrear una lista de imágenes. indentación o numeración). Una lista de imágenes es una colección de imágenes del mismo tamaño accesibles mediante un índice. Se emplea para gestionar eficientemente grandes conjuntos de imágenes o "bitmaps".

Paleta de componentes . como una película. Se emplea para mostrar cómo progresa una operación. file:///D|/Manuales/appendix/components/Win32. Asigna una combinación de teclas a cualquier componente. TreeView ListView HeaderControl StatusBar ToolBar CoolBar PageScroller Muestra un conjunto de objetos estructurados jerárquicamente. Contiene objetos dentro del área de cliente que pueden desplazarse horizontal o verticalmente sin usar una barra de scroll sino empleando las flechas.Win32 ProgressBar UpDown HotKey Animate Es una barra rectangular que se va "llenando" de izquierda a derecha. Gestiona botones rápidos y otros controles. Permite ver una lista en columnas. Este control puede dividirse en varias partes para proporcionar cabeceras para múltiples columnas. MonthCalendar Muestra un calendario que representa un solo mes. Muestra una lista de elecciones que está acompañada de una barra de scroll para seleccionar fechas. colocándolos adecuadamente ajustando su posición y tamaño. Son botones para incrementar y decrementar valores. Área para indicar el estado de acciones o textos de pista amplios ("Hints") en la parte baja de la ventana. Una ventana que se emplea para mostrar ficheros AVI (Audio Video Interleaved) o series de "bitmaps" dispuestos en secuencia. La fecha DateTimePicker puede seleccionarse desde el calendario o empleando la barra de scroll o las flechas. Muestra una colección de controles "CoolBand" dentro de bandas que pueden moverse y redimensionarse.html (2 of 2) [27/02/2003 16:23:56] . Muestra un encabezamiento sobre columnas de texto o números.

Paleta de componentes - System

Curso de C++ Builder La paleta de componentes

Página System
Iconos de los componentes agrupados en la página System

Esta página incluye controles muy especializados:

Timer PaintBox MediaPlayer OleContainer

Es un componente no visual que actúa como temporizador. Se emplea para ejecutar una serie de instrucciones (mediante el gestor del evento OnTimer) que deben ejecutarse cuando se alcanza el valor especificado como intervalo (propiedad Interval). Especifica un área rectangular sobre un formulario que delimita la zona en la que puede dibujarse desde una aplicación. Muestra una ventana con botones (similares a los de cualquier reproductor de audio o video) para reproducir video o sonido. Crea un área de cliente OLE (Object Linking and Embedding) en un formulario.

DdeClientConv Establece una conexión cliente a una aplicación servidora DDE (Dynamic Data Exchange).

file:///D|/Manuales/appendix/components/System.html (1 of 2) [27/02/2003 16:23:56]

Paleta de componentes - System

DdeClientItem Especifica los datos del cliente DDE (Dynamic Data Exchange) que se transfieren en una conversación DDE. DdeServerConv Establece una conexión servidora a una aplicación cliente DDE (Dynamic Data Exchange). DdeServerItem Especifica los datos del servidor DDE (Dynamic Data Exchange) que se transfieren en una conversación DDE.

file:///D|/Manuales/appendix/components/System.html (2 of 2) [27/02/2003 16:23:56]

Paleta de componentes - Internet

Curso de C++ Builder La paleta de componentes

Página Internet
Iconos de los componentes agrupados en la página Internet

Los componentes de esta página ofrecen diferentes protocolos de acceso a Internet:

Add to a form or data module to turn an application into a TCP/IP client. ClientSocket specifies a desired connection to a TCP/IP server, manages the open connection, and terminates the completed connection. Add to a form or data module to turn an application into a TCP/IP server. ServerSocket listens for requests for TCP/IP ServerSocket connections from other machines and establishes connections when requests are received. Converts an ordinary data module to a Web module and enables the Web server application to respond to HTTP request WebDispatcher messages. Converts an HTML template into a string of HTML commands that can be interpreted by a client application such as a PageProducer Web browser. The commands and HTML-transparent tags are replaced with customized content by the OnHTMLTag event. Assembles a sequence of HTML commands to generate a tabular display of the records from a TQuery object, which QueryTableProducer obtains its parameters from an HTTP request message. Assembles a sequence of HTML commands to generate a tabular display of the records from a TDataSet object. This DataSetTableProducer allows an application to create images of a dataset for an HTTP response message. ClientSocket
file:///D|/Manuales/appendix/components/Internet.html (1 of 2) [27/02/2003 16:23:57]

Paleta de componentes - Internet

DataSetPageProducer NMDayTime NMEcho NMFinger NMFTP NMHTTP NMMsg NMMsgServ NMNNTP NMPOP3 NMUUProcessor NMSMTP NMStrm NMStrmServ NMTime NMUDP PowerSock NMGeneralServer HTML NMURL

Converts an HTML template that contains field references into a string of HTML commands that can be interpreted by a client application such as a Web browser. Special HTML-transparent tags are replaced with field values. Gets the date and time from an internet/intranet daytime server. Sends text to an internet echo server, and echoes it back to you. Gets information about a user from an internet finger server, using the Finger protocol described in RFC 1288. Implements file transfer protocol. Invisible ActiveX control provides easy access for Internet File Transfer Protocol (FTP) services for transferring files and data between a remote and local machine. Invisible ActiveX control implements the HTTP Protocol Client, allowing users to directly retrieve HTTP documents if no browsing or image processing is necessary. Sends simple ASCII text messages across the internet or intranet using TCP/IP protocol. Receives messages sent with the TNMMsg component. Invisible ActiveX Client Control allows applications to access Networking News Transfer Protocol (NNTP) news servers. It provides news reading and posting capabilities. Invisible ActiveX control that retrieves mail from UNIX or other servers supporting POP3 protocol. MIME encodes or UUEncodes files and decodes MIME-encoded or UUEncoded files. ActiveX control that gives applications access to SMTP mail servers and mail posting capabilities. Sends streams to a stream server across the internet or an intranet. Receives streams sent with the TNMStrm component. Gets the date and time from Internet time servers, as described in RFC 868. Invisible WinSock ActiveX Control provides easy access to User Datagram Protocol (UDP) network services. It implements WinSock for both client and server and represents a communication point utilizing UDP network services. It can also be used to send and retrieve UDP data. Serves as a base for creating controls for dealing with other protocols, or for creating custom protocols. Serves as a base class for developing multi-threaded internet servers, such as custom servers or servers that support RFC standards. Invisible ActiveX control implements an HTML viewer, with or without automatic network retrieval of HTML documents, and provides parsing and layout of HTML data, as well as a scrollable view of the selected HTML page. The HTML component can also be used as a nonvisual HTML parser to analyze or process HTML documents. Decodes URL data into a readable string, and encodes standard strings into URL data format.

file:///D|/Manuales/appendix/components/Internet.html (2 of 2) [27/02/2003 16:23:57]

Paleta de componentes - Data Access

Curso de C++ Builder La paleta de componentes

Página Data Access
Iconos de los componentes agrupados en la página Data Access

Esta página incluye componentes especialzados para acceso a bases de datos:

DataSource Acts as a conduit between a dataset component such as TTable and data-aware components such as TDBGrid. Retrieves data from a physical database table via the BDE and supplies it to one or more data-aware components through a Table DataSource component. Conversely, it also sends data received from a component to a physical database via the BDE. Uses SQL statements to retrieve data from a physical database table via the BDE and supplies it to one or more data-aware Query components through a TDataSource component. Conversely, uses SQL statements to send data from a component to a physical database via the BDE. Enables an application to access server stored procedures. Sends data received from a component to a physical database via StoredProc the BDE. Database Sets up a persistent connection to a database, especially a remote database requiring a user login and password.

file:///D|/Manuales/appendix/components/Data_Access.html (1 of 2) [27/02/2003 16:23:58]

Paleta de componentes - Data Access

Provides global control over a group of Database components. A default TSession component is automatically created for each C++Builder database application. You must use the TSession component only if you are creating a multithreaded database application. Each database thread requires its own session component. BatchMove Copies a table structure or its data. Can be used to move entire tables from one database format to another. Lets you use cached updates support with read-only datasets. For example, you could use a TUpdateSQL component with a "canned" query to provide a way to update the underlying datasets, essentially giving you the ability to post updates to a UpdateSQL read-only dataset. You associate a TUpdateSQL component with a dataset by setting the dataset's UpdateObject property. The dataset automatically uses the TUpdateSQL component when cached updates are applied. NestedTable Retrieves the data in a nested dataset field and supplies it to data-aware controls through a datasource component. Session

file:///D|/Manuales/appendix/components/Data_Access.html (2 of 2) [27/02/2003 16:23:58]

Paleta de componentes - Data Controls

Curso de C++ Builder La paleta de componentes

Página Data Controls
Iconos de los componentes agrupados en la página Data Controls

Esta página incluye componentes especialzados para gestión de bases de datos:

DBGrid

DBNavigator DBText DBEdit DBMemo DBImage DBListBox DBComboBox

Data-aware custom grid that enables viewing and editing data in a tabular form similar to a spreadsheet. Makes extensive use of TField properties (set in the Fields editor) to determine a column's visibility, display format, ordering, and so on. Data-aware navigation buttons that move a table's current record pointer forward or backward. The navigator can also place a table in Insert, Edit, or Browse state, post new or modified records, and retrieve updated data to refresh the display. Data-aware label that displays a field value in the current record. Data-aware edit box that displays or edits a field in the current record. Data-aware memo box that displays or edits BLOB text in the current record. Data-aware image box that displays, cuts, or pastes bitmapped BLOB images to and from the current record. Data-aware list box that displays a scrolling list of values from a column in a table. Data-aware combo box that displays or edits a scrolling list of values from a column in a table.

file:///D|/Manuales/appendix/components/Data_Controls.html (1 of 2) [27/02/2003 16:23:58]

Paleta de componentes - Data Controls

DBCheckBox DBRadioGroup

Data-aware check box that displays or edits a Boolean data field from the current record. Data-aware group of radio buttons that display or set column values. DBLookupListBox is a data-aware list box that derives its list of display items from either a Lookup field defined for a dataset or a secondary data source, data field, and key. In either case, a user is presented with a restricted list of choices DBLookupListBox from which to set a valid field value. When a user selects a list item, the corresponding field value is changed in the underlying dataset. To specify list box items using a lookup field, the dataset to which you link the control must already define a lookup field. DBLookupComboBox is a data-aware combo box that derives its drop-down list of display items from either a lookup field defined for a dataset or a secondary data source, data field, and key. In either case, a user is presented with a DBLookupComboBox restricted list of choices from which to set a valid field value. When a user selects a list item, the corresponding field value is changed in the underlying dataset. To specify combo box list items using a lookup field, the dataset to which you link the control must already define a lookup field. DBRichEdit A multiline edit control that can display and edit a rich text memo field in a dataset. A DBCtrlGrid control displays multiple fields in multiple records in a tabular grid format. Each cell in the grid displays DBCtrlGrid multiple fields from a single record. DBChart Place the component on a form and right-click it to display the third-party developer's Help topics.

file:///D|/Manuales/appendix/components/Data_Controls.html (2 of 2) [27/02/2003 16:23:58]

MIDAS Curso de C++ Builder La paleta de componentes Página MIDAS Iconos de los componentes agrupados en la página MIDAS Esta página incluye componentes que permiten el desarrollo de aplicaciones multicapa con MIDAS: Implements a database-independent dataset that can be used independently in a single-tiered application. See Connecting to the DCOMConnection application server Establishes a TCP/IP connection to a remote server in a multi-tiered database application. See Connecting to OLEnterpriseConnection the application server Encodes data from a dataset into packets than can be sent to client applications and applies updates that are received DataSetProvider from client applications to that dataset. See Creating a data provider for the application server.Paleta de componentes . ClientDataSet file:///D|/Manuales/appendix/components/MIDAS. See Creating and using a client dataset Establishes a DCOM connection to a remote server in a multi-tiered database application. See Connecting to the SocketConnection application server Establishes an OLEnterprise connection to a remote server in a multi-tiered database application.html (1 of 2) [27/02/2003 16:23:59] . or to represent data received from a server in a multi-tiered database application. See Creating a data provider for the application server and Providing from and resolving to a dataset Encodes data from a dataset into packets than can be sent to client applications and applies updates that are received Provider from client applications to a dataset or database server.

TCP/IP. (For backward compatibility only) Establishes a DCOM.html (2 of 2) [27/02/2003 16:23:59] . (For backward compatibility only) Establishes a DCOM connection to a remote server in a multi-tiered application. See Brokering connections.Paleta de componentes . file:///D|/Manuales/appendix/components/MIDAS. or OLEnterprise connection to a remote server in a multi-tiered application.MIDAS SimpleObjectBroker RemoteServer MIDASConnection Locates a server for a connection component from a list of available application servers.

See Using decision cubes. See Using decision pivots. DecisionSource Defines the current pivot state of a decision grid or a decision graph.Paleta de componentes . DecisionGrid Displays single and multidimensional data in table form.Decision Cube Curso de C++ Builder La paleta de componentes Página Decision Cube Iconos de los componentes agrupados en la página Decision Cube Esta página incluye componentes para realizar análisis multidimensionales de datos con objeto de tomar decisiones: DecisionCube A multidimensional data store. See Creating decision datasets with the Decision Query DecisionQuery editor. See Creating and Using decision grids. file:///D|/Manuales/appendix/components/Decision_Cube. See Using decision sources. Displays fields from a decision grid as a dynamic graph that changes when dimensions are modified. DecisionPivot Use to open or close decision cube dimensions or fields by pressing buttons. Specialized form of TQuery used to define the data in a decision cube.html [27/02/2003 16:23:59] . See Using decision DecisionGraph graphs.

Se pueden incorporar cabeceras y pies de páginas. agrupaciones con cabeceras y pies.QReport Curso de C++ Builder La paleta de componentes Página QReport Iconos de los componentes agrupados en la página QReport Esta página incluye componentes para diseñar rápidamente informes y resúmenes. Typically you would set up a master/detail relationship between table or query components and create a similar relationship with TQRSubDetail components. It's also useful if you have very long bands that span multiple pages. resúmenes. Drops bands containing strings onto a report. Drop bands on a TQuickRep component and set the BandType property to tell how the band will behave during report generation. TQuery.html (1 of 2) [27/02/2003 16:24:00] . Puede usarse un visalizador previo para comprobar los resultados. Estos informes pueden realizarse a partir de cualquier fuente de datos: TTable. file:///D|/Manuales/appendix/components/QReport. If you have bands with expanding components and want other components to be moved down accordingly you can create a child band and put the moving components on it. Links additional datasets into a report. Create reports by dropping bands and printable components on the TQuickRep component and connecting it to a dataset. matrices. listas. etc. QuickRep QRSubDetail QRStringsBand QRBand QRChildBand The basic report form on which you build all your reports.Paleta de componentes . etc. Automáticamente se realizan cálculos similares a como se hacen en una hoja de cálculo. arrays. It is a visual component that takes the shape of the currently selected paper size.

QRPreview Brings up a form that allows you to preview a report on the screen and print it. Prints all graphics formats supported by C++Builder. Prints a large amount of text that does not come from a database field. footers. QRDBImage Prints images stored in binary (BLOB) fields. and static text. A data-aware version of the TQRLabel that prints the value of a database field. QRExpr Prints database fields. You can split text on QRLabel multiple lines and even multiple pages. Prints static or other non-database text. QRDBRichText Provides a Quick Report wrapper for accessing DBRichText fields in your reports. Select the data to print in the Data QRSysData property. QRHTMLFilter Lets you export the contents of your report into HTML.Paleta de componentes . Set any preceding text in the Text property. including String fields.QReport QRGroup Allows you to group bands together and provides control for headers. date fields and memo fields. Calculated fields and text field types can be printed. QRCSVFilter Lets you export the contents of your report into a comma-delimited database source file. You connect the component to the data field by setting the DataSource and DataField properties. QRCompositeReport Allows you to combine more than one report together. QRExprMemo Allows you to programmatically generate contents using Quick Report expressions. and page breaks. Enter the text to be displayed in the Caption property. Text can span multiple lines and QRDBText pages. Input a valid QuickReport expression in the Expression property. QRImage Displays a picture on a report. file:///D|/Manuales/appendix/components/QReport. current page number. and lines on a report. and so on. You can set the field to expand vertically as needed and then span multiple pages if necessary. QRShape Draws simple shapes like rectangles. Supports all image formats supported by the TPicture class. It can be static text or you can change it during QRMemo report generation. calculations. QRTextFilter Lets you export the contents of your report into text format. circles. various numeric fields. Unlike regular data-aware components. Prints system information such as report title. QRChart Allows you to take a TChart component and drop it onto your Quick Report form. QRRichText Allows you to embed rich text into your report. TQRDBText works even with dataset controls disabled to improve speed.html (2 of 2) [27/02/2003 16:24:00] .

Una ventana de diálogo puede cerrarse desde un programa mediante el método CloseDialog(). file:///D|/Manuales/appendix/components/Dialogs. Una ventana de diálogo se abre al llamar al método Execute(). false si el usuario elige Cancel o sale de la ventana de diálogo sin salvar los cambios. Este método devuelve un valor lógico: true si el usuario elige OK en la ventana de diálogo. Left.Paleta de componentes . Cada ventana de diálogo (excepto la asociada al componente PrinterSetup) tiene la propiedad Options que afecta a su apariencia y comportamiento.Dialogs Curso de C++ Builder La paleta de componentes Página Dialogs Iconos de los componentes agrupados en la página Dialogs Esta página incluye las diferentes ventanas de diálogo comunes en aplicaciones Windows. usar las propiedades Handle.html (1 of 2) [27/02/2003 16:24:00] . guardar e imprimir. Para modificar en tiempo de ejecución su posición. Estas ventanas de diálogo proporcionan un interface consistente para realizar operaciones sobre ficheros como abrir. Top y Position.

tamaño y estilo de letra. Muestra una ventana de diálogo común de Windows para especificar información de impresión. Muestra una ventana de diálogo común de Windows para especificar color. Muestra una ventana de diálogo modal común de Windows para seleccionar y abrir ficheros gráphicos. file:///D|/Manuales/appendix/components/Dialogs.Dialogs OpenDialog SaveDialog OpenPictureDialog Muestra una ventana de diálogo común de Windows para seleccionar y abrir ficheros. FontDialog ColorDialog PrintDialog Muestra una ventana de diálogo común de Windows para especificar la familia. Muestra una ventana de diálogo común de Windows para seleccionar y guardar ficheros. Es idéntica a la ventana asociada a OpenDialog salvo que contiene una región para previsualización de imágenes.Paleta de componentes . Muestra una ventana de diálogo común de Windows para especificar la cadena a buscar y la cadena por la que se va a reemplazar. Es idéntica SavePictureDialog a la ventana asociada a SaveDialog salvo que contiene una región para previsualización de imágenes. Muestra una ventana de diálogo modal común de Windows para seleccionar y guardar ficheros gráphicos.html (2 of 2) [27/02/2003 16:24:00] . PrinterSetupDialog Muestra una ventana de diálogo común de Windows para configurar impresoras. FindDialog ReplaceDialog Muestra una ventana de diálogo común de Windows para especificar la cadena a buscar.

Paleta de componentes . En la siguiente tabla se indica qué control debería usarse en su lugar: Control Win 3.1 Esta página incluye controles propios de Windows 3.1 para permitir compatibilidad con aplicaciones antiguas.1 Sustituir por TabSet Outline NoteBook Header TabControl TreeView PageControl HeaderControl Página Win32 Win32 Win32 Win32 Win32 DBLookupCombo DBLookupComboBox Data Controls TabbedNoteBook PageControl file:///D|/Manuales/appendix/components/Win_3.1 Curso de C++ Builder La paleta de componentes Página Win 3.Win 3.1. Muchos de estos controles tienen su versión actualizada en componentes incluidos en la página Win32.html (1 of 2) [27/02/2003 16:24:01] .1 Iconos de los componentes agrupados en la página Win 3. Estos controles no deberían usarse al desarrollar nuevas aplicaciones.

Used with the Notebook component. FilterComboBox Specifies a filter or mask to display a restricted set of files. file:///D|/Manuales/appendix/components/Win_3. each with its own set of controls.Win 3. Users can resize each section of the region to display different amounts of Header data. You can use the TabSet component with the Notebook component to enable users to change TabSet pages.1 DBLookupList Data-aware list box that displays values looked up from columns in another table at runtime.1.html (2 of 2) [27/02/2003 16:24:01] . FileListBox Displays a scrolling list of files in the current directory. DriveComboBox Displays a scrolling list of available drives.Paleta de componentes . Users select a page by clicking the tab TabbedNotebook at the top of the page Notebook Creates a component that can contain multiple pages. DirectoryListBox Displays the directory structure of the current drive. Creates a component that contains multiple pages. Creates notebook-like tabs. it enables users to change pages. DBLookupCombo Data-aware combo box that displays values looked up from columns in another table at runtime. Creates a sectioned region for displaying data. Users can change directories in a directory list box. Outline Displays information in a variety of outline formats.

El código fuente está disponible en el directorio \EXAMPLES\CONTROLS\SOURCE de la instalación.Samples Curso de C++ Builder La paleta de componentes Página Samples Iconos de los componentes agrupados en la página Samples Esta página incluye ejemplos de componentes personalizados que pueden construirse e incorporarse a la paleta de componentes.html [27/02/2003 16:24:01] . Pie Performance Graph CSpinButton CSpinEdit CGauge CDirectoryOutline CColorGrid CCalendar IBEVentAlerter file:///D|/Manuales/appendix/components/Samples.Paleta de componentes .

appearance. VSSpell Visual Speller.ActiveX Curso de C++ Builder La paleta de componentes Página Active X Iconos de los componentes agrupados en la página Active X Los componentes de esta página son objetos ActiveX. Chartfx file:///D|/Manuales/appendix/components/ActiveX. lets you design a spreadsheet with its full-featured Designer. Son aplicaciones completas y portables creadas por otros desarrolladores.Paleta de componentes . lets you customize a spelling checker. Graph Pinnacle Graph. Lets you create highly customized charts. lets you create 2D graphs. VtChart Lets you create true 3D charts. and end-user functionality of the chart component. Choose Properties to display a tabbed control panel that lets you define the values. F1Book Formula One.html [27/02/2003 16:24:02] .

html [27/02/2003 16:24:02] .1 file:///D|/Manuales/appendix/components/index. Las páginas cuyo título está precedido por el símbolo español. en 14 páginas. por defecto. siguiendo el criterio de utilidad en este curso. En la siguiente tabla agrupamos las páginas según nuestra conveniencia.Paleta de componentes Curso de C++ Builder La paleta de componentes La paleta de componentes se estructura. están traducidas al Standard Additional Win32 System Dialogs Data Access Data Controls QReport Decision Cube Internet MIDAS ActiveX Samples Win 3.

} //------------------------------------------------------------ A continuación. Modificación y consulta de propiedades en tiempo de ejecución Curso de C++ Builder Ejercicio 4. Escribiremos el siguiente fragmento de código: //-----------------------------------------------------------void __fastcall TMainForm::FormCreate(TObject *Sender) { MainForm->Caption = "Primer programa con C++ Builder".Ejercicio 4. el título se establezca en el momento de la creación de la ventana. modificaremos el color del formulario (propiedad Color) siempre que el valor de esta propiedad esté establecido al valor por defecto (clBtnFace): //-----------------------------------------------------------void __fastcall TMainForm::FormCreate(TObject *Sender) { MainForm->Caption = "Primer programa con C++ Builder". observar que su título quedó fijado a Form de Prueba después de modificar la propiedad Caption del formulario. Para modificar su valor en tiempo de ejecución haremos que. Para ello escribiremos un gestor para el evento OnCreate asociado al componente MainForm. Recordar que basta con hacer doble click en OnCreate (pestaña Events del inspector de objetos) del componente MainForm. Modificación y consulta de propiedades en tiempo de ejecución Sobre el formulario que estamos empleando. } // Lectura // Escritura file:///D|/Manuales/intro/ejemplos/ej4.html (1 of 3) [27/02/2003 16:24:02] . por ejemplo. if (MainForm->Color == clBtnFace) MainForm->Color = clWhite.

1. el resultado es el mostrado en la figura E4. Modificación y consulta de propiedades en tiempo de ejecución //------------------------------------------------------------ Finalmente.1.Ejercicio 4. El programa al iniciar su ejecución después de modificar propiedades en tiempo de ejecución. if (MainForm->Color == clBtnFace) MainForm->Color = clWhite. estableceremos que cuando empiece la ejecución del programa se encuentre desactivado el CheckBox: //-----------------------------------------------------------void __fastcall TMainForm::FormCreate(TObject *Sender) { MainForm->Caption = "Primer programa con C++ Builder". CheckBox->Checked = false.html (2 of 3) [27/02/2003 16:24:02] . file:///D|/Manuales/intro/ejemplos/ej4. Figura E4. } //-----------------------------------------------------------// Lectura // Escritura // Escritura Si generamos el ejecutable y ejcutamos el programa.

html (3 of 3) [27/02/2003 16:24:02] .Ejercicio 4. Modificación y consulta de propiedades en tiempo de ejecución Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej4.

Ejercicio 5.1. RadioButton2->Hide(). RadioButton1->Hide(). //--------------------------------------------------------------void __fastcall TMainForm::FormCreate(TObject *Sender) { MainForm->Caption = "Primer programa con C++ Builder". } //--------------------------------------------------------------- Si generamos el ejecutable y ejcutamos el programa. Métodos asociados a componentes Curso de C++ Builder Ejercicio 5. Figura E5. if (MainForm->Color == clBtnFace) MainForm->Color = clWhite.html (1 of 2) [27/02/2003 16:24:03] . el resultado es el mostrado en la figura E5.1. El programa al iniciar su ejecución después de modificar propiedades en tiempo de ejecución y de llamar al método Hide() asociado a los componentes RadioButton file:///D|/Manuales/intro/ejemplos/ej5. // Lectura // Escritura // Escritura // Hide() es el metodo que oculta el // componente sobre el que se aplica. CheckBox->Checked = false. Métodos asociados a componentes Modificaremos el gestor del evento OnCreate del componente MainForm para que no se muestren los dos botones de radio.

Métodos asociados a componentes Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej5.Ejercicio 5.html (2 of 2) [27/02/2003 16:24:03] .

RadioButton2->Show().html (1 of 3) [27/02/2003 16:24:03] .Ejercicio 6. } else { RadioButton1->Hide(). El programa al activar el CheckBox file:///D|/Manuales/intro/ejemplos/ej6. escribiremos el gestor asociado al evento OnClick del componente CheckBox: //-----------------------------------------------------------void __fastcall TMainForm::CheckBoxClick(TObject *Sender) { if (CheckBox->Checked == true) { RadioButton1->Show(). Gestores de eventos Curso de C++ Builder Ejercicio 6. OKButton->Enabled = false. LabelOutput->Caption = "". cuando se activa el CheckBox produce el siguiente resultado: Figura E6.1. Gestores de eventos Construiremos el gestor del evento asociado a modificar el componente CheckBox de forma que cuando se active (inicialmente está desactivado) se muestren los dos botones de radio y se active el botón de OK. } } //------------------------------------------------------------ Al ejecutar el programa. Cuando se desactive. RadioButton2->Hide(). Para ello. RadioButton1->Checked = true. los botones de radio se volverán a ocultar y el botón de Ok se desactivará. OKButton->Enabled = true.

" + Edit>Text.2 y E6. desconocido/a". else LabelOutput->Caption = "Escogió Opción 1. escribiremos el gestor del evento asociado a hacer click sobre el botón OK.3): //-----------------------------------------------------------void __fastcall TMainForm::OKButtonClick(TObject *Sender) { if (RadioButton1->Checked) { if (Edit->Text == "") LabelOutput->Caption = "Escogió Opción 1.html (2 of 3) [27/02/2003 16:24:03] . Observar el siguiente código y dos resultados de la ejecución (figuras E6. Gestores de eventos Finalmente.Ejercicio 6. cuando pueden emplearse los botones de radio. Resultado al seleccionar la opción 1 estando el cuadro de edición vacío. Sr/Sra. Sr/Sra. " + Edit>Text. Sr/Sra. } else { if (Edit->Text == "") LabelOutput->Caption = "Escogió Opción 2. else LabelOutput->Caption = "Escogió Opción 2. Sr/Sra.2. desconocido/a". file:///D|/Manuales/intro/ejemplos/ej6. que está operativo (propiedad Enabled) únicamente cuando el CheckBox está activado. } } //------------------------------------------------------------ Figura E6. y en consecuencia.

Gestores de eventos Figura E6. Resultado al seleccionar la opción 2 habiendo escrito algo en el cuadro de edición. Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej6.html (3 of 3) [27/02/2003 16:24:03] .Ejercicio 6.3.

C++ Builder Curso de C++ Builder Introducción El IDE Componentes La VCL Programación orientada a objetos en C++ Tratamiento de excepciones Programación con hebras Acceso a bases de datos Enlaces interesantes Todo en un ZIP Índice Ejercicios Apéndices file:///D|/Manuales/contents.html (1 of 2) [27/02/2003 16:24:03] .

Queda prohibido su uso comercial sin el consentimiento escrito de los autores. Cualquier uso de este material debe ser comunicado a los autores.html (2 of 2) [27/02/2003 16:24:03] . file:///D|/Manuales/contents.C++ Builder © Francisco José Cortijo Bon & Fernando Berzal Galiano Todos los derechos reservados por los autores sobre el contenido de este documento electrónico.

las ventanas y hasta los controles gráficos.2. por ello también se suelen denominar bibliotecas de clases. Figura 4. En Windows.1. Clases de formularios y aplicaciones. 4. Ejercicios: Pizarra.html (1 of 7) [27/02/2003 16:24:04] . Un paseo por la VCL. Y la aplicación se limita a realizar peticiones de lo que necesita. 4. en su afán de aportar simplicidad y estructuración a la programación en Windows. Normalmente estos marcos de trabajo son orientados a objetos y se implementan como bibliotecas del lenguaje base. La VCL como interface.1. Por todo esto es que los entornos de programación visuales. Restricciones al uso de la VCL en C++ Builder. Controles de edición y Editor.VCL Curso de C++ Builder La VCL (Biblioteca de Componentes Visuales) q q q q q 4. que es un conjunto de funciones que proporciona el sistema operativo para poder habilitar la comunicación. los ficheros. La VCL es un marco de trabajo visual y orientado a objetos.5. 4. no son las aplicaciones quienes manejan los recursos del sistema como pueden ser la memoria. file:///D|/Manuales/intro/4. han desarrollado diversos Marcos de Trabajo.3. poco estructurado y difícil de manejar.4. Es el sistema operativo quién realiza todas estas tareas. Un marco de trabajo es una fase intermedia que se coloca por encima de la API para aportar mayor sencillez a las aplicaciones. Estas peticiones se realizan mediante lo que se denomina la API de Windows. Pero este conjunto de funciones es muy grande. Clases de componentes. 4.

que supuso la revolución en la programación para Windows e inició el desarrollo rápido y sencillo de aplicaciones visuales. suele traducirse en conocer el leguaje base del entorno. mejor que MFC.) la arquitectura de OWL es. MFC es una biblioteca de clases menos abstracta que el OWL y más cercana a la API. Esta forma de trabajo se hizo más popular con Visual Basic. el MFC (Microsoft Foundation Class o Biblioteca Fundamental de Clases de Microsoft) y lo incorporó a los compiladores Microsoft Visual C++ (actualmente incluso en Borland C++ 5). En 1995.. Los marcos de trabajo C++ (OWL y MFC) 2. técnicamente. y su marco de trabajo. La VCL.html (2 of 7) [27/02/2003 16:24:04] . Borland lanzó al mercado Delphi. OWL (Object Windows Library o Biblioteca de Objetos para Windows) fue un marco de trabajo desarrollado por Borland e incorporado a los compiladores Borland C++ (versiones 3 y sucesivas) y supuso un importante hito en la programación para Windows por su potencia y facilidad de uso. Delphi ofrecía el desarrollo rápido de aplicaciones (RAD) empleando componentes (objetos que pueden ubicarse en formularios y manipulados por medio de propiedades. Microsoft desarrolló su propio marco de trabajo. Aunque MFC se usa más que OWL (Microsoft. Delphi empleaba como base al lenguaje Object Pascal (una ampliación file:///D|/Manuales/intro/4.VCL Tan importantes son los marcos de trabajo. Los marcos de trabajo se pueden clasificar en dos categorías: 1. métodos y eventos). que dominar un entorno de programación visual. También resulta más sencillo que OWL para los programadores que conocen la API..

. Es file:///D|/Manuales/intro/4.2 y 4.2 mostramos una pequeña parte de la jerarquía de clases que forman la VCL. aunque algunas clases no hagan referencia componentes concretos: realizan tareas de gestión interna y se emplean como clases bases para derivar mediante herencia otras clases. La VCL desarrollada para Delphi es la misma que se emplea como núcleo de C++ Builder.2. En la figura 4. Un paseo por la VCL Conocer en profundidad la VCL se nos antoja imposible. En las secciones 4. métodos y eventos). por lo que se ejecutaban mucho más rápido que los de Visual Basic.1. 4.html (3 of 7) [27/02/2003 16:24:04] . El objetivo final de la VCL es crear clases que representan a componentes. La VCL hace un uso extensivo del concepto de herencia. está escrita en Object Pascal. Figura 4. de hecho.1.3 describimos con más detalle las clases más importantes de la VCL.VCL de Pascal que incorpora programación orienta a objetos) y permitía la creación de programas ejecutables independientes que no requerían intérprete. además de innecesario. Lo más relevante desde el punto de vista técnico es que Borland creó la VCL (Visual Class Library o Biblioteca de Componentes Visuales) que es un marco de trabajo para crear aplicaciones Windows diseñada en torno al concepto de componente (propiedades. 4. Jerarquía de clases de la VCL..

No se suelen crear objetos directamente a partir de ellas. La funcionalidad de TComponent permite que los objetos aparezcan en la paleta de componentes y que sean manipulados por el diseñador de formularios. TPersistent Esta clase tiene que ver con la habilidad de un objeto de almacenarse en disco o en memoria. instanciación. TObject Es el ancestro de todas las clases de la VCL. como puede ser información de la clase.VCL posible construir aplicaciones Windows de gran calidad con C++ Builder sin un conocimiento exhaustivo de la VCL. TComponent Ésta es una de las clases más importantes de la VCL. y no necesitan ser almacenadas en disco..5. Directamente de TObject heredan aquellas clases que no son componentes. si lo es que lo haga C++ Builder en tiempo de ejecución. así como otros detalles internos de C++ Builder que no es preciso conocer. porque aunque no sea normal que el programador haga uso de los métodos proporcionados por TObject. además de otras capacidades comunes a los componentes. TPersistent y TComponent) se denominan clases "abstractas" porque sirven para estructurar. Suele ser una buena idea derivar nuestras propias clases de TObject. asignarse a otros objetos.2). Los componentes no visuales derivan directamente de TComponent mientras file:///D|/Manuales/intro/4.html (4 of 7) [27/02/2003 16:24:04] . Esta clase proporciona toda la funcionalidad que requiere un componente básico.. no son clases abstractas. aunque consideramos conveniente relizar una somera descripción de la jerarquía de clases que conforman la VCL. porque no tienen métodos virtuales puros (ver sección 5. ya que la mayoría de los objetos que se manejan en una aplicación son componentes. Encapsula el comportamiento común de los objetos en C++ Builder. y agrupar comportamientos comunes de las clases de la VCL. Rigurosamente hablando. Las clases que conforman la parte superior de la jerarquía de la VCL (TObject. pero las podemos considerar como tales en la práctica.

TWinControl Son los controles típicos de Windows. TControl Proporciona la funcionalidad de los componentes visuales (controles). que pueden recibir el foco. gráficos o dibujos. 4. Esta funcionalidad es principalmente el aspecto visual que deben ofrecer los componentes en tiempo de ejecución.2. TGraphicControl Generaliza a los controles que tienen una representación visual. Suelen ser controles para visualizar texto (no editable en tiempo de ejecución). TControl proporciona mayor funcionalidad que la que requieren los componentes visuales: los componentes individuales derivan de TGraphicControl o de TWinControl. que a su vez deriva de TComponent. proporcionar la ayuda contextual. establecer los textos de sugerencia de los botones y barras de estado. Poseen una propiedad Canvas que permite acceder a su área de dibujo.html (5 of 7) [27/02/2003 16:24:04] . TApplication La clase TApplication encapsula una aplicación Windows por lo que caracteriza las operaciones fundamentales de un programa en Windows. Por esta razón se suelen denominar controles a los componentes visuales. file:///D|/Manuales/intro/4. pero no pueden recibir el foco: el usuario podrá verlos pero no interactuar con ellos. pero no se presentan en la paleta de componentes. por lo que podemos decir que Windows tiene un conocimiento directo de la existencia del mismo.VCL que los componentes visuales derivan de TControl. clases derivadas de TControl. y además poseen un manejador de ventana. contener otros controles. Un manejador de ventana es un identificador que proporciona Windows para el control. ocupándose de tareas como gestionar el paso de mensajes. TApplication simplifica el interface entre el programador y el sistema operativo. Clases de Formularios y Aplicaciones Son controles en si mismas.

4. Propiedades. incorpora a todos los componentes que aparecen en la paleta de componentes del IDE de C++ Builder (ver sección 3. métodos y eventos de formularios. ventanas secundarias o cualquier otro tipo de ventana que se pueda imaginar. Clases de componentes Este grupo abarca un amplio espectro de clases. algunas propiedades pueden establecerse en tiempo de diseño seleccionando las páginas Forms o Applicaction después de seleccionar Project | Options. ejecutar cuadros de mensajes.1) lo que implica que se pueden colocar sobre un formulario. En cualquier caso. Todas las aplicaciones de C++ Builder tienen un puntero a un objeto TApplication denominado Application. métodos y eventos de aplicaciones. etc. que se crea automáticamente. Como Application se crea automáticamente no aparece en la paleta de componentes ni está disponible en el inspector de objetos para manipular "visualmente" sus propiedades.html (6 of 7) [27/02/2003 16:24:04] .3. Propiedades. cuadros de diálogo.VCL procesamiento de "teclas rápidas". TForm La clase TForm caracteriza a los formularios en la VCL. Básicamente. file:///D|/Manuales/intro/4. Los formularios se emplean como ventanas principales. gestión de excepciones.

q q 4. Controles de edición y Editor.5. Propiedades. Esto es así porque deben de localizarse en el heap.html (7 of 7) [27/02/2003 16:24:04] . La VCL no asigna valores por defecto a las funciones. Restricciones al uso de la VCL en C++ Builder La VCL se desarrolló originariamente en y para Delphi. q q q Pizarra . y no en la pila. 4. agrupados por páginas. Aunque esto no supone normalmente consideraciones especiales. existen algunos aspectos que deben ser tenidos en cuenta: q Los objetos de la VCL deben crearse siempre dinámicamente (con new).4. No se puede usar herencia múltiple con clases VCL. por lo que está construida en Object Pascal. Controles de edición . Editor. Página principal © Francisco Cortijo Bon file:///D|/Manuales/intro/4.VCL Lista completa de componentes. Ejercicios: Pizarra. métodos y eventos de componentes.

La variable Application Curso de C++ Builder Sobre la variable Application Cuando un programa empieza a ejecutarse. Application->Run(). finalmente. Inicial. //-------------------------------------------------------------------------WINAPI WinMain(HINSTANCE. CreateForm() y Run(). } catch (Exception &exception) { Application->ShowException(&exception). observar el contenido del fichero que C++ Builder crea como fichero principal de la aplicación.cpp: //-------------------------------------------------------------------------#include <vcl. } return 0.h> #pragma hdrstop USERES("Inicial. si retomamos el ejemplo inicial de este curso (proyecto Inicial). Application->CreateForm(__classid(TMainForm). llama a sus métodos Initialize().cpp. MainForm). HINSTANCE. MainForm.cpp". LPSTR. USEFORM("main. int) { try { Application->Initialize().res"). } //-------------------------------------------------------------------------- Atrás file:///D|/Manuales/intro/vcl/application.html (1 of 2) [27/02/2003 16:24:04] . A modo de ejemplo. En Inicial. Recordar que el formulario principal se llamó. C++ Builder instancia la variable Application. &MainForm).

html (2 of 2) [27/02/2003 16:24:04] .La variable Application © Francisco Cortijo Bon file:///D|/Manuales/intro/vcl/application.

Este cuadro aparece cuando ocurre el evento OnHint. métodos y eventos q q q 1. Pueden emplearse las funciones GetShortHint() y GetLongHint() para obtener las dos partes de la propiedad Hint Hint y ShowHint file:///D|/Manuales/appendix/tapplication. Propiedades de las aplicaciones. ShowHint determina si los cuadros de sugerencia estarán activados o desactivados para toda la aplicación. Propiedad Active Descripción Especifica si la aplicación está activa y tiene el foco.TApplication . Hint especifica el texto que debe aparecer en el cuadro de ayuda o texto de sugerencia asociado a la aplicación. métodos y eventos Curso de C++ Builder TApplication . Propiedades de las aplicaciones.Propiedades. Métodos de las aplicaciones.html (1 of 4) [27/02/2003 16:24:05] . 3. por ejemplo.Propiedades. Por defecto se muestra únicamente el cuadro asociado al componente sobre el que está el ratón por lo que usualmente se emplea esta propiedad para mostrar la información extensa de este componente en una barra de estado. 2. Eventos de las aplicaciones. 1.

Devuelve un valor que depende del botón seleccionado para cerrar el cuadro de diálogo. Crea un nuevo formulario. se gestiona a través de WinHelp. y si no hay un gestor para este evento.Propiedades. establecer esta propiedad a false antes de la llamada a Application->Run y asegurarse de que la propiedad Visible del formulario esté también a false.TApplication . Para ocultarla. HelpContext() y HelpJump() MessageBox() file:///D|/Manuales/appendix/tapplication.html (2 of 4) [27/02/2003 16:24:05] . el programador no usa este método ya que las líneas de código para la creación de formularios las añade automáticamente C++ Builder. MainForm y ShowMainForm ShowMainForm especifica si la aplicación debe mostrar la ventana principal al iniciar su ejecución. Muestra un mensaje al usuario en cuadro de diálogo que puede incorporar botones. 2. Pueden establecerse en tiempo de diseño seleccionando Project | Options | Application. Generan un evento OnHelp. CreateForm() HelpCommand(). HelpFile y Para especificar el fichero de ayuda asociado a la aplicación. CurrentHelpFile. métodos y eventos MainForm especifica qué formulario actúa como ventana principal de la aplicación. Métodos de las aplicaciones. que aparecen en la barra de tareas de Windows cuando se minimiza la aplicación. Generalmente. Se emplean para gestionar la ayuda asociada a una aplicación. respectivamente. Método BringToFront() Descripción Establece la última ventana activa como la que se muestra por encima de todas las demás. Icon y Title Especifican el icono y el texto.

mientras que Restore() reestablece el tamaño que tenía la aplicación antes de ser minimizada. OnHint ocurre cuando el cursor se coloca sobre un control o una opción de un menú que puede mostrar un cuadro de sugerencia. respectivamente. OnActivate y OnDeactivate OnHint y OnShowHint OnShowHint ocurre cuando la aplicación va a mostar un cuadro de sugerencia. métodos y eventos Minimize() y Restore() Run() y Terminate() Minimize() minimiza una aplicación y la aloja en la barra de tareas de Windows. Proporciona una manera de gestionar excepciones por defecto en la aplicación. mientras Terminate() termina la ejecución de una aplicación. Muestra un cuadro de diálogo cuando se produce una excepción que no es gestionada por la aplicación. Se suele escribir un gestor para este evento cuando se quiere mostrar el texto largo de sugerencia en la barra de estado. Pueden emplearse las funciones GetShortHint() y GetLongHint() para obtener las dos partes de la propiedad Hint file:///D|/Manuales/appendix/tapplication. Se suele usar para modificar la apariencia del cuadro. Run() ejecuta la aplicación. Eventos de las aplicaciones. Evento Descripción Ocurren cuando se activa o desactiva la aplicación. Para especificar qué excepciones pueden gestionarse en la aplicación. ShowException() HandleException() 3. Una aplicación se activa cuando se genera la aplicación (empieza a ejecutarse) o cuando estaba activa otra aplicación y una ventana de la aplicación a la que se refiere recibe el foco.TApplication . Una aplicación se desactiva cuando el usuario selecciona otra aplicación.html (3 of 4) [27/02/2003 16:24:05] . construir un gestor para el evento OnException.Propiedades.

Ocurre cuando la aplicación recibe una petición de ayuda. Los métodos HelpContext() y HelpJump() gestionan automáticamente este evento. Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/tapplication. métodos y eventos OnMinimize y OnRestore OnHelp Ocurren cuando la aplicación se minimiza o se reestablece al tamaño normal. respectivamente. Ocurre cuando se pulsa una tecla.html (4 of 4) [27/02/2003 16:24:05] .TApplication . Se emplea cuando se desea modificar el comportamiento por defecto de una aplicación cuando se manifiesta alguna excepción que no es tratada por el programa. OnException OnShortCut Se emplea este gestor para realizar acciones antes de que el formulario o los controles del formulario gestionen los eventos oportunos a la pulsación de teclas.Propiedades.

2. y 3. OnKeyDown. por este orden: 1. OnKeyUp Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/tip/tip_tecla. OnKeyPress.html [27/02/2003 16:24:05] .Eventos asociados a las teclas Curso de C++ Builder Sobre los eventos asociados a la pulsación de teclas Cuando se pulsa una tecla se desencadenan los siguientes eventos.

Propiedades de los formularios.1. Propiedades en tiempo de diseño y ejecución.Propiedades. Propiedades de los formularios. q 2.1. Métodos de los formularios. 1. Propiedades en tiempo de ejecución.html (1 of 6) [27/02/2003 16:24:06] . Propiedad ActiveControl Enabled Descripción Establece qué componente tiene el foco cuando se abre el formulario. 3. q 1. métodos y eventos Curso de C++ Builder TForm .TForm . Indica si el formulario está activo (si puede recibir el foco). métodos y eventos q 1. file:///D|/Manuales/appendix/tform.Propiedades.2. Propiedades en tiempo de diseño y ejecución. r r 1. 1. Eventos de los formularios.

Se aplica a todos los componentes ubicados en el formulario.Propiedades.html (2 of 6) [27/02/2003 16:24:06] . Especifica qué cursor se muestra cuando está sobre el formulario. HorzScrollBar Controlan conjuntamente las barras de desplazamiento de un y formulario. Indica qué tipo de borde debe tener el formulario. Al modificar estas propiedades se actualizan Width y Height. Color de fondo del formulario. VertScrollBar BorderIcons BorderStyle Caption y Name Color Cursor Font Indica qué iconos aparecen en la barra de título de un formulario. Determina el tamaño y la posición del formulario. Icon Height y Width ClientWidth y ClientHeight Left y Top Position FormStyle HelpFile y HelpContext file:///D|/Manuales/appendix/tform. Establece el icono que se verá en la barra de título cuando se muestre el formulario en tiempo de ejecución y cuando se minimize. Caption indica la cadena que aparece en la barra de título del formulario mientras que Name indica con qué nombre se refiere al formulario en la aplicación (en el código). Altura y anchura (en píxeles) del formulario. Altura y anchura (en píxeles) del área de cliente del formulario (el área de cliente es la que queda dentro de los bordes del formulario y por debajo de la barra de título y de la barra de menú). métodos y eventos AutoScroll. Coordenadas X e Y del formulario (su esquina superior izquierda) en la pantalla.TForm . Para especificar si un formulario es o no parte de una aplicación multiformulario. Para especificar el fichero de ayuda asociado a la aplicación y gestionar la ayuda contextual. Permite especificar las propiedades de la fuente de letra que se usará en el formulario.

Coordenadas de los cuatro puntos que delimitan el área de cliente del formulario. Visible Indica si el formulario es visible o no. ShowHint determina si los cuadros de sugerencia estarán activados o desactivados para el formulario. . Para establecer el estado inicial del formulario (normal. Propiedades en tiempo de ejecución.html (3 of 6) [27/02/2003 16:24:06] . mapas de bits. por ejemplo.2. texto. Suele usarse con el gestor del evento OnPaint. El valor devuelto cuando se cierra un formulario modal (abierto con el método ShowModal()). minimizado o maximizado) o consultar su estado. La propiedad Canvas da acceso a esta superficie para dibujar líneas.TForm . Propiedad Active Descripción Indica si el formulario está activo (si tiene el foco). si es modal. WindowState 1. en el área de cliente. Los métodos Show() y ShowModal() hacen que un formulario sea visible y lo colocan por encima de todos. Este cuadro aparece cuando ocurre el evento OnHint.. Proporciona información acerca del estado en que se encuentra un formulario (si se está creando. si es visible. etc. Canvas ClientRect ModalResult FormState file:///D|/Manuales/appendix/tform.. El lienzo es la superficie del formulario sobre la que se puede dibujar. Por defecto se muestra únicamente el cuadro asociado al componente sobre el que está el ratón por lo que usualmente se emplea esta propiedad para mostrar la información extensa de este componente en una barra de estado.).Propiedades. métodos y eventos Hint y ShowHint Hint especifica el texto que debe aparecer en el cuadro de ayuda o texto de sugerencia asociado al formulario.

ShowModal() ejecuta (abre) el formulario modalmente: debe cerrarse para que el usuario pueda seguir trabajando con la aplicación. Imprime el contenido del formulario. SetFocus() CanFocus() SetBounds() ClientToScreen() Convierte las coordenadas del área de cliente en coordenadas de y pantalla y viceversa. Devuelve verdad si el formulario puede recibir el foco (si las propiedades Visible y Enabled están a verdad). respectivamente.TForm . Activa el formulario y lo coloca en primer plano. métodos y eventos 2. ScreenToClient() Invalidate(). Establece simultáneamente los valores de las propiedades Top. Close() cierra el formulario tras llamar a CloseQuery() para asegurarse de que es correcto cerrarlo. Esta última llama al manipulador del evento OnCloseQuery. Refresh(). Repaint() y Update() Redibujar un formulario.html (4 of 6) [27/02/2003 16:24:06] .Propiedades. el componente especificado en la propiedad ActiveControl recibe el foco. Oculta el formulario (establece la propiedad Visible a falso). Método BringToFront() y SendToBack() Hide() Print() Show() y ShowModal() Close() y CloseQuery() Descripción Coloca al formulario en primer plano o en último. file:///D|/Manuales/appendix/tform. Además. Left. Width y Height. Para mostrar formularios. poniendo a verdad la propiedad Active. Métodos de los formularios.

respectivamente. Una acción puede desencadenar varios eventos y el orden en ocurren puede ser muy importante: Eventos asociados a la creación y destrucción de un formulario.html (5 of 6) [27/02/2003 16:24:06] . Un formulario se activa cuando se recibe el foco y se desactiva cuando el foco pasa a otro formulario de la misma aplicación. métodos y eventos Release() Destruye un formulario y libera toda la memoria asociada. Eventos asociados al movimiento y pulsación con el ratón. cuando se pincha con él sobre el formulario.TForm . OnClick y OnDblClick file:///D|/Manuales/appendix/tform. OnCreate ocurre cuando se crea inicialmente el formulario (sólo ocurre un evento de este tipo por formulario) y OnDestroy cuando se destruye. 3. OnCreate y OnDestroy OnClose y OnCloseQuery OnMouseDown. Evento OnActivate y OnDeactivate Descripción Ocurren cuando se activa o desactiva un formulario. Hace una llamada a OnCloseQuery para asegurarse de que es correcto cerrarlo. Para responder a los eventos que suceden al mover el ratón o OnMouseUp. Eventos de los formularios.Propiedades. El evento OnClose ocurre cuando se cierra un formulario. OnMouseMove. Eventos asociados a la pulsación de alguna tecla.

Ocurre antes de que cualquier control sea redibujado. Ocurre cuando se pulsa una tecla. OnShow ocurre justo antes de que el formulario se haga visible. Ocurre cuando se recibe una petición de ayuda en el formulario. y aunque los componentes del formulario se redibujan por sí mismos generalmente. Ocurren cuando se oculta o se muestra el formulario. OnKeyUp y OnKeyPress OnHelp OnHide y OnShow Para responder a los eventos que suceden al pulsar alguna tecla sobre el formulario. Ocurre cuando se modifica el tamaño del formulario. Esto ocurre muy frecuentemente. Ocurre cuando el formulario necesita ser redibujado (refrescado). justo después de redimensionar el formulario.TForm . respectivamente (cuando su propiedad Visible se establece a falso o verdad.Propiedades.html (6 of 6) [27/02/2003 16:24:06] . respectivamente). métodos y eventos OnKeyDown. a veces es preciso redibujar "manualmente" el formulario. antes de que ocurra OnKeyDown. OnPaint OnResize OnShortCut Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/tform.

OnCreate. cuando se destruye el formulario se generan los siguientes eventos. que enumeramos ordenadamente: 1. De la misma manera. 4. 3. OnActivate. OnDestroy. 4. OnCloseQuery. OnClose. que enumeramos ordenadamente: 1. El constructor del formulario. OnPaint. 2. 2. 3. OnShow. El destructor del formulario (si existe).Eventos asociados a la creación y destrucción de formularios Curso de C++ Builder Sobre los eventos asociados a la creación y destrucción de formularios Cuando se crea un formulario se generan los siguientes eventos. Atrás file:///D|/Manuales/appendix/tip/tip_form.html (1 of 2) [27/02/2003 16:24:06] . 5.

Eventos asociados a la creación y destrucción de formularios © Francisco Cortijo Bon file:///D|/Manuales/appendix/tip/tip_form.html (2 of 2) [27/02/2003 16:24:06] .

OnClick. OnMouseUp.html (1 of 2) [27/02/2003 16:24:06] . OnMouseDown. Si se quiere atender a la pulsación del ratón sobre un formulario o un control. una pulsación del ratón genera los siguientes eventos. OnClick. que enumeramos ordenadamente: 1. 2. De la misma manera. 4. Si se tienen que utilizar OnMouseDown y OnMouseUp hay que tener en cuenta que OnClick lleva involucrado los eventos OnMouseDown y OnMouseUp. Así. OnDblClick. 3. cuando el usuario pulsa dos veces sobre un formulario o un control se generan los siguientes eventos. tan sólo hay que atender al evento OnClick. que enumeramos ordenadamente: 1. Atrás file:///D|/Manuales/appendix/tip/tip_raton. 3. OnMouseUp. 2.Eventos asociados al ratón Curso de C++ Builder Sobre los eventos asociados al ratón Los eventos del ratón presentan ciertas particularidades que se deben conocer. OnMouseDown.

Eventos asociados al ratón © Francisco Cortijo Bon file:///D|/Manuales/appendix/tip/tip_raton.html (2 of 2) [27/02/2003 16:24:06] .

métodos y eventos q 1. r r 1. Propiedad Align Descripción Establece distintas posiciones y ajustes del componente relativos al componente que lo contiene.1. Aunque cada componente tiene sus propias propiedades. Propiedades de los componentes.Propiedades. Propiedades de los componentes. 1. 3.1. q 2. que comentaremos brevemente. 1. Eventos de los componentes. Propiedades comunes más importantes.html (1 of 5) [27/02/2003 16:24:07] . q 1. file:///D|/Manuales/appendix/tcomponent. Propiedades comunes más importantes.Propiedades. métodos y eventos Curso de C++ Builder TComponent . Otras propiedades de uso corriente.TComponent . métodos y eventos.2. si es verdad que existen algunas propiedades comunes. Métodos de los componentes.

Visible Indica si el componente es visible o no. Name indica el nombre o identificador que se le asigna al componente en el programa y con el que se referirá al componente en la aplicación (en el código). propiedad a la que hacen referencia de su componente padre. Establece qué icono se muestra cuando el usuario mueve el cursor sobre un componente. Tiene dos partes. heredan el valor para la ParentColor.Propiedades. Permite especificar las propiedades de la fuente de letra que se usará en el componente. Hint especifica el texto que debe aparecer en el cuadro de ayuda o texto de sugerencia asociado a un componente. file:///D|/Manuales/appendix/tcomponent.html (2 of 5) [27/02/2003 16:24:07] . métodos y eventos Caption indica el texto que acompaña a algunos componentes. separadas por la barra |. Esta información aparece cuando ocurre el evento OnHint. Enabled Hint y ShowHint Cuando se establecen a verdad. por lo que no responde al ratón. ShowHint determina si la ayuda de sugerencia breve se debe mostrar o no. al teclado ni a eventos del temporizador. La segunda se presenta en la barra de estado. Caption y Name Color Cursor Font Se refiere al color de fondo del componente. Para activar y desactivar componentes: cuando un componente se desactiva no puede recibir el foco. La primera (sugerencia breve) se visualiza cuando el usuario coloca el puntero sobre el componente.TComponent . emplean el valor que tienen establecido para esa ParentShowHint propiedad. En ParentFont y otro caso. C++ Builder usará el valor de la propiedad Name para crear el puntero que referenciará al componente y el programador lo usará para referenciarlo.

Altura y anchura (en píxeles) del componente.html (3 of 5) [27/02/2003 16:24:07] . Métodos de los componentes. No se emplean habitualmente porque las acciones que realizan se efectúan modificando las propiedades del componente. 2. no están disponibles para todos los componentes.2. Para asociar un número de índice de un fichero de ayuda a un componente. Las siguientes propiedades.Propiedades. métodos y eventos 1. Propiedad BorderStyle Height y Width HelpContext Left y Top TabOrder y TabStop Descripción Para diferenciar al componente del formulario o integrarlo en su fondo. aunque se usan frecuentemente. Método Descripción ClientToScreen() Convierte las coordenadas del área de cliente en coordenadas de y pantalla y viceversa.TComponent . ScreenToClient() file:///D|/Manuales/appendix/tcomponent. respectivamente. Coordenadas X e Y del componente (su esquina superior izquierda). Para establecer el order de tabulación y determinar si el componente forma o no parte de la secuencia de tabulación. Otras propiedades de uso corriente.

3. Redibujar un componente. Sitúa el foco sobre un componente y lo convierte en el componente activo. Refresh(). Left. Evento Descripción file:///D|/Manuales/appendix/tcomponent. Eventos de los componentes.html (4 of 5) [27/02/2003 16:24:07] . Repaint() y Update() SetBounds() SetFocus() CanFocus() Hide() oculta el componente. métodos y eventos Hide() y Show() Invalidate(). Eventos asociados a la pulsación de alguna tecla. Puede volver a hacerse visible posteriormente con Show(). Ambos métodos modifican la propiedad Visible. Width y Height.Propiedades. Una acción puede desencadenar varios eventos y el orden en ocurren puede ser muy importante: Eventos asociados al movimiento y pulsación con el ratón. Devuelve verdad si el componente puede recibir el foco (si las propiedades Visible y Enabled están a verdad). Establece simultáneamente los valores de las propiedades Top.TComponent .

Si el objeto es un PaintBox. OnPaint Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/tcomponent. OnKeyDown. siempre que el foco se transfiera a otro componente del mismo formulario. OnMouseMove. OnKeyUp y OnKeyPress Para responder a los eventos que suceden al pulsar alguna tecla cuando el foco está en un componente. cuando se pincha con él sobre el componente. este gestor se encargará de dibujar sobre el Canvas y si no se proporciona este gestor. métodos y eventos OnMouseDown.Propiedades. Este evento ocurre cuando un objeto tiene que ser redibujado. Para responder a los eventos que suceden al mover el ratón o OnMouseUp. OnEnter y OnExit OnExit ocurre cuando el componente pierde el foco.html (5 of 5) [27/02/2003 16:24:07] .TComponent . el PaintBox no se verá en tiempo de ejecución. OnClick y OnDblClick OnEnter ocurre cuando se activa un componente (recibe el foco) siempre que el foco se transfiera desde otro componente del mismo formulario.

//-------------------------------------------------------------------------extern PACKAGE TMainForm *MainForm.Propiedad Name Curso de C++ Builder Sobre la propiedad Name A modo de ejemplo. private: // User declarations public: // User declarations __fastcall TMainForm(TComponent* Owner).hpp> #include <Forms. TEdit *Edit.hpp> #include <StdCtrls.html (1 of 2) [27/02/2003 16:24:07] . observar el contenido del fichero que C++ Builder crea como fichero de declaración del formulario. Recordar que el formulario principal se llamó. main. TButton *OKButton. void __fastcall OKButtonClick(TObject *Sender). TRadioButton *RadioButton1. void __fastcall CheckBoxClick(TObject *Sender).h. TButton *ExitButton. void __fastcall FormCreate(TObject *Sender). TRadioButton *RadioButton2. //-----------------------------------------------------------------------file:///D|/Manuales/appendix/tip/tip_name. si retomamos el ejemplo inicial de este curso (proyecto Inicial). TLabel *LabelOutput. finalmente. }.h: //-------------------------------------------------------------------------#ifndef mainH #define mainH //-------------------------------------------------------------------------#include <Classes. En main. MainForm.hpp> //-------------------------------------------------------------------------class TMainForm : public TForm { __published: // IDE-managed Components TLabel *LabelEdit.hpp> #include <Controls. TCheckBox *CheckBox. void __fastcall ExitButtonClick(TObject *Sender).

. . } //-------------------------------------------------------------------------- Accedemos a la propiedad Checked de RadioButton1 mediante el operador -> porque RadioButton1 es un puntero. En main.cpp nos referimos a este componente usando el valor de la propiedad Name de la siguiente manera: //-------------------------------------------------------------------------void __fastcall TMainForm::OKButtonClick(TObject *Sender) { if (RadioButton1->Checked) { if (Edit->Text == "") LabelOutput->Caption = "Escogió Opción 1.Propiedad Name --#endif Observar que.. por ejemplo.. desconocido/a"..html (2 of 2) [27/02/2003 16:24:07] . al primer botón de radio se le asignó el valor RadioButton1 a su propiedad Name. RadioButton1 es un puntero a un objeto de tipo TRadioButton. En el listado anterior. Sr/Sra. Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/tip/tip_name..

Para más información.cpp. por defecto) como Pizarra. Cambiar el nombre y título del formulario principal: Con el inspector de objetos.html (1 of 4) [27/02/2003 16:24:07] .h ha cambiado automáticamente a FuncsPizarra.bpr. Configurar el formulario principal. pinchar el siguiente enlace: En primer lugar. crear el directorio Pizarra y. Dar como título: PIZARRA y seleccionar un icono.Pizarra Curso de C++ Builder Pizarra 1. Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Pizarra y a continuación. Crear y configurar el proyecto.h 3. Guardar (File | Save Project As) el proyecto (Project1.bpr. Guardar (File | Save As) la unidad asociada al formulario (Unit1. una nueva aplicación ( File | New Applicaction). si procede. 4. 2. Dar un nombre a la aplicación y fijar un icono (Project | Options | Application). 1. Observar que Unit1. por defecto) como FuncsPizarra. cambiar la propiedad Caption por PIZARRA y la propiedad Name por MainForm.cpp. Run | Run. 2.Ejemplos . file:///D|/Manuales/intro/ejemplos/pizarra/index.

3. Debajo del Bevel. Debajo del PaintBox un componente Bevel (solapa Additional). 2. Escribir el código. Align = alTop y Height = 225.html (2 of 4) [27/02/2003 16:24:07] . Fijar las siguientes propiedades: Name = Linea. Fijar las propiedades Name = PaintBox.Ejemplos . centrado horizontalmente un componente BitBtn (solapa Additional). Style = bsLowered y Height = 8.Pizarra El formulario principal deberá tener el siguiente aspecto: Fijar manualmente el tamaño a 300 X 400 (Height = 300 y Width = 400). Align = alTop. 3. file:///D|/Manuales/intro/ejemplos/pizarra/index. un componente PaintBox (solapa System). alineado en lo alto. En la parte superior. Fijar las siguientes propiedades: Name = ExitBtn. Contiene 3 componentes: 1. Kind = bkClose y Caption = &Salir.

y tras seleccionar la pestaña Events haremos doble click en el gestor del evento OnPaint. 100.Pizarra En primer lugar. PaintBox->Canvas->Brush->Color = clYellow. } //----------------------------------------------------------- 4. El gestor de este evento quedará como sigue: //----------------------------------------------------------- void __fastcall TMainForm::ExitBtnClick(TObject *Sender) { Application->Terminate(). Generar el ejecutable. escribiremos el código asociado al evento OnPaint del componente PaintBox. PaintBox->Canvas->Ellipse (100. y tras seleccionar la pestaña Events haremos doble click en el gestor del evento OnClick. file:///D|/Manuales/intro/ejemplos/pizarra/index.Ejemplos . escribiremos el código asociado al evento OnClick del componente BitBtn (ExitBtn). Seleccionar en el inspector de objetos dicho componente. // Dibujar un cuadrado PaintBox->Canvas->Pen->Color = clRed.html (3 of 4) [27/02/2003 16:24:07] . 150. El gestor de este evento quedará como sigue: //----------------------------------------------------------- void __fastcall TMainForm::PaintBoxPaint(TObject *Sender) { // Dibujar un circulo PaintBox->Canvas->Pen->Color = clBlack. PaintBox->Canvas->Brush->Color = clRed. PaintBox->Canvas->Rectangle (200. Seleccionar en el inspector de objetos dicho componente. } //----------------------------------------------------------- Finalmente. 150). 100. 150). 250.

Ejemplos .html (4 of 4) [27/02/2003 16:24:07] . Run | Run.Pizarra Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Pizarra y a continuación. El resultado de la ejecución será el siguiente: Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/pizarra/index.

Ficheros de proyecto en C++ Builder En C++ Builder la gestión de proyectos software se realiza automáticamente y el usuario no necesita construir el fichero makefile ni ejecutar make para obtener el ejecutable: C++ Builder se encarga de todo ésto. Para la creación de un ejecutable se requiere: 1. opcionalmente. La extensión de estos ficheros es . de acuerdo a lo especificado en el fichero makefile. de una serie de módulos adicionales que pueden contener declaraciones de clases. declaraciones de funciones (prototipos). file:///D|/Manuales/appendix/project/index. bibliotecas y el ejecutable final.html (1 of 4) [27/02/2003 16:24:08] . Un fichero makefile en el que se especifica la dependencia entre los diferentes módulos y la manera en la que se generan los módulos objeto. Ejecutar el programa make para que interprete el fichero makefile y desencadene las órdenes oportunas para la creación del ejecutable. etc.Estructura y configuración de un proyecto de C++ Builder Curso de C++ Builder Estructura y configuración de un proyecto Estructura habitual de un proyecto escrito en C++ Una aplicación escrita en C++ se compone de un módulo (fichero) que contiene la función main() y. 2. Para este trabajo estructura los ficheros asociados a una aplicación en un proyecto. Se puede decir que un fichero de proyecto es un fichero makefile.bpr (Borland Project). definiciones de clases.

emplearemos el proyecto Inicial. seleccionar Project | View Source).cpp con el código asociado a esa ventana (usualmente contiene los gestores de los eventos que se pueden gestionar en esa ventana). que se desarrolla en los seis ejercicios introductorios. En este ejemplo. 2. Un módulo con extensión . los ficheros asociados a la ventana principal (y única) se llamarán main. file:///D|/Manuales/appendix/project/index.Estructura y configuración de un proyecto de C++ Builder Ejemplo.cpp Además.cpp y main. Ejemplo. Para cada ventana existirán dos módulos adicionales: 1. Ejemplo.h que contiene la declaración de los componentes que se incluyen en la ventana.html (2 of 4) [27/02/2003 16:24:08] . A modo de ejemplo. Cómo configurar un proyecto en C++ Builder El primer consejo es que cada aplicación debería estar en un directorio propio donde se guardarán todos los ficheros asociados a la aplicación.h. cualquier aplicación contendrá al menos una ventana. Si fuera preciso. La función WinMain() se alojará en el fichero Inicial.bpr En todo proyecto existe un fichero que contiene la función principal. para mostrar en el editor de código el fichero que contiene a la función WinMain(). Un módulo cabecera con extensión . El proyecto se llamará Inicial. Consiste en desarrollar una sencilla aplicación que consta de una única ventana. En aplicaciones que hacen uso de la VCL la función main() se llama WinMain() y se aloja en un fichero cuyo nombre coincide con el del proyecto. q q Habitualmente no es preciso trabajar sobre este fichero.

y 4. además. A) Si se acaba de arrancar C++ Builder aparece. 3. por defecto aparece un formulario vacío llamado Form1 asociado al proyecto Project1. Crear un directorio (p. Cambiar la propiedad Caption por Form de Prueba y la propiedad Name por MainForm.cpp. fichero que contiene la función WinMain().cpp. file:///D|/Manuales/appendix/project/index. Ahora se procede a configurar la aplicación. Project1. fichero de proyecto. Puede comprobarse usando el gestor de proyectos (View | Project Manager). 2. básicamente en proporcionar nombres significativos al proyecto y a los ficheros asociados al proyecto. Ejemplo. Los pasos a seguir son los siguientes: 1. B) Si existe un proyecto vigente. por defecto: 1. fichero que contiene las funciones asociadas al formulario principal (constructor de la ventana y que posteriormente contendrá. lo más cómodo es crear una nueva aplicación (File | New Application) salvando. Cambiar el nombre y título del formulario principal utilizando el inspector de objetos. Guardar ficheros asociados a ventanas (File | Save As) en el directorio adecuado para dar nombres significativos a los ficheros. Unit1. si se desea el proyecto vigente.h (especificacion de los componentes del formulario principal). Ejercicio) para guardar los ficheros asociados al proyecto.bpr. En cualquier caso se crean. Unit1.html (3 of 4) [27/02/2003 16:24:08] .bpr.Estructura y configuración de un proyecto de C++ Builder Ejemplo. 2. Consiste. Project1.e. los gestores de los eventos que puede gestionar).

Comprobar que Inicial.h).h cambia automáticamente a main.Estructura y configuración de un proyecto de C++ Builder Ejemplo.bpr como Inicial.cpp como main. Estos datos aparecerán al minimizar el programa durante su ejecución.bpr.bpr tiene la estructura de un fichero makefile.html (4 of 4) [27/02/2003 16:24:08] . (Observar que Project1. Dar un nombre a la aplicación y fijar un icono. Dar como título: Ejemplo inicial y seleccionar cualquier icono.cpp. 3. Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/project/index.cpp. (Unit1. 4. Podemos comprobarlo desplegando el menú Project. Ejemplo.cpp ha cambiado automáticamente a Inicial. Ejemplo. Guardar el proyecto: (File | Save Project As) en el directorio adecuado. y que éste contiene a la función WinMain). Guardar Project1. Guardar Unit1. Selecionar Project | Options | Application. Observar que el proyecto vigente se llama ahora Inicial.

Uso del inspector de objetos para escribir gestores de eventos con el editor de código. Modificación y consulta de propiedades en tiempo de ejecución. Gestores de eventos.2 3.html (1 of 2) [27/02/2003 16:24:08] .C++ Builder .Ejercicios Curso de C++ Builder Índice de ejercicios Ejercicios introductorios Diseño de un formulario.2 5.2 5.2 2.5 4.2 Sección 2.2 2. Ejercicios adicionales Ejemplos de aplicaciones simples y de consola.5 4.7.2 file:///D|/Manuales/exercises.2 3. Métodos asociados a componentes.2 3.6 4. Uso del inspector de objetos para modificar propiedades.6. Pizarra Controles de edición Editor Programación dirigida a objetos en C++Builder Ejemplo 0 Ejemplo 1 Ejemplo 2 Sección 2.5 Sección 5.5.

5 Sección 7 Sección 8 Atrás file:///D|/Manuales/exercises.C++ Builder .Ejercicios Ejemplo 3 Reproductor de sonidos Programación concurrente Ejemplos de programación con hebras q Creación de una hebra q Ejecución de una hebra q Control de la ejecución de una hebra q Coordinación entre hebras: Synchronize q Coordinación entre hebras: Bloqueo de objetos q Coordinación entre hebras: Secciones críticas q Sincronización entre hebras: TEvent Acceso a bases de datos Un componente 'data-aware' TDBDateTimePicker Un formulario Un diálogo de búsqueda genérico Una aplicación sencilla (Paradox) Gestión de una pequeña base de datos culinaria Una aplicación algo más compleja (InterBase) Diccionario de citas Ejercicio Desarrollo completo de una aplicación 6.html (2 of 2) [27/02/2003 16:24:08] .3 6.

2. Diseño de un formulario 1.1.1 Figura E1. pinchar el siguiente enlace: 1.Ejercicio 1. file:///D|/Manuales/intro/ejemplos/ej1. Todos los componentes necesarios para realizar este ejemplo se encuentran en la página de componentes Standard. Diseñar este formulario. Diseño de un formulario Curso de C++ Builder Ejercicio 1. Directorio: Ejercicio.html (1 of 2) [27/02/2003 16:24:09] . Colocar componentes en un formulario y redimensionarlo para que quede (aproximadamente) como se indica en la figura E1. Crear y configurar el proyecto: Para más información.

bpr.html (2 of 2) [27/02/2003 16:24:09] . 4. Proyecto (Project1. 3. por defecto): Inicial. por defecto): main.cpp. Unidad asociada al formulario (Unit1.Ejercicio 1. Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej1. Ejecutar el "programa": Seleccionar Run | Run. Generar el ejecutable: Seleccionar Project | Build. Diseño de un formulario 2. 3.cpp.bpr.

por file:///D|/Manuales/intro/ejemplos/ej2.html (1 of 3) [27/02/2003 16:24:09] . Figura E2. se trata de modificar los valores de las propiedades Caption y Name: q q Caption: Se refiere al título o leyenda que acompaña a los componentes (por ejemplo. En la lista siguiente se detallan las modificaciones a realizar.Ejercicio 2. Uso del inspector de objetos para modificar propiedades Curso de C++ Builder Ejercicio 2. Uso del inspector de objetos para modificar propiedades Cambiar el formulario diseñado en el ejercicio 1 para que tenga el aspecto que se indica en la figura E2. El formulario de la figura 6 modificado. básicamente.1. Name: Se refiere al nombre con el que se va a referenciar al componente desde el programa. al texto que aparece sobre un botón). Las modificaciones se realizarán usando el Inspector de Objetos (pestaña Properties). Al ser un identificador (como un nombre de variable.1. Observar que.

Button2 : Caption = Salir y Name = ExitButton. Así.2. Generar el ejecutable y ejecutar el "programa". Label1 : Caption = Nombre y Name = LabelEdit. Edit1 : Dejar vacío el valor de Text y Name = Edit. El resultado se muestra en la figura E2. Size = 10 y Color = Marine. Resultado de la ejecución tras modificar propiedades en tiempo de diseño. Activar el cuadro de diálogo asociado a la propiedad Font y establecer los siguientes valores: Font = MS Serif.h en este ejemplo) y gracias a ello se puede acceder al componente a través del código. C++ Builder asigna nombres como Button1 y Button2 y es conveniente asignarles otros más clarificadores como OKButton o ExitButton. por ejemplo. Button1 : Caption = OK. Cuando se coloca un componente en un formulario. RadioButton2 : Caption = Opción 2 y Name = RadioButton2.Ejercicio 2. Figura E2. C++ Builder crea un puntero al componente en la declaración del formulario (fichero main. RadioButton1 : Caption = Opción 1 y Name = RadioButton1. las modificaciones a realizar son las siguientes: q q q q q q q q q Form1 : Caption = Form de Prueba y Name = MainForm. Font Style = Bold.html (2 of 3) [27/02/2003 16:24:09] . Uso del inspector de objetos para modificar propiedades ejemplo) debe ser significativo. Name = OKButton y Enabled = false. Label2 : Dejar vacío el valor de Caption y Name = LabelOutput. Por defecto.2. Name = CheckBox y Checked = true. CheckBox1 : Caption = Activar opciones. file:///D|/Manuales/intro/ejemplos/ej2. C++ Builder emplea la propiedad Name del componente para denominar al puntero.

Ejercicio 2.html (3 of 3) [27/02/2003 16:24:09] . Uso del inspector de objetos para modificar propiedades Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej2.

El editor de código muestra el siguiente código. Seleccionar el componente ExitButton y en la pestaña Events del inspector de objetos. generar el ejecutable y ejecutar el programa: al hacer click sobre el botón de salir. file:///D|/Manuales/intro/ejemplos/ej3. Se trata de que al pinchar sobre este botón la aplicación termine su ejecución.Ejercicio 3.html (1 of 2) [27/02/2003 16:24:09] . Uso del inspector de objetos para escribir gestores de eventos con el editor de código Curso de C++ Builder Ejercicio 3. Uso del inspector de objetos para escribir gestores de eventos con el editor de código Vamos a construir el gestor del evento que se genera al hacer click sobre el botón de salir. generado automáticamente: //-----------------------------------------------------------void __fastcall TMainForm::ExitButtonClick(TObject *Sender) { } //------------------------------------------------------------ Escribir el siguiente código: //-----------------------------------------------------------void __fastcall TMainForm::ExitButtonClick(TObject *Sender) { Application->Terminate(). hacer doble click en OnClick. el programa deja de ejecutarse. } //------------------------------------------------------------ Ahora.

Ejercicio 3.html (2 of 2) [27/02/2003 16:24:09] . Uso del inspector de objetos para escribir gestores de eventos con el editor de código Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/ej3.

Veamos cómo. En cualquier caso. Una aplicación de consola no utiliza los objetos de la VCL. Una aplicación de consola se crea usando el asistente Console Wizard.html (1 of 6) [27/02/2003 16:24:10] . indicar que se va a crear una aplicación de consola (Console). Seleccionar File | New | Console Wizard y en el asistente. El editor de código aparece de la siguiente manera: Observar que el editor de código no presenta las líneas necesarias para la inclusión de las file:///D|/Manuales/intro/ejemplos/simples/index. Aplicaciones de consola. C++ Builder permite la creación de este tipo de aplicaciones. y el aspecto de una aplicación de este tipo es el generado por los compiladores "tradicionales".Ejemplos . ejecutándose sobre una consola MS-DOS.Aplicaciones simples Curso de C++ Builder Ejemplos de aplicaciones simples 1.

i++) cout << "Valor de i = " << i << endl. Seleccionar File | Save Project As y guardar Project1. i<5.Aplicaciones simples definiciones de objetos de la VCL y la función principal es la conocida main(). return 0.h> #include <conio.bpr como Console. Escribir el siguiente código: #pragma hdrstop #include <condefs.h> #include <iostream. Run | Run. Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Console y a continuación. } //----------------------------------------------------------- Finalmente. char* argv[]) { for (int i=0.Ejemplos .bpr. guardar el proyecto y ejecutar el programa.h> //----------------------------------------------------------- #pragma argsused int main(int argc.html (2 of 6) [27/02/2003 16:24:10] . El resultado de la ejecución será el siguiente: file:///D|/Manuales/intro/ejemplos/simples/index. getch(). donde ésta se llama WinMain(). al contrario que ocurre en las aplicaciones "visuales".

Unit1.bpr.h del proyecto vigente.cpp como Unit1. Ejemplo 1: Saludo. El resultado de la ejecución será el siguiente: file:///D|/Manuales/intro/ejemplos/simples/index. 1.html (3 of 6) [27/02/2003 16:24:10] . LPSTR. return 0.cpp tiene asociado el formulario principal Form1.Aplicaciones simples 2. Para escribir el código del programa. Confirmar el borrado y de esta forma se eliminan tanto Unit1. Run | Run. } //----------------------------------------------------------- Finalmente. Aplicaciones visuales sencillas. Activar el formulario y a continuación seleccionar Project | Remove from project. El primer paso es crear una aplicación de la manera usual: Seleccionar File | New Application. seleccionar Project | View Source y escribir el siguiente código: //----------------------------------------------------------- #include <vcl. En este ejemplo escribiremos un programa que lanza una ventana de mensaje con un saludo. Pueden construirse aplicaciones visuales (hacen uso de la VCL) sin necesidad de usar el diseñador de formularios. Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Saludo y a continuación. guardar el proyecto y ejecutar el programa. HINSTANCE.h> //----------------------------------------------------------- WINAPI WinMain(HINSTANCE.Ejemplos . int) { ShowMessage ("Hola"). Como la aplicación no tendrá un formulario y por defecto se asocia uno a la aplicación debemos borrarlo. Seleccionar File | Save Project As y guardar Project1.bpr como Saludo.

html (4 of 6) [27/02/2003 16:24:10] . Finalmente. para escribir el código del programa. Activar el formulario para eliminarlo del proyecto: seleccionar Project | Remove from project.bpr. Como antes. en cada iteración. . presentando cada valor individualmente.i<5 . } //----------------------------------------------------------- Guardar el proyecto (File | Save Project As) llamándolo Ciclo. Quinta iteración file:///D|/Manuales/intro/ejemplos/simples/index. .i++){ ShowMessage ("Valor de i = " + AnsiString(i)). en primer lugar se crea una aplicación: Seleccionar File | New Application. } return 0. será el siguiente. . .h> //----------------------------------------------------------- WINAPI WinMain(HINSTANCE. int) { for (int i=0 .Aplicaciones simples 2.Ejemplos . El resultado de la ejecución. seleccionar Project | View Source y escribir el siguiente código: //----------------------------------------------------------- #include <vcl. . Ejemplo 2: Ciclo (múltiples ventanas secuenciales). HINSTANCE. de forma que en cada iteración aparece una sóla ventana. Primera iteración Segunda iteración . Este programa presenta los valores guardados en un vector en una ventana de mensajes (recordar el ejemplo anterior). LPSTR. construir el ejecutable (Project | Build Ciclo) y ejecutarlo Run | Run). Para pasar a la siguiente iteración hay que pulsar el botón OK.

for (int i=0. } ShowMessage (cadena).bpr.h> //----------------------------------------------------------- WINAPI WinMain(HINSTANCE.html (5 of 6) [27/02/2003 16:24:10] . Ejemplo 3: Resultado compuesto en una única ventana. Se procede como en los dos casos anteriores. delete []vector.Aplicaciones simples .. return 0. vector = new int[5]. HINSTANCE. i++) { vector[i] = i*2... AnsiString cadena = "". 3.. El código que escribiremos es el siguiente: //----------------------------------------------------------- #include <vcl. LPSTR. cadena = cadena + "vector[" + AnsiString (i) + "] = " + AnsiString (vector[i]) + "\n".. } file:///D|/Manuales/intro/ejemplos/simples/index. En este ejemplo se crea un vector dinámico de 5 enteros y se muestra su contenido en una única ventana. y llamaremos al proyecto Vector. i<5. int) { int *vector.Ejemplos .

html (6 of 6) [27/02/2003 16:24:10] .Aplicaciones simples //----------------------------------------------------------- La ejecución de este programa produce el siguiente resultado: Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/simples/index.Ejemplos .

Para más información. Run | Run. Guardar (File | Save As) la unidad asociada al formulario (Unit1. una nueva aplicación ( File | New Applicaction). Configurar el formulario principal. por defecto) como FuncsEdicion.Ejemplos . Guardar (File | Save Project As) el proyecto (Project1. 2.Una aplicación con componentes de edición Curso de C++ Builder Construcción de una aplicación con componentes de edición 1.bpr.html (1 of 5) [27/02/2003 16:24:10] . 2. Observar que Unit1.cpp.h 3. cambiar la propiedad Caption por Controles de edición y la propiedad Name por MainForm. Crear y configurar el proyecto. pinchar el siguiente enlace: En primer lugar.bpr. Dar como título: Controles de Edición y seleccionar un icono. Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Edicion y a continuación. por defecto) como Edicion. El formulario principal debe tener el siguiente aspecto: file:///D|/Manuales/intro/ejemplos/controles/index. Cambiar el nombre y título del formulario principal: Con el inspector de objetos.cpp. crear el directorio Edicion y.h ha cambiado automáticamente a FuncsEdicion. 4. 1. Dar un nombre a la aplicación y fijar un icono (Project | Options | Application). si procede.

Una aplicación con componentes de edición Contiene 8 componentes: tres Label (solapa Standard). Este formulario tiene un único componente Label llamada Label. cambiar las propiedades de estas componentes prestando especial cuidado al nombre (Name) de forma que los nombres queden como se indica en la figura: 3. tres Edit (solapa Standard). Configurar el formulario secundario. El aspecto del formulario será el siguiente: file:///D|/Manuales/intro/ejemplos/controles/index. Utilizando el inspector de objetos.Ejemplos . Añadir un nuevo formulario al proyecto: seleccionar File | New Form y fijar Name =SaludoBox y Caption= Cuadro de salutación. y dos botones BitBtn (solapa Additional).html (2 of 5) [27/02/2003 16:24:10] .

EditNombre->SetFocus(). EditApellido2->Text = "". Run | Run.muy habitual. la pestaña Events y hacer doble click el gestor del evento OnClick. Seleccionar en el inspector de objetos dicho componente. } } //----------------------------------------------------------- 5.hcambia a Saludo. "Error en la entrada de datos". Seleccionar File | Save ally guardar Unit1. Escribir el código. El gestor de este evento quedará como sigue: //----------------------------------------------------------- void __fastcall TMainForm::BotonOKClick(TObject *Sender) { if (EditNombre->Text == "" || EditApellido1->Text == "" || EditApellido2->Text == "" ) { Application->MessageBox ( "Debe especificar todos los campos". " + EditNombre->Text + " " + EditApellido1->Text + " " + EditApellido2->Text.cpp(observar que Unit1. sólo se escribirá código para el evento OnClick del componente BotonOK del formulario principal.h). En este caso. MB_OK). EditNombre->Text = "". EditApellido1->Text = "".ya que file:///D|/Manuales/intro/ejemplos/controles/index. Generar el ejecutable. } else { SaludoBox->Label->Caption = "Bienvenido.Ejemplos . 4. todo hay que decirlo . Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build Edicion y a continuación. Observar que se produce un error de compilación .cppcomo Saludo.html (3 of 5) [27/02/2003 16:24:10] .Una aplicación con componentes de edición Guardar el formulario (con los ficheros asociados). SaludoBox->Show().

cpp observaremos que este fichero no incluye a Saludo. Resulta poco profesional que la única posibilidad de cerrar un formulario sea pinchar sobre el botón del aspa situado en el marco de una ventana. Modificar el código asociado al método BotonOKClick de manera que la ventana de saludo se ejecute modalmente.Una aplicación con componentes de edición no se puede encontrar la definición de SaludoBox. Añadir al formulario secundario un botón para cerrarlo.h. seleccionar File | Include Unit Hdr y seleccionar Saludo. 1. Ejercicios adicionales.cpp. Volver a generar el ejecutable y ejecutar el programa. si el usuario introduce los siguientes datos en las líneas de edición: Al pulsar el botón de confirmación.h". objeto que es usado en FuncsEdicion. Estando activo en el editor de código FuncsEdicion. file:///D|/Manuales/intro/ejemplos/controles/index. 2.html (4 of 5) [27/02/2003 16:24:10] . De hecho. si miramos FuncsEdicion. Como ejemplo de ejecución.Ejemplos . se produce el siguiente resultado: 6. Observar que se añade la línea #include "Saludo.cpp.

Una aplicación con componentes de edición Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/controles/index.Ejemplos .html (5 of 5) [27/02/2003 16:24:10] .

Editor de texto Curso de C++ Builder Un sencillo editor de texto En este ejemplo se explica cómo crear rápidamente una aplicación para Windows con C++ Builder. Mostramos con profundidad cómo configurar un formulario. y el alumno puede añadirle más funcionalidad. lo que le permitirá ampliar sus conocimientos sobre programación de aplicaciones visuales con C++ Builder. La aplicación que se va a presentar consiste en un editor de texto con bastante funcionalidad.) file:///D|/Manuales/intro/ejemplos/editor/index.Ejemplos . Básicamente. En esta sección se presentan los componentes habituales de una aplicación Windows.. Mostramos diversas técnicas para añadir menús y submenús y cómo incorporar un menú cotextual. a asociar nombres representativos a los ficheros descartando los que C++ Builder asocia por defecto. Este ejercicio se estructura como sigue: 1. desde añadir una barra rápida hasta cuadros de diálogo. aunque muy mejorable. Crear y Configurar el proyecto. Mostramos cómo crear un proyecto (conjunto de ficheros de programa y formularios asociados a una aplicación) y cómo configurarlo. 4. 2. Configurar el formulario principal. Añadir menús al formulario. 3.html (1 of 15) [27/02/2003 16:24:12] . Una vez diseñado el formulario hay que escribir el código C++ de los manipuladores de eventos asociados a los componentes 5. Añadir un nuevo formulario (Acerca de . No debe entenderse que la aplicación presentada está cerrada. Escribir el código del programa.. más bien al contrario.

Sobre la barra de estado y los cuadros de pista (Hints).Ejemplos . pinchar el siguiente enlace: En primer lugar. tal como debe verse en el gestor de proyectos. una nueva aplicación ( File | New Applicaction). 1. 6. Crear y configurar el proyecto. Como referencia. si procede.html (2 of 15) [27/02/2003 16:24:12] . Para más información. crear el directorio EjemploEditor y. esta es la estructura del proyecto que vamos vamos a crear.Editor de texto Aquí mostramos cómo se pueden añadir nuevos formularios. Cambiar el nombre y título del formulario principal: file:///D|/Manuales/intro/ejemplos/editor/index. 1. Mostramos cómo añadir cuadros de pista a los botones rápidos y cómo mostrar información en la barra de estado.

Agregar una barra rápida. seleccionar la propiedad Lines y dejar limpio su contenido con el editor de cadenas.Ejemplos . r Crear un panel para albergar los botones de la barra rápida. 2. Guardar los ficheros: File | Save All 2. Cambiar la propiedad Name por Memo.1. Ahora podemos construir el ejecutable y probarlo: seleccionar Project | Build MiEditor y a continuación. Agregar un componente Memo.h ha cambiado automáticamente a FuncsEditor.h 3.bpr. Colocarlo sobre el formulario (no nos preocupamos de su tamaño ni de su alineación respecto al formulario). Seleccionar.bpr. Observar que Unit1. Guardar (File | Save As) la unidad asociada al formulario (Unit1. 2. Seleccionar un componente Panel (solapa Standard) y colocarlo en algún file:///D|/Manuales/intro/ejemplos/editor/index.html (3 of 15) [27/02/2003 16:24:12] .2. Guardar (File | Save Project As) el proyecto (Project1. el componente Memo. en la solapa Standard de la paleta de componentes. Seleccionar un componente Bevel (solapa Additional).cpp. fijar Name= Bevel.0 y seleccionar un icono. por defecto) como FuncsEditor.Editor de texto Con el inspector de objetos. por defecto) como MiEditor. Height = 2 y alinearlo en lo alto (Align =alTop). 4. Configurar el formulario principal. Run | Run.cpp. r Crear un componente Bevel. Dar como título: Mi editor de texto 1. Dar un nombre a la aplicación y fijar un icono (Project | Options | Application). cambiar la propiedad Captionpor Mi editor de textoy la propiedad Namepor MainForm. 2.

file:///D|/Manuales/intro/ejemplos/editor/index. Glyph: filesave.html (4 of 15) [27/02/2003 16:24:12] . salvar fichero y salir del programa.bmp) y Salir (Name = ExitBtn. Repetir estos pasos para los botones Salvar Fichero (Name =FileSaveBtn. Se colocarán los botones para abrir fichero. Para el botón Abrir Fichero: Seleccionar un componente SpeedButton (solapa Additional) y colocarlo en el panel. Glyph: dooropen.bmp. Fijar: s s s s s Name = SpeedBar Height = 32 BevelOuter = bvNone Caption = (Dejar en blanco) Align = alTop r Colocar los botones de acceso rápido de la barra rápida. Cambiar las propiedades: s s s Name = FileOpenBtn Left = 4 Glyph: Pinchar dos veces en la propiedad Glyph y seleccionar el icono fileopen.Ejemplos .Editor de texto lugar del formulario.bmp).

Ejemplos .Editor de texto 2. 2.3. por lo que el lugar file:///D|/Manuales/intro/ejemplos/editor/index. Estos son componentes no visuales. Reajustar el componente Memo. Agregar una barra de estado. Añadir una barra de scroll vertical: cambiar la propiedad ScrollBars a ssVertical. Añadir las componentes no visuales OpenDialog y SaveDialog Colocar en cualquier sitio del formulario los componentes OpenDialog y SaveDialog (solapa Dialogs).4. Fijar Name = StatusBar.5. Seleccionar el componente Memo y fijar la propiedad Align= alClient. Seleccionar un componente StatusBar (solapa Win32). 2.html (5 of 15) [27/02/2003 16:24:12] .

1) junto con los submenús asociados: Ficheros (sección 3. crearemos un menú contextual (sección 3. 3. El aspecto del formulario será el de la figura siguiente. El menú y los submenús son los típicos de las aplicaciones Windows. Edición (sección 3. En primer lugar. seleccionar el componente no visual file:///D|/Manuales/intro/ejemplos/editor/index.3 y Ayuda (sección 3. Los componentes no visuales OpenDialog y SaveDialog no se ven en tiempo de ejecución. Guardar todos los ficheros del proyecto (File | Save All).2). añadiremos un menú principal (sección 3. Para crear el menú principal y los submenús.Editor de texto de ubicación no es importante. construir el proyecto (Project | Build MiEditor) y ejecutarlo (Run | Run). Cambiar las propiedades Name a OpenDialog y SaveDialog. respectivamente.5). Finalmente.html (6 of 15) [27/02/2003 16:24:12] . Añadir menús al formulario.Ejemplos .4).

Editor de texto MainMenu (solapa Standard) y colocarlo en algún lugar del formulario. r r r Para el submenú Ficheros: Name=FileMenu y Caption=&Ficheros Para el submenú Edicion: Name=EditMenu y Caption=&Edicion Para el submenú Ayuda: Name=HelpMenu y Caption=&Ayuda 3. Las cabeceras de los submenús serán: Ficheros. Diseño del menú principal.1. diseñar el menú.Ejemplos . Deseamos que se abra un submenú asociado a cada una de estas categorías cuando se pinche con el ratón sobre éstas. 3. Menú Ficheros.2. Fijar Name=MainMenu.html (7 of 15) [27/02/2003 16:24:12] . file:///D|/Manuales/intro/ejemplos/editor/index. A continuación. Edicion y Ayuda. Se hará con el diseñador de menús: pinchar dos veces sobre el componente MainMenu.

Guardar. Conf. (separador) y Salir. Guardar como: Name=FileSaveAs y Caption= Guardar &como. Guardar: Name=FileSave y Caption= &Guardar.3. (separador). Caption=Config&urar impresora y Enabled= false Incluir un separador: Caption = Salir: Name=FileExit y Caption=&Salir 3. Abrir.Ejemplos . Menú Edición. file:///D|/Manuales/intro/ejemplos/editor/index. Configurar impresora. Incluir un separador: Caption = Imprimir: Name=FilePrint.html (8 of 15) [27/02/2003 16:24:12] . Guardar como. Para cada opción se procede como antes: r r r r r r r r r Nuevo: Name=FileNew y Caption=&Nuevo Abrir: Name=FileOpen y Caption= &Abrir. impresora: Name=FilePrintSetUp. Caption=&Imprimir y Enabled=false.Editor de texto Añadir las opciones: Nuevo. Imprimir.

y Checked=true file:///D|/Manuales/intro/ejemplos/editor/index.Editor de texto Añadir las opciones: Deshacer.html (9 of 15) [27/02/2003 16:24:12] . Incluir un separador: Caption = Buscar: Name=EditFind. Seleccionar del menú principal la cabecera Edicion. Caption=Seleccionar &todo y ShortCut=Ctrl+A. (separador). Buscar. Copiar: Name=EditCopy. (separador) y Ajustar. (separador). Reemplazar: Name=EditReplace. y ShortCut=Ctrl+X. Reemplazar. Caption=P&egar y ShortCut=Ctrl+V. Este submenú se creará usando una plantilla de menú. Pegar: Name=EditPaste. Caption=&Deshacer. Caption=&Copiar y ShortCut=Ctrl+C. Seleccionar todo.Cortar. Caption=&Ajustar. Caption=&Reemplazar y Enabled=false Incluir un separador: Caption = Ajustar: Name=EditWordWrap. ShortCut=Ctrl+Z Incluir un separador: Caption = Cortar: Name=EditCut. Caption=&Buscar y Enabled=false. Seleccionat todo: Name=EditSelectAll. Caption=C&ortar. A continuación. modificar el submenú Edicion para que quede: r r r r r r r r r r r Deshacer:Name=EditUndo. Copiar. Pegar.Ejemplos . Camiar la nueva cabecera Edit para dejarla Name=EditMenu y Caption=&Edicion. Pulsar el botón derecho del ratón y seleccionar Insert from Template | Edit Menu. Borrar la antigua cabecera Edicion.

5. Para crear el menú contextual.Ejemplos . cerrar el diseñador de menús. seleccionar el componente no visual PopUpMenu file:///D|/Manuales/intro/ejemplos/editor/index.Editor de texto 3. Menú Ayuda. Finalmente. Establecer las propiedades Name=HelpAbout y Caption=Ace&rca de .4. Solamente tendrá una opción: Acerca de .. Menú Contextual. El aspecto del formulario será el siguiente: 3... .html (10 of 15) [27/02/2003 16:24:12] ..

: Name=PopUpAbout y Caption=Ace&rca de . y ShortCut=Ctrl+X. Copiar: Name=PopUpCopy. Caption=P&egar y ShortCut=Ctrl+V. Escribir el código del programa. . Para esto. Pegar. y los demás se completarán siguiendo las líneas aquí descritas. Incluir un separador: Caption = Acerca de . El menú contextual puede asociarse a cualquier componente que tenga asociada la propiedad PopupMenu. Caption=&Copiar y ShortCut=Ctrl+C.Editor de texto (solapa Standard) y colocarlo en algún lugar del formulario. Cada opción del menú y cada botón de la barra rápida debe tener asociada una acción.. Para cada opción: r r r r r Cortar: Name=PopUpCut. Detallaremos cómo se hace el de la opción Ficheros | Salir.. Pegar: Name=PopUpPaste.Ejemplos . Este menú se diseñará con el diseñador de menús. Se activa el editor de código. seleccionar el componente Memo. Copiar. La acción se asocia a cada componente mediante el gestor de eventos del inspector de objetos. de la misma manera que se ha hecho con el menú principal. Añadir las opciones: Cortar. En este caso se asociará al componente Memo para que al pulsar el botón derecho del ratón se despliegue el menú que acabamos de crear. Caption=C&ortar.. mostrando el gestor que se va a completar: //-----------------------------------------------------------void __fastcall TMainForm::FileExitClick(TObject *Sender) { } //------------------------------------------------------------ file:///D|/Manuales/intro/ejemplos/editor/index. Fijar Name=PopUpMenu. Todos los manipuladores de eventos se escriben con una metodología similar.. (separador) y Acerca de. acceder a la propiedad PopupMenu y seleccionar PopUpMenu (el único disponible). Seleccionar Ficheros | Salir del menu principal. 4.html (11 of 15) [27/02/2003 16:24:12] .

Para ello.Editor de texto Completar la función de la siguiente forma: //-----------------------------------------------------------void __fastcall TMainForm::FileExitClick(TObject *Sender) { Application->Terminate(). seleccionar el componente ExitBtn en el inspector de objetos. Así.html (12 of 15) [27/02/2003 16:24:12] . pulsar en la pestaña Events y en en evento OnClick. Opción: Edición | Copiar y Copiar del menú contextual. proceder de la misma forma. la función FileExitClick() se activa desde Ficheros | Salir y desde el botón rápido ExitBtn. desplegar la lista de funciones pulsando sobre la flecha que aparece a la derecha del evento OnClick (ahora sólo está FileExitClick()) y seleccionarla. Para cada opción. el resultado final debe ser: r Opción: Ficheros | Nuevo Opción: Ficheros | Abrir y botón rápido FileOpenBtn Opción: Ficheros | Guardar y botón rápido FileSaveBtn Opción: Ficheros | Guardar como Opción: Edición | Deshacer Opción: Edición | Cortar y Cortar del menú contextual. Dicho de otra forma. Opción: Edición | Seleccionar todo r r r r r r r r file:///D|/Manuales/intro/ejemplos/editor/index. Opción: Edición | Pegar y Pegar del menú contextual.Ejemplos . } //------------------------------------------------------------ Como el botón rápido para salir ExitBtn debe realizar la misma tarea. Para seleccionar una de las funciones ya escritas. le asignamos las misma función al evento OnClick.

) Seleccionar File | New Form. Fijar Kind = bkOK. Añadir un nuevo formulario (Acerca de. diseñar una ventana modal titulada Acerca de Mi editor de texto con el siguiente aspecto: Fijar las propiedades del formulario Caption = Acerca de Mi editor de texto.. fijar Autosize = true. 3. 2. Añadir un botón de OK. Fijar Shape = bsFrame. Name = AboutBox y BorderStyle = bsDialog y configurarlo: 1. y © Curso de Programación Visual. file:///D|/Manuales/intro/ejemplos/editor/index. Seleccionar el componente Bevel (solapa Additional) y enmarcar el texto.Editor de texto r Opción: Edición | Ajustar 5. Añadir tres componentes Label (solapa Standard) con textos (Caption): Mi editor de texto. Crear un marco que englobe a los tres componentes Label. Sobre este formulario. Corresponde al componente BitBtn (solapa Additional). respectivamente.html (13 of 15) [27/02/2003 16:24:12] . Versión 1.. Para este componente.Ejemplos . 4. Añadir un icono (el mismo que se asoció a la aplicación) seleccionando un componente Image (solapa Additional).0.

éste se especifica también en la misma propiedad separado por la barra |. Observar que al poner el cursor sobre el botón se muestra el cuadro de pista pero no en la barra de estado. Seleccionar File | Save y darle el nombre About. seleccionar el botón FileOpenBtn y fijar la propiedad Hint a Abrir fichero | Abrir un fichero existente y fijar ShowHint = true. o Acerca de ..cpp Añadir esta unidad al proyecto. Ahora. en el menú contextual debe abrirse la ventana que hemos creado. Si se desea que aparezca un texto más amplio en la barra de estado.cpp y File | Include Unit Hdr. Modificar las propiedades Hint de los botones FileSaveBtn y ExitBtn fijándolas a Guardar fichero | Guardar en un fichero el texto mostrado y file:///D|/Manuales/intro/ejemplos/editor/index. Seleccionar About.Ejemplos . 6. construir el proyecto y ejecutar. Finalmente.Editor de texto Almacenar la unidad.. y completar el manipulador HelpAboutClick() de la siguiente forma: //----------------------------------------------------------- void __fastcall TMainForm::HelpAboutClick(TObject *Sender) { AboutBox->ShowModal(). Se puede asociar a cada componente un cuadro de pista (Hint) fijando al valor de su propiedad Hint al texto que se quiere mostrar.. El código que abre esta ventana se completa como sigue: seleccionar la opción Ayuda | Acerca de ..html (14 of 15) [27/02/2003 16:24:12] . Por ejemplo. construir el proyecto y ejecutarlo.. } //----------------------------------------------------------- Asignar la misma función al gestor del evento OnClick de PopUpAbout. Salvar. cuando se seleccione Ayuda | Acerca de . Sobre la barra de estado y los cuadros de pista (Hints).. Seleccionar FuncsEditor.

Para que aparezca el texto largo en la barra de estado basta con establecer la propiedad AutoHint de la barra de estado a true.Editor de texto Salir | Terminar la ejecución del programa.html (15 of 15) [27/02/2003 16:24:12] . respectivamente. construir el proyecto y ejecutar. y fijar para ambos ShowHint = true.Ejemplos . Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/index. salvar. Finalmente.

} // Borrar el contenido de Memo. SaveDialog->FileName = "". guardar el archivo actual. // Sustituir el valor de la propiedad FileName del cuadro // de dialogo Save por espacios en blanco. if (result == IDYES) FileSaveClick(Sender).html (1 of 2) [27/02/2003 16:24:12] .Ejemplos . Asi se sabe // que el fichero no se ha guardado aun. ¿Salvar los cambios?". // Si se pulsa YES. if (result == IDCANCEL) return. no hacer nada. int result = Application->MessageBox( "El fichero activo ha cambiado. "!Cuidado!". Primero hay que verificar // que el fichero actual tiene que guardarse. if (Memo->Modified) { // Mostrar un cuadro de mensaje. si lo hay. if (Memo->Lines->Count > 0) Memo->Clear(). MB_YESNOCANCEL).Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Ficheros | Nuevo //---------------------------------------------------------void __fastcall TMainForm::FileNewClick(TObject *Sender) { // Abre un nuevo fichero. // Si se pulsa CANCEL. file:///D|/Manuales/intro/ejemplos/editor/fich_nuevo.

Editor de texto } //----------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/fich_nuevo.html (2 of 2) [27/02/2003 16:24:12] .Ejemplos .

Ejemplos . ¿Salvar los cambios?". Verificar en primer lugar si hay que // salvar el archivo actual. Igual que en FileNewClick() if (Memo->Modified) { // Mostrar un cuadro de mensaje. file:///D|/Manuales/intro/ejemplos/editor/fich_abrir.Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Ficheros | Abrir y botón FileOpenBtn //---------------------------------------------------------void __fastcall TMainForm::FileOpenClick(TObject *Sender) { // Abrir un fichero.html (1 of 3) [27/02/2003 16:24:12] . int result = Application->MessageBox( "El fichero activo ha cambiado.

Ejemplos . si lo hay. OpenDialog->FileName = "". } // Abrir el cuadro de diálogo File Open.html (2 of 3) [27/02/2003 16:24:12] . if (result == IDYES) FileSaveClick(Sender).Editor de texto "!Cuidado!". // Si se pulsa CANCEL. file:///D|/Manuales/intro/ejemplos/editor/fich_abrir. MB_YESNOCANCEL). if (Memo->Lines->Count > 0) Memo->Clear(). if (OpenDialog->Execute()) { // Borrar el contenido de Memo. guardar el archivo actual. if (result == IDCANCEL) return. no hacer nada. // Si se pulsa YES.

} } //---------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/fich_abrir. SaveDialog->FileName = OpenDialog->FileName.Ejemplos .Editor de texto // Leer el fichero a Memo.html (3 of 3) [27/02/2003 16:24:12] . Memo->Lines->LoadFromFile(OpenDialog->FileName).

html (1 of 2) [27/02/2003 16:24:13] .Ejemplos .Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Ficheros | Guardar y botón FileSaveBtn //----------------------------------------------------------- void __fastcall TMainForm::FileSaveClick(TObject *Sender) { // Si ya se ha especificado un nombre de fichero no es // necesario abrir el cuadro de diálogo Guardar Fichero. // Solo hay que guardarlo con SaveToFile(). if (SaveDialog->FileName != "") { Memo->Lines->SaveToFile(SaveDialog->FileName). file:///D|/Manuales/intro/ejemplos/editor/fich_guardar.

} //----------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/fich_guardar.Editor de texto // Establecer ahora la propiedad Modified a FALSE. Memo->Modified = false.Ejemplos .html (2 of 2) [27/02/2003 16:24:13] . } // Si no se ha dado un nombre. ejecutar SaveAs(). else FileSaveAsClick(Sender).

if (SaveDialog->Execute()) { Memo->Lines->SaveToFile(SaveDialog->FileName). } file:///D|/Manuales/intro/ejemplos/editor/fich_guardar_como.Ejemplos .html (1 of 2) [27/02/2003 16:24:13] .Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Ficheros | Guardar como //----------------------------------------------------------- void __fastcall TMainForm::FileSaveAsClick(TObject *Sender) { SaveDialog->Title = "Save As". Memo->Modified = false.

Ejemplos .html (2 of 2) [27/02/2003 16:24:13] .Editor de texto } //----------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/fich_guardar_como.

html (1 of 2) [27/02/2003 16:24:13] .Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Deshacer //----------------------------------------------------------- void __fastcall TMainForm::EditUndoClick(TObject *Sender) { Memo->Undo(). // Llamada a TMemo->Undo() } //----------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/editor/edic_deshacer.Ejemplos .

Editor de texto Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_deshacer.html (2 of 2) [27/02/2003 16:24:13] .Ejemplos .

// Llamada a TMemo->CutToClipboard() } //----------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/editor/edic_cortar. //----------------------------------------------------------- void __fastcall TMainForm::EditCutClick(TObject *Sender) { Memo->CutToClipboard().html (1 of 2) [27/02/2003 16:24:13] .Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Cortar y Cortar del menú contextual.Ejemplos .

Editor de texto Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_cortar.Ejemplos .html (2 of 2) [27/02/2003 16:24:13] .

Ejemplos .Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Copiar y Copiar del menú contextual.html (1 of 2) [27/02/2003 16:24:14] . //----------------------------------------------------------- void __fastcall TMainForm::EditCopyClick(TObject *Sender) { Memo->CopyToClipboard(). //Llamada a TMemo->CopyToClipboard() } //----------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/editor/edic_copiar.

html (2 of 2) [27/02/2003 16:24:14] .Ejemplos .Editor de texto Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_copiar.

Ejemplos .html (1 of 2) [27/02/2003 16:24:14] . // TMemo->PasteFromClipboard() } //----------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/editor/edic_pegar. //----------------------------------------------------------- void __fastcall TMainForm::EditPasteClick(TObject *Sender) { Memo->PasteFromClipboard().Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Pegar y Pegar del menú contextual.

Editor de texto Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_pegar.Ejemplos .html (2 of 2) [27/02/2003 16:24:14] .

Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Seleccionar todo //----------------------------------------------------------- void __fastcall TMainForm::EditSelectAllClick(TObject *Sender) { Memo->SelectAll().html (1 of 2) [27/02/2003 16:24:14] . // TMemo->SelectAll() } //----------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/editor/edic_seleccionar_todo.Ejemplos .

html (2 of 2) [27/02/2003 16:24:14] .Editor de texto Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_seleccionar_todo.Ejemplos .

Editor de texto Curso de C++ Builder Un sencillo editor de texto Opción: Edición | Ajustar //----------------------------------------------------------- void __fastcall TMainForm::EditWordWrapClick(TObject *Sender) { // Modificar la propiedad TMemo::WordWrap.Ejemplos . una barra. dos. // Si WordWrap está activo. Memo->WordWrap = !Memo->WordWrap.html (1 of 2) [27/02/2003 16:24:14] . Si no. EditWordWrap->Checked = Memo->WordWrap. file:///D|/Manuales/intro/ejemplos/editor/edic_ajustar.

Editor de texto if (Memo->WordWrap) Memo->ScrollBars = ssVertical.Ejemplos .html (2 of 2) [27/02/2003 16:24:14] . else Memo->ScrollBars = ssBoth. } //----------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/editor/edic_ajustar.

} //---------------------------------------------------------------------- PPAL. &PpalFrm).cpp"). USEUNIT("ObjGraf. Application->CreateForm(__classid(TPpalFrm). HINSTANCE. USEFORM("Ppal.Ejemplo 0 Curso de C++ Builder Ejemplo 0 Corresponde al final de la sección 5.html (1 of 7) [27/02/2003 16:24:15] . Application->Run().4. int) { try { Application->Initialize(). tras la herencia y antes de ABSTRACCIÓN.2.res"). EJEMPLO.cpp".OOP .H //---------------------------------------------------------------------file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0. } return 0.CPP //---------------------------------------------------------------------#include <vcl.h> #pragma hdrstop USERES("Ejemplo. LPSTR. //----------------------------------------------------------------------WINAPI WinMain(HINSTANCE. } catch (Exception &exception) { Application->ShowException(&exception). PpalFrm).

OOP .hpp> <Forms. }. private: // User declarations public: // User declarations __fastcall TPpalFrm(TComponent* Owner).h" #include <Buttons.hpp> <StdCtrls. void __fastcall FormDestroy(TObject *Sender).hpp> <Controls. //---------------------------------------------------------------------#endif PPAL. //---------------------------------------------------------------------extern PACKAGE TPpalFrm *PpalFrm. void __fastcall FormCreate(TObject *Sender). TBitBtn *BotonSalir.hpp> #include "ObjGraf.hpp> <ExtCtrls. void __fastcall PaintBoxPaint(TObject *Sender).h> #pragma hdrstop #include "Ppal.h" //---------------------------------------------------------------------file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0.hpp> //---------------------------------------------------------------------class TPpalFrm : public TForm { __published: // IDE-managed Components TPaintBox *PaintBox.html (2 of 7) [27/02/2003 16:24:15] .CPP //---------------------------------------------------------------------#include <vcl.Ejemplo 0 #ifndef PpalH #define PpalH //---------------------------------------------------------------------#include #include #include #include #include <Classes. void __fastcall BotonSalirClick(TObject *Sender).

*Cuad2.OOP . 20). Cir2 = new TCirculo (PaintBox.dfm" TPpalFrm *PpalFrm. 45). 25). *Cir2. // Punteros a objetos de las clases derivadas. delete Cuad1.html (3 of 7) [27/02/2003 16:24:15] . Cir2->Mostrar(). } //---------------------------------------------------------------------void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender) { Cir1->Mostrar(). clBlack. delete Cuad2. 200. clRed. 70. Cuad2->Mostrar(). clYellow. Cuad1->Mostrar(). //---------------------------------------------------------------------- __fastcall TPpalFrm::TPpalFrm(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------- void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Cir1 = new TCirculo (PaintBox. 120.Ejemplo 0 #pragma package(smart_init) #pragma resource "*. } file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0. } 30). 100. TCuadrado *Cuad1. } //---------------------------------------------------------------------void __fastcall TPpalFrm::BotonSalirClick(TObject *Sender) { Application->Terminate(). delete Cir2. clGreen. TCirculo *Cir1. 150. 210. 40. 100. //---------------------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete Cir1. Cuad1 = new TCuadrado (PaintBox. Cuad2 = new TCuadrado (PaintBox.

TColor _Color=clBlack. // Metodo virtual puro }. int _Y=0). // Constructor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox.H //---------------------------------------------------------------------#ifndef ObjGrafH #define ObjGrafH //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { public: int X.Ejemplo 0 //---------------------------------------------------------------------- OBJGRAF. int Y.OOP . // Otros metodos virtual void Mostrar (void) = 0. file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0. TColor TPaintBox // Propiedades Color. TColor _Color=clBlack.html (4 of 7) [27/02/2003 16:24:15] . // Metodo constructor TCirculo (TPaintBox *_PaintBox. int _X=0. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { public: int Radio. //*************************************************/ // Definicion de la clase derivada TCirculo. *PaintBox.

CPP //---------------------------------------------------------------------#include <vcl. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { public: int Lado.h" //---------------------------------------------------------------------#pragma package(smart_init) /*****************************************************/ // Metodos asociados a la clase base TObjGraf /*****************************************************/ file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0.html (5 of 7) [27/02/2003 16:24:15] .OOP . int _Y=0. //*************************************************/ // Definicion de la clase derivada TCuadrado.h> #pragma hdrstop #include "ObjGraf. TColor _Color=clBlack. }. // Metodo constructor TCuadrado (TPaintBox *_PaintBox. int _X=0. //---------------------------------------------------------------------#endif OBJGRAF. int _Y=0. // Instanciacion del metodo virtual puro de la clase TObjGraf void Mostrar (void). int _Lado=1).Ejemplo 0 int _X=0. }. int _Radio=1). // Instanciacion del metodo virtual puro de la clase TObjGraf void Mostrar (void).

int _Y) { PaintBox = _PaintBox. } /*****************************************************/ // Metodos asociados a la clase derivada TCuadrado. // TCuadrado deriva de la clase base TObjGraf. /*****************************************************/ TCuadrado :: TCuadrado (TPaintBox *_PaintBox. PaintBox->Canvas->Rectangle(X. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCirculo :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. int _X. PaintBox->Canvas->Brush->Color = Color. _X. int _Y. _X.OOP . PaintBox->Canvas->Ellipse(X. // TCirculo deriva de la clase base TObjGraf.Ejemplo 0 TObjGraf :: TObjGraf (TPaintBox *_PaintBox. } /*****************************************************/ // Metodos asociados a la clase derivada TCirculo. _Color.html (6 of 7) [27/02/2003 16:24:15] . X+Lado. } file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0. int _X. int _Lado) : TObjGraf (_PaintBox. int _Y. _Color. X+Radio*2. Color = _Color. int _Radio) : TObjGraf (_PaintBox. TColor _Color. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCuadrado :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. Y = _Y. TColor _Color. PaintBox->Canvas->Brush->Color = Color. /*****************************************************/ TCirculo :: TCirculo (TPaintBox *_PaintBox. Y+Lado). TColor _Color. Y. _Y) { Radio = _Radio. int _X. Y+Radio*2). X = _X. _Y) { Lado = _Lado. Y.

html (7 of 7) [27/02/2003 16:24:15] .OOP .Ejemplo 0 Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/oop/Ejemplo0.

5. Propiedades Virtuales.1.6. r r r 5. 5. Herencia de Constructores y Destructores (Inicialización de Clases II). es un paradigma de programación que se fundamenta en los conceptos de objeto y clase. Herencia Múltiple. Constructores y Destructores (Inicialización de Clases I).2. Creación y Destrucción de Objetos. Abstracción..O. En primer lugar. q 5.Programación Orientada a Objetos en C++ Curso de C++ Builder Programación Orientada a Objetos en C++ q q q q q 5.2.2. Un objeto es una instancia de una clase. Restricciones de acceso en C++.1. 5. preparemos el camino creando un proyecto: file:///D|/Manuales/intro/5.7. En esta sección no se pretende dar una teoría completa de P.. definamos que entendemos por objeto y clase: Objeto: Una entidad autónoma con una funcionalidad concreta y bien definida. q 5.7. Así. Los conceptos presentados en esta sección se ilustrarán usando un ejemplo que se irá completando poco a poco a medida que se introduzcan nuevos conceptos. tan sólo se presentarán los conceptos necesarios para una correcta programación en C++ Builder.5.6. Es más. r r 5.2. 5.3. El Paradigma de la POO en C++. 5.5.O. Encapsulamiento. 5.1. La P.O. Sobrecarga de funciones. este mismo ejemplo se emplea en las secciones dedicadas al tratamiento de excepciones y a la programación con hebras.3.html (1 of 28) [27/02/2003 16:24:17] .5.1. Clase: Especificación de las características de un conjunto de objetos. 5. Clases Abstractas.6. 5. 5. r r 5.4.7.O. Polimorfismo en las clases y métodos virtuales. Herencia. Polimorfismo.

con Align=alTop. Crear una unidad (File | New | Unit). que contendrá la definición (implementación de los métodos) de éstas.cpp y el proyecto como Ejemplo. Colocar un bevel de ancho 4 y alinearlo en lo alto (Align=alTop).1. Dejar espacio por debajo del PaintBox para colocar un botón. que se file:///D|/Manuales/intro/5. q q q q q En ObjGraf. y. Colocar un PaintBox de la página de componentes System que se llame PaintBox. La idea es que delimite la parte inferior del PaintBox.h. El Paradigma de la POO en C++ Existen cuatro principios básicos que cualquier sistema orientado a objetos debe incorporar. en realidad.cpp.cpp Cuando se crea una unidad de esta manera se crean. #endif //-------------------------------------------------- Nótese que el nombre de la clase va precedido por una T.Programación Orientada a Objetos en C++ q Crear un proyecto (File | New | Application) Cambiar el nombre del formulario (Name=PpalFrm).h. y ObjGraf. aunque no es obligatorio. dos ficheros.h: //-------------------------------------------------#ifndef ObjGrafH #define ObjGrafH // Definición de la clase TObjGraf class TObjGraf {}. que contendrá las declaraciones de las clases con las que vamos a trabajar. disponemos de dos ficheros: ObjGraf. Así. Guardarla con el nombre ObjGraf. pero no se crea ningún objeto. si es muy recomendable ya que es una convención de C++ Builder que casi todos los nombres de clases vayan precedidos por T.cpp y otro con extensión . El botón estará centrado horizontalmente en la parte inferior del formulario. Guardar el código del formulario como Ppal.html (2 of 28) [27/02/2003 16:24:17] . 5. Muy Importante: Con el ejemplo anterior sólo conseguimos definir la clase.bpr. Colocar un botón bit que permita terminar la ejecución del programa. uno con extensión .

Para poder utilizar la funcionalidad contenida en la misma.cpp: Pulsando dos veces en OnCreate de la pestaña Events del editor de objetos de PpalFrm: //-------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { TObjGraf ObjGraf1(). Pilares de la POO. En Ppal. 5. TObjGraf ObjGraf2.1.2.Programación Orientada a Objetos en C++ esquematizan en la figura 5.h" En Ppal. Creación por Declaración.html (3 of 28) [27/02/2003 16:24:17] . Figura 5. 1.h: #include "ObjGraf. declarando una variable del tipo de la clase. Un objeto se puede instanciar de una forma simple. se deben instanciar las clases.1. } file:///D|/Manuales/intro/5. Creación y Destrucción de Objetos Ya se ha dicho que una clase es únicamente una especificación.

En definitiva.cpp: TObjGraf * ObjGraf. } //-------------------------------------------------- La forma de establecer el estado inicial o destruir las componentes de un objeto se estudiarán en el apartado dedicado a Constructores y Destructores (sección 5. En Ppal. La duración de los objetos suele ir más allá de una simple función o bloque. fundamentalmente: 1. ¡Cuidado! Cuando se utiliza esta forma de instanciación de clases es responsabilidad únicamente del programador la correcta destrucción de los mismos. Esto es así por dos razones. No se puede usar esta modalidad de creación con la VCL. Por lo tanto. y bastante utilizada en la programación de C++ clásica. nosotros no la utilizaremos. 2. y se realiza mediante el operador new . suele ser habitual que un objeto se cree en un gestor de eventos y se destruya en otro. // Variable Global.Programación Orientada a Objetos en C++ //-------------------------------------------------- Aunque esta forma es posible. // ObjGraf es un puntero a objetos de tipo TObjGraf //-------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf.4). Debido al enfoque de la programación dirigida por eventos. en C++ Builder se utiliza en muy contadas ocasiones. 3. Cuando usamos new para instanciar un objeto. Destrucción de objetos file:///D|/Manuales/intro/5. se requiere la declaración previa de un puntero a objetos del tipo del que se va a crear. Creación Dinámica Es la forma habitual de crear objetos en C++ Builder. se usa una variable que referencie o apunte al nuevo objeto creado (de otra manera éste quedaría totalmente inaccesible). 2.html (4 of 28) [27/02/2003 16:24:17] .

La especificación de las propiedades de un objeto y los métodos de acceso se realiza en la declaración de la clase de la que se instancia el objeto. } //-------------------------------------------------- 5. La declaración de propiedades y métodos de los objetos de la clase TObjGraf se realiza de la siguiente manera: file:///D|/Manuales/intro/5. La destrucción de objetos creados en tiempo de ejecución con new se realiza mediante el operador delete. Propiedades y métodos de los objetos de la clase TObjGraf.html (5 of 28) [27/02/2003 16:24:17] .2.Programación Orientada a Objetos en C++ Cuando un objeto deja de ser útil hay que eliminarlo. En un objeto podemos distinguir dos aspectos bien diferenciados: q q Estado -----------> Propiedades Comportamiento ---> Métodos En P.) existen datos y procedimientos que actúan sobre esos datos. p.e.O.O. No hay una relación aparente entre datos y procedimientos (funciones) y esta relación se establece de manera más o menos pecisa de acuerdo a la profesionalidad del programador.2 esquematizamos las propiedades y métodos que se van a asociar a los objetos de la clase TObjGraf: Figura 5. En Ppal. De esta manera la aplicación recupera los recursos (memoria) que ese objeto había acaparado cuando se creó.3. los datos y los procedimientos que los gestionan están relacionados explícitamente y se "encapsulan" en un objeto.cpp: Pulsando dos veces en OnDestroy de la pestaña Events del editor de objetos de PpalFrm: //-------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete ObjGraf. Encapsulamiento En la programación clásica (lenguaje C. En la figura 5.

int ValorY. //Equivalente a (*Obj). ValorY = ObjGraf->Y.h: //-------------------------------------------------class TObjGraf { public: int X. Constructores y Destructores (Inicialización de Clases I) Son métodos que permiten establecer el estado inicial y final de un objeto. simplemente significan que se omite una parte del código.html (6 of 28) [27/02/2003 16:24:17] . Como nosotros siempre creamos los objetos con new. TPaintBox *PaintBox. //-------------------------------------------------- Acceso a Miembros de un Objeto Para acceder a los miembros de un objeto se usan los operadores típicos de acceso a miembros: el operador . 5. .. TColor Color.Programación Orientada a Objetos en C++ En ObjGraf.. ya sea porque es irrelevante o porque ya se ha expuesto anteriormente. Los constructores se pueden file:///D|/Manuales/intro/5. ObjGraf->Mostrar(). } //-------------------------------------------------- Nota: Los puntos suspensivos no son una palabra reservada de C++.4. y los referenciamos mediante un puntero. ObjGraf->X = 5.. // Propiedades void Mostrar (void). int Y.. para referencia directa al objeto y el operador -> para acceso a través de un puntero. el operador de acceso que utilizaremos es el operador -> En Ppal. // Métodos }.cpp: //-------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { .Mostrar().

liberar la memoria dinámica que ocupa el objeto que se va a destruir. ó 2) cuando se crea dinámicamente con el operador new. int _X=0. De ser así.Programación Orientada a Objetos en C++ definir con un conjunto de argumentos arbitrario. int _X.. Y los destructores no pueden recibir ni devolver ningún valor. básicamente.5.h: class TObjGraf { .. // Constructor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox. int _Y) { PaintBox = _PaintBox. 10). int _Y=0).html (7 of 28) [27/02/2003 16:24:17] . y el destructor el nombre de la clase precedido del carácter ~ Un constructor se ejecuta cuando se crea un nuevo objeto: 1) por declaración. la clase derivada incorpora todos los miembros de la clase base además file:///D|/Manuales/intro/5. TColor _Color=clBlack. En ObjGraf. Herencia Cuando una clase hereda de otra. El constructor debe llamarse igual que la clase. 5. Y = _Y. X = _X. clRed.cpp: TObjGraf :: TObjGraf (TPaintBox * _PaintBox. Color = _Color. 10. En ObjGraf. TColor _Color. }. la tarea del destructor será. // El destructor sería: ~TObjGraf (void). ó 2) cuando se libera explícitamente con el operador delete.cpp: void __fastcall TPpalFrm::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf (PaintBox. } Importante: No es necesario escribir un destructor salvo si el objeto requiere memoria dinámica adicional. Un destructor se ejecuta cuando el objeto deja de existir: 1) porque su ámbito acaba. } En Ppal. pero no pueden devolver nada.

Mejora del mantenimiento. Esto significa que los objetos de estas clases tienen asociados las propiedades y métodos de la clase base. Tomando como base la clase TObjGraf se van a construir dos nuevas clases. además de los suyos propios. que derivan de TObjGraf. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { public: int Lado.html (8 of 28) [27/02/2003 16:24:17] .Programación Orientada a Objetos en C++ de los suyos propios. Reusabilidad de clases (propias o no). Las clases TCirculo y TCuadrado heredan las propiedades y métodos de la clase TObjGraf. TCirculo y TCuadrado. En la figura 5. //*************************************************/ // Definicion de la clase derivada TCuadrado.4 En ObjGraf. // Propiedad exclusiva de TCuadrado file:///D|/Manuales/intro/5.3. // Propiedad exclusiva de TCirculo }. TObjGraf.3 esquematizamos el mecanismo de herencia para las nuevas clases y las nuevas propiedades que se asocian a los objetos de las clases derivadas. Figura 5. La herencia es una herramienta muy importante en muchos aspectos del desarrollo de aplicaciones: q q q Organización del diseño.h: //*************************************************/ // Definicion de la clase derivada TCirculo // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { public: int Radio.

// Propiedad exclusiva de TCuadrado file:///D|/Manuales/intro/5. int _X=0. TColor _Color=clBlack. De ser así. Para determinar con qué parámetros se llaman a los constructores de las clases base. es necesario saber: 1. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { public: int Lado.5. // Propiedad exclusiva de TCirculo // Metodo constructor TCirculo (TPaintBox *_PaintBox. 5.1.h: //*************************************************/ // Definicion de la clase derivada TCirculo // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { public: int Radio. que los constructores y destructores de las clases base son invocados automáticamente antes que los constructores de las clases derivadas.Programación Orientada a Objetos en C++ }. En ObjGraf. //*************************************************/ // Definicion de la clase derivada TCuadrado. int _Radio=1). no obstante. por lo que nosotros supondremos que sólo existe la public. Antes del nombre de la clase base hay que poner public. Pero ésta no se suele usar. Deberemos crear en las clases hijas sus propios constructores y destructores. emplear los constructores de la clase base pero hay que indicarlo explícitamente. int _Y=0. }. que los destructores de las clases derivadas se invocan antes que los de las clases base.html (9 of 28) [27/02/2003 16:24:17] . Es posible. y 2. esto es así porque C++ permite también la herencia private. Herencia de Constructores y Destructores (Inicialización de Clases II) Los constructores y destructores de una clase no son heredadas automáticamente por sus descendientes. se utiliza la lista de inicialización.

_X. int _Y=0. int _Lado=1). // Otros metodos virtual void Mostrar (void) = 0.2. int _Radio) : TObjGraf (_PaintBox. _Color. _Y) { Lado = _Lado. _Color. En terminología C++ se dice que una clase abstracta es aquella que posee al menos un método virtual puro.h: class TObjGraf { public: . Clases Abstractas Clase abstracta: es una clase que no está completamente especificada (posee métodos sin implementar). TColor _Color. q q Virtual: obliga a las clases derivadas a implementar ese método. int _Lado) : TObjGraf (_PaintBox. } 5. int _X=0. Puro: no pueden crearse instancias de esa clase. // Metodo virtual puro }. }. _X. int _X. Una clase abstracta se usa para servir de clase base a otras clases..cpp: TCirculo :: TCirculo (TPaintBox * _PaintBox. En ObjGraf..html (10 of 28) [27/02/2003 16:24:17] . En ObjGraf.5. TColor _Color=clBlack. } TCuadrado :: TCuadrado (TPaintBox * _PaintBox.Programación Orientada a Objetos en C++ // Metodo constructor TCuadrado (TPaintBox * _PaintBox. _Y) { Radio = _Radio. int _X. class TCirculo : public TObjGraf { file:///D|/Manuales/intro/5. int _Y. int _Y. TColor _Color. por lo tanto no se pueden crear instancias de la misma.

cpp el gestor asociado al evento OnCreate del formulario está escrito como sigue: //-------------------------------------------------- file:///D|/Manuales/intro/5. De esta forma estamos seguros de que todas las clases descendientes no abstractas de TObjGraf poseen el método. } ¿Por qué se especifica el método Mostrar en TObjGraf. en lugar de omitirlo? Fundamentalmente podemos considerar dos razones para usar métodos virtuales puros: 1. Y.html (11 of 28) [27/02/2003 16:24:17] . Para evitar que se puedan crear instancias de la clase abstracta. y se podrá invocar con seguridad. como virtual puro.. Y+Lado). class TCuadrado : public TObjGraf { public: .cpp: void TCirculo :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. X+Radio*2. En ObjGraf.. } . }. PaintBox->Canvas->Rectangle(X. Para obligar a que las clases descendientes los implementen.Programación Orientada a Objetos en C++ public: . }.. PaintBox->Canvas->Ellipse(X. Y.. En este estado. // Instanciacion del metodo virtual puro de la clase TObjGraf void Mostrar (void).. X+Lado. void TCuadrado :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. nos aparecerá un error: no se puede crear una instancia de una clase abstracta. // Instanciacion del metodo virtual puro de la clase TObjGraf void Mostrar (void). si probamos a ejecutar el programa. 2. Y+Radio*2). PaintBox->Canvas->Brush->Color = Color. ¿Porqué?: Recordar que en Ppal. PaintBox->Canvas->Brush->Color = Color..

// Variable Global. modificaremos la función FormCreate para que cree dos objetos de cada clase referenciados por los punteros declarados anteriormente: //-------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Cir1 = new TCirculo (PaintBox. En segundo lugar. 10). 200. 120. file:///D|/Manuales/intro/5. 100. Cuad1 = new TCuadrado (PaintBox. delete Cir2. clGreen. 45).Programación Orientada a Objetos en C++ void __fastcall TPpalFrm::FormCreate(TObject *Sender) { ObjGraf = new TObjGraf (PaintBox. 100. 40.cpp hay que borrar la declaración de la variable global: TObjGraf *ObjGraf. *Cuad2. Finalmente. 25). clBlack. TCirculo *Cir1. delete Cuad1. modificaremos la función FormDestroy para que elimine los objetos creados: //-------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete Cir1. dos para referenciar a objetos de tipo TCirculo y otros dos para referenciar a objetos de tipo TCuadrado: // Punteros a objetos de las clases derivadas. clYellow. }. 20). Cir2 = new TCirculo (PaintBox. 210. }. en Ppal. 10. clRed. clRed. 3. 70. //-------------------------------------------------- Así. 150. *Cir2. TCuadrado *Cuad1. delete Cuad2. //-------------------------------------------------- 30).html (12 of 28) [27/02/2003 16:24:17] . 2. creemos entonces objetos de las clases hijas: 1. y en su lugar se declararán cuatro punteros. Cuad2 = new TCuadrado (PaintBox. En primer lugar.

4: 4 Figura 5. Resultado del proyecto Ejemplo. ¿Porqué? En ningún momento se ha llamado al método Mostrar() asociado a cada objeto. al ejecutar el programa se crean y se destruyen objetos de las clases derivadas. Cuad1->Mostrar().html (13 of 28) [27/02/2003 16:24:17] .Programación Orientada a Objetos en C++ } //-------------------------------------------------- Ahora. Ejercicio: Construir la clase TTriangulo y modificar el proyecto para que proporcione un resultado similar al de la figura 5. file:///D|/Manuales/intro/5. el proyecto debe estar como se indica en el proyecto Ejemplo0. basta con indicarlo en el gestor asociado al evento OnPaint del componente PaintBox: //-------------------------------------------------void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender) { Cir1->Mostrar().4. El resultado es el mostrado en la figura 5. Cuad2->Mostrar(). aunque no se visualizan en la ventana. Para mostrar los objetos. Cir2->Mostrar(). } //-------------------------------------------------- En este punto.5.bpr.

5. . class TCocheEnVenta : public TProducto. }. 5.. file:///D|/Manuales/intro/5. }. public TVehiculo { ..html (14 of 28) [27/02/2003 16:24:17] . .3.. Herencia Múltiple La herencia múltiple es el hecho de que una clase derivada se genere a partir de varias clases base.Programación Orientada a Objetos en C++ Figura 5. Ejemplo: En un concesionario de coches podríamos considerar la siguiente jerarquía de clases: class TProducto { long Precio.5.. Resultado del proyecto Ejemplo..bpr mostrando objetos de la clase TTriangulo. }.. Observar que los objetos de la clase TCocheEnVenta derivan de las clases TProducto y TVehiculo. class TVehiculo { int NumRuedas.

protected: Implementación de la familia.6. 5. protected: desde los métodos de la clase y desde los métodos de las clases derivadas.h: //*************************************************/ file:///D|/Manuales/intro/5. Ninguna de las dos posibilidades es mejor que la otra. private: desde los métodos de la clase. 5. Implementación: cómo lleva a cabo su cometido.Programación Orientada a Objetos en C++ Existen dos formas para que una clase saque partido de las ventajas de otra.1. Que herede de TObjGraf y contenga un objeto de la clase TCirculo y otro de TCuadrado. podemos decidir distintas estrategias a la hora de llevarlo a cabo: q q q q Que herede de TCirculo y TCuadrado. Restricciones de acceso en C++ En C++ se puede especificar el acceso a los miembros de una clase utilizando los siguientes especificadores de acceso: q q q public: Interfaz de la clase. únicamente controlan desde dónde se pueden usar los miembros de la clase: q q q public: desde cualquier sitio. pero no cómo lo lleva a cabo. en cada caso particular habrá que estudiar cual es la mejor opción. Que herede de TCuadrado y contenga un objeto de la clase TCirculo. y la otra es que una clase contenga un objeto de la otra clase.html (15 of 28) [27/02/2003 16:24:17] . private: Implementación de la clase. Que herede de TCirculo y contenga un objeto de la clase TCuadrado.6. Podemos distinguir en una clase dos aspectos desde el punto de vista de la abstracción: q q Interfaz: lo que se puede ver/usar externamente de un objeto. Resumiendo: nos interesa saber qué nos ofrece un objeto. Abstracción Es la ocultación de detalles irrelevantes o que no se desean mostrar. Estos especificadores no modifican ni la forma de acceso ni el comportamiento. si quisieramos diseñar una clase (TMarco) que represente un marco (representado por un cuadrado y un círculo). Por ejemplo. En ObjGraf. una es la herencia.

// Constructor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox. Modificar de la misma manera las clases TCirculo y TCuadrado para que sus propiedades Radio y Lado queden protegidas y los métodos públicos: //*************************************************/ // Definicion de la clase derivada TCirculo. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y sus descendientes. protected: // Pueden acceder los objetos de esta clase y sus descendientes.html (16 of 28) [27/02/2003 16:24:17] . int _X=0. int _X=0. TColor _Color=clBlack. int _Y=0). int Radio. file:///D|/Manuales/intro/5. int _Y=0. public: // Pueden usarlas todas. // Otros metodos virtual void Mostrar (void) = 0. // Metodo virtual puro }. // Puede acceder SOLO los objetos de esta clase. void Mostrar (void). TPaintBox * PaintBox. int _Radio=1). TColor _Color=clBlack. // Instanciacion del metodo virtual puro // de la clase TObjGraf }. TColor Color. public: // Metodo constructor TCirculo (TPaintBox *_PaintBox. int Y.Programación Orientada a Objetos en C++ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int X.

// Instanciacion del metodo virtual puro // de la clase TObjGraf }. Cir1->X = 10.cpp escribiéramos: //-------------------------------------------------void __fastcall TPpalFrm::FormCreate (TObject *Sender) { . Esta es la técnica clásica que se emplea en C++ 2. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y sus descendientes. // Se puede. } //-------------------------------------------------- En realidad estos tres especificadores de acceso son los propios de C++. file:///D|/Manuales/intro/5. void Mostrar (void). int _X=0. // No se puede porque X es private. int _Lado=1). TColor _Color=clBlack. porque su uso está restringido al IDE. Cuando en una clase veamos una sección __published quiere decir que los miembros contenidos en la misma son mantenidos automáticamente por el IDE y no deberemos modificar nada en dicha sección. ¿Entonces cómo se puede cambiar el estado de un objeto desde el exterior? 1. A través de los métodos y de las propiedades "virtuales"..Programación Orientada a Objetos en C++ //*************************************************/ // Definicion de la clase derivada TCuadrado. ya que de lo contrario los resultados pueden ser imprevisibles. public: // Metodo constructor TCuadrado (TPaintBox * _PaintBox. int Lado. Así. si en Ppal. pero en C++ Builder existe otro adicional. Cir1->Mostrar(). De esta manera son los métodos los que acceden a las propiedades y el usuario de la clase sólo accede a través de ellos. que es el __published. int _Y=0. Esta técnica es exclusiva de C++ Builder y la describimos en la siguiente sección. No vamos a dar mucha importancia a este modificador. ya que si esto ocurriera podría peligrar la integridad del objeto. Ofreciendo métodos (públicos) que se encarguen de modificar las propiedades (privadas) que se desee.. Es una buena técnica de programación no permitir el acceso público a las propiedades de un objeto.html (17 of 28) [27/02/2003 16:24:17] .

El usuario de la clase usa estas propiedades como si fueran propiedades reales y en última instancia se traducen en la llamada a un método o en el acceso a una propiedad real.e. write=SetY }. int _Y=0). int FY. int _X=0. La acción que se produce cuando la propiedad virtual es de lectura se especifica. // OJO: Se ha cambiado Color por FColor // Pueden usarlas todas. // Metodo virtual puro // NUEVAS FORMAS DE ACCESO CON PROPIEDADES VIRTUALES. no existen. Veamos un ejemplo. file:///D|/Manuales/intro/5. // OJO: Se ha cambiado el nombre a // los miembros X e Y por FX y FY. sintácticamente. realmente. __property int X = __property int Y = __property TColor Color = {read=FX. void SetY (int _Y).2. Propiedades Virtuales Son propiedades definidas mediante métodos de lectura (read) y/o escritura (write). en la parte derecha de una asignación) se traduce en una acción diferente que si esa popiedad virtual se usa para escritura. En ObjGraf. Es más.html (18 of 28) [27/02/2003 16:24:17] . // Otros metodos virtual void Mostrar (void) = 0. // Metodo virtual puro virtual int GetAlto (void) = 0. {read=FColor. write=FColor}.6. FColor. {read=FY. // Metodo virtual puro protected: TColor TPaintBox public: // Pueden acceder los objetos de esta clase y descendientes.Programación Orientada a Objetos en C++ 5. write=SetX }. virtual int GetAncho (void) = 0. // Constructor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox. si una propiedad virtual se usa para lectura (p. void SetX (int _X).h: //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int FX. Se llaman virtuales porque. // Puede acceder SOLO los objetos de esta clase. mediante la palabra reservada read mientras que si se usa para escritura se especifica con write. *PaintBox. TColor _Color=clBlack.

La última instrucción. FY). directamente. en la propiedad real FColor. povocaría un error porque SetX() es un método privado. el valor: una ventaja adicional. Observaciones: q Observar que la "antigua" propiedad X (resp. povocaría un error porque FX es una propiedad privada. q Como hemos incorporado dos nuevos métodos a la clase base TObjGraf (GetAncho() y GetAlto()) y éstos se han declarado virtuales puros necesitamos instanciarlos en las clases derivadas: file:///D|/Manuales/intro/5. observar que las propiedades virtuales Ancho y Alto no tienen asociados métodos de acceso para escritura. En realidad es como si se hiciera Cir1->SetX(100).Programación Orientada a Objetos en C++ __property int __property int }. Y) se llama ahora FX (resp. Al "redirigir" la escritura al método SetX() podemos controlar la validez del parámetro y corregir. ya que cuando se accede para lectura a la propiedad (virtual) X en realidad se accede a la propiedad (real) FX. q La propiedad virtual Color tiene asociado el mismo método de acceso para lectura y escritura: devuelve o escribe. no obstante. Además. Estas propiedades están declaradas en la clase TObjGraf lo que significa que sus descendientes también las heredan. Y). La última instrucción. En realidad es como si se hiciera int CX = Cir1->FX. ya que cuando se accede para escritura a la propiedad (virtual) X en realidad se llama al método SetX(). }. Si se usara esta propiedad para escritura: Cir1->X = 100. no obstante. Si en Ppal. hay una propiedad virtual (pública) llamada X (resp. en su caso.cpp se usara esta propiedad para lectura: int CX = Cir1->X. Finalmente. Ancho = Alto = {read=GetAncho {read=GetAlto }.html (19 of 28) [27/02/2003 16:24:17] .

// Instanciacion del metodo virtual puro de // la clase TObjGraf }.} (void) {return(Lado). int _Radio=1). inline int GetAncho inline int GetAlto public: // Metodo constructor TCirculo (TPaintBox *_PaintBox.} Ahora.} int Lado. void Mostrar (void). añadimos (en ObjGraf. int _X=0. int _Lado=1).} (void) {return(Radio*2). TColor _Color=clBlack. (void) {return(Radio*2).Programación Orientada a Objetos en C++ //*************************************************/ // Definicion de la clase derivada TCirculo. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y descendientes. // Instanciacion del metodo virtual puro de // la clase TObjGraf }. int _Y=0.cpp) las funciones write de las propiedades virtuales X e Y: file:///D|/Manuales/intro/5. inline int GetAncho inline int GetAlto public: // Metodo constructor TCuadrado (TPaintBox * _PaintBox. void Mostrar (void). int _X=0. //*************************************************/ // Definicion de la clase derivada TCuadrado. TColor _Color=clBlack. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y descendientes.html (20 of 28) [27/02/2003 16:24:17] . int _Y=0. (void) {return(Lado). int Radio.

// No se puede llamar a los metodos virtuales puros FY = _Y. El resultado el el mismo que el mostrado en la figura 5. // Ajustar al margen izquierdo else if (_X > (PaintBox->Width .cpp: TObjGraf :: TObjGraf (TPaintBox *_PaintBox. // MUY IMPORTANTE: Estas tres lineas han cambiado: FX = _X. En este caso. TColor _Color. Ancho) desde un // constructor de la clase base. file:///D|/Manuales/intro/5. En ObjGraf.Ancho)) // Demasiado alta FX = PaintBox->Width .Alto)) // Demasiado alta FY = PaintBox->Height . // Ajustar al margen derecho else FX = _X. int _Y) { PaintBox = _PaintBox. int _X. el proyecto debe estar como se indica en el proyecto Ejemplo1. FColor = _Color.Alto. // (GetAncho. } En este punto. // Ajustar al margen inferior else FY = _Y. // Correcto: escribir sin modificar } Muy importante: Cambiamos el constructor de la clase TObjGraf porque no se puede llamar a los métodos virtuales puros de una propiedad virtual desde un constructor de una clase base.Programación Orientada a Objetos en C++ // Funciones de escritura de las propiedades virtuales X e Y void TObjGraf :: SetX (int _X) { if (_X < 0) // Coordenada negativa FX = 0. // Ajustar al margen superior else if (_Y > (PaintBox->Height . no se puede llamar a los métodos virtuales puros (GetAncho() y GetAlto()) de las propiedades virtuales (Ancho y Alto) desde el constructor de la clase base TObjGraf.html (21 of 28) [27/02/2003 16:24:17] . // Correcto: escribir sin modificar } void TObjGraf :: SetY (int _Y) { if (_Y < 0) // Coordenada negativa FY = 0. GetAlto) para fijar el valor de una // propiedad virtual (Alto.Ancho.4.

que en última instancia llaman al constructor de la clase base para establecer los valores de las propiedades reales FX. por: Cir1 = new TCirculo (PaintBox. Observar que la propiedad virtual X se usa para lectura y escritura. Cir2. FColor y PaintBox. -100.Programación Orientada a Objetos en C++ Experimentación con las propiedades virtuales. La línea anterior fija la coordenada X al valor 100. con coordenadas incorrectas no se corrigen ya que como el constructor de la clase base no puede utilizar la propiedad virtual X para escritura no se emplea el método SetX(). 2. clBlack. en la función FormCreate()de Ppal. La consecuencia es que si se crea un círculo.cppcambiar la línea: Cir1 = new TCirculo (PaintBox.html (22 of 28) [27/02/2003 16:24:17] . 30). Observar que el círculo negro no se muestra. Observar que el círculo negro tiene el valor 0 en la coordenada X: este valor se ha fijado a través del método de escritura SetX(). Cuad1 y Cuad2) se crean con sus correspondientes constructores. FY. por ejemplo. Un ejemplo más clarificador es cambiar la línea anterior por: if (Cir1->X < 0) Cir1->X = -200.7. Modificar la función PaintBoxPaint() de Ppal. Como demostración. 100. Los objetos gráficos (Cir1. clBlack. Los constructores no verifican coordenadas. 100. 1. Polimorfismo file:///D|/Manuales/intro/5. 100. 5. 30). Lectura/escritura a través de propiedades virtuales.cpp añadiendo esta línea al principio: if (Cir1->X < 0) Cir1->X = 100.

Por ejemplo. En ObjGraf.cpp: TObjGraf::TObjGraf (TObjGraf *ObjGraf) { PaintBox = ObjGraf->PaintBox. FX = ObjGraf->FX. Enlace dinámico: métodos virtuales.1. El compilador los considera como dos métodos distintos y aplicará cada uno de ellos en la situación apropiada. Clases: es al que se refiere normalmente el concepto de polimorfismo.2. Para ilustrar el polimorfismo.7. Como tenemos variables (punteros) que pueden contener objetos de distintas clases. TPelota. FColor = ObjGraf->Color. } 5. Una clase se puede comportar como cualquiera de sus antecesoras (en la asignación por ejemplo). el compilador no sabe qué tipo de objeto es al que realmente apunta la variable (en tiempo de compilación) por lo tanto hay retrasar el enlace a tiempo de ejecución. Puede darse de tres formas diferentes: q Funciones: sobrecarga. crearemos una nueva clase.html (23 of 28) [27/02/2003 16:24:17] . q q 5. podría sobrecargarse el constructor de la clase TObjGraf añadiendo un nuevo constructor de copia: En ObjGraf. El enlace dinámico es retrasar el enlace de una llamada a un método (función) al tiempo de ejecución. Polimorfismo en las clases y métodos virtuales.Programación Orientada a Objetos en C++ Es demostrar comportamientos distintos según la situación.Sobrecarga de funciones. para ser más precisos) es un círculo que tiene la capacidad de file:///D|/Manuales/intro/5.h: TObjGraf (TObjGraf *ObjGraf).7. Una pelota (un objeto de tipo TPelota. FY = ObjGraf->FY. Ocurre cuando en una clase existen dos métodos con idéntico nombre pero con distinta lista de parámetros. que derive de la clase TCirculo.

Programación Orientada a Objetos en C++ movimiento.html (24 of 28) [27/02/2003 16:24:17] . modificamos la declaración del método Mostrar() de la clase TCirculo para obligar a sus descendientes a implementar su propio método Mostrar(): basta con indicar que en el método Mostrar() de la clase TCirculo es virtual.h: //*************************************************/ // Definicion de la clase derivada TCirculo. Para implementar el movimiento de una pelota necesitamos incorporar nuevas propiedades y métodos propios a la clase TPelota. En ObjGraf. SE=5. el metodo Mostrar() se declara virtual. Ahora nos centramos en la nueva clase TPelota. E=4.. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { private: . por comodidad y claridad.4 E \ 5 SE file:///D|/Manuales/intro/5. public: .h: // Tipo definido por enumeracion para la direccion de TPelota. definimos un tipo por enumeración para la dirección del movimiento: En ObjGraf.. SO=9. O=8. en este momento nos interesa poner de manifiesto el polimorfismo.. N 2 | * | 1 S NE 6 / --.. // 2) Por no ser puro: puede llamarse a este metodo con objetos TCirculo. Antes.. lo que conseguimos a través del método Mostrar() asociado a la clase TPelota. NE=6. Sin embargo. aunque no es puro: // 1) Por ser virtual: cualquier clase que derive de TCirculo debe // tener su propio metodo Mostrar(). NO=10}. virtual void Mostrar (void). Antes. }. Codificacion: /* NO 10 \ O 8 --/ 9 SO */ enum TDireccion {S=1.. // Ahora. N=2. .

SetDireccion}. int _Y=0. int _Velocidad) : TCirculo (_PaintBox. _Y. // TPelota deriva de la clase TCirculo. que a su // vez deriva de la clase base TObjGraf /*****************************************************/ TPelota :: TPelota (TPaintBox *_PaintBox. int _Radio. FVelocidad}. GetDireccion. // Dir. en el eje X int FDirY. _Color. void Mover (void). int _Velocidad=5). // Velocidad del movimiento void TDireccion public: // Constructores TPelota (TPaintBox *_PaintBox. file:///D|/Manuales/intro/5. GetDireccion (void). _Radio) { Direccion = _Direccion.cpp: /*****************************************************/ // Metodos asociados a la clase derivada TPelota. __property int Velocidad = {read = write= __property TDireccion Direccion = {read = write= }. TColor _Color. TColor _Color=clBlack. void Borrar (void). TDireccion _Direccion. SetDireccion (TDireccion _Direccion). _X. TDireccion _Direccion=SE. FVelocidad.h: //*************************************************/ // Definicion de la clase derivada TPelota. int _Y. int _X. int _Radio=1. int _X=0. // TPelota deriva de la clase TCirculo.Programación Orientada a Objetos en C++ La declaración de la clase TPelota se hará en ObjGraf. // Otros metodos void Mostrar (void). que a su // vez deriva de la clase base TObjGraf //*************************************************/ class TPelota: public TCirculo { private: int FDirX. La implementación de los métodos propios de la clase TPelota se hará en ObjGraf. Velocidad = _Velocidad.html (25 of 28) [27/02/2003 16:24:17] . en el eje Y int FVelocidad. // Dir.

PaintBox->Canvas->Ellipse(X. El polimorfismo se va a manifestar invocando a la función Mostrar() para cada uno de esos objetos. _Dir = (TDireccion) ((FDirY == +1) ? 1 : ((FDirY == -1 ) ? 2 : 0)). Y. Y. FDirX = (_Dir & 4) ? +1 : ((_Dir & 8) ? -1 : 0). PaintBox->Canvas->Brush->Color = PaintBox->Color. file:///D|/Manuales/intro/5. return (_Dir). Y += FDirY * Velocidad. } void TPelota :: Mover (void) { Borrar (). Y+Radio*2). } TDireccion TPelota :: GetDireccion (void) { TDireccion _Dir.Programación Orientada a Objetos en C++ } // Instanciacion del metodo virtual puro de la clase TObjGraf // y virtual en TCirculo. que provocan diferentes acciones dependiendo del tipo de objetos al que se aplican. } void TPelota :: SetDireccion (TDireccion _Dir) { FDirY = (_Dir & 1) ? +1 : ((_Dir & 2) ? -1 : 0). void TPelota :: Mostrar (void) { PaintBox->Canvas->Pen->Color = clBlack. para ilustrar el polimorfismo nos basaremos en la existencia de diferentes métodos con el mismo nombre: Mostrar(). Mostrar (). // Observar la diferencia PaintBox->Canvas->Brush->Color = Color. _Dir = (TDireccion) (_Dir + (FDirX == +1) ? 4 : ((FDirX == -1 ) ? 8 :0)). X+Radio*2. X += FDirX * Velocidad. PaintBox->Canvas->Ellipse(X. Estos objetos van a ser referenciados (mediante punteros) desde un vector de objetos de tipo TObjGraf *. } // Otras funciones propias de TPelota void TPelota :: Borrar (void) { PaintBox->Canvas->Pen->Color = PaintBox->Color. X+Radio*2.html (26 of 28) [27/02/2003 16:24:17] . Y+Radio*2). } Finalmente. Vamos a crear dinámicamente cuatro objetos de diferentes clases.

// POLIMORFISMO En este punto. clGreen. (PaintBox. 150.cpp: //---------------------------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Objs = new TObjGraf * [4]. delete []Objs. clRed. 70.6. (PaintBox. } //---------------------------------------------------------------------= = = = new new new new TCirculo TCuadrado TCirculo TPelota (PaintBox. 120. 100. 40. i<4. Así. (PaintBox. i<4. 20). en Ppal. clBlack. Resultado del proyecto Ejemplo.cpp declararemos la variable global: TObjGraf **Objs. 25). que se interpreta como: Objs es un puntero a una zona de memoria que contendrá punteros a objetos de tipo TObjGraf. El resultado es el mostrado en la figura 5.html (27 of 28) [27/02/2003 16:24:17] . 45). 200. i++) Objs[i]->Mostrar(). i++) delete Objs[i]. 100. 210.bpr. Objs[0] Objs[1] Objs[2] Objs[3] } //---------------------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { for (int i=0.Programación Orientada a Objetos en C++ En Ppal. el proyecto debe estar como se indica en el proyecto Ejemplo2. 30).6: Figura 5. clYellow. } //---------------------------------------------------------------------void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender) { for (int i=0. file:///D|/Manuales/intro/5.

Programación Orientada a Objetos en C++ Página principal © Francisco Cortijo Bon file:///D|/Manuales/intro/5.html (28 of 28) [27/02/2003 16:24:17] .

Captura de excepciones. Por lo tanto lanza una excepción. lo cual complica enormemente un sencillo algoritmo. La correcta programación de excepciones significa diseñar los algoritmos pensando únicamente en la forma habitual en la que deben ejecutarse. *p3. file:///D|/Manuales/intro/6. 6. lo habitual es que exista suficiente memoria disponible y no haya ningún problema.4. Pero si queremos realizar una aplicación robusta deberemos de tener en cuenta la eventualidad de que dicha memoria no se conceda.1. Cuando solicitamos memoria al sistema. En este momento termina la ejecución del método más interno y se retorna inmediatamente al método llamador.2.Tratamiento de excepciones Curso de C++ Builder Tratamiento de excepciones q q q q q 6. Lanzamiento de excepciones. Excepciones no tratadas. Veamos una función escrita en C que simplemente intenta asignar memoria dinámica para tres enteros: void SinExcepciones (void) { int *p1.html (1 of 16) [27/02/2003 16:24:19] . *p2. robusto y fácil de mantener. Este método más interno se encuentra en una situación que puede considerarse como excepcional. 6. El método llamador debe capturar la excepción y la trata. la calidad de las aplicaciones que se desarrollen aumentará considerablemente. De esta manera se consigue un diseño mucho más estructurado. Las excepciones son situaciones anómalas que requieren un tratamiento especial. legible.5. 6. Especificación de excepciones. Ejemplo. Excepciones de la VCL. ¡¡No tienen por qué ser errores!! Si se consigue dominar su programación. 6. manejando las situaciones extraordinarias a parte.3. El funcionamiento general del mecanismo de lanzamiento y tratamiento de excepciones es el siguiente: q q q q Existe un método que invoca la ejecución de otro. Parte del tratamiento de la excepción puede ser volver a lanzarla al método que invocó a este.

abort(). abort(). y en particular. Si alguna de las instrucciones del bloque try provocara una excepción el flujo del programa se dirige al final de ese bloque.. } catch(.. *p3. buscando un bloque catch que capture la excepción (si no lo encontrara. if (p3 == NULL) { printf("No hay suficiente memoria"). Las instrucciones que pueden provocar el lanzamiento de una excepción (la "zona crítica") se encierran en un bloque try.) captura cualquier excepción. p2 = new int. printf("No hay suficiente memoria"). en este caso. } p3 = (int*) malloc(sizeof(int)). p3 = new int. abort(). try { p1 = new int. *p2.html (2 of 16) [27/02/2003 16:24:19] . la instrucción catch(...){ // Comportamiento excepcional. // Comportamiento normal. } p2 = (int*) malloc(sizeof(int)).Tratamiento de excepciones p1 = (int*) malloc(sizeof(int)). file:///D|/Manuales/intro/6. En este caso. el programa terminaría -ver sección 6. abort(). El tratamiento que se efectúa es. if (p1 == NULL) { printf("No hay suficiente memoria"). la excepción bad_alloc. } } El ANSI C++ especifica que si una instrucción new falla (no hay memoria disponible) debe lanzar la excepción bad_alloc (definida en el fichero de cabecera new).4-). if (p2 == NULL) { printf("No hay suficiente memoria"). } } Si programamos en C++ y hacemos uso de las excepciones: void ConExcepciones (void) { int *p1. mostrar un mensaje de error y terminar la ejecución del programa.

""). return (0). Cociente. // // // // Leer dividendo y convertirlo.h> #pragma hdrstop //---------------------------------------------------------------WINAPI WinMain(HINSTANCE.1. "Dividendo". recoger y tratar la excepción. LPSTR. } //---------------------------------------------------------------- Cuando se produce la excepción. introducir la siguiente modificación: file:///D|/Manuales/intro/6. Si el divisor es cero. Leer divisor y convertirlo. Para proteger la instrucción crítica. //---------------------------------------------------------------#include <vcl. al no estar tratada por el programa.Tratamiento de excepciones Ejemplo. // Calcular cociente. Zona critica: peligro si Divisor == 0 Cociente = Dividendo / Divisor.html (3 of 16) [27/02/2003 16:24:19] . se intenta realizar una división por cero y el programa lanza una excepción de división por cero (EZeroDivide). Divisor. // Leer datos de entrada: dividendo y divisor Valor = InputBox ("División". // Mostrar el resultado ShowMessage ("Cociente = " + AnsiString(Cociente)). int) { AnsiString Valor. ""). Divisor = StrToFloat (Valor). Dividendo = StrToFloat (Valor). Valor = InputBox ("División". HINSTANCE. El siguiente programa (proyecto Division) lee dos valores y calcula el cociente entre ambos. el entorno se hace cargo de ella y muestra la siguiente ventana: Figura 6. Ventana de error que surge debido a una excepción EDivByZero no tratada. "Divisor". float Dividendo.

Tratamiento de excepciones try { Cociente = Dividendo / Divisor.").3. Ventana resultante de la gestión de la excepción..) { ShowMessage ("El divisor no puede ser cero.2. al ejecutar el programa e intoducir el valor 0 como divisor se muestra la ventana mostrada en la figura 6. file:///D|/Manuales/intro/6. } Para ceder el control de la gestión de excepciones a nuestro programa debemos desabilitar la opción por la que el entorno integrado gestiona las interrupciones e indicar que se van a gestionar por el programa: seleccionaremos Tools | Debuggber Options y abriremos la carpeta OS Exceptions para dejarla como se indica en la figura 6. Ahora.. ShowMessage ("Cociente = " + AnsiString(Cociente)).html (4 of 16) [27/02/2003 16:24:19] .3 Figura 6. Ventana Debugger Options Con esto indicamos al depurador de C++ Builder que nuestro programa se encargará de manejar las excepciones C++ que ocurran. Figura 6. } catch (.2.

Lanzamiento de excepciones El lanzamiento de una excepción se realiza llamando a la función throw().2. En ObjGraf.Tratamiento de excepciones 6. se le pueden añadir. Suele ser muy útil crear clases de excepciones propias para controlar las situaciones anómalas de nuestra aplicación. Por ejemplo. Cuando se lanza una excepción.h: //*************************************************/ // Definicion de la clase EFueraRango // Clase de excepcion por entrar en "fuera de rango": // salirse de los limites del PaintBox al calcular // las nuevas coordenadas de dibujo de la pelota. no tiene ningún miembro (propiedades o métodos). //*************************************************/ class EFueraRango {}. Aunque en el ejemplo anterior la clase creada para la excepción. si tuvieramos un método que lanzara una excepción por falta de memoria. Por ejemplo. que podrá ser utilizada por la sección de código que lo trate. y precisamente será dicho objeto la excepción en sí. podría ser interesante que incorporara una propiedad que indicara cual era el máximo de memoria disponible cuando se lanzó la excepción. en file:///D|/Manuales/intro/6. que sirve para enumerar. en realidad lo que se hace es crear un objeto de la clase que se le indique a throw(). Éstos servirán para poder incorporar información en el objeto excepción.html (5 of 16) [27/02/2003 16:24:19] . 6. y no por T como el resto de las clases. Especificación de excepciones C++ cuenta con una característica denominada especificación de excepciones. en C++ Builder existe la convención de que su nombre empiece por la letra E. acerca de la situación en la que se produjo la excepción.1. Con lo que podríamos lanzar una excepción de la siguiente manera: throw EfueraRango(). Nota: Aunque las excepciones sean clases.

// Metodo virtual puro virtual int GetAlto (void) = 0.html (6 of 16) [27/02/2003 16:24:19] .. Si queremos que un método pueda lanzar un determinado tipo de excepción deberemos especificarlo de esta manera. // Ajustar al margen derecho throw EFueraRango(). int FY.h. // Correcto: escribir sin modificar } void TObjGraf :: SetY (int _Y) throw (EFueraRango) { if (_Y < 0) { // Coordenada negativa FY = 0.Alto.Ancho)) { // Demasiado alta FX = PaintBox->Width . // Lanzar excepcion file:///D|/Manuales/intro/6. En ObjGraf.crean un (int _Y) throw (EFueraRango).Alto)) { // Demasiado alta FY = PaintBox->Height . // Metodo virtual puro . En ObjGraf. las excepciones que puede lanzar un método.. en la clase TObjGraf: //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int FX. // Ajustar al margen inferior throw EFueraRango(). // Lanzar excepcion } else if (_X > (PaintBox->Width .Tratamiento de excepciones una declaración. // Ajustar al margen izquierdo throw EFueraRango().Ancho. // Lanzar excepcion } else if (_Y > (PaintBox->Height . void SetX void SetY EFueraRango (int _X) throw (EFueraRango).cpp: // Funciones de escritura de las propiedades virtuales X e Y void TObjGraf :: SetX (int _X) throw (EFueraRango) { if (_X < 0) { // Coordenada negativa FX = 0. // Ajustar al margen superior throw EFueraRango(). // Si hay problemas. // objeto de clase virtual int GetAncho (void) = 0. // Lanzar excepcion } else FX = _X.

) se capturará cualquier excepción.. } catch (EFueraRango) { FDirY = -FDirY. En ObjGraf. try { <bloque de instrucciones críticas> } catch (<tipo excepción1> <variable1>) { <manejador 1> } catch (<tipo excepción2> <variable2>) { .Tratamiento de excepciones } else FY = _Y.cpp: void TPelota :: Mover (void) { Borrar (). }. La excepción no tiene porqué lanzarse explícitamente en el bloque try sino que puede ser consecuencia de la ejecución de una función que se ha llamado dentro de ese bloque. try { X += FDirX * Velocidad.. en el bloque catch. } catch (EFueraRango) { FDirX = -FDirX.. } Podemos especificar tantos bloques catch para un bloque try como deseemos. } file:///D|/Manuales/intro/6. Captura de excepciones El bloque susceptible de producir alguna excepción ("zona crítica") se encierra en un bloque try. // Correcto: escribir sin modificar } 6..html (7 of 16) [27/02/2003 16:24:19] . Si se especifica catch (. }. Mostrar (). try { Y += FDirY * Velocidad. la captura (discriminación de la excepción que se ha producido) se efectúa en una instrucción catch y su procesamiento se realiza a continuación.3. en el momento que ocurra una excepción se ejecutará el bloque catch cuya clase concuerde con la de la excepción.

Modificar las funciones FormCreate() y FormDestroy() para que queden: //---------------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Pelota = new TPelota (PaintBox. donde se observa que es el método SetX() el que puede provocar el lanzamiento de la excepción. seleccionar Tools | Debuggber Options. la instrucción "crítica": X += FDirX * Velocidad. se traduce a: X = X + FDirX * Velocidad.cpp: 1. } //---------------------------------------------------------- NOTA: El entorno debe estar configurado para que el programa gestione las excepciones. Si no fuera sí. En el evento OnTimer poner: //---------------------------------------------------------void __fastcall TPpalFrm::Timer1Timer(TObject *Sender) { Pelota->Mover(). 120. y como X es una propiedad virtual. abrir la carpeta OS Exceptions y dejarla como se indica en file:///D|/Manuales/intro/6.Tratamiento de excepciones En este ejemplo. clYellow. Eliminar el manejador del evento OnPaint del componente PaintBox (borrando su cuerpo solamente). 2. Dejar únicamente la siguiente declaración global: TPelota *Pelota. en realidad se trata de hacer: SetX (FX + FDirX * Velocidad). 4. } 3. 70.html (8 of 16) [27/02/2003 16:24:19] . no el entorno. Añadir a PpalFrm un TTimer (Carpeta System) y fijar Interval=100. En Ppal. 25). } //---------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete Pelota.

Excepciones de la VCL Si se utilizan componentes de la VCL en las aplicaciones. la VCL llevará a cabo un tratamiento por defecto. entonces se llama a la función unexpected() la cual por defecto llama a terminate(). de E/S de archivos. de conversiones de tipos y otras file:///D|/Manuales/intro/6. Pero de igual manera que con terminate() podemos definir nuestra propia función unexpected() con set_unexpected(). Si no se realiza un tratamiento de la excepción. Pero se puede definir nuestra propia función terminate() con la orden set_terminate().5.4. se llamará a la función terminate(). Excepciones no tratadas Si una excepción que ha sido lanzada no encuentra un manejador apropiado. El resultado es el mostrado en la figura 6. aparece un mensaje que describe el tipo de error que se ha producido.2. El motivo es que las excepciones están integradas en numerosas clases y se lanzan automáticamente cuando se presenta un situación no esperada. 6.4: Figura 6.Tratamiento de excepciones la figura 6.4. la cual por defecto realiza un abort(). En este punto. el proyecto debe estar como se indica en el proyecto Ejemplo3.html (9 of 16) [27/02/2003 16:24:19] . Algo muy parecido ocurre si un método lanza una excepción de un tipo que no tiene listado en su especificación de excepciones. C++ Builder incorpora un extenso conjunto de clases de excepción integradas que permiten tratar automáticamente errores de división por cero. 6. Dos instantes del movimiento de la pelota. Clases de Excepciones. Normalmente. 1. es necesario comprender el mecanismo de tratamiento de excepciones de la VCL.

Las excepciones pueden pasarse a un bloque catch que toma un parámetro de tipo Exception. 2. Todas las clases excepción de VCL se derivan de un objeto raíz denominado Exception. HINSTANCE. Emplear la siguiente sintaxis para capturar las excepciones de la VCL: catch (const exception_class & exception_variable) Se especifica la clase de excepción que se desea capturar y se proporciona una variable por medio de la cual hacer referencia a la excepción. pasarse a los constructores y recuperarse mediante la propiedad Message.5 Figura 6.Tratamiento de excepciones muchas situaciones anómalas. } catch (const Exception & E) { ShowMessage("Clase de la excepción capturada: " + AnsiString(E. Todas las excepciones que descienden de Exception cuentan con un mensaje que puede presentarse en pantalla. } //-------------------------------------------------------- La sentencia throw del ejemplo anterior crea una instancia de la clase Exception y llama a su constructor.Message). file:///D|/Manuales/intro/6.ClassName()) + "\nMensaje: " + E. Ejemplo de lanzamiento y captura de excepción VCL. } return (0).h> #pragma hdrstop //-------------------------------------------------------WINAPI WinMain(HINSTANCE. int) { try { throw Exception("Mi excepción VCL"). LPSTR. //-------------------------------------------------------#include <vcl. como todas las clases de la VCL deben de localizarse en el heap (creación dinámica). Por ejemplo. que encapsula las propiedades y métodos fundamentales de todas las excepciones por parte de las aplicaciones. Las excepciones de tipo VCL deben lanzarse con sintaxis "por valor".html (10 of 16) [27/02/2003 16:24:19] . El resultado de la ejecución del programa anterior es el mostrado en la figura 6. por lo que se deberá tener en cuenta lo siguiente: r r Las clases de excepción de tipo VCL solamente pueden capturarse por puntero o por referencia (preferible). Tratamiento de Excepciones de la VCL Las excepciones de tipo VCL.5.

El siguiente programa (proyecto Division2) es una ampliación del proyecto Division. Veamos una selección de las clases de excepción más utilizadas en C++ Builder. las excepciones de la VCL si suelen ser errores. LPSTR. Clases de excepción típicas Aunque las excepciones no tienen porque indicar un error en la ejecución de una aplicación. Ejemplo. Aunque todas estas clases funcionen de la misma manera. HINSTANCE. respectivamente).html (11 of 16) [27/02/2003 16:24:19] . Indica un error de impresión. Captura errores de división por cero (para división entera y real. más que capturar cualquier excepción. Clase EAccessViolation EDatabaseError EDBEditError EDivByZero EZeroDivide EInOutError EInvalidPointer EPrinterError Descripción Error de acceso a memoria. Datos incompatibles con una máscara especificada.Tratamiento de excepciones 3. Especifica un error de acceso a base de datos.h> #pragma hdrstop //--------------------------------------------------------------------WINAPI WinMain(HINSTANCE. En éste se van a discriminar distintas excepciones. Operaciones no válidas con punteros. int) { file:///D|/Manuales/intro/6. //--------------------------------------------------------------------#include <vcl. cada una de ellas tiene particularidades derivadas de la excepción concreta que indican. Representa un error de E/S de archivo.

while (sigo) { try { // Leer dividendo y convertirlo Valor =InputBox ("Division".html (12 of 16) [27/02/2003 16:24:19] . } } // try // Se captura si se ha realizado una división por cero. float sigo = true.Message). Divisor. Dividendo = StrToFloat (Valor). Cociente = (Dividendo / Divisor). catch (Exception & e) { ShowMessage ("Se produjo una excepción: "+AnsiString(e. file:///D|/Manuales/intro/6.6. if (Dividendo == 0) sigo = false.Tratamiento de excepciones AnsiString Valor.ClassName())+ "\n " + e. "Dividendo". } } // while sigo return (0). else { // Leer divisor y convertirlo Valor =InputBox ("Division". "")."). catch (EZeroDivide & ) { ShowMessage ("El divisor no puede ser cero. } //--------------------------------------------------------------------- Si se intenta realizar una division por cero el resultado es el que se indica en la figura 6. "Divisor".6: Figura 6. ShowMessage ("Cociente = " + AnsiString(Cociente)). Divisor = StrToFloat (Valor). } // Más general: se alcanza si no se captura la anterior. float Dividendo. Ejemplo de división por cero. ""). Cociente.

Ejemplos de desbordamiento: A) En la entrada de datos y B) En el cálculo del cociente. si se produjera algún tipo de desbordamiento también podría controlarse con el último bloque catch (ver figura 6. file:///D|/Manuales/intro/6. Figura 6. Figura 6. Ejemplo de entrada incorrecta. la función StrToFloat() lanzaría una excepción EConvertError que se captura con el último bloque catch (ver figura 6.html (13 of 16) [27/02/2003 16:24:19] .8). Es más.7).Tratamiento de excepciones Si se introdujera un dato incorrecto.8.7.

Message). si añadimos el siguiente bloque catch entre los dos anteriores: catch (EMathError & e) { ShowMessage ("Operación no válida: " + e. } file:///D|/Manuales/intro/6.9. Figura 6. Otra manera de capturar la división por cero. Para finalizar.Tratamiento de excepciones Si quitáramos el primer bloque catch podría capturarse la interrupción EZeroDivide (ver figura 6.9).html (14 of 16) [27/02/2003 16:24:19] .

file:///D|/Manuales/intro/6. EJERCICIO: Reproductor de sonidos. EOverflow. Otra manera de capturar desbordamientos: A) En la entrada de datos y B) En el cálculo del cociente.10. ..10: Figura 6.) el alumno deberá interpretar el resultado de la figura 6.Tratamiento de excepciones y consideramos (una parte de) la jerarquía de clases de excepciones: TObject-->Exception-->EExternal-->EMathError-->(EZeroDivide..html (15 of 16) [27/02/2003 16:24:19] .

Tratamiento de excepciones Página principal © Francisco Cortijo Bon file:///D|/Manuales/intro/6.html (16 of 16) [27/02/2003 16:24:19] .

CPP //---------------------------------------------------------------------- #include <vcl. Application->Run(). } return 0. EJEMPLO. USEUNIT("ObjGraf. //---------------------------------------------------------------------WINAPI WinMain(HINSTANCE.res").html (1 of 10) [27/02/2003 16:24:20] . } //---------------------------------------------------------------------- PPAL. int) { try { Application->Initialize(). USEFORM("Ppal. Application->CreateForm(__classid(TPpalFrm).cpp").H file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. PpalFrm).Ejemplo 3 Curso de C++ Builder Ejemplo 3 Corresponde al final de la sección 7. LPSTR.h> #pragma hdrstop USERES("Ejemplo3.cpp".OOP . En este ejemplo se muestra el tratamiento de excepciones para el movimiento de la pelota. HINSTANCE. } catch (Exception &exception) { Application->ShowException(&exception). &PpalFrm).

hpp> #include "ObjGraf.hpp> <StdCtrls. private: // User declarations TPelota *Pelota.Ejemplo 3 //---------------------------------------------------------------------#ifndef PpalH #define PpalH //---------------------------------------------------------------------#include #include #include #include #include <Classes. TBitBtn *BotonSalir. }. void __fastcall BotonSalirClick(TObject *Sender).hpp> <Controls.hpp> <Forms. void __fastcall FormDestroy(TObject *Sender).hpp> //---------------------------------------------------------------------class TPpalFrm : public TForm { __published: // IDE-managed Components TPaintBox *PaintBox.hpp> <ExtCtrls. //---------------------------------------------------------------------#endif PPAL. public: // User declarations __fastcall TPpalFrm(TComponent* Owner).h> #pragma hdrstop file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. TTimer *Timer1. void __fastcall FormCreate(TObject *Sender).html (2 of 10) [27/02/2003 16:24:20] .OOP . void __fastcall Timer1Timer(TObject *Sender).h" #include <Buttons.CPP //---------------------------------------------------------------------#include <vcl. //---------------------------------------------------------------------extern PACKAGE TPpalFrm *PpalFrm.

120.H //---------------------------------------------------------------------#ifndef ObjGrafH #define ObjGrafH file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. clYellow. 70. } //---------------------------------------------------------------------- OBJGRAF.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*. 25).html (3 of 10) [27/02/2003 16:24:20] . } //---------------------------------------------------------------------void __fastcall TPpalFrm::BotonSalirClick(TObject *Sender) { Application->Terminate().dfm" TPpalFrm *PpalFrm. //---------------------------------------------------------------------__fastcall TPpalFrm::TPpalFrm(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Pelota = new TPelota (PaintBox.OOP .Ejemplo 3 #include "Ppal. } //---------------------------------------------------------------------void __fastcall TPpalFrm::Timer1Timer(TObject *Sender) { Pelota->Mover(). } //---------------------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete Pelota.

// Metodo virtual puro virtual int GetAlto (void) = 0. {read=FColor. // Si hay problemas. // objeto de clase virtual int GetAncho (void) = 0. {read=GetAncho }. {read=FY. *PaintBox. int _X=0.Ejemplo 3 //*************************************************/ // Definicion de la clase EFueraRango // Clase de excepcion por entrar en "fuera de rango": // salirse de los limites del PaintBox al calcular // las nuevas coordenadas de dibujo de la pelota. int int TColor int int X Y Color Ancho Alto = = = = = {read=FX. int FY. TObjGraf (TObjGraf *ObjGraf).crean un (int _Y) throw (EFueraRango). write=SetX }. // Metodo virtual puro protected: TColor TPaintBox public: // Constructores de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox. //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int FX.OOP . // Metodo virtual puro __property __property __property __property __property }. //*************************************************/ class EFueraRango {}. int _Y=0). FColor. // Otros metodos virtual void Mostrar (void) = 0.html (4 of 10) [27/02/2003 16:24:20] . TColor _Color=clBlack. write=SetY }. void SetX void SetY EFueraRango (int _X) throw (EFueraRango). write=FColor}. file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. {read=GetAlto }.

que a su // vez deriva de la clase base TObjGraf //*************************************************/ enum TDireccion {S=1. // Instanciacion del metodo virtual puro de // la clase TObjGraf __property int Radio = }. write=FRadio}. NO=10}. O=8. SO=9.html (5 of 10) [27/02/2003 16:24:20] .} //*************************************************/ // Definicion de la clase derivada TPelota.4 E \ \ 5 SE file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. // TPelota deriva de la clase TCirculo. // Otros metodos void Mostrar (void). {read=FRadio. inline int GetAncho inline int GetAlto public: // Constructores TCirculo (TPaintBox *_PaintBox.OOP .} (void) {return(FRadio*2). E=4. (void) {return(FRadio*2). int _Radio=1). NE=6. N=2. SE=5. int _Y=0. int _X=0. /* Tipo definido por enumeracion para la direccion de TPelota La codificacion es: NO 10 \ \ O 8 ---/ / 9 SO */ N 2 | | | | 1 S NE 6 / / ---. TColor _Color=clBlack.Ejemplo 3 //*************************************************/ // Definicion de la clase derivada TCirculo. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { private: int FRadio.

int _X=0. int _Velocidad=5).} (void) {return(FLado). SetDireccion (TDireccion _Direccion). TDireccion _Direccion=SE. int FDirY. write=SetDireccion}. void Mover (void). // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { private: int FLado. void TDireccion public : // Constructores TPelota (TPaintBox *_PaintBox. // Otros metodos void Mostrar (void). write=FVelocidad}. void Borrar (void). __property TDireccion Direccion = {read = GetDireccion. TColor _Color=clBlack. GetDireccion (void). //*************************************************/ // Definicion de la clase derivada TCuadrado. int FVelocidad. int _X=0. TColor _Color=clBlack. int _Y=0.Ejemplo 3 class TPelota: public TCirculo { private: int FDirX. inline int GetAncho inline int GetAlto public: // Constructores TCuadrado (TPaintBox *_PaintBox.html (6 of 10) [27/02/2003 16:24:20] . // Otros metodos (void) {return(FLado). int _Lado=1). int _Radio=1. __property int Velocidad = {read = FVelocidad.} file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. int _Y=0.OOP . }.

h" //---------------------------------------------------------------------#pragma package(smart_init) /*****************************************************/ // Metodos asociados a la clase base TObjGraf /*****************************************************/ // Constructores TObjGraf :: TObjGraf (TPaintBox *_PaintBox. FColor = _Color. FX = _X. TColor _Color. } // Funciones de escritura de las propiedades virtuales X e Y void TObjGraf :: SetX (int _X) throw (EFueraRango) file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3.h> #pragma hdrstop #include "ObjGraf. write=FLado}. int _X. FColor = ObjGraf->Color. int _Y) { PaintBox = _PaintBox. } TObjGraf :: TObjGraf (TObjGraf *ObjGraf) { PaintBox = ObjGraf->PaintBox. // Instanciacion del metodo virtual puro de // la clase TObjGraf __property int Lado = }. FY = _Y. OBJGRAF. FX = ObjGraf->FX.html (7 of 10) [27/02/2003 16:24:20] .CPP //---------------------------------------------------------------------#include <vcl. //---------------------------------------------------------------------#endif {read=FLado. FY = ObjGraf->FY.OOP .Ejemplo 3 void Mostrar (void).

} else FY = _Y. int _X. PaintBox->Canvas->Ellipse(X. int _Y. _X. TColor _Color.Ancho)) { FX = PaintBox->Width . throw EFueraRango(). /*****************************************************/ TCirculo :: TCirculo (TPaintBox *_PaintBox.html (8 of 10) [27/02/2003 16:24:20] .Ancho. Y+Radio*2). } else FX = _X.Ejemplo 3 { if (_X < 0) { FX = 0. _Color. int _Radio) : TObjGraf (_PaintBox.Alto)) { FY = PaintBox->Height . X+Radio*2. throw EFueraRango().Alto. throw EFueraRango(). _Y) { Radio = _Radio. } void TObjGraf :: SetY (int _Y) throw (EFueraRango) { if (_Y < 0) { FY = 0. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCirculo :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. } else if (_Y > (PaintBox->Height . } /*****************************************************/ file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. throw EFueraRango().OOP . PaintBox->Canvas->Brush->Color = Color. // TCirculo deriva de la clase base TObjGraf. } else if (_X > (PaintBox->Width . Y. } /*****************************************************/ // Metodos asociados a la clase derivada TCirculo.

} void TPelota :: Mover (void) { Borrar (). _X. try { X += FDirX * Velocidad. PaintBox->Canvas->Ellipse(X. }. Y+Radio*2). int _Radio. Y. } file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. X+Radio*2. } catch (EFueraRango) { FDirX = -FDirX. Y+Radio*2). } // Otras funcione propias de TPelota void TPelota :: Borrar (void) { PaintBox->Canvas->Pen->Color = clBtnFace. } catch (EFueraRango) { FDirY = -FDirY. Velocidad = _Velocidad. PaintBox->Canvas->Ellipse(X. // PaintBox->Color.OOP . try { Y += FDirY * Velocidad. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TPelota :: Mostrar (void) { PaintBox->Canvas->Pen->Color = clBlack. Y. _Color. PaintBox->Canvas->Brush->Color = Color.html (9 of 10) [27/02/2003 16:24:20] . PaintBox->Canvas->Brush->Color = clBtnFace. TDireccion _Direccion. // TPelota deriva de la clase TCirculo. X+Radio*2. _Y. int _Y. int _Velocidad) : TCirculo (_PaintBox. }. TColor _Color.Ejemplo 3 // Metodos asociados a la clase derivada TPelota. que a su // vez deriva de la clase base TObjGraf /*****************************************************/ TPelota :: TPelota (TPaintBox *_PaintBox. Mostrar (). int _X. _Radio) { Direccion = _Direccion. //PaintBox->Color.

_X. TColor _Color. _Color. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCuadrado :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color.OOP . _Dir = (TDireccion) (_Dir + (FDirX == +1) ? 4 :((FDirX == -1 )? 8:0)). X+Lado. _Y) { Lado = _Lado. int _Lado) : TObjGraf (_PaintBox. Y+Lado).Ejemplo 3 void TPelota :: SetDireccion (TDireccion _Dir) { FDirY = (_Dir & 1) ? +1 : ((_Dir & 2) ? -1 : 0). _Dir = (TDireccion) ((FDirY == +1) ? 1 : ((FDirY == -1 ) ? 2 : 0)). // TCuadrado deriva de la clase base TObjGraf. return (_Dir). FDirX = (_Dir & 4) ? +1 : ((_Dir & 8) ? -1 : 0). Y. PaintBox->Canvas->Brush->Color = Color. PaintBox->Canvas->Rectangle(X. /*****************************************************/ TCuadrado :: TCuadrado (TPaintBox *_PaintBox. } /*****************************************************/ // Metodos asociados a la clase derivada TCuadrado.html (10 of 10) [27/02/2003 16:24:20] . } TDireccion TPelota :: GetDireccion (void) { TDireccion _Dir. } Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/oop/Ejemplo3. int _Y. int _X.

ErrorBtn y OtrosBtn con el texto (Caption) indicado en la figura anterior. Guardar proyecto: Salvar Unit1. Un control MediaPlayer (pestaña System) no visible (Visible=false). 3. Un botón BitBtn para terminar. una nueva aplicación ( File | New Application). file:///D|/Manuales/intro/ejemplos/Sonidos/index. 1.bpr 2. Crear y configurar el proyecto. Utilizaremos la gestión de excepciones para controlar la correcta ejecución del programa. pinchar el siguiente enlace: En primer lugar. Para más información.Ejemplos .bpr como Sonidos.Sonidos Curso de C++ Builder Sonidos En este ejemplo se crará un formulario que contendrá un componente MediaPlayer que servirá para reproducir ficheros . Configurar el formulario. crear el directorio Sonidos.html (1 of 4) [27/02/2003 16:24:20] . si procede. MSSoundBtn. 2. y.cpp y Project1. Configurar el formulario para que tenga el aspecto mostrado en la figura siguiente: Cambiar el título (Caption por Sonidos) y añadir los siguientes componentes: 1.cpp como Ppal.WAV. Cuatro botones normales (Button) llamados (Name): LogoffBtn.

MediaPlayer1->Close(). } } //-------------------------------------------------------------void __fastcall TForm1::MSSoundBtnClick(TObject *Sender) { MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\The Microsoft Sound. La gestión de las interrupciones capturadas se realiza con una función común cuyo prototipo es: void Error (AnsiString & name. try { MediaPlayer1->Open(). Escribir los gestores de eventos asociados a la pulsación de los botones. MediaPlayer1->Close().Sonidos 4.cpp. MediaPlayer1->Play(). file:///D|/Manuales/intro/ejemplos/Sonidos/index. e). Un cuadro de diálogo OpenDialog (pestaña Dialogs). } } //-------------------------------------------------------------void __fastcall TForm1::ErrorBtnClick(TObject *Sender) { MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\NoEsta.html (2 of 4) [27/02/2003 16:24:20] . Exception & e).wav". MediaPlayer1->Wait = true. } catch (Exception & e) { Error (MediaPlayer1->FileName. try { MediaPlayer1->Open(). que se escribirá por encima de todas las funciones de Ppal.wav". MediaPlayer1->Wait = true. e). los gestores de los eventos OnClick asociados a los botones serán los siguientes: //-------------------------------------------------------------void __fastcall TForm1::LogoffBtnClick(TObject *Sender) { MediaPlayer1->FileName = "C:\\WINDOWS\\MEDIA\\Logoff.wav". Así. 3. } catch (Exception & e) { Error (MediaPlayer1->FileName. MediaPlayer1->Wait = true. try { MediaPlayer1->Open().Ejemplos . MediaPlayer1->Play(). MediaPlayer1->Play().

wav) | *. try { MediaPlayer1->Open(). e).Ejemplos . if (OpenDialog1->Execute()) { MediaPlayer1->FileName = OpenDialog1->FileName. MediaPlayer1->Wait = true.wav aparece la siguiente ventana: file:///D|/Manuales/intro/ejemplos/Sonidos/index. Exception & e) { ShowMessage ("Fallo en la reproducción del fichero de sonido: " + name + "\nExcepción: " + AnsiString(e. si se pulsa en el botón Error (se supone que el fichero de sonido que se quiere reproducir no existe) aparece la siguiente ventana: En cambio.Sonidos MediaPlayer1->Close(). } //-------------------------------------------------------------- Cuando se ejecuta este programa. } } // if (OpenDialog1->Execute()) } //-------------------------------------------------------------void Error (AnsiString & name.ClassName()) + "\nDetalles: " + AnsiString(e. } } //-------------------------------------------------------------void __fastcall TForm1::OtrosBtnClick(TObject *Sender) { OpenDialog1->Title = "Abrir un fichero de sonido". MediaPlayer1->Play(). si se quiere reproducir un fichero cuyo formato no sea .Message)).WAV".html (3 of 4) [27/02/2003 16:24:20] . OpenDialog1->InitialDir = "C:\\WINDOWS". OpenDialog1->Filter = "Ficheros de sonido (*. MediaPlayer1->Close(). } catch (Exception & e) { Error (MediaPlayer1->FileName. } catch (Exception & e) { Error (MediaPlayer1->FileName. e).

html (4 of 4) [27/02/2003 16:24:20] .Sonidos Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/Sonidos/index.Ejemplos .

C++ Builder Curso de C++ Builder Programación con Hebras Introducción q ¿Por qué usar hebras? La clase TThread q q q Creación de hebras Liberación de hebras Prioridad de una hebra Ejecución de hebras q q q El método Execute() Variables locales a las hebras Control de la ejecución de una hebra: Suspend. Resume & Terminate Coordinación entre hebras q Uso de recursos compartidos r r r La hebra principal de la VCL Bloqueo de objetos Secciones críticas q Sincronización entre hebras r Esperar la finalización de una hebra file:///D|/Manuales/threads/index.html (1 of 2) [27/02/2003 16:24:20] .

html (2 of 2) [27/02/2003 16:24:20] .C++ Builder r Esperar a que se complete una tarea Ejemplos Página principal © Fernando Berzal Galiano file:///D|/Manuales/threads/index.

Con varias hebras. podemos aprovechar los períodos de inactividad del sistema. Consideraciones: q q q q Cada hebra supone una carga adicional al sistema. el programa debe detener completamente la ejecución mientras espera a que se realice cada tarea. La depuración de las aplicaciones es difícil. Ejemplo: Supongamos que nuestra aplicación tiene que ocuparse de la realización de copias de seguridad de los datos con los que trabaja.C++ Builder Curso de C++ Builder Programación con Hebras Introducción Una aplicación multihebra es una aplicación que contiene varías vías simultáneas de ejecución. Con una única hebra tendríamos que programar las copias de seguridad fuera del horario habitual de trabajo (¿y si tiene que funcionar las 24 horas del día?).html (1 of 2) [27/02/2003 16:24:21] . ¿Por qué usar Hebras? El uso de hebras (de paralelismo. en general) proporciona una serie de ventajas frente a las limitaciones de los sistemas monotarea. Las hebras han de coordinarse de algún modo. El diseño de aplicaciones multihebra es complejo. La CPU permanece ocupada file:///D|/Manuales/threads/introduction. Aprovechamiento de los recursos del sistema Cuando se utiliza una sola hebra.

Establecimiento de prioridades Como es lógico. Si se utilizan varias hebras.C++ Builder completamente (o inactiva) hasta que el proceso actual termine. Estructuración: Paralelismo implícito En muchas ocasiones. El diseñador/programador deberá decidir hasta qué punto deben utilizarse. el sistema puede usarse para realizar varias tareas simultáneamente (vg: reproducción de MP3s en background). Multiprocesamiento real En un sistema multiprocesador. un programa puede diseñarse como varios procesos paralelos que funcionen de forma independiente. © Fernando Berzal Galiano file:///D|/Manuales/threads/introduction. IMPORTANTE: El objetivo principal del uso de hebras es mejorar el rendimiento del sistema. La descomposición de una aplicación en varias hebras puede resultar muy beneficiosa en términos de desacoplamiento de código (tareas independientes se implementan por separado) y de calidad del diseño (frente a futuras ampliaciones. el sistema operativo podrá asignar cada una a una de las CPUs del sistema.html (2 of 2) [27/02/2003 16:24:21] . por ejemplo). si la aplicación se descompone en varias hebras. se le asigna mayor prioridad a las tareas más importantes (vg: las que requieran una respuesta más rápida).

). en una clase derivada de TThread se pueden añadir todos los miembros (propiedades y métodos) que se necesiten. Obligatoriamente sólo hay que implementar: q El constructor de la clase (que nos permitirá definir la inicialización de la hebra) El método Execute (“la función main() de la hebra”. Denominamos THebraPelota a la clase derivada de TThread. Para facilitar el trabajo.cpp y HPelota. C++Builder incluye un asistente que lo hace por nosotros. Ya hemos creado nuestra primera hebra en una unidad independiente (que almacenaremos en los ficheros HPelota. La clase TThread es abstracta porque posee un método virtual puro denominado Execute(). Seleccionamos el elemento Thread Object. que será el que rellenemos con el código asociado a la hebra. que contendrá el código asociado a la tarea que tenga que realizar la hebra). para lo cual se ha de crear una clase derivada de TThread..html (1 of 4) [27/02/2003 16:24:21] . q file:///D|/Manuales/threads/TThread. Ejemplo: Crear una hebra Abrimos el repositorio en su página New (al que se accede desde la opción del menú File->New.C++ Builder Curso de C++ Builder Programación con Hebras La clase TThread C++ Builder proporciona la clase abstracta TThread para la creación de hebras. Como sucede con cualquier otra clase..h). Para definir una hebra se debe crear un descendiente de TThread.

tpLower Un punto por debajo del valor normal. Si se aumenta mucho la prioridad de una hebra que requiera muchos recursos (vg: CPU) puede ocurrir que las demás hebras de la aplicación (y del sistema) no lleguen a procesarse a la velocidad adecuada. Asignación de una Prioridad por Defecto La prioridad de una hebra indica qué grado de preferencia tiene la hebra cuando el sistema operativo reparte el tiempo de CPU entre las distintas hebras que se estén ejecutando en el sistema. donde se establecen los valores iniciales de cuantas propiedades sean necesarias. tpHighest Dos puntos por encima del valor normal. tpTimeCritical La hebra tiene la prioridad más alta. Para indicar la prioridad del objeto de hebra hay que fijar el valor de la propiedad Priority: Valor Prioridad tpIdle Se ejecuta cuando el sistema está inactivo. Ejemplo: file:///D|/Manuales/threads/TThread. tpNormal La hebra tiene la prioridad normal. tpHigher Un punto por encima del valor normal. Éste recibe como parámetro false si deseamos que la hebra se ejecute inmediatamente después de ser creada o true si queremos que quede suspendida inicialmente. Antes de invocar al constructor de una clase derivada de TThread.C++ Builder Inicialización de las hebras La inicialización de una hebra se realiza en su constructor. Dos características de las hebras conviene establecerlas en el constructor: su prioridad y cuándo debe liberarse la hebra. tpLowest Dos puntos por debajo del valor normal.html (2 of 4) [27/02/2003 16:24:21] . se invoca al constructor de su clase base (TThread): __fastcall TThread(bool CreateSuspended).

public: TPelota *Pelota. Ejemplo: q En HPelota.html (3 of 4) [27/02/2003 16:24:21] .C++ Builder Si tenemos un proceso que consume una cantidad considerable de tiempo de CPU. __fastcall THebraPelota(TPaintBox *PaintBox).. MUY IMPORTANTE: Antes de liberar una hebra hay que asegurarse de que no se esté ejecutando (ya veremos cómo). basta con fijar el valor de la propiedad FreeOnTerminate a false. Para ello. En este caso. La hebra de alta prioridad no consumirá tiempo de CPU porque estará bloqueada pero. Si la aplicación requiere varias instancias del mismo objeto hebra (para ejecutar la hebra varias veces). se puede aumentar el rendimiento de la aplicación almacenando las hebras en una caché para utilizarlas más adelante. hay casos en que el objeto hebra representa una tarea que debe realizarse varias veces. file:///D|/Manuales/threads/TThread. Sin embargo. será responsabilidad del programador la liberación de la hebra. lo más sencillo es dejar que el objeto hebra se libere a sí mismo. Si este es el caso. en lugar de destruirlas y crearlas de nuevo cada vez. puede ser interesante dar la posibilidad al usuario de cancelar el proceso durante su ejecución. Esto se puede conseguir creando una hebra con prioridad normal para ese proceso y otra hebra de alta prioridad que únicamente esté a la espera de que el usuario pulse un botón de cancelación. Liberación de las hebras A menudo las hebras de una aplicación se ejecutan una sola vez. responderá rápidamente.h" En la clase THebraPelota: . estableciendo la propiedad FreeOnTerminate a true. en el caso de que el usuario pulse el botón..h: #include "ObjGraf.

PaintBox. // ..C++ Builder __fastcall ~THebraPelota(void). TDireccion((random(2)+1) | (random(2)+1)*4))... random(PaintBox->Width).. . (TColor)(random(0xFF) | (random(0xFF)*0x100) | (random(0xFF)*0x10000)). __fastcall THebraPelota::THebraPelota (TPaintBox *PaintBox) : TThread(false) { Priority = tpNormal. random(PaintBox->Height).. random(20)+1. } __fastcall THebraPelota::~THebraPelota(void) { delete Pelota.html (4 of 4) [27/02/2003 16:24:21] . } © Fernando Berzal Galiano file:///D|/Manuales/threads/TThread. q En HPelota... Pelota = new TPelota ( // Objeto pelota. FreeOnTerminate = true.aletorio..cpp: #include <stdlib.h> .

} } Variables locales a las hebras Con la palabra clave __thread podemos definir variables globales que son locales a una hebra. Pelota->Mover(). Ejemplo: q En HPelota. Una hebra puede concebirse como un programa que se ejecuta dentro de la aplicación.cpp: void __fastcall THebraPelota::Execute() { while (true) { // Código de la Hebra. Habrá una copia de la variable para cada una de las hebras que se creen: la variable es global para las funciones de una hebra pero no se comparte con otras hebras. Por otro lado. Por tanto.html (1 of 4) [27/02/2003 16:24:21] . Ejemplo: file:///D|/Manuales/threads/execution. Sleep(100). puede utilizarse la memoria compartida entre las hebras para establecer una comunicación entre ellas. es necesario asegurarse de no escribir en la memoria que utilizan las otras hebras. Una hebra no es un programa independiente porque comparte el mismo espacio con las demás hebras de la aplicación.C++ Builder Curso de C++ Builder Programación con Hebras Ejecución de las hebras El método Execute es la función principal de una hebra.

No es aconsejable utilizar este tipo de variables. Por tanto. Cuando resulte conveniente reanudar la ejecución de la hebra se debe realizar una llamada al método Resume(). Suspend() y Resume() utilizan un contador interno. Las hebras pueden iniciarse y suspenderse tantas veces como sea necesario antes de que finalice su ejecución. indicando así que la hebra ha de finalizar su ejecución en cuanto sea posible. Las variables __thread han de ser estáticas (no pueden ser punteros) y no pueden inicializarse en tiempo de ejecución).C++ Builder int __thread x. de forma que es posible anidar las llamadas a Suspend() y Resume(). La hebra no reanuda su ejecución hasta que todas las suspensiones hayan tenido su correspondiente llamada a Resume().html (2 of 4) [27/02/2003 16:24:21] . Ejemplo: file:///D|/Manuales/threads/execution. el método Execute() ha de comprobar periódicamente el valor de la propiedad Terminated y detener la ejecución de la hebra cuando esté a true. Suspendida. Para hacer que la ejecución de una hebra finalice de forma prematura hay realizar una llamada al método Terminate(). La ejecución de una hebra termina normalmente cuando termina la ejecución del método Execute(). ya que se puede conseguir lo mismo añadiendo una variable de instancia a la clase de la hebra. Para detener una hebra temporalmente hay que realizar una llamada al método Suspend(). Control de la ejecución de una hebra Una hebra puede encontrarse en dos estados: q q Ejecutándose. Terminate() cambia el valor de la propiedad Terminated a true.

void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Objs = new THebraPelota*[4]. . i<4. for (int i=0.C++ Builder q En HPelota..cpp: #include <stdlib.h> .html (3 of 4) [27/02/2003 16:24:21] ..h" .h: Para usar la unidad HPelota desde un formulario: #include "HPelota. Pelota->Mover(). q En Ppal... el estado inicial de ésta dependerá del parámetro que se le pase a su constructor: ejecutándose (false) o suspendida (true). } } Cuando se crea una hebra.. randomize(). file:///D|/Manuales/threads/execution. Ejemplo: q En Ppal. Sleep(100).. ++i) Objs[i] = new THebraPelota (PaintBox).cpp: void __fastcall THebraPelota::Execute() { while (!Terminated) { // Código de la Hebra. private: // User declarations THebraPelota **Objs. Si se crea una hebra inicialmente suspendida se ha de invocar al método Resume() para comenzar su ejecución.

i<4.. ++i) Objs[i]->Terminate(). // Esperar tres segundos. // . Sleep(3000). © Fernando Berzal Galiano file:///D|/Manuales/threads/execution..html (4 of 4) [27/02/2003 16:24:21] . es una chapuza para evitar que se “cuelgue” la aplicación al liberar las hebras (más adelante veremos como solucionar este problema correctamente).. } Nota: La sentencia Sleep(3000).a que se liberen todas las hebras delete[] Objs..C++ Builder } void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { for (int i=0.

pueden ocurrir situaciones no deseadas si dos o más hebras acceden (o intentan acceder) al mismo recurso simultáneamente. la ejecución de una hebra puede depender del resultado de las tareas que realicen en otras hebras. file:///D|/Manuales/threads/coordination. Hay que tener cuidado de no bloquear innecesariamente la ejecución de otras hebras (para no disminuir el rendimiento de la aplicación). Hay que tener cuidado para evitar que dos hebras accedan a un recurso compartido (vg: objeto o variable global) al mismo tiempo. La hebra principal de la VCL No existe garantía alguna (en general) de que los métodos de los componentes de C++ Builder funcionen correctamente cuando son compartidos por varias hebras. Para evitar conflictos con otras hebras. aunque el funcionamiento de la aplicación es correcto. las distintas hebras de una aplicación han de coordinar su ejecución. Además.C++ Builder Curso de C++ Builder Programación con Hebras Coordinación entre hebras El código ejecutado por una hebra debe tener en cuenta la posible existencia de otras hebras que se ejecuten concurrentemente. Es decir.html (1 of 6) [27/02/2003 16:24:22] . ¡Se ha de evitar el acceso simultáneo de las hebras al componente Canvas del PaintBox!. la visualización en el PaintBox sufre algunos errores de forma aleatoria. al acceder a propiedades o ejecutar métodos pueden efectuarse algunas operaciones que utilicen memoria no protegida de las acciones de otras hebras. puede que se necesite bloquear la ejecución de otras hebras al acceder a objetos o variables compartidas. Ejemplo: Si ejecutamos el ejemplo anterior. Por tanto. Uso de recursos compartidos Cuando varias hebras comparten el uso de un recurso. Esto se debe a que los métodos Mostrar() y Borrar() de las distintas hebras se entrelazan en el acceso al Canvas del PaintBox.

Esto permite aumentar el rendimiento de la aplicación porque no es necesario esperar a que la hebra VCL principal entre en su bucle de mensajes (y. Para usar la hebra VCL principal hay que crear un método que realice las acciones necesarias y llamarlo utilizando el método Synchronize(). además.html (2 of 6) [27/02/2003 16:24:22] .cpp: void __fastcall THebraPelota::Execute() { while (!Terminated) { Synchronize(Pelota->Mover). no bloqueamos esta hebra). Si todos los objetos acceden a sus propiedades e invocan a sus métodos dentro de una única hebra. Los componentes de acceso a datos funcionan correctamente con hebras si pertenecen a distintas sesiones (con la excepción de los controladores de Access. q En HPelota. para el acceso a los objetos de la VCL. Ésta es la hebra que gestiona todos los mensajes de Windows que reciben los componentes de la aplicación. } } No siempre es necesario utilizar la hebra VCL principal (de hecho. Ejemplo: q En ObjGraf. Algunos componentes están preparados para funcionar con hebras (son thread-safe) y no hay necesidad de usar el método Synchronize(). por lo que hay que cambiar la definición del método Mover() de TPelota: void __fastcall Mover (void). en algunos casos no se puede usar y tendremos que emplear otros mecanismos como las secciones críticas). que utilizan la biblioteca ADO). la “hebra principal de la VCL”. file:///D|/Manuales/threads/coordination.C++ Builder Por este motivo se reserva una hebra. no hay por qué preocuparse.cpp: El método Synchronize() recibe cómo parámetro un método del tipo void __fastcall <método> (void).h y en ObjGraf. Sleep(100).

Las llamadas a los métodos TCanvas::Lock o TThreadList::LockList pueden anidarse con seguridad.C++ Builder q Los objetos gráficos funcionan correctamente con hebras. Ejemplo: q En HPelota.cpp: Eliminar la llamada al método Synchronize() realizada desde el método THebraPelota::Execute(). No se necesita utilizar la hebra VCL principal acceder a TFont. q En ObjGraf. los objetos de tipo lienzo (TCanvas y sus descendientes) cuentan con un método Lock() que impide a las otras hebras acceder al objeto hasta que se realiza una llamada al método Unlock(). En el caso de TThreadList. TBitmap.. q Bloqueo de objetos Algunos componentes cuentan con mecanismos de bloqueo para que puedan compartirse por varias hebras. Para compartir el uso de objetos lienzo (TCanvas y descendientes) hay que bloquearlos antes. una llamada a TThreadList::LockList() devuelve el objeto de tipo TList asociado e impide que otras hebras accedan a la lista hasta que se realice una llamada a UnlockList().html (3 of 6) [27/02/2003 16:24:22] . Algunos componentes (por ejemplo. . siempre se puede utilizar una sección crítica. Las secciones críticas funcionan como puertas que permiten el paso de una sola hebra cada vez. TList) tienen una versión adecuada para funcionar con varias hebras (TThreadList). Secciones críticas Si un objeto no cuenta con mecanismos de bloqueo incorporados.. Por ejemplo. TMetafile ni TIcon.cpp: Tanto en TPelota::Mostrar() como en TPelota::Borrar(): PaintBox->Canvas->Lock(). TBrush. Para utilizar una sección crítica hay que crear una instancia global de file:///D|/Manuales/threads/coordination. El desbloqueo no se produce hasta que se haya realizado una llamada de desbloqueo por cada llamada de bloqueo. PaintBox->Canvas->Unlock(). TPen.

Ejemplo: q En ObjGraf. file:///D|/Manuales/threads/coordination. eliminar el bloqueo del objeto de tipo TCanvas y emplear en su lugar la sección crítica: { SC->Acquire().C++ Builder TCriticalSection. SC->Release(). las hebras tienen que realizar una llamada al método Release() para que las demás hebras puedan acceder al recurso invocando al método Acquire().hpp> TCriticalSection *SC = new TCriticalSection()...html (4 of 6) [27/02/2003 16:24:22] .. TCriticalSection cuenta con dos métodos: Acquire() (que impide a otras hebras acceder a la sección crítica) y Release() (que elimina el bloqueo).cpp: #include <syncobjs. . por lo cual será necesario que en ciertas ocasiones una hebra espere a que otra termine la ejecución de una acción determinada. Al finalizar sus operaciones. } Sincronización entre hebras Puede que las distintas hebras de una aplicación realicen tareas que no sean completamente independientes. // ¡¡¡Habría que destruirla!!! . En TPelota::Mostrar() y en TPelota::Borrar(). Cada sección crítica se asocia a un recurso que se desea compartir por varias hebras. Todas las hebras que accedan a un mismo recurso deberán utilizar el método Acquire() de la correspondiente sección crítica para asegurarse de que el recurso no está siendo utilizado por ninguna otra hebra. Si se omite la llamada a Release() el recurso quedaría bloqueado para siempre..

C++ Builder

Ejemplo: Tenemos que dos hebras que calculan el total de ingresos y el total de gastos de una compañía respectivamente. Una tercera hebra ha de obtener el balance final, por lo que deberá esperar a que las dos hebras anteriores terminen su trabajo.

Esperar la finalización de una hebra
Para esperar a que finalice la ejecución de otra hebra, se puede utilizar el método WaitFor() de la otra hebra. WaitFor() bloquea la ejecución de la hebra actual hasta que la otra hebra se haya cerrado, ya sea por haber finalizando la ejecución de su método Execute() o por haberse producido una excepción. WaitFor() devuelve un valor entero que es el valor de la propiedad ReturnValue de la hebra. La propiedad ReturnValue puede cambiarse en el método Execute() y su significado se lo daremos nosotros. Ejemplo:
q

En Ppal.cpp:

void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { int i; for (i=0; i<4; i++) Objs[i]->Terminate(); for (i=0; i<4; i++) Objs[i]->WaitFor(); delete[] Objs; }

Esperar a que se complete una tarea: Sucesos
En algunas ocasiones es necesario esperar a que otra hebra haya realizado una tarea determinada sin que ello implique que haya finalizado su ejecución. En estos casos hay que utilizar un objeto de tipo suceso (TEvent).

file:///D|/Manuales/threads/coordination.html (5 of 6) [27/02/2003 16:24:22]

C++ Builder

Cuando una hebra completa una operación de la que dependen otras hebras, realiza una llamada a TEvent::SetEvent(). SetEvent() activa una señal que cualquier otra hebra puede detectar invocando al método TEvent::WaitFor(). Para desactivar esa señal existe el método TEvent::ResetEvent(). El método WaitFor() espera un tiempo determinado (establecido en milisegundos al llamar al método) hasta que se active la señal. WaitFor() puede devolver uno de los siguientes valores: Valor Significado wrSignaled La señal asociada al suceso se ha activado. wrTimeout Ha transcurrido el tiempo especificado sin que la señal se activase. wrAbandoned El objeto de tipo TEvent se destruyó antes de que se llegase al time-out. Se ha producido un error durante la espera. El código del error concreto se wrError puede obtener de la propiedad TEvent::LastError. Si se desea seguir a la espera de un suceso indefinidamente puede pasar el valor INFINITE como parámetro del método WaitFor(). Pero tenga cuidado, la hebra se quedará bloqueada para siempre si nunca llegara a producirse el evento que espera. NOTA: El componente TEvent no es más que un wrapper de un evento de Windows.

© Fernando Berzal Galiano

file:///D|/Manuales/threads/coordination.html (6 of 6) [27/02/2003 16:24:22]

Acceso a bases de datos

Curso de C++ Builder Acceso a bases de datos
Introducción
q q q

Bases de datos locales Bases de datos cliente/servidor Arquitecturas multicapa

El motor de bases de datos de Borland (BDE)
q

Configuración del driver para InterBase

Componentes de acceso a bases de datos
q q

El asistente para formularios de bases de datos Bases de datos de demostración

Controles de acceso a datos
q q q

Bases de datos con fechas Rejillas Pistas y trucos

El componente TDataSource
file:///D|/Manuales/databases/index.html (1 of 3) [27/02/2003 16:24:22]

Acceso a bases de datos

q

TDataLink: Componentes "data-aware"

Conjuntos de datos
q q q q q q q

TDataSet y sus derivados Cursores Actualizaciones en caché El componente TTable: Tablas El componente TQuery: Consultas SQL El componente TStoredProc: Procedimientos almacenados El componente TField: Acceso a los campos

Sesiones y conexiones
q q

El componente TSession El componente TDatabase

Herramientas y utilidades
q q q q q

BDE Administrator Database Desktop SQL Explorer SQL Monitor Datapump

Ejemplos y ejercicios
q q q

q

q

Un componente 'data-aware': TDBDateTimePicker Un formulario: Un diálogo de búsqueda genérico Una aplicación sencilla (Paradox): Gestión de una pequeña base de datos culinaria Una aplicación algo más compleja (InterBase): Diccionario de citas Ejercicio: Desarrollo completo de una aplicación

Apéndice: SQL
file:///D|/Manuales/databases/index.html (2 of 3) [27/02/2003 16:24:22]

Acceso a bases de datos

Página principal © Fernando Berzal Galiano

file:///D|/Manuales/databases/index.html (3 of 3) [27/02/2003 16:24:22]

C++ Builder

Curso de C++ Builder Acceso a Bases de Datos
Acceso a bases de datos relacionales

La mayoría de las aplicaciones de gestión requieren el acceso a bases de datos. C++ Builder incluye componentes que facilitan enormemente el desarrollo de aplicaciones que interactúan con bases de datos. Usualmente trabajaremos con bases de datos relacionales (bases de datos constituidas por tablas). Antes de seguir, definamos dos conceptos básicos:
q

Cursor: Un indicador del registro que se está insertando, modificando o consultando en una tabla relacional, entendiendo ésta en su sentido más amplio (una tabla de la base de datos o la tabla resultado de una consulta). Conjunto de Datos [Dataset]: Una colección de datos obtenido de una base de datos. Un dataset puede ser algo más que los datos incluidos en una tabla; podría ser el resultado de una consulta que contenga datos provenientes de más de una tabla.

q

Bases de Datos Locales
El modelo más sencillo de aplicación que accede a bases de datos es aquél en el cual se accede a bases de datos locales, también denominadas bases de datos de escritorio La base de datos reside en una sola máquina (generalmente la misma en la que se ejecuta la aplicación), y sólo puede tener acceso a la misma un único usuario. Ejemplos de este modelo son dBase, Paradox, Approach o Access.

Bases de Datos Cliente/Servidor
En este caso, un gestor de bases de datos (DBMS) mantiene la base de datos. El
file:///D|/Manuales/databases/introduction.html (1 of 2) [27/02/2003 16:24:23]

C++ Builder

almacenamiento y gestión del acceso a los datos los realiza el gestor (el servidor). Los gestores de bases de datos relacionales también se conocen como servidores SQL, por ser éste el lenguaje que se utiliza para acceder a los datos. Oracle, IBM DB2, InterBase y SQL Server entran dentro de esta categoría. Las aplicaciones de los usuarios (los clientes) hacen peticiones al servidor utilizando algún protocolo predefinido, CLI [Call-Level-Interface] en inglés, que puede ser un estándar (ODBC, JDBC o BDE) o específico de la base de datos que utilicemos. Como es lógico, varios usuarios situados en distintos puestos de trabajo de una red pueden compartir el mismo servidor SQL, que será el responsable de mantener la "acidez" de las transacciones [Atomicity-Consistency-Isolation-Durability].

Arquitecturas multicapa
q

Las aplicaciones que acceden a bases de datos locales corresponden a una arquitectura de una sola capa: las aplicaciones conectan directamente con la base de datos. El modelo cliente/servidor corresponde a una arquitectura con dos capas: el servidor SQL por un lado y las aplicaciones que se conectan como clientes del servidor por otro. También existen arquitecturas multicapa con más de dos capas: las aplicaciones se conectan a servidores de aplicaciones, que son los que acceden a los servidores de bases de datos. En este caso se suele hacer uso de middleware: CORBA, DCOM, DataSnap (=MIDAS)...

q

q

© Fernando Berzal Galiano

file:///D|/Manuales/databases/introduction.html (2 of 2) [27/02/2003 16:24:23]

Un alias de BDE establece el conjunto de parámetros que se requieren para establecer una conexión con una base de datos. Ejemplo file:///D|/Manuales/databases/bde. que no es más que una colección de DLLs. C++ Builder proporciona el Borland Database Engine (BDE).C++ Builder Curso de C++ Builder Acceso a bases de datos BDE El Motor de Bases de Datos de Borland Para permitir el acceso a bases de datos locales y servidores SQL. El BDE necesita un "alias" para acceder a una base de datos particular. tales como el controlador [driver] empleado y la localización de la base de datos. Los alias se definen con ayuda del BDE Administrator (que se encuentra en el Panel de Control de Windows).html (1 of 3) [27/02/2003 16:24:23] . de forma que éstas sean independientes de la base de datos que se utilice. El BDE es un CLI [Call-Level Interface] que hace de intermediario entre las aplicaciones y las bases de datos a las que se accede.

(destino de scache. q WAIT ON LOCKS: ¿Esperar a que un registro esté disponible? Uso de TCP/IP como protocolo de comunicación con el servidor (de forma que no hace falta instalar el cliente y las utilidades de administración de InterBase en todos los puestos): r q Añadir la entrada "gds_db 3050/tcp" al fichero services de Windows (subdirectorio system32\drivers\etc) q Alias (parámetro SERVER NAME): file:///D|/Manuales/databases/bde. los alias BDE disponibles en la máquina.. NOTA: El nivel de lecturas repetibles no es adecuado para las aplicaciones que tienen que estar pendientes de las actualizaciones realizadas en otros puestos. y el formulario con el nombre Ppal. 512: Nivel de aislamiento superior para las transacciones implícitas (lecturas repetibles).ini & *. q Añadir un componente TTable (en la página Data Access) al formulario.cpp.scf) SCHEMA CACHE SIZE = 32 SCHEMA CACHE TIME = -1 q DRIVER FLAGS = 4608 r r 4092: isc_commit_retaining (para confirmar las transacciones implícitas) + COMMIT RETAIN = TRUE para transacciones explícitas.html (2 of 3) [27/02/2003 16:24:23] .C++ Builder Crear una aplicación nueva. q Ver qué valores se pueden seleccionar para la propiedad DataBaseName.. q Configuración del driver para InterBase q ENABLE BCD para poder trabajar con números decimales con una precisión especificada (si no hay que utilizar datos de tipo entero o real!!). ENABLE SCHEMA CACHE ahorra tiempo y ancho de banda: r r r r q ENABLE SCHEMA CACHE = TRUE SCHEMA CACHE DIR = . Guardar el proyecto con el nombre BDEje.

html (3 of 3) [27/02/2003 16:24:23] .C++ Builder r r NetBEUI: //host/db TCP/IP: host:/db © Fernando Berzal Galiano file:///D|/Manuales/databases/bde.

seleccionando "Database Form Wizard" de la pestaña "Business": file:///D|/Manuales/databases/components.. C++ Builder nos ofrece un "potente" asistente para generar formularios sencillos que accedan a bases de datos. El componente TDataSource (enlace entre los anteriores) q q El asistente Aunque podemos crear nuestras aplicaciones de bases de datos directamente a partir de los componentes de bases de datos.html (1 of 16) [27/02/2003 16:24:25] . Para utilizar el asistente hay que seguir los siguientes pasos: 1."). Conjuntos de datos (no visuales).C++ Builder Curso de C++ Builder Acceso a Bases de Datos Componentes de acceso a Bases de Datos Los componentes de la VCL para el acceso a bases de datos se dividen en categorías siguiendo el modelo MVC (Model-View-Controller): q Controles de acceso a datos (visuales).. Llamar al asistente como si fuésemos a añadir a nuestro proyecto un formulario más (con "File/New.

C++ Builder También se puede llamar al asistente directamente desde la opción Form Wizard del menú Database. Seleccionar el tipo de formulario que deseemos (simple o maestro/detalle) y cómo queremos generarlo (mediante tablas o consultas). optaremos por un formulario simple construido con una tabla (TTable): 3. En este caso. seleccionamos la base de datos de file:///D|/Manuales/databases/components. Seleccionamos la tabla a la cual deseamos acceder.html (2 of 16) [27/02/2003 16:24:25] . 2. Para comenzar.

vertical o en una rejilla.C++ Builder demostración que aparece bajo el alias de BCDEMOS y. hemos de indicar qué campos incluiremos en nuestro formulario. la tabla BIOLIFE. dentro de ella. Ahora podemos escoger la disposición de los controles en el formulario: horizontal.DB: 4. Probaremos inicialmente con la disposición horizontal de los controles en el formulario.html (3 of 16) [27/02/2003 16:24:25] . file:///D|/Manuales/databases/components. Una vez seleccionada la tabla. LENGTH_IN (<): 5. Seleccionamos todos (>>) menos la longitud en pulgadas.

Finalmente.C++ Builder 6. le indicamos al asistente que cree un formulario acompañado por un módulo de datos independiente (para separar los objetos que modelizan los conjuntos de datos de los controles que constituyen la vista de esos conjuntos de datos): 7. El resultado obtenido es el siguiente: file:///D|/Manuales/databases/components.html (4 of 16) [27/02/2003 16:24:25] .

si queremos que las etiquetas que indican los nombres de los campos aparezcan a la izquierda o encima de los controles que nos permiten editarlos. Disposición vertical de los controles 5. los campos de tipo MEMO (textos) o BLOB (imagen en el ejemplo) no deben mostrarse en una simple caja de edición. Por ejemplo.C++ Builder El formulario de la imagen está bien aunque aún necesita algunos retoques. Por desgracia. podemos optar por disponer los campos verticalmente (tal como se hace desde tiempos del dBase): 6. además. Seleccionamos la primera de las opciones: file:///D|/Manuales/databases/components.html (5 of 16) [27/02/2003 16:24:25] . Para evitar el error que se producía anteriormente (el uso indiscriminado de cajas de edición incluso para las imágenes). ha puesto todos los campos de la tabla como si se pudiesen editar con un simple TDBEdit. Hemos de indicar. al indicarle al asistente que pusiese los campos horizontalmente.

Como en el ejemplo anterior.. le indicamos al asistente que cree un formulario acompañado por un módulo de datos independiente: 8. y el resultado que obtenemos es el siguiente: file:///D|/Manuales/databases/components. ..html (6 of 16) [27/02/2003 16:24:25] .C++ Builder 7.

para que se vea correctamente la imagen. Creamos ahora un formulario maestro/detalle (master/detail) con objetos de tipo TTable para modelizar los conjuntos de datos: file:///D|/Manuales/databases/components. Formularios maestro/detalle Utilicemos ahora el asistente para algo un poco más complejo: 1.C++ Builder Este formulario está algo mejor que el inicial y. sólo hemos de poner a true la propiedad Stretch del control que nos la muestra (el único TDBImage del formulario) y ajustar un poco el tamaño de los distintos controles.html (7 of 16) [27/02/2003 16:24:25] .

una tabla que contiene información acerca de los clientes de una empresa: 3.DBF de la base de datos BCDEMOS como tabla maestra del formulario. Escogemos los campos que nos interese mostrar y los ordenamos utilizando los botones que aparecen debajo de la lista de campos seleccionados: file:///D|/Manuales/databases/components.C++ Builder 2.html (8 of 16) [27/02/2003 16:24:25] . Seleccionamos la tabla CLIENTS.

Indicamos que los campo de la tabla maestro los dispondremos verticalmente (para evitar que nos pase lo de antes con las imágenes y los textos): file:///D|/Manuales/databases/components.C++ Builder 4.html (9 of 16) [27/02/2003 16:24:25] .

C++ Builder 5. que será la tabla HOLDINGS. Escogemos todos sus campos: file:///D|/Manuales/databases/components.DBF de la base de datos BCDEMOS (tabla que contiene las inversiones en bolsa de nuestros clientes): 6.html (10 of 16) [27/02/2003 16:24:25] . Seleccionamos la tabla detalle.

Y seleccionamos una rejilla para visualizarlos ya que. usualmente.C++ Builder 7. Para completar nuestro formulario maestro/detalle hemos de especificar cómo se reliza la reunión entre las tablas CLIENTS.DBF.DBF y HOLDINGS.html (11 of 16) [27/02/2003 16:24:25] . a través del índice existente sobre la columna ACCT_NBR: file:///D|/Manuales/databases/components. las tablas detalle siempre se muestran en rejillas: 8.

C++ Builder 9.html (12 of 16) [27/02/2003 16:24:25] . Como siempre. le indicamos al asistente que cree un formulario acompañado por un módulo de datos independiente: file:///D|/Manuales/databases/components.

la presentación será la adecuada para incluirlo en alguna de nuestras aplicaciones: file:///D|/Manuales/databases/components. Voilà! Ya tenemos listo un formulario maestro/detalle y.html (13 of 16) [27/02/2003 16:24:25] . con unos cuantos retoques.C++ Builder 10.

tabla holdings. tabla master. q Tabla maestra: Alias BCDEMOS.db. Tipo del Formulario: maestro/detalle con objetos TTable. q q q q q q q q q q q q q q q Limitaciones del asistente Como hemos visto.db. ItemsTotal (en ese orden).db.db. tabla employee. OrderNo. tabla orders. tabla event. Phone (en ese orden). tabla vendors. Tabla detalle: Alias BCDEMOS. Tabla maestra: Alias BCDEMOS. tabla industry. tabla orders. Tabla maestra: Alias BCDEMOS. Tabla detalle: Alias BCDEMOS. Company. q Campos de la tabla detalle: CustNo. q q q Tipo del Formulario: maestro/detalle con objetos TTable. tabla parts. el asistente nos permite crear rápidamente formularios que nos permiten gestionar conjuntos de datos.db. q Disposición de los campos de la tabla maestra: Horizontally. Country. Tabla detalle: Alias BCDEMOS. No obstante. q Campos de la tabla maestra: CustNo.db. tabla items. Addr1. Tabla maestra: Alias BCDEMOS. tabla orders. City.C++ Builder Ejercicios prácticos q Tipo del Formulario: maestro/detalle con objetos TTable. Tipo del Formulario: maestro/detalle con objetos TTable. Tabla detalle: Alias BCDEMOS. Tabla maestra: Alias BCDEMOS. Tabla detalle: Alias BCDEMOS. Tabla detalle: Alias BCDEMOS. State. tabla reservat. SaleDate. q Disposición de los campos de la tabla detalle: In a Grid. q Tabla detalle: Alias BCDEMOS. Tipo del Formulario: maestro/detalle con objetos TTable. cualquier aplicación real requerirá formularios más complejos que los vistos hasta ahora y tendremos que olvidarnos del asistente y crearlos nosotros mismos. Tabla maestra: Alias BCDEMOS. Tipo del Formulario: maestro/detalle con objetos TTable. Tabla maestra: Alias BCDEMOS.db. TaxRate.db.db.db. q Definir la reunión (join) seleccionando el índice CustNo: join CustNo -> CustNo.db.db. tabla customer. Ejercicios para los cuales el asistente se queda corto file:///D|/Manuales/databases/components. tabla master. Tipo del Formulario: maestro/detalle con objetos TTable.db.db.html (14 of 16) [27/02/2003 16:24:25] .

html (15 of 16) [27/02/2003 16:24:25] .C++ Builder Mostrar la relación entre los lugares en que se celebran actividades (venues. Mostrar los pedidos de cada cliente (orders.dbf) de cada cliente (clients.db).db. Mostrar el total de inversiones (holdings.db como detalle de customer.dbf) o el importe total de lo que ha ganado cada proveedor (vendors.db).db) y los clientes que acuden a cada recinto (custoly. Cada evento (event. Bases de datos de demostración Base de datos de inversiones en bolsa Base de datos de reserva de entradas Base de datos de pedidos file:///D|/Manuales/databases/components.db). Mostrar las inversiones de los clientes (relación entre holdings.db) tiene un lugar de celebración (venues. que además está relacionada con vendors.dbf y clients.db) y una serie de reservas (reservat.dbf). no sólo su símbolo.db) indicando los detalles de los pedidos (items.db) y el proveedor de cada pìeza (relación entre items.db) con los pedidos realizados hasta el momento (orders.db).db) realizadas por clientes (custoly.db y parts.dbf) indicando el nombre de las empresas en las que se invierte (almacenado en master.

BIOLIFE.C++ Builder NOTA: Las tablas ANIMALS. © Fernando Berzal Galiano file:///D|/Manuales/databases/components.DB y COUNTRY.DB completan el conjunto de bases de datos incluidas como ejemplo en la distribución del C++Builder.html (16 of 16) [27/02/2003 16:24:25] .DBF.

TDBEdit Presenta un cuadro de edición para un campo concreto. aunque cada fila es en TDBCtrlGrid realidad un panel en el que se pueden colocar controles de datos "replicables". La propiedad VisibleButtons se utiliza para TDBNavigator seleccionar qué botones podrá pulsar el usuario. Se diferencian de los controles estándar en que están enlazados a datos (son componentes data-aware). Igual que las etiquetas normales. Es el campo o columna del datasource al que accede cada control. así como la inserción. Control de navegación: Sirve para controlar el cursor. Permite construir gráficos a partir de un conjunto de datos. Mediante la TDBGrid propiedad Columns se pueden especificar qué campos del conjunto de datos se pueden ver en la rejilla y cuáles son sus propiedades. DataField: Propiedad DataSource DataField Descripción Indica el datasource del que se obtienen y al que se envían los datos. pero enlazado a datos. Muestra el valor de TDBText un campo. Análogo a TEdit.html (1 of 6) [27/02/2003 16:24:25] . la propiedad Hints permite especificar mensajes de ayuda para cada botón (que habrá que traducir). en su caso. Rejilla que permite incluir controles: Como un TDBGrid. La propiedad TDBChart SeriesList se emplea para seleccionar qué datos deseamos representar y cómo Controles orientados a campos Control Descripción Como el componente estándar TLabel. presentaremos los distintos controles de datos del C++ Builder Controles orientados a conjuntos de datos Control Descripción Rejilla de datos: Muestra un DataSource con aspecto de tabla. file:///D|/Manuales/databases/controls.C++ Builder Curso de C++ Builder Acceso a bases de datos Controles de acceso a datos Todos ellos tienen un control homólogo estándar en la paleta de componentes. Dicho enlace se establece mediante un DataSource. A continuación. no consume recursos en Windows. Estos componentes trabajan con los datos seleccionados por las propiedades DataSource y. Por su parte. edición y borrado de datos. el cual no se puede editar.

Igual que en el control TDBListBox. Se emplea en campos que sólo permiten dos valores diferentes. . TField *Field) { if (! FCambiando) try { FCambiando = True. En la propiedad Items se TDBListBox fijan los valores permitidos. El comportamiento de todos los controles anteriores ante modificaciones se puede alterar con las propiedades AutoEdit y ReadOnly. Se utiliza para campos que sólo permiten varios valores. Para mostrar imágenes contenidas en una base de datos (en formato BMP o TDBImage WMF). En la propiedad Items se TDBRadioGroup fijan los identificadores que el usuario ve en el grupo de botones. con la capacidad adicional de dar formato al texto del TDBRichEdit campo (en formato RTF). las distintas TDBComboBox posibilidades se colocan en la propiedad Items. private: bool FCambiando. Dichas listas se especifican mediante una serie de valores separados por punto y coma. En la propiedad Values se indican los valores que en realidad se almacenan en la base de datos.. }.html (2 of 6) [27/02/2003 16:24:25] . Con las propiedades ValueChecked y ValueUnchecked se establecen listas de valores para TDBCheckBox que el TDBCheckBox esté activado o desactivado.. La propiedad KeyField indica el campo cuyos valores se almacenan en la base de datos. Establece una lista de posibles valores para un campo. Ideal para textos sin formato. aunque la lista aparece como un TComboBox. file:///D|/Manuales/databases/controls. Ideal para claves externas: Como TDBListBox. El DataSource que se TDBLookupListBox consulta se establece con la propiedad ListSource. que son fijos. OnDataChange y OnUpdateData. También es necesario personalizar el evento OnExit del componente TDateTimePicker. Los valores de la lista se obtienen a partir de los valores de un campo de otro conjunto de datos. Igual que TDBMemo. Bases de datos con fechas Se puede adaptar TDateTimePicker (página Win32 de la paleta de componentes) para que funcione con un TDataSource especificando sus eventos OnStateChange. aunque la lista de valores permitidos no la establece el programador. El campo que se muestra en la lista de valores viene dado por la propiedad ListField.C++ Builder TDBMemo Caja de edición con múltiples líneas. Ejemplo class TFormDate : public TForm { . TComboBox enlazado a datos. TDBLookupComboBox Igual que TDBLookupListBox... void __fastcall TFormDate::DataSourceDataChange(TObject *Sender.

::TableBeforeDelete(TDataSet *DataSet) { if ( MessageDlg ( "¿Desea eliminar la tupla actual?". TMsgDlgButtons()<<mbYes<<mbNo. Por defectro. mtConfirmation. mientras que la combinación 'Control+Supr' se utiliza para eliminarlas. } } void __fastcall TFormDate::DataSourceUpdateData(TObject *Sender) { Table->FieldValues["HireDate"] = DateTimePicker->DateTime. } } void __fastcall TFormDate::DateTimePickerExit(TObject *Sender) { Table->UpdateRecord(). } Uso de rejillas La tecla 'Insert' permite añadir tuplas. 0) != mrYes ) Abort().C++ Builder DateTimePicker->DateTime = Table->FieldValues["HireDate"]. Personalización del color de un campo determinado (según el cumplimiento de alguna condición) file:///D|/Manuales/databases/controls. } __finally { FCambiando = False.. DataSource->Edit(). } void __fastcall TFormDate::DateTimePickerChange(TObject *Sender) { if (! FCambiando) try { FCambiando = True.. } Interceptando el evento OnDrawColumnCell se puede personalizar la presentación de las celdas: cambiar el color.html (3 of 6) [27/02/2003 16:24:25] . } __finally { FCambiando = False. aparece un mensaje en inglés que se puede personalizar interceptando el evento BeforeDelete del conjunto de datos asociado: Ejemplo de personalización de los mensajes mostrados al usuario void __fastcall . el tipo de letra e incluso mostrar imágenes o checkboxes sin tener que recurrir al componente TDBCtrlGrid.

Column. } Imágenes en vez de texto void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender. grid->DefaultDrawColumnCell(Rect. } CheckBoxes (aunque es más cómodo y flexible utilizar TDBCtrlGrid) file:///D|/Manuales/databases/controls. State). Column. int DataCol. grid->Canvas->Font->Style = FS. CaraTriste->Picture->Graphic). TColumn *TColumn. const TRect Rect. grid->DefaultDrawColumnCell(Rect. Column. break. else grid->Canvas->StretchDraw(Rect. State). } Propiedades del tipo de letra void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender. int DataCol. State).C++ Builder void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender. TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender). DataCol. break. usInserted: FS << fsItalic. DataCol. usDeleted: FS << fsStrikeOut. const TRect Rect. if (Column->FieldName != "") grid->DefaultDrawColumnCell(Rect. else if (tbEmpleados->FieldValues["Salary"] >= 150000) grid->Canvas->StretchDraw(Rect. break. DataCol. TFontStyles FS. if (tbParts->FieldValues["OnOrder"] >= tbParts->FieldValues["OnHand"]) grid->Canvas->Font->Color = clRed. int DataCol. TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender). CaraAlegre->Picture->Graphic). TColumn *TColumn.html (4 of 6) [27/02/2003 16:24:25] . switch case case case } (grid->DataSource->DataSet->UpdateStatus()) { usModified: FS << fsBold. TColumn *Column. const TRect& Rect. TGridDrawState State) { TDBGrid *grid = static_cast<TDBGrid*>(Sender).

int DataCol. DFC_BUTTON. } else DBGrid->DefaultDrawColumnCell(Rect. const TRect Rect. if (Table1->FieldValues["ACTIVO"]) check = DFCS_CHECKED. "ACTIVO") == 0) { UINT check = 0. DrawFrameControl(DBGrid1->Canvas->Handle. TColumn *TColumn. DataCol. } Podemos seleccionar la columna por la que se ordenan los datos usando la propiedad IndexFieldNames del conjunto de datos.C++ Builder void __fastcall TFormXXX::DBGridDrawColumnCell (TObject *Sender. Esta propiedad la podemos establecer dinámicamente como respuesta al evento OnTitleClick. TGridDrawState State) { if (CompareText(Column->FieldName. Ordenación dinámica de un conjunto de datos void __fastcall TFormXXX::DBGridTitleClick(TColumn *Column) { try { if (Column->Field->FieldKind == fkLookup) Table->IndexFieldNames = Column->Field->KeyFields. State). (RECT*) &Rect. DFCS_BUTTONCHECK | check).html (5 of 6) [27/02/2003 16:24:25] . se puede responder al evento OnBeforeAction del TDBNavigator de la siguiente forma: Append en vez de Insert file:///D|/Manuales/databases/controls. DBGrid->Canvas->FillRect(Rect). Column. } catch(Exception&) { } } Pistas y trucos q BARRAS DE NAVEGACIÓN: Para que siempre se realice un "Append" (al final) en lugar de "Insert" (antes de la fila activa) cuando añadimos nuevos datos (pulsando la tecla Insert). else Table->IndexFieldNames = Column->FieldName.

De esta forma se añade automáticamente un TDBEdit acompañado por una etiqueta TLabel (con su propiedad FocusControl apuntando al TDBEdit). } } q Durante el diseño de formularios podemos arrastrar campos desde el editor de campos del conjunto de datos sobre el que estemos trabajando.TNavigateBtn Button) { if (Button==nbInsert) { static_cast<TDBNavigator*>(Sender)->DataSource->DataSet->Append().C++ Builder void __fastcall TFormXXX::DBNavigatorBeforeAction(TObject *Sender.html (6 of 6) [27/02/2003 16:24:25] . SysUtils::Abort(). © Fernando Berzal Galiano file:///D|/Manuales/databases/controls.

TTable. El nombre de la base de datos con la que se está trabajando.html (1 of 8) [27/02/2003 16:24:26] . De hecho. TQuery y TStoredProc son casos particulares de conjuntos de datos. Devuelve true cuando el cursor está llega al final del conjunto de datos. Cuando está a true. métodos y eventos que se utilizan en estas clases están definidas realmente en TDataSet. la mayoría de las propiedades. en TBDEDataSet o en TDBDataSet: Propiedades Propiedad Active Bof CachedUpdates CanModify DataSource DatabaseName Eof Descripción Abre el conjunto de datos cuando se establece a true y lo cierra cuando se fija a false. las actualizaciones se mantienen en la caché de la máquina del cliente hasta que el programador los envíe al servidor.C++ Builder Curso de C++ Builder Acceso a bases de datos TDataSet Conjuntos de datos TDataSet es la clase superior de la jerarquía de clases definida en C++Builder para definir conjuntos de datos. todos los cambios realizador en los conjuntos de datos se pasan automáticamente a la base de datos. file:///D|/Manuales/databases/tdataset. Cuando está a false. El componente TDataSource asociado. Determina si el usuario puede editar el conjunto de datos o no. Devuelve true si el cursor está en el primer registro del conjunto de datos.

file:///D|/Manuales/databases/tdataset. Estados vg: Post graba una nueva fila si el estado es dsInsert. Devuelve el valor de un campo especificado en el registro actual. La escritura no se realiza realmente hasta que se invoca al método CommitUpdates(). Columnas del conjunto de datos: array de objetos de tipo TField. Devuelve el estado actual del conjunto de datos.C++ Builder FieldCount Fields FieldValues Found Modified RecNo RecordCount State UpdatesPending Es el número de columnas o campos del conjunto de datos. Cancela cualquier modificación en el registro actual si no ha sido enviada con Post(). El número de registro actual en el dataset. Indica si una operación de búsqueda ha tenido éxito o no. Añade un registro especificado al final del conjunto de datos. Indica si el registro actual ha sido modificado.html (2 of 8) [27/02/2003 16:24:26] . Envía a la base de datos cualquier actualización en caché que estuviese pendiente. Cancela cualquier actualización en caché que estuviese pendiente. Devuelve el número de registros en el dataset. Cuando está a true. Vacía el contenido de todos los campos del registro actual. el buffer del conjunto de datos contiene modificaciones de los datos que aún no han sido enviadas a la base de datos. actualiza la actual si es dsEdit Métodos Método Append() AppendRecord() ApplyUpdates() Cancel() CancelUpdates() ClearFields() Descripción Crea un registro vacío y lo añade al final del conjunto de datos.

Sitúa el cursor en el último registro. Después de que se ha modificado un registro. Elimina el registro actual. Mueve el cursor un número determinado de filas. Búsqueda de un registro en particular. Mueve el cursor al registro anterior. Localiza un registro por el medio más rápido posible y devuelve el dato contenido en el mismo (se usan índices si es posible). Cuando se utiliza la caché. Escribe los datos modificados de un registro en el conjunto de datos (los envía a la base de datos o al buffer de actualizaciones en caché). Después de insertar un registro. Inserta un registro en blanco y pone el conjunto de datos en modo de edición.C++ Builder CommitUpdates() Close() Delete() DisableControls() Edit() EnableControls() FetchAll() FieldByName() First() GetFieldNames() Insert() InsertRecord() Last() Locate() Lookup() MoveBy() Next() Open() Post() Prior() Refresh() RevertRecord() SetFields() UpdateStatus() Se indica a la base de datos que realice las actualizaciones que estaban en caché y se vacía el buffer de actualizaciones en caché. Devuelve un campo TField dado su nombre. Permite la edición del registro actual. Después de abrir un conjunto de datos. Desactiva los controles de datos asociados al conjunto de datos (muy útil para evitar el parpadeo de los controles visuales). Establece los valores para todos los campos de un registro. Actualiza el contenido del registro actual leyéndolo de la base de datos. Abre el conjunto de datos. este método ignora los cambios hechos previamente que todavía no han sido enviados a la base de datos. Mueve el cursor al siguiente registro. Mueve el cursor al primer registro. Eventos Evento AfterCancel AfterClose AfterDelete AfterEdit AfterInsert AfterOpen file:///D|/Manuales/databases/tdataset.html (3 of 8) [27/02/2003 16:24:26] Descripción (¿cuándo se genera?) Después de cancelar las modificaciones. Inserta un registro en el conjunto de datos con los datos que se le indiquen y los envía con Post(). Recupera la lista con los nombres de los campos del conjunto de datos. Activa los controles de datos asociados al conjunto de datos. Devuelve el estado actual cuando las actualizaciones en caché se activan. Obtiene todos los registros desde la posición actual del cursor hasta el final del conjunto de datos y los almacena localmente. Cuando se cierra un conjunto de datos Después de que un registro se haya eliminado. . Cierra el conjunto de datos.

Antes de abrir el conjunto de datos. Antes de entrar en modo edición. con la posibilidad de generar una excepción (DatabaseError) file:///D|/Manuales/databases/tdataset. Cuando ocurre algún error al eliminar una tupla.html (4 of 8) [27/02/2003 16:24:26] . Antes de que se cierre un conjunto de datos. Antes de que se cancelen los cambios. } Validaciones a nivel de registros Comprobaciones como respuesta al evento BeforePost. Cuando ocurre un error al enviar los cambios. Cuando ocurre un error al actualizar los datos. Cuando ocurre algún error al editar una tupla. Introducción de datos Asignación de valores por omisión en el evento OnNewRecord utilizando FieldValues void __fastcall TDataModuleXXX::TableNewRecord(TDataSet *DataSet) { DataSet->FieldValues["Date"] = Date(). Antes de eliminar un registro. Antes de enviar las modificaciones.C++ Builder AfterPost BeforeCancel BeforeClose BeforeDelete BeforeEdit BeforeInsert BeforeOpen BeforePost OnDeleteError OnEditError OnNewRecord OnPostError OnUpdateError OnUpdateRecord EJEMPLOS DE USO DE EVENTOS Después de enviar los cambios de un registro. Cuando se actualiza el registro en la BD. Siempre que se añade un nuevo registro. Antes de que se inserte un registro.

0). OnPostError. TMsgDlgButtons()<<mbYes<<mbNo.html (5 of 8) [27/02/2003 16:24:26] . if (! tbLineas->Eof) if (MessageDlg("¿Eliminar detalles?". } else { Abort(). 0)==mrYes) { do { tbLineas->Delete(). } Eliminación en cascada Eliminar las líneas detalle de una relación master/detail interceptando el evento BeforeDelete void __fastcall TDataModulePedidos::tbPedidosBeforeDelete(TDataSet *DataSet) { tbLineas->First(). OnDeleteError Posible solución ante un error de bloqueo no concedido file:///D|/Manuales/databases/tdataset. } while (! tbLineas->Eof).mtConfirmation.tbEmpleadosHireDate->Value < 365 && tbEmpleadosSalary->Value > TopeSalarial) DatabaseError("¡Este es un enchufado!".C++ Builder void __fastcall TDataModulePersonal::tbEmpleadosBeforePost(TDataSet *DataSet) { if (Date() . } } Gestión de errores Eventos de detección de errores: OnEditError.

0) == mrRetry ) { // Esperar entre 1 y 2 segundos antes de reintentar Sleep(1000 + random(1000)). E>NativeError.E->Message)))). } } Códigos de error BDE void __fastcall TDataModuleXXX::TablePostError (TDataSet *TDataSet. ARRAYOFCONST((E->ErrorCode. Action = daRetry. EDatabaseError *E. TDBError *E = Err->Errors[i]. } else { // Abortar Action = daAbort. 0). i++) { if (i > 0) AppendStr(S. TDataAction &Action) { AnsiString S. '\n'). } } Mensajes de error personalizados file:///D|/Manuales/databases/tdataset. EDatabaseError *E. TMsgDlgButton() << mbRetry << mbAbort. if (Err) { for (int i = 0.html (6 of 8) [27/02/2003 16:24:26] . mtWarning.4x (%d): %s". EDBEngineError *Err = dynamic_cast<EDBEngineError*>(E). i < Err->ErrorCount. TDataAction &Action) { // Consultar al usuario if ( MessageDlg ( E->Message. } DatabaseError(S. Format( "%.C++ Builder void __fastcall TDataModuleXXX::TableEditError (TDataSet *DataSet. AppendStr(S.

TDataAction &Action) { TTable *T = static_cast<TTable*>(DataSet). TMsgDlgButtons() << mbYes << mbNo. // Reintentar el borrado en la tabla de pedidos Action = daRetry. I++) { TDBError *dbe = Err->Errors[I]. mtConfirmation. EDatabaseError *E. TDataAction &Action) { if (GetBDEError(E) == DBIERR_DETAILRECORDSEXIST) if ( MessageDlg( "¿Eliminar también las líneas de detalles?". file:///D|/Manuales/databases/tdataset. if (dbe->NativeError == 0) return dbe->ErrorCode. } // Relaciones maestro/detalle void __fastcall TDataModulePedidos::tbPedidosDeleteError (TDataSet *TDataSet. 0). switch (GetBDEError(E)) { case DBIERR_KEYVIOL: DatabaseErrorFmt("Clave repetida en la tabla %s". if (Err) for (int I = 0. } return -1.C++ Builder int GetBDEError(EDatabaseError *E) { EDBEngineError *Err = dynamic_cast<EDBEngineError*>(E). EDatabaseError *E. while (! tbLineas->Eof) tbLineas->Delete(). ARRAYOFCONST((T->TableName)). Tabla: %s". I < Err->ErrorCount. 0) == mrYes) { tbLineas->First(). } // Evento OnPostError para cualquier tabla void __fastcall TDataModuleXXX::PostError (TDataSet *DataSet.html (7 of 8) [27/02/2003 16:24:26] . } else // Fallar sin mostrar otro mensaje Action = daAbort. break. case DBIERR_FOREIGNKEYERR: DatabaseErrorFmt("Error en clave externa.

html (8 of 8) [27/02/2003 16:24:26] .C++ Builder ARRAYOFCONST((T->TableName)). break. } } © Fernando Berzal Galiano file:///D|/Manuales/databases/tdataset. 0).

de forma que podemos utilizarlo para hacer nuestros componentes "data-aware".C++ Builder Curso de C++ Builder Acceso a bases de datos El componente TDataSource TDataSource El componente TDataSource ofrece un mecanismo para enganchar los conjuntos de datos (Table.). etc. La propiedad AutoEdit del componente TDataSource determina si se invoca automáticamente al método Edit del conjunto de datos asociado cuando un control (un TDBEdit. solamente hay que modificar su propiedad DataSet.html (1 of 2) [27/02/2003 16:24:27] . por ejemplo) con los controles visuales que muestran los datos (TDBGrid. file:///D|/Manuales/databases/tdatasource. El código común a todos los controles de datos está recogido en TDataLink (y en su descendiente TFieldDataLink). Para cambiar el conjunto de datos enlazado a un componente de tipo TDataSource (ya sea éste una tabla o una consulta). TDataSource se encarga de toda la comunicación necesaria entre ellos. por ejemplo) recibe el foco. Implementación de componentes "data-aware" Para crear nuestros propios componentes de forma que se puedan enlazar a un conjunto de datos hemos de automatizar el intercambio de mensajes con los componentes TDataSource. TDBEdit. TDBListBox. TQuery y TStoredProc.

html (2 of 2) [27/02/2003 16:24:27] .C++ Builder © Fernando Berzal Galiano file:///D|/Manuales/databases/tdatasource.

} Iteradores Clase auxiliar para el recorrido secuencial de un conjunto de datos file:///D|/Manuales/databases/cursor. Next. MoveBy.html (1 of 2) [27/02/2003 16:24:27] . EOF. Prior.C++ Builder Curso de C++ Builder Acceso a bases de datos Cursores Cursores Ejercicios q Navegar por un conjunto de datos utilizando First. BOF. q Comprobar el efecto de DisableControls y EnableControls. try { // Mover la fila activa } __finally { // Regresar a la posición inicial Table->Bookmark = BM. Last. IsEmpty y RecordCount. Marcadores (TBookmarkStr) TBookmarkStr BM = Table->Bookmark.

} }. TDataSet* dataset. dataset->EnableControls(). ...html (2 of 2) [27/02/2003 16:24:27] . ds->First(). Screen->Cursor = crDefault. } © Fernando Berzal Galiano file:///D|/Manuales/databases/cursor. while (! Table->Eof) { // Hacer algo con la fila activa. Table->Next().. BM = ds->Bookmark.C++ Builder class TDataSetIterator { private: TBookmarkStr BM.. ds->DisableControls(). public: TDataSetIterator(TDataSet* ds) : dataset(ds) { Screen->Cursor = crHourGlass. } ~TDataSetIterator() { dataset->Bookmark = BM. TDataSetIterator dsi(Table).

También se pueden anular las modificaciones hechas en un registro con el método RevertRecord().html (1 of 2) [27/02/2003 16:24:27] . Los conjuntos de datos de C++ Builder vienen equipados con una propiedad. CachedUpdates. Para confirmar los cambios se ha de llamar a CommitUpdates(). los cambios en los registros no se escriben en la base de datos.C++ Builder Curso de C++ Builder Acceso a bases de datos Actualizaciones en caché Actualizaciones en caché Las actualizaciones en caché son un recurso del BDE para mejorar el rendimiento de las transacciones en entornos cliente/servidor. se escriben en un buffer de la máquina local. file:///D|/Manuales/databases/cache. Cuando la propiedad CachedUpdates está a true. En su lugar. que decide si los cambios efectuados en el conjunto de datos son grabados inmediatamente en la base de datos o si se almacenan en la memoria del ordenador cliente y se envían en bloque al servidor a petición del programa cliente. Para anular los cambios almacenados en caché se puede usar el método CancelUpdates(). Los registros se mantienen en la caché hasta que se llama al método ApplyUpdates().

html (2 of 2) [27/02/2003 16:24:27] . Más fácil mantener la atomicidad de las transacciones (se permite hacer commit o rollback de varios cambios a la vez). // this = la base de datos sobre la que estemos trabajando try { for (int i = 0. i <= DataSets_size. } Ventajas q Disminuye el número de paquetes enviados por la red (se reduce el tráfico de red). © Fernando Berzal Galiano file:///D|/Manuales/databases/cache. } catch(Exception&) { Rollback(). i++) DataSets[i]->CommitUpdates(). // Propagar la excepción } for (int i = 0. Los registros de la base de datos sólo se bloquean cuando se hace el volcado de la caché (transacciones más cortas). throw.C++ Builder StartTransaction(). i++) DataSets[i]->ApplyUpdates(). q q Desventajas q Varios usuarios pueden trabajar con el mismo registro simultáneamente (al no existir bloqueos). // Nunca fallan Una alternativa es forzar el vaciado de los buffers escribiendo: void __fastcall TDataModuleXXX::TableAfterPost(TObject *Sender) { static_cast<TDBDataSet*>(Sender)->FlushBuffers(). // Pueden fallar Commit(). i <= DataSets_size.

Fijar las propiedades necesarias para especificar correctamente la relación maestro/detalle (vg: reunión CustNoÞCustNo usando como índice CustNo). ReadOnly Métodos: Open&Close.html (1 of 6) [27/02/2003 16:24:28] . Entre sus múltiples propiedades y métodos destacan: q Propiedades: DatabaseName. Ejercicio q Crear un módulo de datos (DataModule) que contenga dos tablas (clientes y pedidos. TableName. q Establecer la propiedad MasterSource en la tabla detalle para que apunte al DataSource de la tabla maestra. Además. GotoCurrent q Relaciones maestro/detalle Para construir una relación maestro/detalle en C++ Builder basta con indicar el DataSource de la tabla maestro en la propiedad MasterSource de la tabla detalle y establecer la condición de la reunión (join) mediante la propiedad MasterFields. Para ello es necesario realizar el #include correspondiente.C++ Builder Curso de C++ Builder Acceso a bases de datos TTable El componente TTable facilita el acceso más simple y rápido a una tabla. Filtros Para realizar búsquedas se pueden utilizar tablas con filtros. por ejemplo) y sus correspondientes DataSources. hay que especificar IndexName o IndexFieldNames para establecer un orden en la tabla detalle (y ¡para que C++Builder lo haga eficientemente!). Un filtro se puede construir usando la file:///D|/Manuales/databases/ttable. Búsquedas Una necesidad bastante común en cualquier aplicación de bases de datos es la de seleccionar un conjunto de registros que cumplan una condición. q Crear un formulario que contenga dos componentes TDBGrid enlazados a las tablas del módulo de datos (a sus DataSources para ser más precisos).

C++ Builder propiedad Filter (con FilterOptions) o el evento OnFilterRecord. // Extraer el nombre del campo AnsiString Campo = DBGrid->SelectedField->FieldName. Table->Filtered = True. // Activar directamente el filtro miActivarFiltro->Checked = True. La propiedad Filtered indica si el filtro está activo. ARRAYOFCONST((Table1->Filter.'. Table->Filtered = miActivarFiltro->Checked. Operador = Sender == miIgual ? "=" : Sender == miMayorIgual ? ">=" : Sender == miMenorIgual ? "<=" : "<>". Medite antes de decidirse a utilizar OnFilterRecord. Table->Refresh(). AnsiString Operador. ARRAYOFCONST((Campo. Valor))). } void __fastcall TFormX::miActivarFiltroClick(TObject *Sender) { miActivarFiltro->Checked = ! miActivarFiltro->Checked. Campo. file:///D|/Manuales/databases/ttable. // Extraer y dar formato al valor seleccionado if (TiposConComillas. FindNext(). ftDataSet> TiposConComillas. // Activar o desactivar en dependencia del estado de la opción del menú. TiposConComillas < ftString < ftDate < ftTime < ftDateTime. else Table->Filter = Format("%s AND [%s] %s %s". else { Valor = DBGrid->SelectedField->AsString. void __fastcall TFormX::Filtrar(TObject *Sender) { Set<TFieldType.Contains(DBGrid->SelectedField->DataType)) Valor = QuotedStr(DBGrid->SelectedField->AsString). Valor))). i <= Valor. i++) if (Valor[i] == DecimalSeparator) Valor[i] = '. Un conjunto de datos filtrado puede recorrerse usando los métodos FindFirst().html (2 of 6) [27/02/2003 16:24:28] . } // Combinar la nueva condición con las anteriores if (Table->Filter == "") Table->Filter = Format("[%s] %s %s".Length(). Valor. ftUnknown. Operador. lo cual implica que la aplicación debe bajarse a través de la red incluso los registros que no satisfacen el filtro. for (int i = 1. FindPrior() y FindLast(). Este tipo de filtro se aplica en el cliente. Operador.

} void __fastcall TFormX::miEliminarFiltroClick(TObject *Sender) { miActivarFiltro->Checked = False.html (3 of 6) [27/02/2003 16:24:28] . Table->Filtered = False.C++ Builder Table->Refresh(). Table->Refresh(). Debe existir un índice sobre esas columnas.ButtonClick(TObject *Sender) { Table->SetKey(). Alternativamente se pueden utilizan las combinaciones SetKey+GotoKey (en vez de FindKey) y SetKey+GotoNearest (sustituyendo a FindNearest) void __fastcall TFormDatos. } Rangos También se puede limitar el conjunto de registros de un conjunto de datos utilizando rangos mediante los métodos SetRange y CancelRange. Un rango es una restricción de las filas visibles de una tabla en la que se muestran sólo aquéllas tuplas en las cuales los valores de ciertas columnas se encuentran entre dos valores dados. Table->Filter = "". } NB: Los filtros también son aplicables a componentes de tipo TQuery Índices Se pueden hacer búsquedas usando el índice activo de una tabla (establecido por IndexName o IndexFieldNames) usando los métodos FindKey y FindNearest. else Table->Cancel(). file:///D|/Manuales/databases/ttable. // FormSearch => diálogo del tipo OK/Cancel con TDBEdits if (FormSearch->ShowModal() == mrOk) Table->GotoNearest().

"Nombre. } Locate & Lookup Los métodos Locate y Lookup amplían las posibilidades de los métodos de búsqueda con índices. // Actualizamos los controles asociados Table->Refresh(). 0). AnsiString TDataModulePersonal::ObtenerNombre(int Codigo) { return VarToStr(tbClientes->Lookup("Código". else // Activamos el rango correspondiente Table->SetRange(ARRAYOFCONST((Letra)). Letra = TabControl->Tabs->Strings[TabControl1->TabIndex]. Codigo. al revés.C++ Builder void __fasctcall TFormAgenda::TabControlChange(TObject *Sender) { AnsiString Letra.Apellido"). if (VarIsNull(V)) DatabaseError("Empleado no encontrado". "Código"). Nombre))). 0).ARRAYOFCONST((Letra + "zzz"))). Codigo. para buscar el nombre de un empleado conociendo su código personal o. const AnsiString Nombre) { Variant V = tbEmpleados->Lookup( "Apellido. } AnsiString TDataModulePersonal::NombreDeEmpleado(int Codigo) { Variant V = tbEmpleados->Lookup("Codigo". El primero intenta encontrar un registro con los valores deseados (usando índices si los hay). if (VarIsNull(V)) DatabaseError("Empleado no encontrado".Nombre". file:///D|/Manuales/databases/ttable. VarArrayOf(ARRAYOFCONST((Apellido. "Nombre")).html (4 of 6) [27/02/2003 16:24:28] . para encontrar el código de un empleado del que conocemos su nombre). return V. if (TabControl->TabIndex == 0) // Si es la pestaña con el asterisco mostramos todas las filas. mientras que el segundo se utiliza para buscar el valor de una columna utilizando como clave una diferente (por ejemplo. Table->CancelRange(). } int TDataModulePersonal::ObtenerCodigo(const AnsiString Apellido.

GetElement(0) + " " + V. } Actualizaciones Actualización programada TableDetail->Edit().GetElement(1)... file:///D|/Manuales/databases/ttable. try { // Asignaciones a campos. // == TableDetail->FieldByName("Fecha")->AsDateTime = Date(). } return Rslt. char LastChar = 'A'. i <= Longitud. // Post TableDetail->Post(). TableDetail->Fields->Fields[x]->Assign(TableMaster->Fields>Fields[x]). for (int i = 1. TableDetailConcepto->Clear(). throw. i++) { LastChar = strchr("AEIOUNS". AnsiString Rslt. Rslt[i] = LastChar. } catch (Exception&) { TableDetail->Cancel().SetLength(Longitud). TableDetailFecha->Value = Date(). Rslt. LastChar) ? random(26) + 'A' : Vocales[random(5)]. // == TableDetail->FieldValues["Fecha"] = Date().C++ Builder return V. } Inserción de datos AnsiString RandomString (int Longitud) { char* Vocales = "AEIOU".html (5 of 6) [27/02/2003 16:24:28] .

2) Tabla->AppendRecord( ARRAYOFCONST ( RandomString(longitud). Table->Cancel(). while (registros > 0) try { 1) Tabla->Append(). Tabla->Post().html (6 of 6) [27/02/2003 16:24:28] . random(MAXINT) ) )). int longitud = Tabla->FieldByName("Cadena")->Size.C++ Builder } void CrearDatosSinteticos (TTable *Tabla. Tabla->FieldValues["Entero"] = random(MAXINT). © Fernando Berzal Galiano file:///D|/Manuales/databases/ttable. Tabla->FieldValues["Cadena"] = RandomString(longitud). randomize(). registros--. // NOTA: Sería más eficiente si se agrupasen // distintas inserciones en una única transacción intentos = 3. int registros) { int intentos = 3. } } Refresco de los datos El contenido actual de la fila activa se puede obtener llamando de forma consecutiva a Edit y Cancel (lo que es más eficiente que llamar a Refresh sobre el conjunto completo de datos) Table->Edit(). if (intentos == 0) throw. } catch(Exception&) { intentos--.

no todas las consultas son actualizables. En tiempo de ejecución. UPDATE o DELETE. Sentencias SQL con parámetros En las sentencias SQL se pueden utilizar parámetros. Enlazar el DataSource que tenía la tabla a la nueva consulta. En la propiedad SQL de la consulta. se puede usar Open() para ejecutar una consulta (SELECT). El valor de tales parámetros se puede establecer file:///D|/Manuales/databases/tquery. Enlazarla con la base de datos BCDEMOS (propiedad DatabaseName). En los siguientes apartados se describen sus propiedades y métodos básicos: La consulta SQL La propiedad SQL es de tipo TStringList (un lista de cadenas de caracteres) y contiene la sentencia SQL que ha de ejecutarse sobre la base de datos indicada mediante la propiedad DatabaseName. Por desgracia.C++ Builder Curso de C++ Builder Acceso a bases de datos TQuery El componente TQuery permite realizar consultas en SQL.html (1 of 4) [27/02/2003 16:24:28] . teclear: select * from customer where CustNo > 1300 Otra propiedad bastante interesante del componente TQuery es LiveRequest. Los parámetros son variables que se escriben en la sentencia SQL precedidos de : (dos puntos). o ExecSQL() para ejecutar una sentencia SQL de tipo INSERT. que podamos editar su conjunto de datos sin tener que preocuparnos de cómo almacenar los cambios en la base de datos). que permite que una consulta sea actualizable (es decir. Ejecución de sentencias SQL Para ejecutar en tiempo de diseño la sentencia SQL correspondiente a una consulta (un SELECT) basta con poner su propiedad Active a true (lo que equivale a invocar al método Open()). Ejemplo: q q q q Cambiar la tabla de clientes por una consulta.

query->SQL->Add( "select * from customer where CustNo > :ValorMinimo"). La propiedad Prepared nos indica si una consulta ha sido preparada o no.html (2 of 4) [27/02/2003 16:24:28] . query->Open(). Para ello hemos de dejar file:///D|/Manuales/databases/tquery. Preparación inicial de una consulta if (! Query->Prepared) Query->Prepare(). En tiempo de diseño: Preparar una consulta SQL con: select * from customer where CustNo > :ValorMinimo Editar la propiedad Params estableciendo el parámetro ValorMinimo como un integer con valor 1300. Query->Open(). } En los parámetros también se pueden utilizar comodines: Query->ParamByName("id")->AsString = Edit->Text + "%". query->ParamByName("ValorMinimo")->AsInteger = 1300. En tiempo de ejecución: { query->SQL->Clear(). que serán más eficientes si se ejecutan múltiples veces siempre que nuestra base de datos permita este tipo de consultas optimizadas.C++ Builder accediente a la propiedad Params del componente TQuery o mediante el método ParamByName. Consultas dependientes [linked queries] Mediante consultas también se pueden establecer relaciones maestro/detalle. Liberación de recursos Query->Close(). if (Query->Prepared) Query->UnPrepare(). Los métodos Prepare() y UnPrepare() sirven para ejecutar consultas preparadas.

} catch(Exception&) { if (--Intentos == 0) throw. try { int Intentos = 3. query->DatabaseName = ADatabase. CantRegistros--. en la consulta SQL hay que indicar las tablas utilizando la notación :ALIAS:tabla. int CantRegistros) { randomize(). Para enlazar la consulta basta entonces establecer su propiedad DataSource para que apunte a la tabla maestra. return query->RowsAffected. Intentos = 3. Query->ExecSQL(). Query->Prepare(). Para ello. file:///D|/Manuales/databases/tquery. } Datos sintéticos insert into TablaAleatoria(Entero. update & delete) int __fastcall ejecutarSQL(const AnsiString ADatabase.C++ Builder un parámetro de la consulta detalle asociado a una columna del conjunto de datos que hace de maestro. SIN especificar su tipo. while (CantRegistros > 0) try { Query->ParamByName("ENT")->AsInteger = random(MAXINT). query->ExecSQL(). :Cad) void RellenarTabla(TQuery *Query. query->SQL->Text = Instruccion. Query->ParamByName("CAD")->AsString = RandomString(35). const AnsiString Instruccion) { std::auto_ptr query(new TQuery(NULL)). donde ALIAS es el alias BDE de la base de datos donde se encuentra la tabla tabla. Actualizaciones (insert. por lo que usualmente preferiremos utilizar tablas (TTables). Este tipo de consultas NO son actualizables.html (3 of 4) [27/02/2003 16:24:28] . Cadena) values (:Ent. Consultas heterogéneas El motor de bases de datos de Borland (BDE) permite incluso realizar consultas que involucren tablas almacenadas en distintas bases de datos.

} } © Fernando Berzal Galiano file:///D|/Manuales/databases/tquery.C++ Builder } } __finally { Query->UnPrepare().html (4 of 4) [27/02/2003 16:24:28] .

CantidadTotal int. Llamar al método UnPrepare() cuando ya no se vaya a ejecutar más veces el procedimiento almacenado. TotalVentas int.html (1 of 5) [27/02/2003 16:24:28] . TotalClientes int ) as declare variable Precio int. El esquema de utilización de procedimientos almacenados es: q Indicar su nombre en la propiedad StoredProcName. Invocarlo tantas veces como sea necesario con ExecProc(). begin select Precio from Articulos where Codigo = :CodProd into :Precio. Preparar su ejecución con el método Prepare(). count(distinct RefCliente) from Pedidos where :CodProd file:///D|/Manuales/databases/tstoredproc. select count(Numero).C++ Builder Curso de C++ Builder Acceso a bases de datos TStoredProc El componente TStoredProc representa un procedimiento almacenado en un servidor de bases de datos. Establecer sus parámetros (igual que en una consulta TQuery). q q q q Procedimientos almacenados que devuelven valores create procedure EstadisticasProducto (CodProd int) returns ( TotalPedidos int.

} } Procedimientos almacenados que devuelven conjuntos de datos file:///D|/Manuales/databases/tstoredproc. :TotalClientes. sp->ParamByName("CodProd")->AsString = S. if ( InputQuery("Información". S) && Trim(S) != "" ) { TStoredProc *sp = DataModuleProductos->spEstadisticas.::EstadisticasProducto(TObject *Sender) { AnsiString S. sum(Cantidad*:Precio*(100-Descuento)/100) from Detalles where Detalles. :TotalVentas. end ^ void __fastcall .RefArticulo = :CodProd into :CantidadTotal. sp->ParamByName("CantidadTotal")>AsInteger.html (2 of 5) [27/02/2003 16:24:28] . ARRAYOFCONST((sp->ParamByName("TotalPedidos")>AsInteger. select sum(Cantidad).. "Código del producto".C++ Builder in ( select RefArticulo from Detalles where RefPedido = Numero ) into :TotalPedidos. sp->ParamByName("TotalClientes")>AsInteger. sp->ParamByName("TotalVentas")>AsFloat)))).. sp->ExecProc(). ShowMessage( Format( "Pedidos: %d\nClientes: %d\nCantidad: %d\nTotal: %m".

SUB TID not null references CATEGORY. description TDESCRIPTION. create domain TDESCRIPTION as VARCHAR(128).C++ Builder Definimos una base de datos (en InterBase) para almacenar una jerarquía de conceptos (como las categorías de un índice en Internet tipo Yahoo!): create domain TID as INTEGER.html (3 of 5) [27/02/2003 16:24:28] . for select * from DESCENDANTS(:sub) into :sub do begin if (sub is not null) then SUSPEND. end end END end ^ create procedure ANCESTORS (sub integer) file:///D|/Manuales/databases/tstoredproc. create table CATEGORY ( ID TID not null. create table HIERARCHY ( SUPER TID not null references CATEGORY. primary key (SUPER. Creamos sendos procedimientos almacenado recursivos que nos devuelven todas las categorías por debajo (o por encima) de una categoría dada en la jerarquia: create procedure DESCENDANTS (super integer) returns (sub integer) as begin FOR SELECT sub FROM HIERARCHY WHERE SUPER = :super INTO :sub DO BEGIN if (sub is not null) then begin SUSPEND. primary key (ID) ).SUB) ).

end end END end ^ set term .^ Para utilizar los procedimientos almacenados anteriores. se puede escribir alguna de las siguientes consultas parametrizadas en la propiedad SQL de un TQuery: select distinct * from descendants(:id) select distinct * from ancestors(:id) Ejecución de un procedimiento almacenado en una hebra independiente file:///D|/Manuales/databases/tstoredproc.C++ Builder returns (super integer) as begin FOR SELECT id FROM HIERARCHY WHERE SUB = :sub INTO :super DO BEGIN if (super is not null) then begin SUSPEND.html (4 of 5) [27/02/2003 16:24:28] . for select * from ANCESTORS(:super) into :super do begin if (super is not null) then SUSPEND.

// Ejecutar la hebra } // // // // DataModuleSPThread es un módulo de datos con tres componentes: . } } // Ejecución void __fastcall TForm1::Btn1Click(TObject *Sender) { new TSPThread.C++ Builder class TSPThread : public TThread { protected: void __fastcall Execute(). Resume(). void __fastcall TSPThread::Execute() { DataModuleSPThread->DatabaseSPThread->Open().html (5 of 5) [27/02/2003 16:24:28] . try { DataModuleSPThread->StoredProcSPThread->ExecProc(). } __finally { DataModuleSPThread->SessionSPThread->Close(). . }.SessionSPThread (de tipo TSession).DatabaseSPThread (de tipo TDatabase).StoredProcSPThread (de tipo TStoredProc). } © Fernando Berzal Galiano file:///D|/Manuales/databases/tstoredproc. public: __fastcall TSPThread(). y . __fastcall TSPThread::TSPThread():TThread(True) // Crear hebra "suspendida" { FreeOnTerminate = True.

TFloatField y TDateField.).. Sus descendientes incluyen a TStringField. TField es una clase base de la que se derivan otras muchas. y también se puede acceder a su valor a través de propiedades como AsString o AsInteger. índice. si es obligatorio..html (1 of 7) [27/02/2003 16:24:29] . TIntegerField. entre otros muchos. si es un campo calculado o de búsqueda.C++ Builder Curso de C++ Builder Acceso a bases de datos TField Acceso a las columnas de un conjunto de datos La clase TField representa un campo (una columna) en un conjunto de datos. Por medio de esta clase pueden establecer los atributos de un campo (tipo. Nuevos en C++Builder 4: file:///D|/Manuales/databases/tfield. tamaño.

q __property TFields* TDataSet::Fields. __property TField* TFields::Fields[int Index].html (2 of 7) [27/02/2003 16:24:29] . __property int TFields::Count. q El método FieldByName() de TDataSet. TField* __fastcall TDataSet::FieldByName(const AnsiString Nombre). Ejemplo file:///D|/Manuales/databases/tfield.C++ Builder Acceso a los valores de los campos Para recuperar o establecer el valor de un campo podemos usar: q Un objeto TField creado con el editor de campos [Fields Editor]. La propiedad Fields de TDataSet.

ej. Personalización de la visualización.C++ Builder TablaApellidos->Value = "Pérez Martín". file:///D|/Manuales/databases/tfield. Restricción en el valor del campo. El Editor de Campos [Fields Editor] Desde el menú contextual de cualquier descendiente de TDataSet (vg: TTable o TQuery) se permite el acceso al "Fields Editor" en tiempo de diseño. De esta forma se pueden especificar aquellos campos que se quieren incluir en el conjunto de datos y sus propiedades. Valor en la fila activa. q Añadir los campos que deseemos utilizar. Mensaje de error asociado. Tabla->FieldByName("Apellidos")->Value = "Pérez Martín". Propiedades interesantes de TField Propiedad FieldName DisplayLabel Value IsNull DisplayFormat EditMask CustomConstraint ConstraintErrorMessage Descripción Nombre de la columna en la BD.html (3 of 7) [27/02/2003 16:24:29] . Control de la edición del campo. seleccionándolos en el Fields Editor). q Seleccionar Add Fields en el menú del Fields Editor. Ejemplo q Seleccionar del menú contextual (botón derecho del ratón) de cualquier TDataSet la opción Fields Editor. Texto descriptivo empleado por TDBGrid. Tabla->Fields->Fields[0]->Value = "Pérez Martín". Indica si el valor es nulo. q Ver las propiedades de los campos en el Inspector de Objetos (p.

"MMM"}.html (4 of 7) [27/02/2003 16:24:29] . if (Sender->AsInteger > 3999) { Text = "Infinitum". "D". static AnsiString Centenas[10] = {"". "LX". void __fastcall . Uso de TField Visualizacion personalizada Definiendo la respuesta al evento GetText Seleccionar un campo de tipo entero y hacer que se visualice con números romanos. "XX". "II". bool DisplayText) { static AnsiString Unidades[10] = {"". "XXX". "DC". Al editar valores. // Hay que ser consecuentes con el lenguaje } else { int i = Sender->AsInteger. "DCC".. "M". "DCCC". "VI". "VII". "IV". static AnsiString Decenas[10] = {"". "X". "III". "XL".C++ Builder ReadOnly Campo de sólo lectura Los eventos de TField Evento OnChange OnValidate OnGetText OnSetText Descripción Cuando cambia el valor del campo.::tbFieldGetText (TField *Sender. Validación a nivel de campos. "VIII". "CC". "XC"}. AnsiString &Text. "C". Text = Miles[i / 1000] file:///D|/Manuales/databases/tfield. "IX"}. "CCC". "I". static AnsiString Miles[4] = {"". "MM". "CD". "L". "LXXX". "LXX". Al visualizar valores. "V". "CM"}..

::tbFieldSetText(TField *Sender. AnsiString S = Text. for ( i=1.Length().C++ Builder + Centenas[i / 100 % 10] + Decenas[i / 10 % 10] + Unidades[i % 10]. Definiendo la respuesta al evento SetText: Forzar que las iniciales de los nombres sean siempre letras mayúsculas void __fastcall . const AnsiString Text) { int i.html (5 of 7) [27/02/2003 16:24:29] .. Utilizando el evento OnValidate: Un nombre propio no puede incluir dígitos ni otros simbolos file:///D|/Manuales/databases/tfield. i<=S. i++) if ( i==1 || S[i-1]==' ') CharUpperBuff(&S[i]. } 2. 1).. } } Restricciones a nivel de campos 1. Sender->AsString = S.

C++ Builder

void __fastcall ...::tbFieldValidate(TField *Sender) { AnsiString S = Sender->AsString; for (int i = S.Length(); i > 0; i--) if (S[i] != ' ' && !IsCharAlpha(S[i])) DatabaseError("Carácter no permitido en nombre propio", 0); }

3. Controlando el valor que puede tomar un campo mediante sus propiedades EditMask y CustomConstraint. Cuando se utiliza esta última, lo normal es definir también ConstraintErrorMessage para que el usuario sepa por qué no puede darle determinados valores a un campo. Valores no nulos CustomConstraint = value is not null Código postal EditMask = !99999;1;_ Teléfono o fax EditMask = !999 99 99 99;0;_ Dirección de correo electrónico CustomConstraint = value is null or value='' or value like '%_@%_.%_'

Campos calculados
Se crean con New field (Calculated) desde el menú contextual del editor de campos y se manejan a través del evento OnCalcFields, que se produce cada vez que se cambia o se modifica la fila activa del conjunto de datos (si está a true la propiedad AutoCalcFields del conjunto de datos).

file:///D|/Manuales/databases/tfield.html (6 of 7) [27/02/2003 16:24:29]

C++ Builder

Campos de búsqueda [lookup fields]
Se pueden crear con la opción New field (Lookup) del menú contextual del editor de campos. Se definen mediante las propiedades KeyFields, LookupDataset, LookupKeyFields y LookupResultField. Mediante LookupCache se pueden cargar los valores permitidos en la propiedad LookupList, la cual se puede actualizar llamando a RefreshLookupList.

BLOBs: TBlobField
Los campos de tipo BLOB [Binary Large OBject] en una base de datos se pueden utilizar para almacenar ficheros completos, imágenes, sonidos o cualquier otro tipo de información digitalizada. El contenido de este tipo de campos se puede modificar invocando al método LoadFromFile, mientras que su complementario (SaveToFile) nos permite recuperar la información almacenada en la base de datos. Imágenes en formato JPG (jpeg.hpp) void __fastcall ...::DataSourceImagenDataChange(TObject *Sender, TField *Field) { if (tbImagenesFoto->IsNull) Image->Picture->Graphic = NULL; else { std::auto_ptr BS(new TBlobStream(tbImagenesFoto, bmRead)); auto_ptr Graphic(new TJPEGImage); Graphic->LoadFromStream(BS.get()); Image->Picture->Graphic = Graphic.get(); } }

© Fernando Berzal Galiano

file:///D|/Manuales/databases/tfield.html (7 of 7) [27/02/2003 16:24:29]

C++ Builder

Curso de C++ Builder Acceso a bases de datos
TSession

El componente TSession gestiona una sesión de la base de datos (un conjunto de conexiones desde una misma aplicación). Cada vez que se inicia una aplicación que accede a bases de datos a través del motor de bases de datos de Borland, el BDE establece un objeto de tipo TSession global llamado Session con el cual se puede acceder a las propiedades de la sesión actual. En principio, no hay que crear un objeto TSession propio salvo que se esté construyendo una aplicación multihebra. Este componente incluye algunos métodos de interés:

Gestión de alias BDE
AddAlias(), AddStandardAlias(), ModifyAlias(), DeleteAlias() y SaveConfigFile() son métodos que pueden usarse para gestionar alias BDE en tiempo de ejecución.
void __fastcall TSession::AddAlias (const AnsiString Nombre, const AnsiString Ctrldor, TStrings *Lista); void __fastcall TSession::AddStandardAlias (const AnsiString Nombre, const AnsiString Dir, const AnsiString Ctrldor); void __fastcall TSession::ModifyAlias (const AnsiString Alias, TStrings *Parametros); void __fastcall TSession::DeleteAlias (const AnsiString Alias); void __fastcall TSession::SaveConfigFile();

Acceso al catálogo
GetAliasNames(), GetDatabaseNames(), GetDriverNames(), GetTableNames() y GetStoredProcNames() se pueden utilizar para conseguir información acerca de las bases de datos disponibles en el sistema.
void __fastcall TSession::GetDriverNames (TStrings *Lista);
file:///D|/Manuales/databases/tsession.html (1 of 2) [27/02/2003 16:24:29]

C++ Builder

void __fastcall TSession::GetDriverParams (const AnsiString Controlador, TStrings *Lista); void __fastcall TSession::GetDatabaseNames (TStrings *Lista); void __fastcall TSession::GetAliasNames (TStrings *Lista); AnsiString __fastcall TSession::GetAliasDriverName (const AnsiString Alias); void __fastcall TSession::GetAliasParams (const AnsiString Alias, TStrings *Lista); void __fastcall TSession::GetTableNames (const AnsiString Alias, const AnsiString Patron, bool Extensiones, bool TablasDeSistema, TStrings *Lista); void __fastcall TSession::GetStoredProcNames (const AnsiString Alias, TStrings *Lista);

Ejemplo:

Session->GetDatabaseNames(DBNamesComboBox->Items);

© Fernando Berzal Galiano

file:///D|/Manuales/databases/tsession.html (2 of 2) [27/02/2003 16:24:29]

C++ Builder

Curso de C++ Builder Acceso a bases de datos
TDatabase

El componente TDatabase permite controlar las conexiones a una base de datos. Aunque su uso no es estrictamente necesario, hay ciertas operaciones para las que resulta imprescindible:

Conexiones persistentes con bases de datos
La propiedad KeepConnections de TDatabase se utiliza para controlar cómo se manejan las conexiones con las bases de datos cuando se cierra un dataset. Si KeepConnections está a false, cuando se cierra el último dataset, la conexión con la base de datos se pierde y habrá que reiniciarla la próxima vez que se abra otro dataset, lo que consumirá una cantidad considerable de tiempo y, si no hacemos nada para evitarlo, volverá a solicitar la clave de acceso del usuario.

Establecimiento de la conexión [Login]
El componente TDatabase también permite controlar el login de una forma automática:
q

Estableciendo la propiedad LoginPrompt a false y fijando explícitamente los parámetros de la conexión. Desde el código

file:///D|/Manuales/databases/tdatabase.html (1 of 4) [27/02/2003 16:24:30]

C++ Builder

Database->AliasName = "Oracle"; Database->DatabaseName = "MiDB"; Database->Params->Values["user name"] = "scott"; Database->Params->Values["password"] = "tiger"; Table->DatabaseName = Database->DatabaseName; Table->TableName = "CUSTOMER"; Table->Open();

Desde el inspector de objetos En el editor de listas asociado a la propiedad Params:
USER NAME=scott PASSWORD=tiger

q

Interceptando el evento OnLogin, el cual se genera cada vez que se ha de establecer una conexión cuando la propiedad LoginPrompt está a true.
void __fastcall ...::DatabaseLogin (TDatabase *Database, TStrings *LoginParams) { LoginParams->Values["user name"] = "scott"; LoginParams->Values["password"] = "tiger"; }

Schema cache
void __fastcall ...::DatabaseLogin (TDatabase *Database, TStrings *LoginParams) { ... // Schema cache AnsiString S; S.SetLength(255); int L = GetTempPath(255, S.c_str()); if (S.IsPathDelimiter(L)) L--;

file:///D|/Manuales/databases/tdatabase.html (2 of 4) [27/02/2003 16:24:30]

C++ Builder

S.SetLength(L); Database1->Params->Values["ENABLE SCHEMA CACHE"] = "TRUE"; Database1->Params->Values["SCHEMA CACHE DIR"] = S; }

Control de Transacciones
Otro uso más del componente TDatabase (puede que el más importante) es el control explícito de las transacciones con la base de datos. Una transacción es una colección de operaciones sobre la base de datos (inserciones, modificaciones o eliminaciones de registros) que ha de realizarse de forma atómica. Una transacción con la base de datos se inicia explícitamente llamando al método StartTransaction(). Las modificaciones realizadas sobre la base de datos no se harán efectivas hasta que se invoque al método Commit(). Si se quiere cancelar la transacción en curso hay que recurrir al método Rollback(), lo cual hará que las operaciones efectuadas en la transacción sean ignoradas. Mediante la propiedad TransIsolation se puede establecer la el nivel de aislamiento entre distintas transacciones. El nivel tiRepeatableRead (lecturas repetibles) será siempre el deseable, aunque con determinados servidores SQL sólo se llega a tiCommitedRead ("lecturas comprometidas") y las bases de datos de escritorio (tipo Paradox, dBase o Access) sólo permiten tiDirtyRead. Una transferencia bancaria TLocateOptions Opt;
// Iniciar la transacción Database->StartTransaction(); try { if (! Table->Locate("Cliente", cliente1, Opt)) DatabaseError("No existe el primer cliente", 0); Table->Edit(); Table->FieldValues["Saldo"] -= importe; Table->Post(); if (! Table->Locate("Cliente", cliente2, Opt)) DatabaseError("No existe el segundo cliente", 0);
file:///D|/Manuales/databases/tdatabase.html (3 of 4) [27/02/2003 16:24:30]

Table->Post().1. } Cancelar los cambios realizados desde el ultimo commit/rollback void CancelarCambios (TDatabase* ADatabase) { ADatabase->Rollback(). for (int i = ADatabase->DataSetCount . // Confirmar la transacción Database->Commit(). i >= 0. } © Fernando Berzal Galiano file:///D|/Manuales/databases/tdatabase. throw. i--) ADatabase->DataSets[i]->Refresh(). Table->Refresh().C++ Builder Table->Edit(). Table->FieldValues["Saldo"] += importe. } catch(Exception&) { // Cancelar la transacción Database->Rollback().html (4 of 4) [27/02/2003 16:24:30] .

C++Builder y JBuilder) que permite crear. Visualización de tablas Visualizar el contenido de las tablas BCDEMOS:holdings.DB con los siguientes campos: q q q q q NOMBRE (alpha. 64 caracteres) EMAIL (alpha.db (en formato Paradox). file:///D|/Manuales/databases/examples/agenda. 32 caracteres) DIRECCIÓN (memo) FOTO (graphic) NACIMIENTO (date) BDE Administrator Panel de control de Windows Es la utilidad que permite gestionar los alias del motor de bases de datos de Borland. visualizar.C++ Builder Curso de C++ Builder Acceso a bases de datos Un ejemplo completo Database Desktop Es una herramienta incluida en los entornos de desarrollo de Borland/Inprise (Delphi. consultar y ordenar tablas almacenadas en distintos formatos (como Paradox o dBase). Creación de tablas Crear una tabla Paradox llamada AGENDA.dbf (en formato dBase) y BCDEMOS:vendors.html (1 of 3) [27/02/2003 16:24:30] .

Al módulo de datos lo llamamos dmAgenda y la unidad correspondiente la guardamos como DataAgenda. Tenemos que establecer las propiedades DatabaseName y TableName del componente TTable. Para que los componentes del módulo de datos sean visibles desde el formulario hemos de añadir el #include correspondiente en el fichero .DB.C++ Builder Creación de alias Creamos un nuevo alias de tipo STANDARD (el usado para tablas Paradox y dBase) y lo denominamos AGENDA.cpp del formulario. C++Builder Desarrollo de la aplicación Creamos un proyecto llamado Agenda y su formulario principal lo guardamos con el nombre FormAgenda. Añadimos al formulario principal los componentes necesarios para poder manejar nuestra agenda. NOTA: La creación de alias la prodríamos haber realizado desde la opción Alias Manager del Database Desktop e incluso desde el código de nuestra aplicación. Para introducir fotos en nuestra base de datos podemos utilizar el componente file:///D|/Manuales/databases/examples/agenda. Con el "Fields Editor" del menú contextual de TableAgenda creamos los cinco componentes TField correspondientes a las cinco columnas de nuestra tabla. Esto es equivalente a mantener la propiedad Active del conjunto de datos a true (aunque es preferible porque no tiene sentido mantener conexiones abiertas cuando no se están utilizando). Creamos un módulo de datos que contendrá un componente TTable denominado TableAgenda con su TDataSource asociado (dsAgenda). De la misma forma interceptamos el evento OnDeactivate del formulario e invocamos al método Close de la tabla. Hemos de llamar al método Open de nuestra tabla cuando se produce el evento OnActivate del formulario.html (2 of 3) [27/02/2003 16:24:30] . En su propiedad PATH ponemos la ruta al directorio donde hemos almacenado anteriormente la tabla AGENDA. así como la propiedad DataSet del TDataSource. En la propiedad DataSource de todos los componentes data-aware seleccionaremos dmAgenda->dsAgenda.

Así mismo. Para permitir búsquedas en nuestro conjunto de datos podemos utilizar filtros NOTA: Se podría crear un cuadro de diálogo genérico que nos permita realizar búsquedas sobre cualquier conjunto de datos.. También podemos utilizar el portapapeles de Windows para poner la imagen. NOTA: El conjunto de datos debe estar en modo edición para poder establecer el valor de la imagen. Para evitar que los mensajes asociados al TDBNavigator aparezcan en inglés debemos interceptar el evento BeforeAction de este componente. los cuales devolverán un valor booleano según la búsqueda se haya realizado con éxito o no. el InstallShield Express for C++Builder. © Fernando Berzal Galiano file:///D|/Manuales/databases/examples/agenda. podríamos distribuirla generando un programa de instalación con. Sería aconsejable establecer las validaciones oportunas a nivel de campos para que se sólo se puedan introducir direcciones de correo electrónico válidas. También podríamos permitir la impresión de fichas con los datos de nuestra tabla.C++ Builder OpenPictureDialog. una vez que tengamos nuestra aplicación terminada. Para ello tendríamos que utilizar un TQuickReport o acceder directamente al canvas de la impresora (TPrinter). nuestro diálogo TDBDlgSearch debería tener una propiedad DataSet (definida utilizando la palabra reservada __property) así como métodos que permitan realizar la búsqueda (vg: find. un botón que lo llame y el método LoadFromFile de TGraphicField. deberíamos tratar mejor la introducción de fechas (para lo cual lo ideal es crear un componente derivado de TDateTimePicker). por ejemplo.. Para ello. findNext y findPrior). Finalmente.html (3 of 3) [27/02/2003 16:24:30] . Así mismo. podemos traducir las pistas asociadas a los distintos botones del TDBNavigator (propiedad Hints) y permitir su visualización (ShowHints).

En 1978. Una cuarta generación de SQL. Los datos se almacenan como filas en las tablas (tuplas). que estaba basado en un trabajo de E. Codd ("A relational model of data for large shared data banks". May 1974.). Visión general El concepto fundamental de SQL es el de tabla. ACM.C++ Builder Curso de C++ Builder Acceso a bases de datos SQL SQL es el lenguaje que se utiliza usualmente para consultar y gestionar bases de datos relacionales. integridad referencial. el estándar actualmente utilizado por la mayor parte de las bases de datos. Los disparadores [triggers] especifican acciones que el DBMS ha de realizar cada vez que se produce algún evento determinado y los procedimientos almacenados sirven para encapsular conjuntos de sentencias SQL.. y SQL utiliza 'null' para representar este hecho. en cooperación con el grupo correspondiente de ISO. ISO/IEC 9075:1992). cadena. con una o más columnas que tienen un nombre y un tipo (numérico.. aún está por conseguir su estandarización de hecho. el ANSI comenzó a estandarizar un lenguaje de definición de datos El comité técnico X3H2 del ANSI reconoció la importancia del modelo relacional y. fecha. 1974. cuando Chamberlin y Boyce publicaron el primer artículo de SEQUEL.F. Commun.html (1 of 13) [27/02/2003 16:24:31] .. pp. 249–264). 377–387). pp. Proceedings of the ACM SIGFIDET Workshop.) y su violación produce excepciones que bloquean la ejecución de las sentencias que las ocasionan. Algunos de los datos pueden ser desconocidos o inaplicables. que después se convertiría en SQL ("SEQUEL: A structured English query language". DML: Lenguaje de manipulación de datos SELECT SELECT [DISTINCT] lista-select | * file:///D|/Manuales/databases/sql.135-1992. que fue añadida en el SQL-89. No obstante. 13:6. Los orígenes de SQL se remontan a 1974. Las bases de datos SQL son autodescriptivas: las tablas del catálogo (cuya implementación depende del DBMS) almacenan información acerca de las tablas de la base de datos (metadatos). desarrolló la primera especificación de SQL en 1986. el SQL3. los estándares SQL-86 y SQL-89 no eran adecuados para aplicaciones reales y en 1992 apareció el SQL-92 (ANSI X3. Las restricciones de integridad se utilizan para forzar el cumplimiento de determinadas condiciones ('business rules'.. El SQL-86 no incluía la integridad referencial.

Ejemplo: Seleccionar aquellos vuelos que tengan como origen Madrid. . elimina las tuplas que no satisfacen la condición. SELECT * FROM VUELOS WHERE ORIGEN IN ('MADRID'. cuando está presente.html (2 of 13) [27/02/2003 16:24:31] . Cuando se indica más de una. 3. Ejemplo: Visualizar todos los vuelos que tengan como origen o destino Granada SELECT * FROM VUELOS WHERE ORIGEN='GRANADA' OR DESTINO='GRANADA' Claúsula IN Expresa la pertenencia del valor de una columna a un determinado conjunto de valores. Barcelona o Sevilla. 2. si existe. elimina duplicados. DISTINCT. 5. los grupos resultantes de GROUP BY que no satisfagan la condición se eliminan. WHERE condición GROUP BY columnas HAVING condición ORDER BY columnas Las consultas a la base de datos se realizan en SQL mediante la sentencia SELECT: 1. agrupa las tuplas que tienen los mismos valores en todas las columnas especificadas. La lista de columnas separadas por comas que aparece en el SELECT determina las columnas que se devuelven (* devuelve todas). tabla .'SEVILLA') o también SELECT * file:///D|/Manuales/databases/sql.C++ Builder FROM tabla. 4. 6.'BARCELONA'. La claúsula ORDER BY sirve para ordenar los valores devueltos por una consulta. La claúsula WHERE. Si existe una claúsula HAVING. Recuperar todas las filas de la(s) tabla(s) especificada en FROM. . La claúsula GROUP BY. 7. se devuelve su producto cartesiano. cuando aparece.

recupérense todos los vuelos que no pertenecen a IBERIA. Los dos primeros caracteres indican la compañía a la que pertenece cada vuelo (vgt: IB Iberia.C++ Builder FROM VUELOS WHERE ORIGEN='MADRID' OR ORIGEN='BARCELONA' OR ORIGEN='SEVILLA' Ejemplo: Visualizar todos los vuelos existentes excepto aquellos que llegan a Londres o a Copenhague.00. cadenas de caracteres que comparten ciertos caracteres: '%' equivale a una cadena de caracteres de longitud comprendida entre 0 y n (el '*' en MS-DOS) y '_' equivale a un único carácter (igual que '?' en MS-DOS). Bajo estas condiciones.00' equivale a SELECT * FROM VUELOS WHERE HORA_SALIDA >= '06. con la ayuda de metasímbolos (comodines).00. file:///D|/Manuales/databases/sql. BA British Airways) y los cuatro siguientes corresponden al número de vuelo.00' AND HORA_SALIDA <= '12. SELECT * FROM VUELOS WHERE NUM_VUELO NOT BETWEEN 'IB0000' AND 'IB9999' Claúsula LIKE Sirve para especificar.00' Ejemplo: La columna NUM_VUELO representa los vuelos con 6 caracteres.00' AND '12. Ejemplo: Recuperar todos los vuelos que salgan entre las 6 y las 12 de la mañana SELECT * FROM VUELOS WHERE HORA_SALIDA BETWEEN '06.00.00.'COPENHAGUE') Claúsula BETWEEN Sirve para establecer o expresar un rango de valores (valores extremos incluidos). SELECT * FROM VUELOS WHERE DESTINO NOT IN ('LONDRES'.html (3 of 13) [27/02/2003 16:24:31] .

Pueden especificarse detrás de SELECT o en la claúsula HAVING (nunca dentro de WHERE).COUNT) a una expresión aritmética en la cual debe participar.28. una columna.28.6 FROM AVIONES Funciones de agregación Son funciones que operan con todas las filas que cumplen la condicion expuesta en la claúsula WHERE. q q f(expresión) aplica una función (MIN. file:///D|/Manuales/databases/sql. Ejemplo: Número de vuelos incluidos en nuestra base de datos. Ejemplo: Visualizar la longitud y la envergadura de todos los aviones expresando las magnitudes en pies en vez de en metros y la velocidad de crucero en mph (en lugar de Km/h). COUNT(*) cuenta el número de filas de una tabla.SUM. al menos. SELECT COUNT(*) FROM VUELOS Claúsula GROUP BY-HAVING Sirve para dividir una tabla en grupos de filas que comparten características comunes. SELECT LONGITUD*3. ENVERGADURA*3. Su resultado es un único valor.C++ Builder Ejemplo: Recuperar todos los vuelos de Iberia.html (4 of 13) [27/02/2003 16:24:31] . VELOCIDAD_CRUCERO/1.AVG. SELECT * FROM VUELOS WHERE NUM_VUELO LIKE 'IB%' o SELECT * FROM VUELOS WHERE NUM_VUELOS LIKE 'IB____' Expresiones aritméticas Pueden ser utilizadas tanto en la lista de columnas que sigue a SELECT como en la claúsula WHERE.MAX.

La claúsula HAVING permite elegir aquellos grupos que se quieren visualizar y no interfiere en la agrupación realizada por GROUP BY. SELECT DESTINO FROM VUELOS GROUP BY DESTINO HAVING COUNT(*) > 2 Ejemplo: Visualizar los vuelos de Iberia que tengan plazas libres. Dos valores nulos no son iguales ni son distintos. La expresión booleana colA=colB es falsa en cuanto colA o colB sean nulos. Es decir. MIN(HORA_SALIDA). DISTINCT no elimina los valores nulos repetidos. GROUP BY agrupa todos los valores nulos en un único grupo. Las columnas sobre las que haya definido un índice único (UNIQUE) sólo pueden incluir un valor nulo (en este caso sí se consideran iguales dos valores nulos). Ejemplo: Visualizar los destinos que tengan más de dos vuelos. CAPACIDAD-COUNT(*) FROM RESERVAS WHERE NUM_VUELO LIKE 'IB%' GROUP BY NUM_VUELO HAVING COUNT(*)<CAPACIDAD Valores nulos q q q q q q q Cualquier operación aritmética sobre un campo nulo nos devolverá como resultado un valor nulo. los valores nulos son mayores o menores que cualquier otro valor cuando se devuelve un conjunto de datos ordenado. COUNT(*) FROM VUELOS GROUP BY DESTINO Notas: q q q GROUP BY crea una serie de subtablas compuestas por las filas que comparten el mismo valor en la(s) columna(s) de agrupamiento (la columna DESTINO en el ejemplo) y las funciones de agregación se aplican a cada subtabla de forma independiente. sino indeterminados. mientras que colA<>colB será cierta si sólo una de las dos columnas es nula (será falsa cuando ambas sean nulas). Las funciones de agregación ignoran los campos nulos.html (5 of 13) [27/02/2003 16:24:31] . AVG(x) no siempre será igual a SUM(x)/COUNT(*). exceptuando la función COUNT. SELECT NUM_VUELO.C++ Builder Ejemplo: Primera salida y número de vuelos diarios para cada destino SELECT DESTINO. Dependiendo del sistema gestor de bases de datos. No se puede poner en GROUP BY una columnaque no se haya incluido en la sentencia SELECT. file:///D|/Manuales/databases/sql.

.) El concatenador puede ser un operador de comparación (<. WHERE columna concatenador (SELECT . Ejemplo: Plazas libres que hay en cada vuelo MADRID-LONDRES del día 20/02/2001..>=) o la claúsula IN.C++ Builder q La expresión IS NULL (e IS NOT NULL) sirve en una consulta para devolver las tuplas cuyo valor para la columna indicada sea nulo (o no).<=.=..>. Ejemplo: Visualizar las tuplas de T cuyo valor para la columna X es nulo: SELECT * FROM T WHERE X IS NULL Subconsultas Responden a la siguiente sintaxis: SELECT . FROM .2001' AND NUM_VUELO IN ( SELECT NUM_VUELO FROM VUELOS WHERE ORIGEN='MADRID' AND DESTINO='LONDRES') ANY y ALL se usan para poder utilizar operadores de comparacion con subconsultas que nos devuelvan más de un valor como resultado: SELECT . SELECT * FROM RESERVAS WHERE FECHA_SALIDA='20. En el primer caso..html (6 of 13) [27/02/2003 16:24:31] ... La subconsulta puede estar correlacionada con la consulta exterior: Ejemplo: Reservas cuyo número de plazas libres sea mayor que la media para ese mismo vuelo.. FROM . file:///D|/Manuales/databases/sql.02... la subconsulta ha de devolver un único valor. WHERE columna operador {ANY/ALL} (subconsulta) Nota: =ANY equivale a IN.<>..

and rownum <= valor SQL Server: . top valor [percent] INSERT La sentencia INSERT se utiliza para insertar tuplas en una tabla. SUM(PLAZAS-LIBRES) FROM VUELOS WHERE EXISTS (SELECT * FROM RESERVAS WHERE RESERVAS.. EXISTS y NOT EXISTS se emplean para comprobar la existencia o ausencia del valor devuelto por una subconsulta: Ejemplo: Obtener los vuelos con reservas efectuadas en los cuales aún quedan plzas libres.. Ordenar por destino para igual número de plazas libres: SELECT NUM_VUELO..html (7 of 13) [27/02/2003 16:24:31] . .C++ Builder SELECT * FROM RESERVAS A WHERE PLAZAS_LIBRES > (SELECT AVG(PLAZAS_LIBRES) FROM RESERVAS WHERE NUM_VUELO=A.NUM_VUELO=VUELOS.. NUM_VUELO Peculiaridades Algunos gestores de bases de datos incluyen extensiones no estándar como. rows only Oracle: .) file:///D|/Manuales/databases/sql. un sobrenombre que se le da a una tabla y que debe ser £nico para toda la consulta.. DESTINO. por ejemplo.NUM_VUELO) A es un alias.. mecanismos para limitar el tamaño de una consulta (que siempre se puede hacer mediante procedimientos almacenados): q q q IBM DB2: fetch first .NUM_VUELO) GROUP BY NUM_VUELO ORDER BY 3 DESC. ordenando el resultado de mayor a menor número de plazas libres de mayor a menor. INSERT INTO tabla VALUES (valor... DESTINO.

DDL: Lenguaje de definición de datos El sublenguaje de definición de datos de SQL se utiliza para crear. triggers. las claves primarias (PRIMARY KEY) aseguran que los valores de las columnas especificadas son únicos y no nulos. procedimientos almacenados.. La siguiente tabla recoge algunos de los más usuales: Servidor SQL estándar Cadenas Enteros Reales Números Fechas Otros date time timestamp file:///D|/Manuales/databases/sql. [WHERE condición] La sentencia UPDATE sirve para actualizar datos. UNIQUE prohíbe que existan valores duplicados en una columna y CHECK restringe los valores que puede tomar una columna. etcétera. Los tipos de datos permitidos para las columnas de las tablas varían según el servidor que utilicemos.C++ Builder INSERT INTO tabla SELECT . las claves externas (REFERENCES) sirven para especificar restricciones de integridad referencial (esto es. cada tupla de la tabla ha de referenciar a una tupla existente en otra tabla con los mismos valores para las columnas incluidas en la clave externa). ALTER TABLE para modificarlas y DROP TABLE para eliminarlas. Se pueden definir restricciones sobre las columnas de una tabla: NOT NULL prohíbe que se inserten valores nulos en una columna. finalmente. vistas. CREATE TABLE sirve para crear tablas. se modifican todas las tuplas de la tabla. Por desgracia. . incluye una claúsula WHERE opcional. Igual que UPDATE. Una claúsula opcional WHERE selecciona los datos que han de modificarse.html (8 of 13) [27/02/2003 16:24:31] .. También se pueden definir restricciones a nivel de tabla: CHECK puede involucrar a varias columnas. DELETE DELETE FROM tabla [WHERE condición] DELETE permite eliminar tuplas. UPDATE UPDATE tabla SET columna=valor. Cuando esta claúsula se omite. no está estandarizado suficientemente por el momento y muchos detalles dependen de la base de datos que utilicemos... modificar y eliminar tablas.

Definición de dominios con create domain (*) create type . incremento) q Definición: create_sequence id increment by valor start with valor Secuencias q Uso: id.d) blob decimal(p...NextVal q Nombre InterBase Oracle SQL Server Identidades Definición de columnas con el atributo identity (valor_inicial.. "sysdate" en Oracle o la función "getdate()" en SQL Server.s) time blob.s) blob.d) date rowid.dbclob timestamp numeric(p.' q Uso con gen_id (id. datetime Las mayores diferencias suelen aparecer al manejar fechas.. Por ejemplo. Aparte de los tipos de datos estándar el usuario también puede definir sus propios tipos: Servidor IBM DB2 InterBase Oracle Mecanismo create distinct type .d])] money. si queremos obtener la hora actual utilizaremos la palabra reservada "Now" en InterBase.html (9 of 13) [27/02/2003 16:24:31] .. long [raw] number(p. clob. Procedimiento almacenado sp_addtype (*) Creación de reglas: create rule SQL Server Asociación de reglas con tipos de datos: sp_bindrule Valor por defecto: create default & sp_binddefault (*) reconocidos automáticamente por C++Builder Generadores Las distintas bases de datos ofrecen distintos mecanismos para asignar enteros diferentes a cada tupla (sin garantizar la secuencialidad de los valores): Servidor Mecanismo q Definición de generadores con create generator q Valor establecido con set generator Generadores q Eliminación con delete from rdb$generators where rdb$generator_name='...clob.. date [var]binary[(n)] numeric[(p[.. text.d])] decimal[(p[. image.C++ Builder IBM DB2 char(n) varchar(n) char(n) varchar(n) char(n) varchar[2](n) integer smallint real=float double InterBase float integer=int double smallint precision Oracle SQL Server int char[(n)] smallint varchar[(n)] tinyint float[(n)] real date [var]graphic(n) decimal(p.incremento) file:///D|/Manuales/databases/sql..CurrVal & id.

BeforePost(TDataSet *DataSet) { spNextID->ExecProc(). 1). como sucede con las claves artificiales..::Table. existe un índice único. o casi único.ID->Value = spNextID->ParamByName("COD")->AsInteger. En un trigger (InterBase): set term ^. Table.. En el servidor (InterBase): create procedure nextID returns (cod integer) as begin cod = gen_id(ID).... end ^ En el cliente (aplicación C++Builder): TStoredProc *spNextID void __fastcall T.C++ Builder Uso de generadores con C++Builder El uso correcto de generadores en C++Builder consiste en crear un procedimiento almacenado en el servidor que devuelva un valor entero e invocar a dicho procedimiento interceptanto el evento OnNewRecord o BeforePost de la tabla en la aplicación cliente. create trigger BItabla for tabla active before insert as begin Codigo = gen_id(generador.. } También podemos ahorrarnos trabajo y asignar la clave primaria en el trigger si la tabla no tiene columnas con valores default. o el valor de la clave primaria no nos importa realmente en nuestra aplicación. end ^ Detalles de InterBase file:///D|/Manuales/databases/sql. sobre alguna columna alternativa a la clave primaria que utilizaremos como criterio de ordenación para la navegación.html (10 of 13) [27/02/2003 16:24:31] .

. max. trim. (active|inactive) set statistics index . sum. Funciones de agregación: count.... substring Procedimientos almacenados y triggers en InterBase create procedure nombre [ ( ParámetrosDeEntrada ) ] [ returns ( ParámetrosDeSalida ) ] as CuerpoDeProcedimiento create trigger nombre for tabla [active | inactive] {before | after} {delete | insert | update} [position prioridad] as CuerpoDeProcedimiento CuerpoDeProcedimiento ::= declaración* begin .. on .... Consultas Valores nulos: is [not] null Sinónimos para las columnas: .. min.... lower. end Declaración de variables declare variable id tipo file:///D|/Manuales/databases/sql. exists Cadenas Operador like (comodines % y _) Concatenación: || Funciones: upper. avg Subconsultas: in..html (11 of 13) [27/02/2003 16:24:31] .. alter index . as .C++ Builder Restricciones Valores nulos no permitidos: not null Valores por defecto: default Restricciones: check Identificación de las restricciones: constraint Clave primaria: primary key Clave candidata: unique Clave externa: references | foreign key Acciones referenciales: (on delete|on update) (no action|cascade|set default) Columnas calculadas: computed by Índices create [unique] [asc|desc] index .

update. delete & singleton select vg: select columna from tabla where condición into :variable Iteradores sobre consultas (con cursores en Oracle o SQL Server) for select into variables do instrucción Instrucción compuesta begin instrucción* end Lanzamiento de excepciones exception id Captura de excepciones (al final de un bloque begin..html (12 of 13) [27/02/2003 16:24:31] .C++ Builder NB: Al usarse..end) when exception id do instrucción when sqlcode n do instrucción when gdscode n do instrucción Instrucciones de control exit suspend (similar a los iteradores del lenguaje CLU) Variables especiales new & old (igual que en Oracle) Excepciones file:///D|/Manuales/databases/sql. si se usa suspend dentro de un bucle Estructuras condicionales if (condición) then instrucción [else instrucción] Bucles while (condición) do instrucción Instrucciones SQL: insert. los identificadores de variables van precedidos de ':' Asignación variable = expresión Ejecución de un procedimiento almacenado NB: No se pueden pasar expresiones como parámetros execute procedure nombre [(ParsEntrada)] [returning_values ParsSalida] select * from nombre [(ParsEntrada)].

html (13 of 13) [27/02/2003 16:24:31] .C++ Builder create exception id "mensaje" Alertas InterBase: C++Builder: componentes) UDFs User Defined Functions: DLLs + declare external function post_event mensaje Componente TIBEventAlerter (página Samples de la paleta de © Fernando Berzal Galiano file:///D|/Manuales/databases/sql.

ejemplos.C++ Builder Curso de C++ Builder Enlaces interesantes En español q Calling Dr. q Borland C++Builder La página oficial del C++Builder en Inprise. ejemplos. artículos. ejemplos. FAQs y pistas sobre C++Builder. un libro en español acerca del desarrollo de aplicaciones de gestión con C++Builder. file:///D|/Manuales/links/index. información técnica. herramientas. noticias. Ejemplos y trucos para sacarle el máximo partido a la VCL (en Delphi y C++Builder). q BCBDEV. enlaces y prácticamente cualquier cosa que esté relacionada con C++Builder. q Delphi Super Page Montones de recursos para Delphi y C++Builder: componentes shareware y freeware. trucos. Muy recomendable. En inglés q Bytamin-C: The C++Builder Developer Site! Componentes. trucos y componentes shareware para C++Builder. q Club Builder Tutoriales.COM Más artículos. Marteens "La Cara Oculta de C++Builder" en PDF. etc.html (1 of 2) [27/02/2003 16:24:32] . q The Bits Página británica con información. componentes y tutoriales para C++Builder. utilidades.

html (2 of 2) [27/02/2003 16:24:32] .C++ Builder Otros sitios de interés q Publicaciones r r r C++Builder Developer's Journal C++Builder Informant Dr.net (portal técnico para científicos e ingenieros) Patrones de diseño (porque no todo se diseña con el ratón) Página principal © Fernando Berzal Galiano file:///D|/Manuales/links/index. Dobb's Journal q Productos relacionados r r Delphi InterBase q Programación r r r ACCU (Association of C & C++ Users) Mathtools.

El almacén de objetos 2. Páginas de componentes. La VCL de C++ Builder file:///D|/Manuales/toc. 3.6. Un estudio detallado del IDE de C++ Builder 2.2.5. El sistema de ayuda 2. Propiedades. ejecución y depuración de programas 2.Índice Curso de C++ Builder Índice del curso 1. 4.3. Componentes visuales y no visuales.4. Componentes en C++ Builder 3.1.2. Ejercicios: Ejemplos de aplicaciones simples y de consola 3.1. Una visión general del IDE de C++ Builder 2. El IDE de C++ Builder 2.html (1 of 5) [27/02/2003 16:24:32] . métodos y gestores de eventos.C++ Builder . Compilación. Introducción 2.3. 3.

Programación Orientada a Objetos en C++ 5. 5. Abstracción.2.1.1. 5. Creación y Destrucción de Objetos.C++ Builder .7. Controles de edición y Editor. 4. Herencia Múltiple. Restricciones de acceso en C++..3. 5.5.Índice 4. 4. 4.5.2.5.7. 5. Herencia de Constructores y Destructores (Inicialización de Clases II).1. 5. 5.2. 5. 5.4. 5. Ejercicios: Pizarra. El Paradigma de la POO en C++. 5.6.5. Clases Abstractas. Propiedades Virtuales. 5. Constructores y Destructores (Inicialización de Clases I).5.4. 5.6. Encapsulamiento.2.html (2 of 5) [27/02/2003 16:24:32] . file:///D|/Manuales/toc.3. Clases de componentes. 4.1.3. 5. Polimorfismo. Clases de formularios y aplicaciones.6.1. Sobrecarga de funciones. Herencia. Un paseo por la VCL. Restricciones al uso de la VCL en C++ Builder.

Programación con hebras 7. 6. 7.4. Excepciones no tratadas. 6.2 Sincronización entre hebras 7.C++ Builder .html (3 of 5) [27/02/2003 16:24:32] .7.4 Coordinación entre hebras 7.1 Uso de recursos compartidos 7..3.1.3 Ejecución de hebras 7. Tratamiento de excepciones 6. 6. 6.2.Índice 5.5.4. Polimorfismo en las clases y métodos virtuales.4.2 La clase TThread 7. 6. Lanzamiento de excepciones. Acceso a bases de datos file:///D|/Manuales/toc. Especificación de excepciones.5 Ejemplos (ZIP) 8.1 Introducción 7. Captura de excepciones.2. Excepciones de la VCL.

html (4 of 5) [27/02/2003 16:24:32] .2 Cursores 8.8 Ejemplos y ejercicios Apéndice: SQL Enlaces interesantes file:///D|/Manuales/toc.1 Introducción 8.4 Controles de acceso a datos 8.1 TDataSet y sus derivados 8.C++ Builder .7.2 El motor de bases de datos de Borland (BDE) 8.3 Actualizaciones en caché 8.6.2 El componente TDatabase 8.6.6 El componente TStoredProc: Procedimientos almacenados 8.3 Componentes de acceso a bases de datos 8.Índice 8.5 El componente TQuery: Consultas SQL 8.6 Conjuntos de datos 8.6.4 El componente TTable: Tablas 8.7 El componente TField: Acceso a los campos 8.7.1 El componente TSession 8.8 Herramientas y utilidades 8.6.7 Sesiones y conexiones 8.5 El componente TDataSource 8.6.6.6.

html (5 of 5) [27/02/2003 16:24:32] .C++ Builder .Índice Volver file:///D|/Manuales/toc.

C++ Builder .html [27/02/2003 16:24:32] .Apéndices Curso de C++ Builder Apéndices Listado de propiedades. La paleta de componentes Lista completa de menús Página principal © Francisco Cortijo Bon file:///D|/Manuales/appendix/index. métodos y eventos de: Aplicaciones Formularios Componentes Estructura y configuración de un proyecto de C++ Builder.

h> #pragma hdrstop USERES("Ejemplo.cpp"). LPSTR. antes de POLIMORFISMO.5. HINSTANCE.OOP .H file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. //--------------------------------------------------------------------WINAPI WinMain(HINSTANCE. } return 0. int) { try { Application->Initialize(). Application->CreateForm(__classid(TPpalFrm).cpp". USEFORM("Ppal.Ejemplo 1 Curso de C++ Builder Ejemplo 1 Corresponde al final de la sección 5. PpalFrm).2.CPP //--------------------------------------------------------------------#include <vcl.html (1 of 8) [27/02/2003 16:24:33] . } catch (Exception &exception) { Application->ShowException(&exception). &PpalFrm). EJEMPLO. Application->Run().res"). } //--------------------------------------------------------------------- PPAL. USEUNIT("ObjGraf.

hpp> //----------------------------------------------------------------------class TPpalFrm : public TForm{__published: // IDE-managed Components TPaintBox *PaintBox. void __fastcall PaintBoxPaint(TObject *Sender).CPP //----------------------------------------------------------------------#include <vcl. //----------------------------------------------------------------------extern PACKAGE TPpalFrm *PpalFrm. void __fastcall FormDestroy(TObject *Sender).h> #pragma hdrstop #include "Ppal. TBitBtn *BotonSalir.h" file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. //----------------------------------------------------------------------#endif PPAL. void __fastcall BotonSalirClick(TObject *Sender).hpp> <StdCtrls.h" #include <Buttons.html (2 of 8) [27/02/2003 16:24:33] .Ejemplo 1 //----------------------------------------------------------------------#ifndef PpalH #define PpalH //----------------------------------------------------------------------#include #include #include #include #include <Classes. void __fastcall FormCreate(TObject *Sender). private: // User declarations public: // User declarations __fastcall TPpalFrm(TComponent* Owner).hpp> <Forms.hpp> <ExtCtrls.hpp> #include "ObjGraf.OOP .hpp> <Controls. }.

// Punteros a objetos de las clases derivadas. Cir2 = new TCirculo (PaintBox. clGreen. //----------------------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { delete Cir1. *Cuad2. } //----------------------------------------------------------------------void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender) { Cir1->Mostrar(). 25). Cuad2->Mostrar(). } 30). 40. //----------------------------------------------------------------------__fastcall TPpalFrm::TPpalFrm(TComponent* Owner): TForm(Owner) { } //----------------------------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Cir1 = new TCirculo (PaintBox. Cuad1->Mostrar(). delete Cuad2.html (3 of 8) [27/02/2003 16:24:33] .OOP . 150. } //----------------------------------------------------------------------void __fastcall TPpalFrm::BotonSalirClick(TObject *Sender) { Application->Terminate(). delete Cuad1. TCirculo *Cir1.dfm" TPpalFrm *PpalFrm. } //----------------------------------------------------------------------- file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. clBlack. Cuad2 = new TCuadrado (PaintBox.Ejemplo 1 //----------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*. TCuadrado *Cuad1. clYellow. 200. *Cir2. clRed. 20). Cir2->Mostrar(). 45). delete Cir2. 100. 120. Cuad1 = new TCuadrado (PaintBox. 100. 70. 210.

int _Y=0). {read=FY. (int _X). // Metodo virtual puro // NUEVAS FORMAS DE ACCESO AL DECLARAR PRIVATE LOS MIEMBROS FX y FY. {read=FColor. {read=GetAlto }. // OJO: Se ha cambiado Color por FColor TColor TPaintBox public: // Pueden usarlas todas. TColor _Color=clBlack. // Puede acceder SOLO los objetos de esta clase. write=FColor}. // Metodo virtual puro void SetX void SetY virtual int virtual int protected: // Pueden acceder los objetos de esta clase y // sus descendientes. write=SetX }. // OJO: Se ha cambiado el nombre a // los miembros X e Y por FX y FY.html (4 of 8) [27/02/2003 16:24:33] . file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. (int _Y). __property __property __property __property __property int int TColor int int X Y Color Ancho Alto = = = = = {read=FX. *PaintBox. {read=GetAncho }. // Otros metodos virtual void Mostrar (void) = 0. GetAncho (void) = 0. int FY. // Constructor de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox.H //----------------------------------------------------------------------#ifndef ObjGrafH #define ObjGrafH //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int FX. // Metodo virtual puro GetAlto (void) = 0.Ejemplo 1 OBJGRAF. FColor. int _X=0. write=SetY }.OOP .

inline int GetAncho inline int GetAlto public: // Metodos // Constructores y destructores TCuadrado (TPaintBox *_PaintBox.} int Lado.Ejemplo 1 }. TColor _Color=clBlack. // Instanciacion del metodo virtual puro de // la clase TObjGraf }.OOP . int _X=0.} . (void) {return(Radio*2).} (void) {return(Lado). // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y // sus descendientes. int _Y=0. inline int GetAncho inline int GetAlto public: // Metodo constructor TCirculo (TPaintBox *_PaintBox. int _Radio=1). TColor _Color=clBlack. void Mostrar (void). file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. int _Y=0. int _X=0.} (void) {return(Radio*2). int _Lado=1). //*************************************************/ // Definicion de la clase derivada TCuadrado. //*************************************************/ // Definicion de la clase derivada TCirculo. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { protected: // Pueden acceder los objetos de esta clase y // sus descendientes. // Instanciacion del metodo virtual puro de // la clase TObjGraf }. int Radio. void Mostrar (void).html (5 of 8) [27/02/2003 16:24:33] (void) {return(Lado).

// No se puede llamar a los metodos virtuales puros FY = _Y.Ancho)) FX = PaintBox->Width .html (6 of 8) [27/02/2003 16:24:33] . int _X. // MUY IMPORTANTE: Estas tres lineas han cambiado: FX = _X.Ejemplo 1 //----------------------------------------------------------------------#endif OBJGRAF. else FX = _X. } // Funciones de escritura de las propiedades virtuales X e Y void TObjGraf :: SetX (int _X) { if (_X < 0) FX = 0. Ancho) desde un // constructor de la clase base. TColor _Color. } void TObjGraf :: SetY (int _Y) { if (_Y < 0) FY = 0.OOP .Ancho. int _Y) { PaintBox = _PaintBox. else file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. FColor = _Color.CPP //----------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "ObjGraf. // (GEtAncho. else if (_X > (PaintBox->Width .h" //----------------------------------------------------------------------#pragma package(smart_init) /*****************************************************/ // Metodos asociados a la clase base TObjGraf /*****************************************************/ TObjGraf :: TObjGraf (TPaintBox *_PaintBox. GetAlto) para fijar el valor de una // propiedad virtual (Alto.

int _Y. PaintBox->Canvas->Rectangle(X. _X. Y. /*****************************************************/ TCuadrado :: TCuadrado (TPaintBox *_PaintBox. } /*****************************************************/ // Metodos asociados a la clase derivada TCuadrado.html (7 of 8) [27/02/2003 16:24:33] . PaintBox->Canvas->Ellipse(X. _Color.Alto)) FY = PaintBox->Height . } file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1. int _Lado) : TObjGraf (_PaintBox. X+Radio*2. TColor _Color. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCirculo :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCuadrado :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. int _X.Alto. // TCirculo deriva de la clase base TObjGraf. _Y) { Radio = _Radio. /*****************************************************/ TCirculo :: TCirculo (TPaintBox *_PaintBox. _Color. int _Y. int _X. // TCuadrado deriva de la clase base TObjGraf.OOP . PaintBox->Canvas->Brush->Color = Color. Y+Lado). X+Lado. } /*****************************************************/ // Metodos asociados a la clase derivada TCirculo. TColor _Color. _Y) { Lado = _Lado. int _Radio) : TObjGraf (_PaintBox.Ejemplo 1 if (_Y > (PaintBox->Height . _X. PaintBox->Canvas->Brush->Color = Color. Y. else FY = _Y. Y+Radio*2).

html (8 of 8) [27/02/2003 16:24:33] .OOP .Ejemplo 1 Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/oop/Ejemplo1.

int) { try { Application->Initialize().h> #pragma hdrstop USERES("Ejemplo2. LPSTR.H file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. //---------------------------------------------------------------------WINAPI WinMain(HINSTANCE.cpp").OOP .CPP //---------------------------------------------------------------------- #include <vcl. EJEMPLO. Application->Run(). En este ejemplo se muestra el POLIMORFISMO (Polimorfismo de clases y métodos virtuales). &PpalFrm). } //---------------------------------------------------------------------- PPAL. USEFORM("Ppal.html (1 of 10) [27/02/2003 16:24:34] . } catch (Exception &exception) { Application->ShowException(&exception).res"). USEUNIT("ObjGraf. } return 0.cpp". PpalFrm). Application->CreateForm(__classid(TPpalFrm). HINSTANCE.Ejemplo 2 Curso de C++ Builder Ejemplo 2 Corresponde al final de la sección 5.

}.hpp> <ExtCtrls. //---------------------------------------------------------------------#endif PPAL.hpp> #include "ObjGraf.html (2 of 10) [27/02/2003 16:24:34] . void __fastcall PaintBoxPaint(TObject *Sender).hpp> <Forms.hpp> <Controls.CPP //---------------------------------------------------------------------#include <vcl. void __fastcall FormCreate(TObject *Sender).h> file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. void __fastcall FormDestroy(TObject *Sender).h" #include <Buttons. void __fastcall BotonSalirClick(TObject *Sender).hpp> //---------------------------------------------------------------------class TPpalFrm : public TForm { __published: // IDE-managed Components TPaintBox *PaintBox. private: // User declarations TObjGraf **Objs. public: // User declarations __fastcall TPpalFrm(TComponent* Owner). //---------------------------------------------------------------------extern PACKAGE TPpalFrm *PpalFrm. TBitBtn *BotonSalir.Ejemplo 2 //---------------------------------------------------------------------#ifndef PpalH #define PpalH //---------------------------------------------------------------------#include #include #include #include #include <Classes.OOP .hpp> <StdCtrls.

OOP . 25). 20). i++) delete Objs[i]. clRed. i++) Objs[i]->Mostrar(). i<4.html (3 of 10) [27/02/2003 16:24:34] . 30).dfm" TPpalFrm *PpalFrm. Objs[0] Objs[1] Objs[2] Objs[3] } //---------------------------------------------------------------------void __fastcall TPpalFrm::FormDestroy(TObject *Sender) { for (int i=0. } //---------------------------------------------------------------------void __fastcall TPpalFrm::BotonSalirClick(TObject *Sender) { Application->Terminate(). } //---------------------------------------------------------------------void __fastcall TPpalFrm::PaintBoxPaint(TObject *Sender) { for (int i=0. (PaintBox. 70. 210. delete []Objs. //---------------------------------------------------------------------__fastcall TPpalFrm::TPpalFrm(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------------------void __fastcall TPpalFrm::FormCreate(TObject *Sender) { Objs = new TObjGraf * [4]. 120. } = = = = new new new new TCirculo TCuadrado TCirculo TPelota (PaintBox. clYellow. 100. i<4. clGreen. 45). 40. clBlack. 150. (PaintBox.Ejemplo 2 #pragma hdrstop #include "Ppal.h" //---------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*. file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. 200. 100. (PaintBox.

OOP . write=SetY }. // Metodo virtual puro GetAlto (void) = 0. (int _X). {read=FColor. // Otros metodos virtual void Mostrar (void) = 0. TColor _Color=clBlack. TObjGraf (TObjGraf *ObjGraf). // Metodo virtual puro // NUEVAS FORMAS DE ACCESO AL DECLARAR PRIVATE LOS MIEMBROS FX y FY. *PaintBox. write=FColor}. int FY. int _X=0. __property __property __property __property __property int int TColor int int X Y Color Ancho Alto = = = = = {read=FX. int _Y=0). (int _Y). {read=GetAncho }. {read=GetAlto }.html (4 of 10) [27/02/2003 16:24:34] .Ejemplo 2 //---------------------------------------------------------------------- OBJGRAF. GetAncho (void) = 0. void SetX void SetY virtual int virtual int protected: TColor TPaintBox public: // Constructores de objetos TObjGraf TObjGraf (TPaintBox *_PaintBox. write=SetX }.H //---------------------------------------------------------------------#ifndef ObjGrafH #define ObjGrafH //*************************************************/ // Definicion de la clase base TObjGraf //*************************************************/ class TObjGraf { private: int FX. {read=FY. FColor. // Metodo virtual puro file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2.

{read=FRadio.} (void) {return(FRadio*2). // TPelota deriva de la clase TCirculo. //*************************************************/ // Definicion de la clase derivada TCirculo.Ejemplo 2 }.4 E \ \ 5 SE .} //*************************************************/ // Definicion de la clase derivada TPelota. // Instanciacion del metodo virtual puro de // la clase TObjGraf __property int Radio = }. // Deriva de la clase base TObjGraf //*************************************************/ class TCirculo : public TObjGraf { private: int FRadio.html (5 of 10) [27/02/2003 16:24:34] N 2 | | | | 1 S NE 6 / / ---. int _Y=0. int _Radio=1). inline int GetAncho inline int GetAlto public: // Constructores TCirculo (TPaintBox *_PaintBox. int _X=0. (void) {return(FRadio*2).OOP . que a su // vez deriva de la clase base TObjGraf //*************************************************/ // Tipo definido por enumeracion para la direccion de TPelota // La codificacion es: /* NO 10 \ \ O 8 ---/ / 9 SO */ file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. // Otros metodos void Mostrar (void). TColor _Color=clBlack. write=FRadio}.

void Mover (void). SetDireccion (TDireccion _Direccion). int FVelocidad. N=2.html (6 of 10) [27/02/2003 16:24:34] . E=4. // Deriva de la clase base TObjGraf //*************************************************/ class TCuadrado : public TObjGraf {private: inline int GetAncho inline int GetAlto public: // Constructores TCuadrado (TPaintBox *_PaintBox. TColor _Color=clBlack. SE=5. NO=10}. __property TDireccion Direccion = {read = GetDireccion. write=SetDireccion}. NE=6. int _Velocidad=5). void TDireccion public : // Constructores TPelota (TPaintBox *_PaintBox. // Otros metodos void Mostrar (void). class TPelota: public TCirculo { private: int FDirX. //*************************************************/ // Definicion de la clase derivada TCuadrado. __property int Velocidad = {read = FVelocidad. void Borrar (void). int _Lado=1). int _Y=0. O=8. int _X=0. SO=9.} file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. int _Radio=1. (void) {return(FLado). // Otros metodos int FLado. int _Y=0. TDireccion _Direccion=SE.} (void) {return(FLado).Ejemplo 2 enum TDireccion {S=1. GetDireccion (void). }. TColor _Color=clBlack. write=FVelocidad}. int FDirY.OOP . int _X=0.

// Instanciacion del metodo virtual puro de // la clase TObjGraf __property int Lado = }.Ejemplo 2 void Mostrar (void). FColor = ObjGraf->Color. //---------------------------------------------------------------------#endif {read=FLado. } TObjGraf :: TObjGraf (TObjGraf *ObjGraf) { PaintBox = ObjGraf->PaintBox. OBJGRAF. FY = ObjGraf->FY.html (7 of 10) [27/02/2003 16:24:34] .OOP .h> #pragma hdrstop #include "ObjGraf. } // Funciones de escritura de las propiedades virtuales X e Y file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. FX = _X. FColor = _Color.CPP //---------------------------------------------------------------------#include <vcl. int _X. FY = _Y. write=FLado}. int _Y) { PaintBox = _PaintBox. TColor _Color. FX = ObjGraf->FX.h" //---------------------------------------------------------------------#pragma package(smart_init) /*****************************************************/ // Metodos asociados a la clase base TObjGraf /*****************************************************/ // Constructores TObjGraf :: TObjGraf (TPaintBox *_PaintBox.

else FY = _Y. else FX = _X. Y+Radio*2).Alto)) FY = PaintBox->Height . /*****************************************************/ TCirculo :: TCirculo (TPaintBox *_PaintBox. _Color. // TCirculo deriva de la clase base TObjGraf.Ancho. int _Radio) : TObjGraf (_PaintBox. // TPelota deriva de la clase TCirculo.OOP . } /*****************************************************/ // Metodos asociados a la clase derivada TCirculo. } /*****************************************************/ // Metodos asociados a la clase derivada TPelota. _X.html (8 of 10) [27/02/2003 16:24:34] . int _X. Y. PaintBox->Canvas->Ellipse(X. file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2.Ancho)) FX = PaintBox->Width .Alto. que a su // vez deriva de la clase base TObjGraf /*****************************************************/ TPelota :: TPelota (TPaintBox *_PaintBox. TColor _Color. else if (_X > (PaintBox->Width . PaintBox->Canvas->Brush->Color = Color. TColor _Color. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCirculo :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color.Ejemplo 2 void TObjGraf :: SetX (int _X) { if (_X < 0) FX = 0. } void TObjGraf :: SetY (int _Y) { if (_Y < 0) FY = 0. X+Radio*2. else if (_Y > (PaintBox->Height . _Y) { Radio = _Radio. int _Y.

} void TPelota :: SetDireccion (TDireccion _Dir) { FDirY = (_Dir & 1) ? +1 : ((_Dir & 2) ? -1 : 0). X+Radio*2. int _Velocidad) : TCirculo (_PaintBox. int _Radio. Y+Radio*2). Y += FDirY * Velocidad. PaintBox->Canvas->Brush->Color = Color. } void TPelota :: Mover (void) { Borrar (). } /*****************************************************/ file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. Mostrar (). PaintBox->Canvas->Ellipse(X. TDireccion _Direccion.OOP .html (9 of 10) [27/02/2003 16:24:34] . Y. _Y. } TDireccion TPelota :: GetDireccion (void) { TDireccion _Dir. _Dir = (TDireccion) ((FDirY == +1) ? 1 : ((FDirY == -1 ) ? 2 : 0)). FDirX = (_Dir & 4) ? +1 : ((_Dir & 8) ? -1 : 0). Y.Ejemplo 2 int _X. _Dir = (TDireccion) (_Dir + (FDirX == +1) ? 4 : ((FDirX == -1 ) ? 8 :0)). } // Otras funcione propias de TPelota void TPelota :: Borrar (void) { PaintBox->Canvas->Pen->Color = PaintBox->Color. X+Radio*2. _Radio) { Direccion = _Direccion. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TPelota :: Mostrar (void) { PaintBox->Canvas->Pen->Color = clBlack. _X. Velocidad = _Velocidad. Y+Radio*2). X += FDirX * Velocidad. int _Y. _Color. PaintBox->Canvas->Ellipse(X. PaintBox->Canvas->Brush->Color = PaintBox->Color. return (_Dir).

int _Lado) : TObjGraf (_PaintBox. } Atrás © Francisco Cortijo Bon file:///D|/Manuales/intro/ejemplos/oop/Ejemplo2. _X. Y. _Y) { Lado = _Lado.html (10 of 10) [27/02/2003 16:24:34] . X+Lado. // TCuadrado deriva de la clase base TObjGraf. } // Instanciacion del metodo virtual puro de la clase TObjGraf void TCuadrado :: Mostrar (void) { PaintBox->Canvas->Pen->Color = Color. /*****************************************************/ TCuadrado :: TCuadrado (TPaintBox *_PaintBox.Ejemplo 2 // Metodos asociados a la clase derivada TCuadrado.OOP . PaintBox->Canvas->Rectangle(X. int _Y. int _X. TColor _Color. Y+Lado). _Color. PaintBox->Canvas->Brush->Color = Color.

if (MainForm->Color == clBtnFace) MainForm->Color = clWhite.cpp" //----------------------------------------------------------------#include <vcl. RadioButton1->Hide().Estructura y configuración de un proyecto de C++ Builder: MAIN. RadioButton2->Hide().h" //----------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TMainForm *MainForm. //----------------------------------------------------------------__fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) { } //----------------------------------------------------------------void __fastcall TMainForm::ExitButtonClick(TObject *Sender) { Application->Terminate(). CheckBox->Checked = false. } //----------------------------------------------------------------void __fastcall TMainForm::FormCreate(TObject *Sender) { MainForm->Caption = "Primer programa con C++ Builder".h> #pragma hdrstop #include "main.html (1 of 3) [27/02/2003 16:24:34] . file:///D|/Manuales/appendix/project/main_cpp.CPP Curso de C++ Builder Estructura y configuración de un proyecto Fichero "main.

else LabelOutput->Caption >Text. Sr/Sra. } { = "Escogió Opción 1. " + Edit- } //----------------------------------------------------------------- Atrás file:///D|/Manuales/appendix/project/main_cpp. = "Escogió Opción 2. Sr/Sra. RadioButton2->Hide(). OKButton->Enabled = false.CPP } //----------------------------------------------------------------void __fastcall TMainForm::CheckBoxClick(TObject *Sender) { if (CheckBox->Checked == true) { RadioButton1->Show(). } else { if (Edit->Text == "") LabelOutput->Caption desconocido/a". RadioButton2->Show(). Sr/Sra.Estructura y configuración de un proyecto de C++ Builder: MAIN. OKButton->Enabled = true. } } //----------------------------------------------------------------void __fastcall TMainForm::OKButtonClick(TObject *Sender) { if (RadioButton1->Checked) if (Edit->Text == "") LabelOutput->Caption desconocido/a". else LabelOutput->Caption >Text. Sr/Sra. LabelOutput->Caption = "".html (2 of 3) [27/02/2003 16:24:34] . " + Edit- = "Escogió Opción 2. } else { RadioButton1->Hide(). = "Escogió Opción 1. RadioButton1->Checked = true.

html (3 of 3) [27/02/2003 16:24:34] .Estructura y configuración de un proyecto de C++ Builder: MAIN.CPP © Francisco Cortijo Bon file:///D|/Manuales/appendix/project/main_cpp.

hpp> #include <Controls. TRadioButton *RadioButton1. TEdit *Edit. void __fastcall OKButtonClick(TObject *Sender). void __fastcall CheckBoxClick(TObject *Sender).hpp> #include <StdCtrls. private: // User declarations public: // User declarations __fastcall TMainForm(TComponent* Owner).hpp> //----------------------------------------------------------------class TMainForm : public TForm { __published: // IDE-managed Components TLabel *LabelEdit. //----------------------------------------------------------------#endif file:///D|/Manuales/appendix/project/main_h. }. TRadioButton *RadioButton2. TLabel *LabelOutput.h" //----------------------------------------------------------------#ifndef mainH #define mainH //----------------------------------------------------------------#include <Classes. //----------------------------------------------------------------extern PACKAGE TMainForm *MainForm.Estructura y configuración de un proyecto de C++ Builder: MAIN.H Curso de C++ Builder Estructura y configuración de un proyecto Fichero "main.html (1 of 2) [27/02/2003 16:24:34] . void __fastcall ExitButtonClick(TObject *Sender). TButton *OKButton. void __fastcall FormCreate(TObject *Sender). TCheckBox *CheckBox.hpp> #include <Forms. TButton *ExitButton.

html (2 of 2) [27/02/2003 16:24:34] .H //----------------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/project/main_h.Estructura y configuración de un proyecto de C++ Builder: MAIN.

HINSTANCE. USEFORM("main.res").cpp" //----------------------------------------------------------------#include <vcl.html [27/02/2003 16:24:35] .cpp". Application->CreateForm(__classid(TMainForm). } return 0. int) { try { Application->Initialize(). &MainForm). Application->Run(). LPSTR. } //----------------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/project/inicial_cpp.Estructura y configuración de un proyecto de C++ Builder: INICIAL. //----------------------------------------------------------------WINAPI WinMain(HINSTANCE. } catch (Exception &exception) { Application->ShowException(&exception).CPP Curso de C++ Builder Estructura y configuración de un proyecto Fichero "Inicial. MainForm).h> #pragma hdrstop USERES("Inicial.

bpi teedb40.bpi vcljpg40.bpi Vcldb40. # -------------------------------------------------------------------------VERSION = BCB. # It is recommended to use the IDE to change any of the values in this # section.bpi \ ibsmp40.bpi Dss40.obj RESFILES = Inicial.bpi Qrpt40.Estructura y configuración de un proyecto de C++ Builder: INICIAL.bpi bcbsmp40.obj main.exe OBJFILES = Inicial.bpi TeeUI40.04 # -------------------------------------------------------------------------PROJECT = Inicial.res RESDEPEN = $(RESFILES) main.bpr" # -------------------------------------------------------------------------!if !$d(BCB) BCB = $(MAKEDIR)\.html (1 of 5) [27/02/2003 16:24:35] .BPR Curso de C++ Builder Estructura y configuración de un proyecto Fichero "Inicial.bpi tee40.bpi DEFFILE = # -------------------------------------------------------------------------PATHCPP = ..bpi Inetdb40.bpi Vclmid40.bpi Inet40.bpi vcldbx40.dfm LIBFILES = IDLGENFILES = IDLFILES = LIBRARIES = SPARELIBS = Vcl40.bpi \ NMFast40.. file:///D|/Manuales/appendix/project/inicial_bpr.bpi dclocx40. !endif # -------------------------------------------------------------------------# IDE SECTION # -------------------------------------------------------------------------# The following section of the project makefile is managed by the BCB IDE.lib PACKAGES = Vcl40.04.bpi Vclx40.

$(RELEASELIBPATH) -aa -Tpe -x -Gn -v # -------------------------------------------------------------------------ALLOBJ = c0w32.obj $(OBJFILES) ALLRES = $(RESFILES) ALLLIB = $(LIBFILES) $(LIBRARIES) import32. PATHASM = ..0.USEPACKAGES # -------------------------------------------------------------------------CFLAG1 = -I$(BCB)\include.0 file:///D|/Manuales/appendix/project/inicial_bpr.0..Lib $(PACKAGES) sysinit.0.$(BCB)\include\vcl -$YD -$W -$O. DEBUGLIBPATH = $(BCB)\lib\debug RELEASELIBPATH = $(BCB)\lib\release USERDEFINES = SYSDEFINES = _RTLDLL.$(BCB)\lib.lib # -------------------------------------------------------------------------!ifdef IDEOPTIONS [Version Info] IncludeVerInfo=0 AutoIncBuild=0 MajorVer=1 MinorVer=0 Release=0 Build=0 Debug=0 PreRelease=0 Special=0 Private=0 DLL=0 Locale=3082 CodePage=1252 [Version Info Keys] CompanyName= FileDescription= FileVersion=1.$(RELEASELIBPATH) \ -I$(BCB)\include.-w-par -w-inl -Vx -tW -tWM \ -D$(SYSDEFINES).obj Memmgr. PATHRC = .$(BCB)\include\vcl AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zd LFLAGS = -L$(BCB)\lib\obj.0.-v -JPHNE -M RFLAGS = -i$(BCB)\include.$(BCB)\lib.0 InternalName= LegalCopyright= LegalTrademarks= OriginalFilename= ProductName= ProductVersion=1.html (2 of 5) [27/02/2003 16:24:35] .-c -b.BPR PATHPAS = .Estructura y configuración de un proyecto de C++ Builder: INICIAL..$(USERDEFINES) IDLCFLAGS = -I$(BCB)\include -I$(BCB)\include\vcl -src_suffixcpp PFLAGS = -U$(BCB)\lib\obj.NO_STRICT.lib cp32mti.\ -a8 -k -y -v -vi.csm -w -Ve -r.$(BCB)\include\vcl -Od -Hc H=$(BCB)\lib\vcl40.

$(BCB)\include\vcl [HistoryLists\hlLibraryPath] Count=1 Item0=$(BCB)\lib\obj.BPR Comments= [HistoryLists\hlIncludePath] Count=1 Item0=$(BCB)\include.autodepend # -------------------------------------------------------------------------!if !$d(BCC32) BCC32 = bcc32 !endif !if !$d(CPP32) CPP32 = cpp32 !endif file:///D|/Manuales/appendix/project/inicial_bpr.$(BCB)\lib [HistoryLists\hlDebugSourcePath] Count=1 Item0=$(BCB)\source\vcl [Debugging] DebugSourceDirs=$(BCB)\source\vcl [Parameters] RunParams= HostApplication= RemoteHost= RemotePath= RemoteDebug=0 [Compiler] InMemoryExe=0 ShowInfoMsgs=0 [CORBA] AddServerUnit=1 AddClientUnit=1 PrecompiledHeaders=1 !endif # -------------------------------------------------------------------------# MAKE SECTION # -------------------------------------------------------------------------# This section of the project file is not used by the BCB IDE.html (3 of 5) [27/02/2003 16:24:35] . # -------------------------------------------------------------------------.Estructura y configuración de un proyecto de C++ Builder: INICIAL. It is for # the benefit of building from the command-line using the MAKE utility.

C = $(PATHCPP) !endif !if $d(PATHPAS) .html (4 of 5) [27/02/2003 16:24:35] . + $(DEFFILE).PAS = $(PATHPAS) !endif !if $d(PATHASM) .PATH. + $(ALLLIB).Estructura y configuración de un proyecto de C++ Builder: INICIAL.PATH.PATH.PATH.. + $(PROJECT).pas.PATH.BPR !if !$d(DCC32) DCC32 = dcc32 !endif !if !$d(TASM32) TASM32 = tasm32 !endif !if !$d(LINKER) LINKER = ilink32 !endif !if !$d(BRCC32) BRCC32 = brcc32 !endif !if !$d(IDL2CPP) IDL2CPP = idl2cpp !endif # -------------------------------------------------------------------------!if $d(PATHCPP) .hpp: $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } file:///D|/Manuales/appendix/project/inicial_bpr.RC = $(PATHRC) !endif # -------------------------------------------------------------------------$(PROJECT): $(IDLGENFILES) $(OBJFILES) $(RESDEPEN) $(DEFFILE) $(BCB)\BIN\$(LINKER) @&&! $(LFLAGS) + $(ALLOBJ). + $(ALLRES) ! # -------------------------------------------------------------------------.ASM = $(PATHASM) !endif !if $d(PATHRC) .CPP = $(PATHCPP) .

cpp.c.obj: $(BCB)\BIN\$(TASM32) $(AFLAGS) $<.Estructura y configuración de un proyecto de C++ Builder: INICIAL.cpp.obj: $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } .c.rc. $@ .html (5 of 5) [27/02/2003 16:24:35] .asm.i: $(BCB)\BIN\$(CPP32) $(CFLAG1) -n.res: $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< # -------------------------------------------------------------------------- Atrás © Francisco Cortijo Bon file:///D|/Manuales/appendix/project/inicial_bpr. {$< } .BPR . {$< } .obj: $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } .i: $(BCB)\BIN\$(CPP32) $(CFLAG1) -n.obj: $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< } .pas.

You're Reading a Free Preview

Descarga
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->