Curso Basico de Delphi

74
1. La ventana principal Cuando ejecutamos Delphi, nos encontramos ante un entorno como el que se ve en la imagen, compuesto por varias partes: En la barra de título de la ventana principal (la superior) vemos el nombre del entorno (Delphi) seguido del nombre del proyecto en curso. Bajo la barra de título encontramos el menú, con las opciones típicas de ficheros, herramientas, edición, etc. La parte inferior izquierda de la ventana principal está ocupada por un conjunto de botones, separados en tres grupos, como vemos en el gráfico: Mediante ellos podemos cargar un nuevo proyecto, salvar el actual, etc. Cada uno de estos botones tiene una correspondencia con una opción del menú y algunos de ellos también tienen asociada una tecla de acceso rápido. Por último, en la ventana principal de Delphi, encontramos las paletas de componentes Delphi: En principio la paleta activa es la llamada Standard, en la que podemos encontrar los componentes y controles más habituales en un programa. Las pestañas existentes en la parte superior nos permitirán acceder a la demás paletas de controles. Menú de Opciones Este elemento contiene las diferentes opciones del programa agrupadas en varias principales. En Delphi el menú de opciones es un apartado con estructura casi fija (es decir, siempre las mismas opciones en el mismo lugar), salvando la posibilidad de añadir opciones mediante la creación de extensiones al entorno.

description

programación delphi para principiantes aprende a programar con este curso basico

Transcript of Curso Basico de Delphi

Page 1: Curso Basico de Delphi

1. La ventana principal Cuando ejecutamos Delphi, nos encontramos ante un entorno como el que se ve en la imagen, compuesto por varias partes:

En la barra de título de la ventana principal (la superior) vemos el nombre del entorno (Delphi) seguido del nombre del proyecto en curso. Bajo la barra de título encontramos el menú, con las opciones típicas de ficheros, herramientas, edición, etc.

La parte inferior izquierda de la ventana principal está ocupada por un conjunto de botones, separados en tres grupos, como vemos en el gráfico:

Mediante ellos podemos cargar un nuevo proyecto, salvar el actual, etc. Cada uno de estos botones tiene una correspondencia con una opción del menú y algunos de ellos también tienen asociada una tecla de acceso rápido.

Por último, en la ventana principal de Delphi, encontramos las paletas de componentes Delphi:

En principio la paleta activa es la llamada Standard, en la que podemos encontrar los componentes y controles más habituales en un programa. Las pestañas existentes en la parte superior nos permitirán acceder a la demás paletas de controles.

Menú de Opciones

Este elemento contiene las diferentes opciones del programa agrupadas en varias principales. En Delphi el menú de opciones es un apartado con estructura casi fija (es decir, siempre las mismas opciones en el mismo lugar), salvando la posibilidad de añadir opciones mediante la creación de extensiones al entorno.

La Paleta de Botones

Page 2: Curso Basico de Delphi

Otro de los elementos de la ventana principal de Delphi es la Paleta de botones o acciones rápidas. Nos permite ejecutar de forma directa algunas de las opciones del menú sin necesidad de buscar por las distintas ventanas. Hay que observar que aquellos que no están disponibles se muestran en gris. Si dejamos un momento el cursor sobre un botón, aparecerá una pequeña etiqueta (un hint) que nos indicará de forma breve cuál es su función.

Al igual que otros elementos de Delphi, la paleta de botones tiene asociado un menú emergente o contextual, que podemos hacer aparecer pulsando el botón derecho del ratón. Estas opciones nos permiten ocultar la barra de botones, pedir ayuda, decir si queremos que se muestren los hints o no, y personalizarla añadiendo/quitando botones en properties. Si ocultamos la barra de botones, siempre tenemos la opción de volver a mostrarla en el menú View, opción Speedbar.

Paleta de Componentes

Aquí podemos seleccionar los elementos que vamos a insertar en un form. Esta también puede ser personalizada mediante el menú emergente, idéntico al de los botones. Igualmente, si ocultamos la paleta de componentes, podemos volver a mostrarla con la opción Component Palette del menú View.

Hay que hacer notar lo siguiente: en el panel de la derecha, además del icono y nombre del componente, también aparece el nombre del paquete en que está incluido. En Delphi, todo componente instalado en el entorno debe estar contenido en un paquete, bien de forma aislada o con otros.

El Form

La interfaz de las aplicaciones que escribamos con Delphi estará basada en el uso de forms, nombre con el que se denomina a las ventanas del entorno Windows en las que se alojarán los distintos controles encargados de interactuar con el usuario. Cada vez que se inicia un nuevo proyecto, en pantalla veremos aparecer un form vacío, en el que podremos insertar los componentes que seleccionemos de la Paleta de componentes.

Prácticamente en todas las aplicaciones contaremos con varios forms, uno principal, que será aquel que aparezca inicialmente al ejecutar el programa, y otros que se irán usando según las opciones que el usuario de la aplicación vaya seleccionando.

En el menú File disponemos de opción New Form, que nos permite insertar un nuevo form en nuestro proyecto. Habitualmente en pantalla sólo tendremos visible aquel form sobre el que estemos trabajando en cada momento, mientras los demás permanecen cerrados (o no visibles por estar detrás del form activo).

Para abrir uno de los forms ya existentes en el proyecto podemos utilizar la opción Forms del

menú View; o pulsar el botón de la Paleta de botones. En cualquiera de los dos casos aparecerá la lista de los forms existentes.

El Inspector de Objetos

Otro de los elementos que habitualmente está visibles en pantalla es el Inspector de objetos, cuya finalidad es facilitar la edición de las propiedades correspondientes al componente que se seleccione.

Page 3: Curso Basico de Delphi

En la parte superior aparece el nombre del componente que se está inspeccionando así como su tipo. Es posible seleccionar cualquier componente de la lista desplegable asociada a este campo, o bien marcar el componente en el form.

La columna izquierda de la ventana sirve para mostrar los nombres de las propiedades, mientras que en la derecha se muestran los valores que tienen actualmente.

El visualizador de objetos

La mayor parte del tiempo, durante la creación de una aplicación con Delphi, estaremos trabajando con objetos, que pueden ser controles y objetos no visuales. Estos objetos disponen en su interior de miembros de datos, métodos, propiedades, pueden definir tipos, etc. Toda la información disponible sobre un cierto objeto la podemos obtener fácilmente mediante el visualizador, que podemos abrir mediante la opción Browse Symbol del menú Search, o bien con la opción Browser del menú View. Para poder analizar un cierto símbolo u objeto con el Visualizador, previamente debemos haber compilado nuestro programa, ya que es del código objeto de donde se obtiene esta información. Si no hemos compilado el programa, veremos que esta opción no está disponible.

En el panel izquierdo del Visualizador podemos seleccionar el objeto del que deseamos obtener información, mostrándose ésta de forma inmediata en el panel derecho de la ventana. En dicho panel existen en realidad tres páginas mostrándose en la primera, Scope, todos los tipos, constantes, métodos, etc., que tiene el objeto; en la segunda la jerarquía de tipos correspondiente al objeto, y en la tercera las referencias existentes a dicho objeto en el código de nuestro programa.

En principio en la página Scope aparecen todos los identificadores existentes en el objeto, tanto si han sido definidos en él como si son heredados. Los botones existentes en la parte superior del Visualizador, tras la palabra Show, nos permiten seleccionar qué información deseamos ver. Los primeros cinco botones nos permiten activar/desactivar la visualización de constantes, métodos, tipos, variables y propiedades, respectivamente. Los dos siguientes botones realizan la misma acción con aquellos miembros que son heredados o son virtuales. Por último tenemos cuatro botones más, que representan a los indentificadores privados, protegidos y públicos.

Page 4: Curso Basico de Delphi

El depósito de objetos

Al seleccionar la opción New del menú File, Delphi abrirá la ventana del Depósito de objetos, en la que podremos optar por crear un nuevo elemento desde cero, o bien partir de otro ya existente. En la primera página de la ventana, que es la que aparece abierta por defecto, podemos optar por iniciar una nueva aplicación estándar, un nuevo componente, librería de enlace dinámico, módulo, etc. La página siguiente llamada ActiveX, contiene los elementos que facilitan la creación de controles ActiveX, forms Active, etc. A continuación tenemos una página que tendrá como título el nombre del proyecto sobre el que estamos trabajando. En ella aparecerán los forms que en ese momento existan en dicho proyecto, permitiendo crear otros nuevos a partir de ellos. En las páginas siguientes, Forms, Dialogs, Data Modules y Projects, encontraremos plantillas de forms, cuadros de diálogo, módulos de datos y proyectos, respectivamente, que podemos copiar en nuestro proyecto, utilizar o bien crear un nuevo elemento heredando las características de uno ya existente.

Reutilización de Forms en un mismo proyecto

Por defecto, cada vez que añadimos un nuevo form al proyecto, éste aparece vacío y es descendiente directo del tipo TForm. Como sabemos, un form no está compuesto sólo por un módulo de código, sino que, además, cuenta con un archivo en el que se almacena toda la información referida a las propiedades de los componentes que hay en el form, lo que dificulta la posibilidad de crear un form utilizando otro ya existente como base. Esta posibilidad, sin embargo, ha sido implementada en Delphi de una forma muy notable, permitiendo compartir forms entre distintos proyectos e incluso dentro de uno mismo, básicamente gracias a lo que Borland ha llamado herencia visual.

Object Pascal es un lenguaje orientado a objetos y, como tal, permite utilizar el concepto de herencia, derivando nuevos objetos de otros ya existentes. Sin embargo, al definir un form hemos de tener en cuenta que no todo en él es código, ya que, además, existe el archivo DFM en el que se almacenan las propiedades de todos los componentes que existen en él. La estructura de estos archivos se ha visto modificada con el fin de aplicar al mismo concepto de herencia.

Modificaciones a un form base

Sin duda la posibilidad que acabamos de conocer, creando nuevos forms a partir de otros ya existentes, es muy potente, y puede ahorrarnos bastante trabajo. Sin embargo, ahí no acaba todo, ya que no estamos hablando de plantillas de forms que se copian en nuestro proyecto, sino de verdadera herencia, con todas las implicaciones que ello tiene.

Imaginemos que hemos escrito la definición de un determinado objeto, del cual posteriormente hemos derivado un nuevo tipo. ¿Qué ocurre si ahora modificamos alguna de las características del tipo base? Está claro que el tipo descendiente o derivado también heredará de forma inmediata las modificaciones. Pues bien, esto mismo es aplicable a los forms que han sido heredados de otros.

Al modificar por ejemplo la posición de un botón en el form base, lo que estamos modificando es el valor que se almacena en el archivo DFM de este form. Puesto que el form de entrada de datos no almacena en su archivo DFM información acerca de estos compnentes sino que la hereda, una modificación se muestra de forma inmediata.

Personalización de un form derivado

Un objeto derivado de otro puede no sólo ampliar sus capacidades, añadiendo nuevos métodos o en el caso de un form, nuevos componentes, sino que además también es posible, si lo deseamos, redefinir métodos que han sido heredados, modificando así el comportamiento por defecto del objeto. En un form que ha sido heredado de otro esto también es posible y podemos alterar las propiedades de aquellos elementos que inicialmente se encuentran definidos en el form base.

Cuando se modifica una propiedad heredada, de un form derivado o de uno de los componentes existentes en él, al archivo de definición de este form se añade una entrada indicando que este componente es heredado, pero que se modifica el valor de dicha propiedad. En realidad es como si hubiéramos redefinido un método de cualquier objeto derivado de otro.

Reutilización de Forms entre proyectos

Page 5: Curso Basico de Delphi

Un form que ha nacido en una determinada aplicación como base para el desarrollo de otras más especializadas, puede sernos útil posteriormente en otros programas, sobre todo si pretendemos que todos nuestros desarrollos compartan una apariencia común. Aunque podemos salvar el form que vamos a utilizar como base e incorporarlo con posterioridad a otros proyectos, resultará mucho más fácil añadirlo al Depósito de objetos de tal forma que la tengamos disponible en todo momento.

Para añadir el form FormBase al Depósito de objetos, hay que situarse con el ratón sobre él, pulsar el botón derecho y seleccionar la opción Add To Repository. En la ventana que aparece, existe una lista con los nombres de todos los forms del proyecto actual. Seleccionamos el que deseamos almacenar en el Depósito de objetos, a continuación damos un título u opcionalmente una descripción. En la lista desplegable Page habrá que seleccionar la página del Depósito de objetos en la que aparecerá el form; selecciona, por ejemplo la página Forms, que es el destino más lógico. Po último podemos facilitar el nombre del autor y un icono con el que se mostrará el form, finalizando el proceso con la pulsación del botón OK.

Copiar, heredar o usar un form del depósito de objetos.

Al abrir la página Forms del Depósito de objetos y seleccionar uno de los forms existentes, observamos que en la parte inferior de la ventana se activan tres opciones mediante las cuales podemos: copiar el form en nuestro proyecto, derivar un nuevo form a partir de él o bien utilizarlo directamente. La opción a usar dependerá obviamente del resultado que deseemos obtener.

Copiar el form en nuestro proyecto, que es la primera opción disponible, añade a nuestro proyecto un nuevo módulo de código y un form, que inicialmente cuenta con unas determinadas propiedades y componentes. Este form que se ha añadido a nuestro proyecto no guardará ninguna relación con el form original, por lo que no se verá afectado por ninguna modificación posterior en este.

La segunda opción es la que hemos estado usando en los supuestos anteriores, derivando un form que hereda las características de otro, pero que sigue estando relacionado con él, de tal forma que cualquier modificación en el form base tiene su reflejo inmediato en el form derivada.

Por último tenemos la opción Use, que será la que utilicemos cuando en nuestro proyecto deseamos usar el form original que existe en el depósito de objetos, no una copia ni un nuevo form derivado de él. Al utilizar un form de esta forma, cualquier modificación que se realice sobre él afectará de forma indirecta a cualquier otro form derivado de él, incluso de otras aplicaciones.

Reutilización de proyectos enteros

Además de forms individuales, Delphi también nos permite reutilizar aplicaciones o proyectos completos. De hecho en la página Projects del Depósito de objetos existen varios modelos de aplicación ya "prefabricados". Esta posibilidad está dirigida sobre todo a reducir el tiempo que se emplea en la creación del esqueleto de una aplicación, que suele ser siempre igual.

Para añadir un proyecto al Depósito de objetos deberá abrir el menú Project y seleccionar la opción Add To Repository. Esto mostrará una ventana en donde tendremos que introducir un título, una descripción e indicar la página del Depósito de objetos en la que aparecerá. También podemos facilitar el nombre del autor y un icono que le identifique. Dado este paso, siempre que deseemos iniciar un nuevo proyecto podemos elegir la página adecuada del Depósito de objetos y hacer un doble clic sobre el icono, ahorrando mucho trabajo.

Los proyectos que vayan a añadirse al Depósito de objetos para ser posteriormente utilizados, deberán almacenarse en un directorio que tan sólo contenga los elementos de ese proyecto. Al crearse una nueva aplicación tomando esa plantilla como base, Delphi preguntará cuál será el directorio del nuevo proyecto y copiará en él todos esos archivos.

Personalizar el depósito de objetos

Page 6: Curso Basico de Delphi

Al igual que la mayoría de los elementos en Delphi, la ventana del Depósito de objtos cuenta con un menú emergente, que podemos hacer aparecer simplemente pulsando el botón derecho del ratón. En este menú podemos elegir entre diferentes modos de visualización, el orden de los elementos en la ventana y una opción, llamada Properties, que nos da acceso a la ventana de propiedades del Depósito de objetos, en la que podremos adecuarlo a nuestras preferencias. También podemos acceder a esta ventana mediante la opción Repository del menú Tools.

Esta ventana cuenta con dos listas y una serie de botones que ocupan la parte central. La ventana de la izquierda contiene el nombre de cada una de las páginas del Depósito de objetos, así como un elemento, Object Repository, que representa a todos los anteriores juntos. La lista de la derecha muestra los nombres de los elementos existentes en la página que hay seleccionada actualmente en la lista de la izquierda, como forms y proyectos. Mediante los botones existentes en la parte central podemos acceder a la mayoría de las opciones disponibles.

Añadir, eliminar y modificar páginas

Tanto el form como el proyecto que hemos añadido, en los pasos anteriores, al Depósito de objetos, han tenido como destino páginas que ya existían. Nada nos impide, sin embargo, añadir nuestra propia página con el fin de almacenar en ella los elementos definidos por nosotros, los cuales seguramente utilizaremos con mayor asiduidad. Para añadir una nueva página simplemente pulsamos el botón Add Page y, a continuación, facilitaremos el título que deseamos darle.

Eliminar una página del Depósito de objetos es aún más simple, ya que simplemente tenemos que seleccionarla y pulsar el botón Delete Page. Sin embargo, deberemos tener en cuenta que la página se habrá de encontrar vacía, no permitiéndosenos el borrado en caso contrario. Para dejar vacía una página seleccionamos cada uno de los elementos que ésta contiene y pulsamos el botón Delete Object.

Los nombres de las páginas que ya existen pueden ser modificados. Esta es la finalidad del botón Rename Page.

Gestión de los objetos de las páginas

Cada vez que se selecciona una página en la lista de la izquierda, en la que hay en la derecha aparecen los nombres e iconos de los objetos que ésta contiene. Haciendo un doble clic sobre cualquiera de ellos, podremos editar su título, descripción, icono, página en la que se almacena y autor.

Si deseamos mover objetos entre las páginas del Depósito de objetos, el método más rápido y fácil consiste en seleccionar la página Object Repository, que nos permite disponer en la lista de la derecha de todos los objetos existentes en ese momento. Tomando cualquiera de ellos y arrastrándolo hasta la página deseada lo moveremos.

2.I. Características de un Form La principal cualidad de un form es la de tratarse de un componente "contenedor", lo que le permite albergar en su interior otros componentes. Aunque el form en sí dispone ya de una cierta funcionalidad, realmente su utilidad la obtendremos cuando en él insertemos otros componentes que nos sirvan para mostrar o solicitar información al usuario del programa. Este proceso, en el cual los componentes se van situando en el form y se van modificando según las necesidades, es el diseño de la interfaz de nuestra aplicación.

Propiedades

Durante la etapa de diseño de la interfaz, las propiedades de un objeto pueden ser consultadas y modificadas mediante el Inspector de Objetos. Básicamente, el Inspector de objetos está compuesto de una cabecera, en la que aparece el nombre del tipo del objeto que se está inspeccionando en ese momento, y dos páginas, una donde aparecen las propiedades y otra correspondiente a los eventos. En la página de propiedades nos encontramos con dos columnas, conteniendo la izquierda el nombre de la propiedad y la derecha su valor actual. Existen ciertas propiedades que sólo son accesibles durante el diseño, mientras que otras sólo lo son durante la ejecución del programa.

Modificación de una propiedad

Page 7: Curso Basico de Delphi

El método de modificación de una propiedad en tiempo de diseño dependerá directamente del tipo de la propiedad, que al igual que una variable puede contener una cadena, un número, una numeración, etc. Además una propiedad también puede ser un objeto, que a su vez contenga sus propiedades particulares.

Para modificar el valor de una propidad simple, que contiene una cabecera o un número, bastará con pulsar sobre el nombre o el valor actual. Al hacerlo veremos que automáticamente se marca el contenido actual.

Otras propiedades sólo pueden tomar un valor de una lista predeterminada, que podemos abrir pulsando sobre la flecha hacia abajo que aparecerá al seleccionar dicha propiedad.

Un tercer tipo de propiedad la componen aquellas que contiene otras propiedades y a las que por tanto se pueden llamar propiedades compuestas. Estas tienen un valor que aparece como si fuese una cadena de caracteres, pero que en realidad no podremos modificar directamente. Si nos fijamos, a la izquierda del nombre de la propiedad aparece un signo +, lo que indica que esta propiedad es una propiedad compuesta. Realizando un doble clic sobre el nombre conseguiremos desplegar su contenido, teniendo acceso a las propiedades que la componente y pudiendo modificar su valor por alguno de los métodos anteriores. Podemos volcer a cerrar el contenido de una propiedad compuesta de la misma forma, realizando un doble clic sobre el nombre.

Además de los tres tipos anteriores de propiedades, nos podemos encontrar con casos particulares en los cuales, para editar el valor de la propiedad, se facilita algún tipo de herramienta adicional a la que llamaremos editor de propiedad.

Eventos

Un form que contenga los componentes nacesarios con sus correspondientes propiedades establecidas correctamente, nos será de poca utilidad si no tenemos algo más. Una interfaz por sí sola no tiene finalidad alguna ya que aunque el usuario puede interactuar con el form y sus componentes, nuestro programa no hará nada a no ser que nosotros escribamos algo de código.

El código de una aplicación Delphi habitualmente siempre está asociado a eventos, de tal forma que su ejecución no se produce de forma secuencial, desde el principio hasta el fin del programa.

Un evento es una señal, externa o interna a la aplicación, que nuestro programa puede aprovechar para ejecutar un cierto bloque de código, el cual escribiremos en un método. El nombre y parámetros de estos métodos están predeterminados por Delphi, de tal forma que si deseamos responder a un evento tan sólo hemos de escribir el código que queremos ejecutar.

El evento por defecto

Sólo existe un evento por defecto para cada componente, por lo que para acceder al resto de eventos tendremos que utilizar la página Events del Inspector de objetos. Al abrirla podremos ver el nombre de todos los eventos posibles para el componente seleccionado en ese momento. Realizando un doble clic sobre la columna derecha de un evento, en la ventana de código aparecerá el método de respuesta correspondiente, en el que podremos insertar las sentencias que deseemos.

Eventos con métodos comunes

Aunque inicialmente es posible crear un método de respuesta distinto para cada evento, en caso de que el código a ejecutar sea el mismo, Delphi nos permite que múltiples eventos compartan un solo método de respuesta. Para conseguir esto, primero tendremos que crear dicho método, realizándose un doble clic a la derecha del primer evento que vayamos a agrupar. En la ventana de código podemos entonces introducir las sentencias que necesitemos. Hecho esto no tenemos mas que seleccionar el segundo evento, pulsando sobre su nombre, y abrir la lista desplegable de método mediante la flecha que aparece en la columna derecha. En esta lista seleccionaremos el método correspondiente, que quedará así asociado también a este evento. El proceso lo podemos repetir tantas veces como sea necesario, asociando múltiples eventos a un solo método.

Para modificar el código de un método de respuesta a un evento, suponiendo que éste no esté visible en ese momento en la ventana de código, bastará con realizar un doble clic en la columna derecha del evento en cuestión para que el cursor se desplace hasta el cuerpo de dicho método.

Page 8: Curso Basico de Delphi

Parámetros de eventos

Al igual que ocurre con cualquier procedimiento, los métodos de respuesta a eventos también pueden recibir parámetros de distintos tipos. El número y tipo de los parámetros a recibir dependerán directamente del evento del que se trate.

2.II. Manipulación de componentes Los componentes a insertar en el form, los seleccionamos de la Paleta de componentes, eligiendo primero, si es necesario, la página en que se encuentre el componente necesitado.

Existen varias formas de insertar un componente en el form, aún cuando el resultado final será el mismo. Si hacemos un doble clic sobre un componente de la Paleta conseguiremos que éste se inserte automáticamente en el centro del form, tomando un tamaño por defecto. Si lo deseamos, podemos fijar un tamaño distinto.

En caso de que necesitemos insertar en el form múltiples componentes del mismo tipo, podemos usar un método más rápido, que consiste en pulsar la tecla de <Mayúscula> antes de pulsar el componente de la Paleta. Hecho esto, el componente quedará seleccionado y, simplemente pulsando sobre el form, podremos ir insertando tantas copias del control como sea necesario. Cuando hayamos terminado, tendremos que pulsar sobre el icono que representa al cursor del ratón, que aparece siempre a la izquierda de la Paleta de componentes.

Posición y tamaño de los componentes

Aunque en el momento en que un control se inserta en el form éste ya toma una posición y un tamaño determinados, estos atributos son modificables siempre y cuando no esté activa la opción Lock Controls, en el menú Edit.

Para modificar la posicición en la que se encuentra un componente bastará con <pincharlo>, situando el cursor del ratón sobre él y pulsando el botón izquierdo y <arrastrarlo>, desplazando el cursor del ratón hasta la posición que deseemos, momento en que liberaremos la pulsación.

Con el fin de alterar el tamaño de un componente, primero deberemos seleccionarlo, para lo que bastará con realizar una pulsación sobre él con el cursor del ratón. Hecho esto, el componente aparecerá delimitado por una serie de bloques, que realmente nos indican los puntos por los que podemos redimensionar el control.

Aunque todos los componentes tienen una posición en el form, no todos tienen un tamaño definible. Por ejemplo, el componente PrintDialog tiene un tamaño fijo, al tratarse de un componente no visual, que en tiempo de ejecución no aparecerá en el form.

Cortar, copiar y pegar componentes

Los componentes existentes en un form pueden cortarse, copiarse al portapapeles y pegarse desde el portapapeles, de igual forma que podemos hacer con un texto en el editor de código. Al copiar un componente al portapapeles, se conservará información acerca de las dimensiones del componente y los valores de sus propiedades, de tal forma que si posteriormente lo pegamos, obtendremos una copia exacta del componente original, a excepción del nombre.

Los comandos Cut, Copy y Paste pueden ser ejecutados desde el menú Edit, pero es mucho más rápido y cómodo usar las combinaciones de teclas <Control+X>, <Control+C> y <Control+V>.

Selección de componentes

Para seleccionar un componente basta con realizar una pulsación con el botón izquierdo del ratón, habiendo situado previamente el cursor sobre el componente en cuestión. Otra forma consiste en desplegar la lista existente en la parte superior del Inspector de objetos, eligiendo una de las líneas. Al hacerlo, en el form automáticamente se mostrará seleccionado el componente correspondiente a dicha línea.

En ocasiones puede ser interesante seleccionar múltiples componentes en el form, con la finalidad de tratarlos de forma genérica. Para ello podemos usar básicamente dos métodos: ir pulsando con

Page 9: Curso Basico de Delphi

el ratón sobre los distintos componentes mientras mantenemos pulsada la tecla de <Mayúscula>, o bien trazar en el form, usando el botón izquierdo del ratón, un cuadrado o rectángulo que delimite a todos los componentes que deseamos agrupar.

Un grupo de componentes seleccionados puede ser copiado al portapepeles, borrado, desplazado en el form e incluso es posible modificar aquellas propiedades y eventos que son comunes.

Alineación y otras opciones

Por defecto, en el interior del form siempre aparece una rejilla de puntos, que sólo es visible durante el diseño, desapareciendo en tiempo de ejecución. La finalidad de esta rejilla es facilitar el correcto posicionamiento de los componentes del form, siendo configurable la distancia entre puntos.

Las opciones relacionadas con la rejilla podemos modificarlas en la página Preferences de la opción Environment Options del menú Tools.

Análisis del código

A medida que en nuestro proyecto vayamos insertando forms, en estos añadimos controles a los cuales asociaremos métodos de respuesta a eventos, etc., Delphi irá generando automáticamente todo el código necesario para que, posteriormente, sea posible obtener un ejecutable simplemente compilando, sin necesidad de pasos intermedios. El conocimiento del código generado por Delphi nos permitirá una mejor comprensión del funcionamiento general de nuestra propia aplicación, facilitándonos posteriores tareas de modificación y mantenimiento.

Módulos y Forms

Delphi utiliza el programa principal para almacenar el código del proyecto, que habitualmente no se hace visible. Sim embargo, podemos usar la opción Project Source del menú View para hacer aparecer dicho código, que se almacena en un archivo que en lugar de tener extensión PAS, como los módulos habituales de Pascal, tiene la extensión DPR, con el fin de diferenciar un proyecto de cualquier otro módulo de código.

Además del código del proyecto, cualquier aplicación típica contará con al menos un form, que tendrá asociado un módulo de código. Por cada form adicional existirá un módulo adicional con el código correspondiente. Por último también es posible tener otros módulos no asociados a forms, conteniendo objetos o procedimientos y funciones definidos por nosotros mismos.

Cada módulo de código asociado a un form contendrá la definición de un objeto, conteniendo los componentes y métodos de respuesta a eventos necesarios. Todos los forms se definen como objetos descendientes del tipo TForm, que se caracteriza por contener los atributos comunes a cualquier form. A la definición del nuevo tipo de objeto se añadirán tantos miembros como componentes insertemos en la ficha y tantos métodos como eventos controlemos.

El código del proyecto

A medida que vayamos añadiendo forms a nuestro proyecto, en el código correspondiente, que podemos visualizar mediante la opción Project Source del menú View, se irán añadiendo entradas a la cláusula Uses, relacionando todos los módulos existentes en el proyecto principal. Por lo demás, el código del proyecto, que es por donde comenzará la ejecución de la aplicación, se suele reducir a la creación del form principal y al inicio de lo procesos necesarios para que dicho form pueda interactuar con el usuario.

Archivos DFM

En el código del módulo asociado a un form no se almacenan los valores de las propiedades de cada componente, como puede ser su posición, dimensiones, título, etc. Este tipo de información se almacena en un archivo separado, con extensión DFM, que es incluido en la aplicación durante la compilación, como si se tratase de un recurso.

Los archivos de definición de componentes están en un formato binario, que no es legible directamente. Sin embargo, el propio editor de Delphi nos permite ver y editar el contenido de

Page 10: Curso Basico de Delphi

estos archivos. Para ello lo único que debemos hacer es pulsar el botón derecho del ratón sobre el form, seleccionando la opción View As Text. También podemos pulsar la combinación de teclas <Alt + F12>. Al cargar el archivo éste aparecerá en forma de texto en el editor, conteniendo por cada componente su nombre, tipo y valores de las propiedades.

Aunque no es una técnica habitual, el contenido de este archivo puede ser modificado en el editor de código. Para que las modificaciones tengan efecto deberemos convertir de nuevo el texto que tenemos en el editor al formato del archivo DFM, para lo que bastará con salvarlo con dicha extensión o simplemente volver a convertirlo en un form utilizando la misma combinación de teclas citada antes.

2.III. Propiedades de TForm Nombre del componente

Cada uno de los componentes usados en una aplicación, incluyendo en este conjunto los forms, ha de tener un nombre único que nos servirá para hacer referencia a ellos de una forma inequívoca. El nombre de los componentes se fija en tiempo de diseño, mediante la propiedad Name, convirtiéndose en una propiedad de sólo lectura durante la ejecución.

En el momento en que se produce el cambio de nombre del componente, el código generado por Delphi se actualizará automáticamente, por ejemplo en los métodos de respuesta a eventos, serán modificados.

Titulo del form

Su finalidad es la de identificar la ventana en tiempo de ejecución. En principio, el título del form coincidirá con el nombre que se haya asignado a éste, de tal forma que si modificamos la propiedad Name el mismo valor será asignado también a la propiedad Caption, que es la encargada de mantener el título de los componentes que cuentan con este elemento.

La asociación entre las propiedades Name y Caption es temporal ya que, aunque en principio la modificación de la primera influye en la segunda, este lazo se rompe en el momento en que nosotros modifiquemos el valor de Caption, introduciendo el título que más nos convenga. Dicho título es una cadena de caracteres, no un identificador, por lo que puede contener espacios en blanco y otra serie de caracteres especiales no permitidos en un identificador como es Name.

Podemos alterar el título de un form desde el interior del programa simplemente asignando un nuevo valor a su propiedad Caption.

Ámbito de tipo

Para acceder a un miembro de un objeto debemos primero especificar el identificador del objeto, seguido de un punto y el identificador del miembro que se desea manipular. Esto es lo que se llama un referencia completa o cualificada, que nos permite acceder a identificar de forma inequívoca, ya que en dos objetos distintos pueden existir miembros con los mismos nombres, pero, sin embargo, no podemos tener dos objetos con el mismo nombre en el mismo ámbito.

El código que nosotros podemos escribir en el interior de un método de respuesta a un evento, se encuantra en el ámbito del objeto. Al encontrarnos en el mismo ámbito que el objeto, para acceder a sus miembros no es necesario componer una referencia cualificada. De esta forma, para acceder a la propiedad Caption del objeto Form1 desde un método del propio objeto, no es necesario componer la referencia Form1.Caption, basta con el nombre de la propiedad. Sin embargo, si quisiéramos acceder a esa misma propiedad de otro form o componente distinto, sí que sería necesaria la composición de una referencia cualificada.

Posición y dimensiones del form

A medida que un componente es desplazado y redimensionado, su posición y tamaño actuales quedan almacenados en cuatro propiedades : Left contiene la coordenada horizontal, Top la vertical, Width la anchura del componente y Height la altura, medidas todas éstas expresadas en puntos de pantalla. La posición de cualquier componente de un form es relativa al interior de él, mientras que la posición de un form es absoluta, refiriéndose Left y Top a posiciones de pantalla.

Page 11: Curso Basico de Delphi

Generalmente, en tiempo de ejecución el form aparecerá en la misma posición en la que lo situamos durante el diseño y con el mismo tamaño, aunque por medio de la propiedad Position podemos configurar ambos parámetros. Esta propiedad puede tomar cualquiera de los siguientes valores:

poDesigned. Es el valor tomado por defecto, causando que el form aparezca en la misma posición y con el mismo tamaño que se fijó en tiempo de diseño.

poDefault. Dando este valor a Position, la posición y el tamaño del form irán cambiando con cada ejecución, tomando la posición que les corresponda por defecto y el mayor tamaño posible.

poDefaultPosOnly. Esta opción es una variación de la anterior, en la que el tamaño del form permanece fijo, mientras que la posición va cambiando con cada ejecución.

poDefutoSizeOnly. Inversa a la anterior, conserva la posición del form pero el tamaño es fijado en el momento de la ejecución.

poScreenCenter. Por medio de esta opción conseguiremos que el form permanezca con su tamaño original, modificándose su posición para que aparezca ocupando el centro de la pantalla.

La apariencia inicial de un form en pantalla también podemos fijarlo mediante la propiedad WindowState, que puede tomar los valores wsNormal, wsMinimize y wsMaximize, según deseemos que la ventana aparezca en su estado normal, minimizada como un icono, o maximizada ocupando la pantalla completa. Estos tres estados son independientes de las opciones que hayamos fijado mediante la propiedad anterior.

El área cliente

La existencia de una barra de título, un borde de más o menos grosor, unos botones, etc., limitan el área realmente "útil" del form, que para nosotros es su interior, al que se denomina área cliente.

Obviamente, al modificar el tamaño de la ventana también estamos alterando las dimensiones del área cliente, ya que está ocupa todo el interior del form. Podemos conocer y modificar las dimensiones del área cliente mediante las propiedades ClientWidth (ancho) y ClientHeight (alto).

Proporciones generales

Por defecto el efecto de escalado no se produce, aunque la propiedad Scaled tiene al valor True. Dando el valor True a esta propiedad activaremos el escalado, cuya proporción vandrá dada por el valor que asignaremos a la propiedad PixelsPerInch. Dicho valor indica cuántos puntos de medida entrarán en cada pulgada, por lo que cuanto más grande sea el número, más reducida aparecerá el form y viceversa. Dando el valor False a la propiedad Scaled desactivaremos el escalado, a pesar de que hayamos asignado cualquier valor a PixelsPerInch.

Hay que tener en cuenta que no es lo mismo escalar el form que redimensionarlo. En este último caso lo que hacemos es cambiar el tamaño del form, de tal forma que los componentes que hay en su interior pueden quedar ocultos en parte. Al escalar un form automáticamente se modifica también el tamaño de todos los componentes que hay en él, adecuando su tamaño, que se aumenta o reduce, para adecuarlo al del form.

Estilo y controles del form

Por defecto, un form contiene a la derecha de su barra de título tres botones, mediante los cuales podemos minimizar el form, maximizarlo o restaurarlo, o bien cerrarlo. En la esquina izquierda de la barra también existe un icono, que nos permite acceder al típico menú de sistema que tienen la mayoría de las ventanas Windows. La existencia o no de estos controles en el form dependerá de los valores que contenga la propiedad BorderIcons, que es un conjunto que puede contener tres valores distintos: biMinize, que representa el primer botón de los tres que hay en la parte derecha del form, biMaximize, representa al segundo de esos botones, biSystemMenu, al tercer botón y al menú de sistema.

A pesar de que en el inspector de objetos indiquemos que no deseamos en el form ciertos botones de los descritos, hasta que no ejecutemos el programa, dichos controles permanecerán activos para permitir la manipulación completa de la ventana.

El borde del form

Page 12: Curso Basico de Delphi

Mientras estamos diseñando un form, éste puede ser redimensionado sin más límites que los de la propia pantalla, con el fin de ajustarlo a nuestras necesidades. Una vez que el programa es ejecutado, las dimensiones del form podrán o no ser modificadas, por parte del usuario, dependiendo básicamente del valor que asignemos a la propiedad BorderStyle. Por defecto esta propiedad toma el valor bsSizeable, lo que permite que durante la ejecución el form pueda ser redimensionado por el usuario simplemente utilizando el cursor del ratón sobre cualquiera de sus extremos. Además de este valor, la propiedad BorderStyle también puede tomar los siguientes:

bsSingle. Esta opción hace que el borde del form aparezca algo menos grueso, además de no permitir redimensionarlo.

bsToolWindow. Como el anterior pero con una barra de título menor, al estilo de las barras de herramientas.

bsDialog. Asignando este valor no modificaremos el grosor del borde de la ventana, evitando sólo el redimensionamiento del form.

bsNone. Elimina el borde de la ventana, así como la barra de título con todos sus controles. bsSizeToolWin. Borde redimensionable con una barra de título con todos sus controles.

Apariencia tridimensional

Las últimas aplicaciones aparecidas para Windows 3.1 incorporaron en su mayoría efectos tridimensionales en ventanas y controles, hasta tal punto que Microsoft creó una librería cuya finalidad era le de crear un estándar en este tipo de controles. En Windows 95 el propio sistema operativo ha incrementado visiblemente los efectos tridimensionales en opciones de menú, botones, etc. También nuestrar aplicaciones Delphi pueden contar con este aspecto, de hecho lo hacen automáticamente a no ser que modifiquemos el valor de la propiedad Ctl3D.

Por defecto esta propiedad tiene el valor True, haciendo, por ejemplo, que el fondo de los forms sea gris, y los distintos controles existentes en él aparezcan como esculpidos. Dando el valor False a esta propiedad desactivaremos el efecto tridimensional, de tal forma que el fondo del form será blanco, como el de cualquier ventana.

La propiedad Color nos permite modificar este color por defecto, pudiendo elegir entre un color concreto, como pueda ser azul, rojo, negro, etc., o bien un color del sistema, por ejemplo el color de la barra de título d la ventana activa, el color de un botón pulsado, etc.

Forms y menús

Cualquier form Delphi puede tener asociado un menú de opciones que aparecerá bajo su barra de título. La propiedad encargada de mantener la referencia al menú asociado al form es Menu. De igual forma, podemos asociar un menú emergente a una form, utilizando la propiedad PopupMenu.

Etiquetas de ayuda

En Delphi, la creación de estas etiquetas de ayuda es de suma facilidad, lo único que hemos de hacer es asignar la cadena que queremos visualizar a la propiedad Hint del componente, dando además el valor True a la propiedad ShowHint. Estas propiedades las tienen prácticamente todos los controles, incluidos los forms, aunque su uso más habitual está asociado con los botones existentes en las barras o paletas de herramientas.

Estado del form

En un momento determinado de la ejecución de un programa, un form que estaba activo, de tal forma que el usuario podía interactuar con ella, puede pasar a estar inactivo o incluso hacerse no visible. El estado del form lo controlaremos básicamente con dos propiedades, Enable y Visible. Ambas pueden tomar los valores True y False, siendo el valor por defecto de las dos True.

Estilo del form

La propiedad FormStyle puede contener uno de cuatro valores indicando el estilo del form, que habitualmente es fsNormal. Este estilo normal se corresponde con un form de carácter

Page 13: Curso Basico de Delphi

independiente, que no puede contener otras ventanas en su interior ni ser a su vez contenido en otra ventana.

Es posible crear un form que actúe como marco para utilizar múltiples forms relacionados entre sí. Al primero lo denominaremos ventana marco o principal, cuyo estilo será fsMDIForm, mientras que a los distintos forms que existan en su interior les llamaremos ventanas hija, siendo el estilo correspondiente fsMDIChild.

El cuarto valor que es posible dar a FormStyle nos permite crear una ventana que no será ocultada cuando otra ventana se active, siepre estará sobre las demás, este estilo es fsStayOnTop.

Iconos y cursores

Por defecto, el icono que aparece en la barra de título de un form y con el que se representa el mismo cuando se minimiza, es el mismo icono de la aplicación, a no ser que nosotros establezcamos uno distinto mediante la propiedad Icon. Esta propiedad es en realidad un objeto, con sus propiedades, eventos y métodos. En tiempo de diseño, podemos cargar un icono mediante el editor que aparecerá al pulsar en los puntos suspensivos que aparecen a la derecha. En tiempo de ejecución, necesitaremos como único parámetro el nombre del archivo en que se encuentra el icono.

Por defecto, al pasar sobre el área cliente de un form, el cursor del ratón es una flecha, pero podemos cambiar a cualquier otro aspecto modificando el valor de la propiedad Cursor. La enumeración de valores que es posible asignar a Cursor la podemos ver desplegando la lista de esta propiedad en el Inspector de objetos.

Estilos de letra

Los distintos controles que insertemos en un form pueden utilizar un tipo y estilo de letra de nuestra elección, para lo cual nos serviremos de la propiedad Font, que es en realidad un objeto del tipo TFont. Al modificar esta propiedad del form, generalmente no observamos cambio alguno, ya que los efectos se producirán en el momento en que insertemos algún control, cuya propiedad Font tomará los mismos valores que hayamos asignado a dicha propiedad en el form.

Las propiedades con que cuenta un objeto TFont nos permiten seleccionar el tipo de letra, color, tamaño, estilo, etc. Podemos modificar dichas propiedades en tiempo de diseño mediante el Inspector de objetos, así como acceder a ellas en tiempo de ejecución. Estas propiedades son:

Color: Establece el color del texto. Hay que recordar que con la propiedad Color del form fijábamos el color de fondo de la ventana.

Height y Size. Ambas propiedades tienen una misma finalidad: especificar el tamaño del tipo de letra, bien facilitando su altura o el tamaño de los puntos.

Name. Asignando a esta propiedad el nombre de un tipo de letra conseguiremos seleccionarlo. En el Inspector de objetos podremos seleccionar cualquiera de los tipos desde una lista desplegable, mientras que durante la ejecución tendremos que asignar a esta propiedad una cadena conteniendo específicamente el tipo.

Style. Se trata de un conjunto, que puede contener los valores fsBold, fsItalic, fsUnderline y fsStrikeOut, según lo cual el texto aparecerá o no en negrita, itálica, subrayado o tachado.

Barras de desplazamiento

El uso automático de barras de desplazamiento está controlado por la propiedad AutoScroll, que por defecto tiene el valor True.

Las características de las barras de desplazamiento pueden ser alteradas mediante las propiedades HorzScrollBar y VertScrollBar, dos objetos que representan respectivamente a la barra de desplazamiento horizontal y vertical. En el caso de un form, las propiedades de estos objetos toman sus valores automáticamente, dependiendo del tamaño de dicho form.

Otras propiedades

En un form encontraremos asimismo otros también editables en tiempo de diseño. Estas propiedades son:

Page 14: Curso Basico de Delphi

ActiveControl. Cuando un form con diversos componentes se muestra inicialmente, el control toma uno de los componentes, que será el que esté activo en principio. Al desplegar la lista asociada a esta propiedad en el Inspector de objetos podremos seleccionar cuál será dicho control.

HelpContext. Mediante esta propiedad podemos asociar al form una determinada página de ayuda contextual.

ObjectMenuItem. Esta propiedad nos permitirá establecer una opción de menú que se hará activa cuando en el form se esté trabajando con un campo OLE.

PrintScale. Es posible imprimir un form con una simple llamada a un método del objeto TForm. Antes necesitaremos especificar la escala con la que deseamos que se realice la impresión. Las opciones posibles son poNone, poProportional y poPrintToFit, según deseemos no mantener proporción alguna, imprimir el mismo número de puntos en impresora que en pantalla o bien ocupar el mayor espacio posible en la página manteniendo la proporción del form, respectivamente.

Tag. Se trata de una propiedad que no tiene significado alguno ni es usada por ninguno de los objetos que cuentan con ella. Su finalidad es permitirnos guardar cualquier valor entero que necesitemos asociar al objeto.

KeyPreview. Por defecto el valor de esta propiedad es False, de tal forma que las pulsaciones de tecla que se produzcan durante la ejecución del programa vayan directamente al control del form que en ese momento está activo. Dándole el valor True a esta propiedad conseguiremos que dichas pulsaciones sean enviadas antes al form y después al control que esté activo, permitiendo así su intercepción.

Controles y componentes

Podemos conocer en tiempo de ejecución el número de componentes y controles que existen en un form, mediante las propiedades ComponentCount y ControlCount. Recordemos que un componente es cualquiera de los elementos existentes en un form, mientras que un control es un componente que cuenta con una interfaz, se trata de un elemento visual.

Conociendo el número de componentes y controles, podemos acceder a cualquiera de ellos usando las matrices Components y Controls, que son otras dos propiedades del form. Estas matrices contendrán tantos elementos como nos indiquen ComponentCount y ControlCount, respectivamente, siendo la base de los índices el cero. Una vez que accedamos a un elemento de cualquiera de estas dos matrices podemos determinar su tipo, realizar las conversiones necesarias y manipular sus propiedades.

Superficie de trabajo

Un form de Delphi tiene una correspondencia directa con una ventana Windows, que es habitualmente manipulado por medio de un identificador o handle, que podremos obtener mediante la propiedad Handle. Este identificador podremos usarlo con cualquiera de las funciones Windows que hacen uso de él, como puede ser BitBlt.

Un método más simple y recomendable para trabajar sobre un form consiste en usar el valor de la propiedad Canvas, que es un objeto que representa todo el espacio interior de la ventana y que cuenta con una serie de métodos que nos permitirán escribir texto, dibujar, etc.

Forms MDI

Un form también cuenta con una serie de propiedades que facilitan el trabajo con ventanas MDI, conteniendo ventanas hijas en su interior. Mediante la propiedad MDIChildCount podremos saber el número de ventanas hijas existentes en un determinado momento, dato que nos servirá para acceder a los elementos de la matriz MDIChildren, cada uno de los cuales representa a una ventana hija.

2.IV. Eventos de TForm Eventos generados por el ratón

Hay varios eventos posibles:

Page 15: Curso Basico de Delphi

OnMouseMove. Este evento es recibido por un componente a medida que el cursor del ratón se mueve sobre él. Este evento lleva asociados varios parámetros, como son X e Y, que representan la posición actual del cursor expresada en puntos, y Shift, un conjunto que puede contener valores dependiendo de qué teclas y botones estén pulsados mientras el ratón se mueve.

Valor Corresponde a... ssShift Una de las teclas de mayúscula. ssAlt La tecla <ALT>. ssCtrl La tecla <Control>. ssRight El botón derecho del ratón. ssLeft El botón izquierdo del ratón. ssMiddle El botón central del ratón. ssDouble Los botones izquierdo y derecho del ratón.

OnMouseDown. Se genera cuando se pulsa cualquiera de los botones del ratón, recibiéndolo aquel control que en ese momento se encuentra bajo el cursor. Además de los parámetros X,Y y Shift, con el mismo significado que en OnMouseMove, el método de respuesta a este evento también recibirá el parámetro Button, que nos permitirá saber qué botón ha sido el que ha producido el evento. Los valores posibles son mbRight, mbLeft y mbMiddle, según se trate del botón derecho, izquierdo o central.

OnMouseUp. Cada vez que se libera un botón del ratón sobre un control, éste recibe el evento OnMouseUp, cuyos parámetros son idénticos a los del evento anterior.

OnClick. Aunque este evento también puede venir producido por la pulsación de la barra espaciadora sobre un control o la pulsación de la tecla <Intro> o <Escape>, en la mayoría de las ocasiones denota una pulsación en el botón izquierdo del ratón sobre algún control.

OnDblClick. Este evento lo recibirá un control cuando se realice una doble pulsación con el botón izquierdo del ratón, teniendo el cursor situado sobre dicho control.

Eventos de teclado

Aunque generalmente un form no recibe directamente las pulsaciones de teclado, sino que éstas van directamente a alguno de los controles, es posible interceptarlas. Los eventos que nos permitirán hacerlo son:

OnKeyDown. Se produce al pulsarse una tecla, cuyo código es facilitado en el parámetro Key. Al igual que los eventos de ratón, también se recibe el parámetro Shift, mediante el cual podremos saber si hay pulsadas otras teclas o botones de ratón. Tengamos en cuenta que el código recibido no es el código ASCII, sino el código virtual de la tecla pulsada.

OnKeyUp. Este evento se genera al liberar una tecla. El método de respuesta correspondiente recibirá los mismos parámetros descritos en el evento OnKeyDown.

OnKeyPress. A diferencia de lo que ocurre con OnKeyDown, que se genera con cualquier tecla alfanumérica, de función, control, etc., este evento sólo se produce por la pulsación de las teclas "normales", excluyendo de este conjunto las de función, edición y, en general, todas aquellas que no dispongan de código ASCII. El parámetro Key que se recibe como parámetro corresponde precisamente al código ASCII de la tecla pulsada.

Tanto OnKeyDown como OnKeUp reciben un código de tecla y no un código ASCII del carácter pulsado. Esto les permite detectar la pulsación de aquellas teclas que no tienen asociado un carácter, como puedan ser las de función o las de edición. Los códigos de teclas están representados por una serie de constantes que comienzan con las iniciales VK_.

Constante Tecla que representaVK_0,VK_1, ..., VK_9 Los dígitos del 0 al 9. VK_NUMPAD0, VK_NUMPAD1 Los dígitos del 0 al 9 de parte numérica VK_A, VK_B, ..., VK_Z Las teclas de la A a la Z. VK_BACK Borrado hacia atrás

Page 16: Curso Basico de Delphi

VK_TAB Tabulador VK_RETURN Intro VK_SHIFT Mayúsculas VK_CONTROL Control VK_MENU Alt VK_PAUSE Pausa/Inter VK_CAPITAL Fija Mayúscula VK_ESCAPE Escape VK_SPACE Barra Espaciadora VK_PRIOR RePág VK_NEXT AvPág VK_END Fin VK_HOME Inicio VK_LEFT Flecha hacia izquierda VK_RIGHT Flecha hacia derecha VK_UP Flecha hacia arriba VK_DOWN Flecha hacia abajo VK_INSERT Insert VK_DELETE Supr VK_ADD + en teclado numérico VK_SUBSTRACT - en teclado numérico VK_MULTIPLY * en teclado numérico VK_DECIMAL . en teclado numérico VK_DIVIDE / en teclado numérico VK_F1, VK_F2, ..., VK_F12 Teclas de función VK_NUMLOCK BloqNum VK_SCROLL BloqDespl

Arrastrar y soltar

Relacionados con esta operación un form puede recibir los dos siguientes eventos: OnDragOver. Se produce cuando sobre un determinado control se desplaza un elemento

que está siendo "arrastrado". Además del parámetro Sender se recibe otro parámetro del tipo TObject; Source, que nos permitirá acceder al componente que está siendo objeto de la operación de arrastrar y soltar. Mediante los parámetros X e Y podremos conocer la posición actual del evento. Mediante el parámetro State obtendremos información acerca del estado de la operación. Dicho parámetro puede tomar los valores dsDragEnter, dsDragMove o dsDragLeave, según que el objeto arrastrado acabe de entrar sobre el control, se esté moviendo sobre él o lo acabe de abandonar, respectivamente. Por último encontramos el parámetro Accept, una variable de tipo Boolean a la que tendremos que asignar el valor True si el objeto arrastrado puede ser soltado sobre el control, o False en caso contrario.

OnDragDrop. A diferencia del evento anterior, que puede recibirse múltiples veces a medida que el objeto arrastrado se mueve por el control, el evento OnDragDrop sólo se recibe cuando dicho objeto es "soltado" sobre el control, liberando la pulsación del botón izquierdo del ratón. El método de respuesta a este evento recibirá los parámetros X, Y y Source, conteniendo respectivamente las coordenadas donde el objeto ha sido soltado y una referencia del mismo.

Otros eventos de TForm

Page 17: Curso Basico de Delphi

OnCreate. Se genera cuando el form va a ser creado, permitiendo así establecer valores iniciales en las propiedades, variables del objeto o cualquier otra operación previa a la creación.

OnActive. Este evento se produce en el momento en que el form se convierte en la ventana activa en el entorno.

OnShow. Antes de que un form se haga visible, siempre se genera el evento OnShow, permitiendo así realizar cualquier operación previa a la visualización.

OnHide. De forma similar al evento anterior, éste se produce justo antes de que el form sea ocultado.

OnDeactivate. Este evento se genera cuando el form se vuelve inactivo, porque se haya cambiado a otra ventana o aplicación.

OnClose. Cuando un form ha dejado de ser útil en pantalla, lo habitual es cerrarlo, bien mediante uno de los controles de la ventana o utilizando un método del objeto. Antes de realizar el cierre de la ventana se generará este evento, que recibe como parámetro una variable llamada Action, a la cual asignaremos uno de estos valores.

Valor Significado caFree El form es cerrado caMinimize El form no se cierra, simplemente se minimiza caHide El form no se cierra, se oculta caNone No se permite el cierre del form

OnCloseQuery. Al igual que el anterior, este evento se genera cuando se va a cerrar el form, recibiéndose como parámetro la variable CanClose, a la que daremos el valor True o False, dependiendo de que se permita o no dicho cierre, respectivamente.

OnDestroy. Generalmente un form que no va a ser utilizado más en el programa, depués de cerrarse ocultándose se destruye, liberando la memoria que ocupaba. Este evento se produce en ese momento.

OnEnter y OnExit. A medida que los distintos componentes de un form se van haciendo activos o inactivos, por el desplazamiento entre ellos, se irán generando porque es su primera visualización o bien porque se activa cuando tenía otras ventanas encima que ocultaban parte de su contenido.

OnResize. Cada vez que el tamaño de un form sea modificado durante la ejecución se generará este evento, que podemos aprovechar para modificar la disposición de los controles en su interior según el nuevo tamaño.

2.V. Métodos de TForm Mostrar y ocultar el form

El form principal de una aplicación se muestra automáticamente cuando ésta se ejecuta, a no ser que hayamos dado durante el diseño el valor False a la propiedad Visible. Otros forms que puedan existir en el proyecto no se visualizan hasta que nuestro programa no las necesita.

Para hacer visible un form haremos uso del método Show, que lo visualizará habitualmente disponiéndolo sobre las demás ventanas que en ese momento estén abiertas. En caso de que el form ya esté visible y lo que deseemos sea disponerla en esa posición, sobre las demás, porque esté oculto en parte, en lugar de Show podemos usar el método BringToFront. El método SendToBack tiene la funcionalidad contraria, enviar la ventana al fondo de la pantalla, debajo de todas las demás ventanas.

Cualquier form, incluido el principal, puede ser ocultado haciéndolo no visible. Para ello bastará con llamar al método Hide. Al ocultar el form de esta forma conseguiremos que no sea accesible por parte del usuario de la aplicación, ya que no aparecerá en la barra de tareas. El form en realidad no se ha cerrado, por lo que es perfectamente válido el acceso a sus componentes, propiedades y métodos.

Cuando un form no vaya a ser utilizado más en el programa, en lugar de ocultarlo podemos cerrarlo, llamando al método Close. Este previamente generará el evento OnCloseQuery, para asegurarse de si la ventana puede cerrarse, y depués procederá a minimizarla, ocultarla o destruirla, dependiendo del valor obtenido del evento OnClose. En caso de que se desee destruir la ventana, se usará el método Destroy, que tiene esa finalidad. Una vez que el form ha sido destruida no será posible volver a acceder a sus miembros, ya que en realidad la referencia al form habrá dejado de ser válida.

Page 18: Curso Basico de Delphi

Imagen del form

Mediante el método Print podemos obtener una copia impresa del form, que tendrá las características que se hayan fijado previamente en la propiedad PrintScale.

Si lo que deseamos es almacenarla o manipularla, deberemos usar el método GetFormImage, una función que nos devolverá un objeto del tipo TBitmap conteniendo los puntos que forman el form.

3.I. Etiquetas de texto: Label

En al paleta de componentes Standard tenemos un control representado por el botón cuyo nombre es Label. Mediante este control podremos mostrar un texto estático en el form, fijando su posición, color de letra, tamaño y, obviamente, el texto a mostrar.

Valores Iniciales

Al insertar un control Label en el form, mediante cualquiera de los métodos que vimos en los capítulos anteriores, algunas propiedades tomarán un valor inicial por defecto, que generalmente tendremos que modificar. Por ejemplo, la propiedad Name tomará el valor Label1, Label2,, etc., al igual que la propiedad Caption. Otras propiedades, como Left y Top, tomarán su valor dependiendo de la posición en la que situemos el control. Por último encontramos un tercer grupo de propiedades cuyo valor por defecto habitualmente no modificaremos, por ejemplo, la propiedad Visible de una etiqueta por regla general siempre será True, ya que de lo contrario el texto no sería visible.

Tras insertar la etiqueta, lo primero que tendremos que hacer es asignarle un nombre al control, para lo que modificaremos el valor de la propiedad Name mediante el Inspector de objetos.

El valor almacenado en la propiedad Caption será el texto que se mostrará en la etiqueta y que, inicialmente, coincide con el nombre del control, es decir, por defecto Name y Caption tienen el mismo valor. Al modificar el nombre de este control, el valor de Caption también se modificará automáticamente tomando el mismo valor, pero esto no volverá a ocurrir desde el momento en que manualmente asignemos un nuevo valor a Caption.

Posición, tamaño y alineación

La posición que inicialmente tenga un control en el form depende directamente del método que hayamos usado para insertarlo. Realizando un doble click con el ratón sobre el control, en la Paleta de componentes, la posición inicial será el centro de la form, pero también podemos pulsar el control y posteriormente "pinchar" en la posición del form donde deseamos situarlo. También es posible mover posteriormente el control, "arratrándolo" sobre la superficie del form. La posición de un control en el form estará determinada por los valores de la propiedades Left y Top, que contienen las coordenadas horizontal y vertical, respectivamente, expresadas en puntos relativos a la posición de origen del form. Esto quiere decir que si Left tiene valor 0, el control estará pegado al margen izquierdo del form y, de forma similar, si el valor de Top es 0, el control estará en la parte superior del form.

El tamaño o dimensiones de un control se almacenan en las propiedades Width (ancho) y Height (alto), existiendo también unos valores por defecto. El valor de estas propiedades puede también ser modificado mediante el Inspector de objetos, introduciendo el número de puntos de ancho y alto que deseamos que tenga el control, o bien visualmente, tomando uno de los márgenes del control con el cursor del ratón y estirándolo o encogiéndolo.

Cuando el contenido de una etiqueta de texto va a ser establecido durante el diseño, no hay problemas en fijar las dimensiones adecuadas, pero el caso es distinto cuando el texto a mostrar se va a fijar durante la ejecución; en este caso puede servirnos de ayuda la propiedad AutoSize, a la que dándole el valor True provocará que las dimensiones del control se ajusten con exactitud a su contenido, en este caso al texto. Otro método para controlar la posición y dimensiones de un control lo obtenemos a partir de la propiedad Align, que puede tomar los valores de la tabla que vemos a continuación. Según el valor asignado, el control se ajusta al margen correspondiente, incluso si posteriormente el form se redimensiona. La propiedad Align controla la alineación de un

Page 19: Curso Basico de Delphi

control en el contenedor en el que se encuentra. En este caso, el control, una etiqueta de texto, está en el interior de un form que actúa como contenedor.

Valor El control se ajusta a... alNone Conserva la posición y dimensiones originales alTop Margen superior del contenedor alBottom Margen inferior del contenedor alLeft Margen izquierdo del contenedor alRight Margen derecho del contenedor alClient Todo el espacio disponible en el contenedor

En caso de que las dimensiones del control sean superiores a las necesarias para mostrar el texto asignado a Caption, éste puede aparecer alineado a la izquierda, derecha o bien centrado. Esta alineación dependerá del valor que se asigne a la propiedad Alignment, que habrá de ser:

Valor Ajuste de textotaLeftJustify A la izquierda taRightJustify A la derecha taCenter Centrado

Si la cantidad de texto a mostrar en la etiqueta hace necesaria la distribución en varias líneas, en lugar de utilizar varios controles Label, podemos dar el valor True a la propiedad WordWrap; así se consigue que el texto asignado a la propiedad Caption se divida en las líneas que sean necesarias, dependiendo de la anchura que hayamos dado al control.

En cualquier momento podemos obtener las coordenadas correspondientes a las cuatro esquinas de una etiqueta de texto, consultando el valor de la propiedad BoundRect. Esta propiedad es un registro del tipo TRect, conteniendo en su interior cuatro miembros: Left, Top, Right y Bottom, que almacenan la columna izquierda, la fila superior, la columna derecha y la fila inferior respectivamente.

Familia, Estilo y Tamaño de Letra

El texto de una etiqueta puede aparecer en pantalla usando cualquiera de las familias de letras de Windows, en cualquier tamaño y con los estilos que estén disponibles. Todas estas características de una etiqueta de texto se encuentran almacenadas en la propiedad Font, que es en realidad un objeto del tipo TFont. Como tal objeto, la propiedad Font tiene a su vez sus propias propiedades, eventos y métodos, que son los que nos permitirán modificar los atributos del texto.

Para establecer los atributos del texto durante el diseño, en realidad no tenemos por qué preocuparnos de las propiedades de Font, ya que bastará con pulsar los puntos suspensivos que aparecen a la derecha de esta propiedad elegir el tipo de letra, su tamaño, estilo y color. Estos valores serán pasados posteriormente, cuando pulsemos el botón OK, al objeto Font, mostrándose el nuevo aspecto de la etiqueta de texto.

Sin embargo, si deseamos modificar los atributos del texto durante la ejecución del programa, tendremos que conocer las particularidades del tipo TFont.

El tipo de letra

Como sabemos, en Windows, a cada familia o tipo de letra se le conoce mediante un nombre, como puede ser Courier o Roman, por poner dos ejemplos. El tipo de letra de un objeto TFont se almacena en la propiedad Name, en forma de cadena de caracteres, por lo que si queremos que en el texto aparezca una cadena con el tipo Courier, lo único que debemos hacer es asignar a la propiedad Name una cadena con ese nombre.

Tamaño de letra

Page 20: Curso Basico de Delphi

Con la propiedad Size facilitaremos el tamaño de letra asignando un número con el que especificaremos el tamaño en puntos de la propia letra, sin contar con el espacio adicional que es necesario para su visualización. El tamaño en puntos es el método más utilizado habitualmente, ya que es la técnica que emplean la mayoría de los programas de dibujo, diseño y procesadores de texto.

El contenido de la propiedad Height, por el contrario, se refiere a la altura del tipo de letra más el espacio adicional necesario para su visualización. Siempre que para fijar el tamaño de letra usemos la propiedad Size, el valor de Height será negativo y viceversa.

El estilo

Para conocer y modificar el estilo de lerta de un objeto TFont usaremos la propiedad Style, que es un conjunto que puede contener los siguientes valores:

Constante Estilo correspondientefsBold Negrita fsItalic Cursiva Itálica fsUnderline Subrayada fsStrikeOut Tachada

Para poder determinar si una de estas constantes se encuentra o no en el conjunto tendremos que utilizar el operador Is.

Color del texto

También mediante la propiedad Font de la etiqueta de texto se podrá controlar el color con que éste aparecerá, gracias a la propiedad Color del tipo Font. Esta propiedad puede tomar cualquiera de los valores del tipo TColor.

Constante Color clBlack Negro clMaroon Marrón clGreen Verde clOlive Verde oscuro clNavy Azul marino clPurple Púrpura clTeal Verde agua clGray Gris clSilver Gris claro clRed Rojo clLime Verde claro clBlue Azul clFuchsia Fucsia cAqua Azul celeste clWhite Blanco

Anchura de carácter

Ciertas familias de letras son de espacio fijo, es decir, sus caracteres tienen todos el mismo ancho, mientras que otras son de espacio variable. Mediante la propiedad Pitch del tipo TFont, podemos asignar cualquiera de los valores mostrados en la siguiente tabla.

Constante Tipo de espacio

Page 21: Curso Basico de Delphi

fpDefault El usado por defecto por el tipo de letra fpVariable De anchura variable fpFixed De anchura fija

El color de fondo

Mediante la propiedad Color de la etiqueta de texto nosotros podemos seleccionar otro color distinto, sobre el que aparecerá dibujado el texto.

Al tener la etiqueta de texto un fondo opaco, ya sea del color del form o de cualquier otro que queramos fijar, cualquier control que quede bajo la extensión del texto no será visible, a no ser que demos el valor True a la propiedad Transparent.

Asociación a otros controles

Uno de los usos más frecuentes del control Label es el de servir de título para otros controles, como pueden ser campos de edición, listas, etc., que se caracterizan por no tener una propiedad Caption, a diferencia de un etiqueta de texto o de un botón.

Cuando utilicemos una etiqueta para esto, en el texto podemos incluir una tecla de acceso rápido, similar a la de los botones, de tal forma que al pulsarla se active el control asociado a la etiqueta.

Para hacer esto lo primero que tendremos en cuenta es el valor de la propiedad ShowAccelChar, que por defecto es True. Esto permite la inclusión en el texto y de otro control, que habrá de existir ya en el form. Si accedemos en el inspector de objetos a la propiedad FocusControl veremos que en la columna de valor aparece una lista, conteniendo los nombres de todos los controles que puedan ser activados.

Otras propiedades del control label

Es posible establecer etiquetas de ayuda a las etiquetas de texto, al igual que a la mayoría de los componentes Delphi. Para ello lo primero que tendremos que hacer será dar el valor True a la propiedad ShowHint, activando así la visualización de la etiqueta de ayuda, cuyo texto introduciremos en la propiedad Hint.

La visualización de la etiqueta de ayuda también se llevará a cabo si el valor de la propiedad ParentShowHint es True y la propiedad ShowHint del componente en el que se haya incluida la etiqueta tiene el mismo valor.

Una etiqueta de texto puede ser visible o no visible, y estar o no activa. Estos estado dependen de los valores que asignemos a las propiedades Visible y Enabled, respectivamente, que pueden ser True o False.

Mediante la propiedad Cursor podemos fijar la apariencia que tomará el cursor del ratón al desplazarlo sobre la etiqueta de texto. Esta prpiedad puede tener uno de estos valores:

Constante Forma del cursor crDefault La que tenga actualmente crArrow El puntero habitual en forma de flecha inclinada crCross Una cruz crBeam El cursor de texto crSize Cuatro flechas unidas indicando reposicionamiento crSizeNESW Flecha doble indicando cambio de tamaño crSizeNS Flecha doble indicando cambio de tamaño crSizeNWSE Flecha doble indicando cambio de tamaño csSizeWe Flecha doble indicando cambio de tamaño

Page 22: Curso Basico de Delphi

crUpArrow Flecha vertical con la punta hacia arriba crHourglass Reloj de arena crDrag Flecha con documento indicando arratrar y soltar crNoDrop Señal de prohibido crHSplit Doble flecha horizontal crVSplit Doble flecha vertical

Al igual que la mayoría de los componentes Delphi, las etiquetas de texto cuentan también con la propiedad Tag, que podemos usar para almacenar cualquier dato asociado al control.

Mediante la propiedad ComponentIndex que tienen todos los componentes, por lo tanto también las etiquetas de texto, podremos conocer el índice de un determinado control en una matriz.

Métodos de label

Una etiqueta de texto además de con propiedades, también cuenta con métodos, que son procedimientos y funciones.

Dos de estos métodos son BringToFront y SendToBack, que nos permiten alterar el orden de profundidad del control en el form, haciendo que aparezca por encima o por debajo de los demás respectivamente.

Para ocultar un control o mostrarlo podemos usar métodos Show y Hide, respectivamente, que al igual que los anteriores no necesitan parámetro alguno. Una llamada al método Show equivale a darle el valor True a la propiedad Visible, mientras que la llamada a Hide sería equivalente a asignar el valor False.

Anteriormente hemos visto las propiedades que nos permiten modificar durante la ejecución la posición y dimensiones de un control. En caso de que necesitemos modificar varias de estas propiedades podemos usar el método SetBounds, que nos permite realizar las modificaciones en un solo paso. Al llamar a este método pasaremos cuatro parámetros, especificando los valores correspondientes a las propiedades Left,Top,Width y Height.

3.II. El control Edit Uno de los controles que nos permiten la entrada de datos por teclado es el que aparece en el

botón que recibe el nombre de Edit.

Propiedades Generales

El nombre del control lo fijaremos en la propiedad Name, al igual que en cualquier otro componente. La posición y dimensiones de un control Edit vienen determinadas por las propiedades Left,Top,Width y Heigth, ya conocidas.

Las propiedades Visible y Enabled controlan el estado del control, que puede ser visible o no y estar activado o no. Para facilitar una etiqueta de ayuda usaremos la propiedad Hint, junto con ShowHint si es necesario. El color de fondo del campo de entrada será fijado mediante la propiedad Color, mientras que los atributos del texto los estableceremos mediante la propiedad Font. Es posible fijar una determinada figura para el cursor del ratón al pasar sobre el campo de edición, asignando el valor apropiado a la propiedad Cursor. Al igual que el resto de componentes insertados en una ficha, un control Edit es un elemento de la matriz Components del form, cuyo índice podemos obteber mediante la propiedad ComponentIndex.

En el control Edit, la propiedad AutoSize, que puede tomar los valores True o False, controla el ajuste automático del control a las dimensiones del tipo de letra que se vaya a utilizar. Si damos a esta propiedad el valor False y modificamos posteriormente el tipo o tamaño de letra, podremos ver cómo el control queda parcialmente vacío o bien no es suficiente grande como para mostrar el contenido.

Page 23: Curso Basico de Delphi

A diferencia de lo que ocurre con el control Label, en un campo de edición la propiedad Align no está disponible en tiempo de diseño, por lo que si deseamos ajustar el control en una determinada posición de la ficha tendremos que hacerlo en tiempo de ejecución, asignando el valor correspondiente a esta propiedad.

Contenido del Campo Edición

El control Edit no tiene una propiedad Caption, ya que no dispone de un título estático. El texto que aparece en ese control se puede editar en tiempo de ejecución y se almacena en la propiedad Text. Podemos asignar cualquier valor inicial que nos interese a esta propiedad, valor que aparecerán en el campo de edición al ejecutar el programa, siendo posible su modificación. La longitud máxima del texto que es posible introducir en este control la podemos establecer asignando a la propiedad MaxLength el máximo número de caracteres que deseamos admitir. Inicialmente esta propiedad tiene el valor cero, indicando que en principio no existe un límite. En cuanto el valor sea distinto de cero, el máximo número de caracteres será ese valor introducido.

Para editar el contenido de un control Edit durante la ejecución, utilizaremos las teclas habituales en cualquier aplicación Windows (podemos movernos con los cursores, podemos usar la tecla de borrar, etc).

Control de la Entrada

Además de controlar la longitud máxima del texto mediante MaxLength, también podemos convertir automáticamente todas las letras introducidas en mayúsculas a minúsculas, o en minúsculas a mayúsculas, según el valor que asignemos a la propiedad CharCase. Estos valores pueden ser:

Constante Conversión realizada ecNormal No se realiza conversión alguna ecLowerCase Todas las mayúsculas a minúsculas ecUpperCase Todas las minúsculas a mayúsculas

Mediante la propiedad Modified podemos saber si el contenido del campo de edición ha sido modificado o no. Cuando el control se crea inicialmente, esta propiedad tiene el valor False. Esta propiedad, en cualquier momento en que el usuario introduzca cualquier carácter o edite el valor inicial del campo tomará el valor True. Podemos dar el valor False a esta propiedad en cualquier momento que nos interese, de tal forma que en una posterior comprobación sepamos si se ha modificado o no.

Inicialmente la finalidad de un control Edit es permitir la entrada o edición de un texto, pero puede darse el caso de que nos interese utilizar este tipo de control sólo para mostrar una información, permitiendo desplazarse por ella pero no permitiendo modificarla. Para conseguir esto lo único que tenemos que hacer es dar el valor True a la propiedad ReadOnly, que inicialmente tiene el valor False.

En caso de que utilicemos un campo de edición para pedir algún dato confidencial, como pueda ser un número secreto o palabra de acceso, podemos hacer que la información introducida por teclado no se refleje en pantalla, sustituyendo cada uno de los carácteres por un cierto carácter, que deberemos asignar a la propiedad PasswordChar.

Seleción de Texto

Podemos conocer la posición a partir de la cual se ha marcado un texto consultando la propiedad SelStart, que contendrá la posición del primer carácter que se haya marcado, teniendo en cuenta que el primer carácter por la izquierda es el 0, el siguiente el 1, etc. También podemos conocer la longitud del texto marcado, o lo que es lo mismo, el número de carácteres existentes en la selección, mediante la propiedad SelLength. Una tercera propiedad, SelText, nos servirá tanto para obtener el texto que se encuentra seleccionado en el control, como para cambiarlo por otro simplemente asignándolo a esta propiedad.

Cuando en un control se ha marcado una porción de texto, esta selección permanece hasta que realiza un movimiento del cursor, permaneciendo aún cuando nos desplacemos de este control a otro que exista enl form. Cuando esto ocurre, el texto que teníamos marcado puede permanecer

Page 24: Curso Basico de Delphi

así o bien mostrarse normal, volviendo a visualizarse marcado al volver a entrar en el campo. Este comportamiento es controlado mediante la propiedad HideSelection, que puede tomar el valor True, ocultando la selección cuando se sale del control, o False, dejándola visible. Por defecto esta propiedad tiene el valor True.

En principio, cada vez que se pasa el control a un campo de edición, haciéndolo activo, todo el contenido de éste se selecciona automáticamente, independientemente del último texto que se hubiese marcado. Esto es debido a que la propiedad AutoSelect tiene por defecto el valor True, indicando al control que cada vez que se active seleccione todo el contenido. Si damos a esta propiedad el valor False, al volver a un campo en el que anteriormente se había marcado una porción de texto, podremos ver que sigue activa la misma selección.

Activación de los Controles

Por regla general, para pasar de un control a otro en un form utilizaremos la tecla <Tabulador>. También puede usarse la combinación <Mayúsculas>+<Tabulador> para ir en sentido inverso. Obviamente se puede activar un cierto control situando el puntero del ratón sobre él y pulsando el botón izquierdo. En caso de que nos interese que un cierto control se active mediante la pulsación de la tecla <Tabulador>, formando parte del recorrido de controles del form, tan sólo hemos de darle el valor False a la propiedad TabStop, que por defecto es True. Al hacer esto no podremos acceder a ese control usando el <Tabulador>, pero siempre podemos activarlo mediante el ratón.

Delphi nos permite establecer el orden de acceso. Seleccionamos la opción Tab Order del menú emergente que aparecerá al pulsar el botón derecho del ratón sobre el form, o bien elegimos esa misma opción del menú Edit en la ventana principal. En ambos casos veremos aparecer una ventana conteniendo el nombre y tipo de cada uno de los controles que pueden ser activados.

En esta ventana podemos establecer el orden de acceso de una forma visual. Si queremos modificar la posición de un cierto control en la lista, lo único que hemos de hacer es "pincharlo" con el cursor del ratón y "arrastrarlo" hasta su nueva posición.

Otras Propiedades de Edit

Al insertar un campo de edición en un form, por defecto aparece con un cierto aspecto tridimensional y un recuadro alrededor. Estos elementos son controlados mediante las propiedades Ctl3D y BorderStyle, respectivamente. La primera de ellas puede tomar los valores True o False, dependiendo de lo cual el control aparecerá o no con aspecto tridimensional. La propiedad BorderStyle puede tomar dos valores distintos, bsNone o bsSingle. El primero de ellos hará aparecer el control sin borde alrededor, mientras que el segundo, que es el valor tomado por defecto, establece un borde simple delimitando la extensión del control.

Además de la propiedad ShowHint, que ya conocemos, el control Edit cuenta también con las propiedades ParentColor, ParentCtl3d y ParentFont, cada una de las cuales puede tomar los valores True o False. La finalidad de estas opciones es permitir que el control tome parte de sus atributos, como el color de fondo, aspecto tridimensional y tipo de letra, de las propiedades del componente en que se haya incluido, al que se le llama padre.

Métodos del Control Edit

Hemos visto anteriormente cómo mediante las propiedades SelStart, SelLength y SelText podemos controlar desde el código de nuestro programa la selección de texto. Además de estas propiedades también disponemos de los métodos SelectAll, que selecciona todo el texto existente en el control, y ClearSelection, que elimina el texto seleccionado en ese momento. Si deseamos dejar el control vacío, borrando todo el texto que contiene, podemos hacerlo usando el método Clear.

Las operaciones con el portapapeles las llevaremos a cabo mediante los métodos CopyToClipboard, que copiará el texto seleccionado en el portapapeles, CutToClipboard, que además de copiarlo lo borrará del campo en que se encuentra editado, y PasteFromClipboard, que tomará el texto existente en el portapapeles y lo pegará a partir de la posición en la que actualmente se encuentra el cursor, insertándolo.

Eventos del control Edit

Page 25: Curso Basico de Delphi

Como casi todos los demás controles que pueden residir en un form, un campo de edición recibe eventos generados por el ratón, OnMouseMove, OnMouseDown y OnMouseUp, y por el teclado, OnKeyPress,OnKeyDown y OnKeyUp.

El evento OnEnter se generará en el momento en que el campo de edición se convierta en el control activo del form, mienrtas que OnExit se producirá cuando deje de serlo.

Cada vez que se realice una modificación en el contenido del control, insertando un nuevo carácter o borrando parte del contenido, se producirá un evento OnChange.

3.III. El control Memo Las posibilidades del control Edit a veces no son suficientes para cubrir todas las necesidades de entrada de datos, especialmente cuando lo que se solicita al ususario del programa es un texto que puede ser más o menos extenso, ya que dicho control sólo facilita la edición de una línea.

Para dar cabida a estas necesidades, existe el control llamado Memo, cuyo botón en la paleta de

componentes es Podemos tratar este control de forma casi idéntica a un control Edit, con la diferencia de que es posible trabajar con una mayor extensión de texto, que puede estar distribuido en múltiples líneas.

Contenido del Control

El texto existente en un control Memo se estructura en múltiples cadenas, que son almacenadas en la propiedad Lines. Es posible dar un valor inicial a un control de este tipo, utilizando para ello el editor de cadenas de Delphi.

También puede cargarse dentro del campo Memo el contenido de un archivo de texto, así como salvar el texto actual del control a un archivo.

En tiempo de ejecución podemos usar la propiedad Lines como si se tratase de una matriz, en la que cada uno de los elementos corresponde a una línea de texto.

En realidad, la propiedad Lines es un objeto de tipo TStrings, que por lo tanto cuenta con sus propios métodos y propiedades. Para conocer el número de líneas que existen actualmente en el control, no tenemos más que consultar el valor de la propiedad Count. A partir de este dato no tendremos problemas en acceder a cada una de las líneas, teniendo en cuenta que la primera tiene como índice de elemento el cero.

Podemos añadir una línea al final del contenido actual mediante el método Add de la propiedad Lines, que tomará como parámetro la cadena de caracteres a añadir. Si no deseamos añadirla al final sino insertarla en una cierta posición, entonces usaremos el método Insert, al que indicaremos como primer parámetro la posición en que se ha de insertar la cadena que se pasa como segundo parámetro.

Para eliminar una de las líneas utilizaremos el método Delete, al que indicaremos el índice correspondiente a la línea a borrar. También puede moverse una determinada línea de una posición a otra, indicando en el método Move el índice actual de la línea y el nuevo índice que deseamos asignar. El método Exchange es similar al anterior, tomando como parámetros dos índices, pero en este caso lo que se hace es intercambiar la posición de las dos cadenas de texto.

El contenido de un control Memo puede ser tomado de un archivo de texto, utilizando el método LoadFromFile, de la propiedad Lines, que nos permitirá salvar el contenido actual del control en un archivo. También podemos guardar el contenido del Memo en un archivo de texto, usando para ello el método SaveToFile de la propiedad Lines. En ambos casos sólo hay que pasar un parámetro, el nombre del archivo del que se va a leer o en el que se va a escribir.

Visualización del Texto

En principio, al introducir un texto en el control el cursor se desplazará a la línea siguiente en el mismo momento en el que lleguemos al margen derecho, dividiendo automáticamente la línea por la última palabra. Este comportamiento se debe al valor asignado a la propiedad WordWrap, que es

Page 26: Curso Basico de Delphi

True. Dando a esta propiedad el valor False, al llegar al margen derecho del control el contenido actual se irá desplazando hacia la izquierda, de tal forma que la línea no se dividirá, pudiendo ser tan extensa como necesitemos. Algo similar ocurre al llegar al límite inferior del control, cuando hayamos introducido tantas líneas de texto que el control aparezca lleno. Al introducir la siguiente línea, el contenido actual se desplazará hacia arriba, dando cabida a tantas cadenas como sea necesario.

Con el fin de facilitar el desplazamiento por el texto contenido en el control, podemos hacer aparecer una barra de desplazamiento vertical, una horizontal o ambas. Para ello, asignaremos uno de los siguientes valores a la propiedad ScrollBars:

Constante Barra de desplazamiento ssNone Ninguna ssHorizontal Horizontal ssVertical Vertical ssBoth Ambas

Tabulaciones y avances de línea

Para poder introducir un tabulador en el texto de un control Memo, podemos utilizar la combinación <Control>+<Tabulador>, mientras que para avanzar a otra línea la combinación a usar será <Control> e <Intro> de forma normal, lo único que hemos de hacer es dar el valor True a las propiedades WantTabs y WantReturns. Por defecto la primera tiene el valor False y la segunda el valor True.

3.IV. El control Button Un botón aparece como un área rectangular que contiene un texto en su interior y que, al pulsarlo, lleva a cabo una determinada acción. En Delphi este control aparece en la paleta de componentes

con el icono y recibe el nombre Button.

Título del botón

El título que aparece en el interior de un botón corresponde al valor asignado a la propiedad Caption, que al igual que ocurría con las etiquetas de texto, pueden contar con un carácter precedido de un &. Este carácter, que aparecerá en el botón subrayando a la letra que le sigue, nos permitirá realizar la acción indicada por el botón usando las teclas ALT+LetraSubrayada.

En el caso de que la propiedad Enable del botón tome el valor False, el título aparecerá en un color más difuminado, y el botón no podrá ser pulsado. Tanto el color como el aspecto del título pueden ser controlados mediante la propiedad Font.

Botón por defecto y de cancelación

El evento Onclick de un botón se produce cuando, siendo el control activo, se pulsa la barra espaciadora, o bien utilizando el cursor del ratón para pulsar sobre él, existiendo la posibilidad de usar también una tecla de acceso rápido. A estos tres métodos, generales a todos los botones que podamos insertar en un form, hay que añadir la pulsación de las teclas <Intro> y <Escape>. Al pulsar la tecla <Intro> se generará el evento OnClick del botón por defecto, que es aquel cuya propiedad Default tiene el valor True. De igual forma, la pulsación de la tecla <Escape> genera el mismo evento en el botón de cancelación, siendo éste el que tiene la propiedad Cancel con el valor True.

Inicialmente las propiedades Default y Cancel de todos los botones tienen el valor por defecto False.

Cuadros de diálogo

Page 27: Curso Basico de Delphi

Un cuadro de diálogo modal se caracteriza por no permitir el acceso a ninguna otra ventana de la aplicación mientras él se encuentre abierto, y al cerrarlo generalmente se devuelve un valor indicando la causa de salida.

Habitualmente, un cuadro de diálogo se cierra por la pulsación de algún botón, que se encarga de establecer el código de salida. En lugar de tener que escribir un gestor para el evento Onclick de un botón cuya única finalidad sea esa, podemos asignar a la propiedad ModalResult del control Button el valor de salida. Al pulsarse este botón el cuadro de diálogo será cerrado automáticamente, devolviendo el código almacenado en ModalResult. Aunque esta propiedad puede tomar cualquier valor que nos interese, existen una serie de constantes con valores predefinidos que son los más usados:

Constantes Valor devuelto mrNone 0 mrYes idYes mrNo idNo mrOk idOk mrCancel idCancel mrAbort idAbort mrRetry idRetry mrIgnore idIgnore

3.V. El control CheckBox Mediante los controles CheckBox, o Cajas de Selección, podemos obtener una entrada de datos.

Este componente aparece en la Paleta de componentes como el siguiente botón: que se llama CheckBox. Este control permite al usuario activar o desactivar una cierta opción sin necesidad de escribir nada, bastará con que realice una pulsación sobre el control.

El título que aparecerá junto a la caja de selección será el que asignemos a la propiedad Caption, pudiendo existir una tecla de acceso rápido como en los botones y etiquetas de texto.

Habitualmente, este control puede aparecer en dos estados distintos, marcado o sin marcar. El estado actual lo podremos conocer mediante la propiedad Checked, que tomará el valor True si está marcado o el valor False en caso contrario.

Si lo deseamos, también podemos activar un tercer estado, en el cual el control no aparecerá ni marcado ni sin marcar, un estado indeterminado. Para permitir este tercer estado habremos de darle el valor True a la propiedad AllowGrayed y en lugar de la propiedad Checked usaremos la propiedad State para conocer el estado del control. Esta propiedad puede tomar los siguientes valores:

Constante Estado del Control cbCheked Marcado cbUnchecked Desmarcado cbGrayed Indeterminado

Los eventos y métodos disponibles para el control CheckBox son los generales a la mayoría de los controles, al igual que para los botones. Esto quiere decir que existen los eventos de teclado y ratón y los métodos Show, Hide, etc.

3.VI. El control RadioButton

Page 28: Curso Basico de Delphi

A veces es necesario dar al usuario a elegir sólo una de las opciones disponibles, creando un grupo de opciones exclusivas entre sí.

Nuestras necesidades serán cubiertas con el control RadioButton, que aparece en la Paleta de

componentes como . El aspecto de este control es circular, en lugar de un cuadrado, y sólo uno de los controles que insertemos en el form podrá estar activo.

El título que aparecerá a la derecha del control será facilitado como siempre en la propiedad Caption. El estado actual del botón, seleccionado o no, lo conoceremos mediante la propiedad Checked, que será True en caso afirmativo o False en caso negativo.

Grupo de botones de radio

Si lo que necesitamos nosotros es disponer de dos grupos con tres botones de radio, lo que en realidad tenemos son seis botones exclusivos entre sí. Para crear estos grupos tendremos que utilizar un nuevo control llamado GroupBox, representado en la Paleta de componentes como

La única finalidad de este control es actuar como padre de otros controles agrupándolos y no dispone de ninguna propiedad especial. Al insertar un control GroupBox en el form, éste aparecerá como un recuadro con un título en la parte superior izquierda. Este título lo podremos establecer modificando el valor de la propiedad Caption, como es habitual. Aunque los controles que normalmente se agrupan son los botones de radio, realmente mediante este control podremos agrupar cualquier conjunto de controles, sin importar su tipo.

Cuando insertemos en un control GroupBox cualquier otro componente, su posición será relativa a la del control que está actuando como contenedor, en este caso el GroupBox. Otra diferencia entre un control insertado directamente en el form y otro insertado en un GroupBox será el valor de la propiedad Parent, de la que disponen todos los componentes. Esta propiedad contiene el nombre del control padre, es decir, el control que actúa como contenedor.

Para que un control pertenezca a un determinado grupo, es necesario que sea insertado en él. En caso de que dispongamos de un determinado componente en el form y lo desplacemos al interior de un control GroupBox, lo único que habremos hecho será modificar la posición, pero realmente dicho control no estará contenido en el grupo. En caso de que los controles a incluir en el GroupBox ya existan en el form, tenemos una alternativa, que es cortarlos al portapapaeles, activar el grupo y pegarlos.

Otras relaciones padre-hijo

Además de la posición de un control, relativa al contenedor en que está incluido, y la pertenencia a dicho contenedor, indicada por el valor de la propiedad Parent, los controles que se incluyen en un contenedor también "heredan" otras propiedades, como puede ser la propiedad Font, el color de fondo, etc.

Si insertamos en un form un control GroupBox, modificamos su propiedad Font, establecidos un determinado tipo y tamaño de letra y, a continuación, insertamos en su interior una etiqueta, un campo de edición o un botón, se verá que estos controles automáticamente aparecen con el mismo tipo de letra. Es más, si durante la ejecución del programa se altera alguna de las características de la propiedad Font del contenedor, automáticamente los controles que hay en su interior también serán modificados. Esto es así porque las propiedades ParentFont, ParentColor, ParentCtld3D y ParentShowHint toman el valor True, indicando así que los valores de las propiedades Font, Color, Clt3D y ShowHint de un determinado control serán tomados del contenedor en que se halle insertado.

Dando el valor False a cualquiera de estas propiedades desactivaremos esta característica.

Puesto que la posición de los controles es relativa al componente, cualquier desplazamiento de éste último resultará en un desplazamiento de todos los controles que haya en su interior.

Grupo de botones de radio

Page 29: Curso Basico de Delphi

Para facilitar el tratamiento de grupos de botones de radio, Delphi dispone del control que recibe el

nombre de RadioGroup, con el siguiente icono en la Paleta de componentes:

Para indicar los botones de radio que deberán existir en el grupo, tendremos que editar la propiedad Items, que al igual que ocurría con la propiedad Lines del control Memo es una lista de cadenas. Por lo tanto en tiempo de diseño podremos modificar el contenido de esta propiedad mediante el editor de cadenas de Delphi, mientras que en tiempo de ejecución tendremos que usar los métodos Add e Insert de la propiedad Items si deseamos añadir un botón de radio al grupo.

Por defecto los botones de radio se reparten en una sola columna, que tendrá tantas filas como botones. Podemos modificar el valor de la propiedad Columns, especificando el número total de controles que se reparte proporcionalmente entre ellas.

La propiedad ItemIndex nos servirá tanto para saber que botón está seleccionado actualmente como para modificar dicha selección. El valor de esta propiedad será un número entero, comprendido entre 0 y el número de botones existentes menos 1. El valor -1 indica que no hay ninguno seleccionado actualmente.

3.VII. El componente ListBox En ocasiones, el número de datos que debe introducir el usuario de un programa o la cantidad de opciones distintas entre las que seleccionar es tan amplia, que el uso de múltiples controles de edición, botones de radio, etc., es poco práctico. En estos casos es mucho más comodo usar una lista, que es un control capaz de contener cadenas de caracteres, cada una de las cuales aparece como elemente de la lista.

En caso de que el número de elementos exceda las dimensiones de la lista, en ésta aparecerán las barras de desplazamiento correspondientes. En Delphi la lista está representada por el control

ListBox, seleccionando el botón de la Paleta de componentes.

Contenido de la lista

Los elementos contenidos en cada momento en la lista pueden ser gestionados mediante la propiedad Items, que es en realidad un objeto del tipo TStrings. Ya hemos conocido anteriormente este tipo en los controles Memo y RadioGroup, por lo que no tendremos problema alguno en añadir elementos a la lista, con los métodos Add e Insert, eliminarlos con Delete, moverlos con Move, o intercambiarlos con Exchange.

La visualización de los elementos en la lista se dividirá en tantas columnas como indique la propiedad Columns, siendo el valor por defecto de una sola columna. Si lo deseamos, podemos mostrar los elementos de la lista ordenados alfabéticamente, simplemente dando el valor True a la propiedad Sorted.

Dando el valor True a la propiedad IntegralHeight, haremos que visualice un elemento completo, no de forma parcial.

Selección de elementos

El hecho de que en la lista sólo pueda haber seleccionado un elemento simultáneamente, está determinado por la propiedad MultiSelect, dándole el valor True a esta propiedad, conseguiremos una lista en la que es posible seleccionar múltiples elementos. Para ello podemos usar dos métodos distintos, dependiendo del valor de la propiedad ExtendedSelect. Por defecto el valor que tiene es True, de tal forma que para seleccionar múltiples elementos tendremos que utilizar las teclas <Mayúscula> y <Control> junto con la pulsación del botón izquierdo del ratón, como se hace habitualmente. Si damos el valor False a esta propiedad podremos seleccionar varios elementos simplemente marcándolos, pulsando sobre ellos con el cursor del ratón.

Cuando en una lista es posible seleccionar varios elementos, tendremos que utilizar la propiedad SelCount para saber cuántos hay marcados actualmente, y la propiedad Selected para conocer qué elementos están marcados. Esta propiedad es en realidad una matriz, con tantos elementos como cadenas existan en la lista.

Page 30: Curso Basico de Delphi

Cada elemento de esta matriz puede tener el valor True, si dicho elemento está seleccionado, o False, en caso de que no lo esté.

Listas especiales

Aunque por regla general los elementos de una lista son cadenas de texto, todas ellas de un mismo tipo de letra, es posible utilizar este control para presentar otros objetos, como elementos gráficos. Para ello lo primero que tendremos que hacer es modificar el valor de la propiedad Style, asignando una de las siguientes constantes:

Constante Estilo de la lista lbStandard Todos los elementos son cadenas lbOwnerDrawFixed Cada elemento es distinto pero con una altura fija lbOwnerDrawVariable CadaElemento tiene una altura variable

En caso de que el estilo seleccionado sea lbOwnerDrawFixed, la altura de cada uno de los elementos de la lista vendrá determinado por el valor de la propiedad ItemHeight, que la indicaremos en puntos.

Si el estilo seleccionado es lbOwnerDrawVariable, entonces al ir a dibujar cada uno de los elementos se generará un evento OnMeasureItem. El método de respuesta a este evento recibirá tres parámetros: la lista que ha generado, el evento, el número de elemento que se va a dibujar y una variable entera, Height, en la que tendremos que devolver la altura necesaria para dibujar el elemento en cuestión.

Si el estilo de una lista no es lbStandard, cada vez que sea necesario dibujar uno de los elementos se generará un evento OnDrawItem, que nos permitirá dar salida al elemento que deseamos mostrar en la lista. El gestor de este evento recibirá los siguientes parámetros:

ListBox. Una referencia a la lista que ha generado el evento. Index. Un entero indicando el elemento que se ha de dibujar. Rect. Un registro del tipo TRect, conteniendo las coordenadas del recuadro en que ha de

ser dibujado el lemento. State. Estado actual del elemento que se ha de dibujar. Se trata de un conjunto que

puede contener los siguientes valores:

Constante Estado actual del elemento odSelected El elemento está seleccionado odDisabled La lista no está actualmente activa odFocused El elemento es el elemento actual de la lista

Para dibujar el elemento se deberá utilizar la propiedad Canvas, que representa la superficie del área cliente de la lista. Esta propiedad es un objeto del tipo Tcanvas, que cuenta con una serie de propiedades y métodos que facilitan el trabajo con entidades gráficas.

Listas combinadas

En Windows existe un control que es una mezcla de ListBox y Edit, al que se conoce como lista

combinada. Su nombre en Delphi es ComboBox:

Estilo de la lista combinada

Un control ComboBox puede actuar de varias formas distintas, dependiendo del estilo que seleccionemos. Para elegir el estilo que nos interese tendremos que asignar a la propiedad Style uno de los siguientes valores.

Constante Estilo

Page 31: Curso Basico de Delphi

csDropDown Lista con campo de edición asociado csSimple Campo de edición sin lista csDropDownList Elementos distintos con altura fija csOwnerDrawVariable Elementos distintos con altura variable

El estilo seleccionado por defecto es csDropDown, que en el form aparece como un control Edit con una flecha en la parte derecha. Pulsando sobre dicha flecha se desplegará automáticamente la lista, en la que podremos seleccionar cualquiera de los elementos existentes, que pasará a mostrarse en el campo de edición. En lugar de desplegar la lista para elegir un elemento, también podemos introducir los primeros caracteres en el campo de edición, pulsando después la tecla del cursor hacia arriba o hacia abajo, lo que provocará la aparición del primer elemento que comience por esa secuencia.

Tanto el estilo csSimple como el csDropDownList son versiones simplificadas de csDropDown. En el primer caso la lista aparecerá como un campo de edición normal, sin lista asociada. Sin embargo, en ese campo podremos utilizar las teclas de desplazamiento del cursor para seleccionar uno de los elementos de la lista, así como introducir las iniciales para su búsqueda. En el segundo caso nos encontraremos con una lista que no tiene asociado un campo de edición, aunque podremos seguir usando las teclas del cursor para elegir un elemento. En la parte derecha del control aparecerá una flecha, que nos servirá también para desplegar la lista.

Dimensiones de la lista

Una lista combinada, a diferencia de una lista normal, sólo muestra permanentemente el elemento que está seleccionado en cada momento, mientras que el resto de los elementos sólo aparecen cuando la lista se despliega. La extensión de la lista en ese momento, al ser desplegada, dependerá del valor que demos a la propiedad DropDownCount, que contendrá el número de líneas que se mostrarán simultáneamente como máximo.

Otras consideraciones

Al igual que una lista normal, es posible saber qué elemento está seleccionado en una lista combinada mediante la propiedad ItemIndex, que contendrá un número comprendido entre 0 y el número de elementos existentes menos 1. Puesto que el elemento que está seleccionado en cada momento se muestra en el área de edición del control, podemos obtener el texto mediante la propiedad Text, como si se tratase de un control Edit. A diferencia de las listas normales, en una lista combinada no es posible seleccionar múltiples elementos. Por ello no existen las propiedades MultiSelect, ExtendedSelect, SelectCount y Selected.

3.VIII. Barras de desplazamiento Supongamos que hemos creado un programa capaz de reproducir discos musicales, una barra de desplazamiento nos podría servir para representar y permitir modificar el volumen. Este es sólo un

ejemplo de las utilidades que podemos encontrar en el control ScrollBar:

Tipo de barra

Una barra de desplazamiento puede aparecer en sentido vertical y horizontal, siendo el primero el estado por defecto. El tipo de barra representada por el control ScrollBar viene determinado por el valor que demos a la propiedad Kind, que será sbHorizontal o sbVertical, según deseemos una barra de desplazamiento horizontal o vertical respectivamente.

Rango de desplazamiento

Los valores extremos de la barra de desplazamiento, que determinan el rango de valores posibles, los tendremos que facilitar en las propiedaddes Min y Max. El valor correspondiente a la posición actual del cursor en la barra lo obtendremos en la propiedad Position, que podemos modificar para posiciones del cursor en un determinado punto de la barra. Tanto la posición actual en la barra

Page 32: Curso Basico de Delphi

como los valores extremos, mínimo y máximo, pueden fijarse en un solo paso, utilizando el método SetParams, al que facilitaremos los tres parámetros en ese mismo orden.

El factor de incremento o decremento pequeño se asigna a la propiedad SmallChange. Este valor habitualmente es 1, permitiendo así recorrer el rango de valores representado por la barra unidad. El factor de desplazamiento grande se asigna mediante la propiedad LargeChange. El desplazamiento pequeño es el que se produce al pulsar sobre las propias flechas cursor de la barra, y el desplazamiento grande es aquel que se produce cuando pinchamos en el interior de la barra, para avanzar más deprisa.

Eventos de ScrollBar

Cada vez que el valor de la propiedad Position es modificado por una acción sobre la barra de desplazamiento, se genera un evento OnChange, que nosotros podemos aprovechar para llevar a cabo la acción que corresponda según la nueva posición del cursor en la barra.

También al manipular la barra de desplazamiento, modificando la posición del cursor, se genera el evento OnScroll, que podemos aprovechar para actuar en consecuencia según la operación que se haya efectuado. El método que actúe como gestor de este evento recibirá un primer parámetro representando a la barra de desplazamiento que ha generado el evento, un segundo parámetro mediante el cual podremos conocer la acción que se ha efectuado sobre la barra y que vendrá representado por una de las constantes mostradas en la siguiente tabla. Por último recibiremos la variable ScrollPos, que podemos modificar para reflejar la nueva posición en la barra.

Constante Operación de desplazamiento scLineUp Ir al paso anterior, arriba o a la izquierda scLineDown Ir al paso siguiente, abajo o a la derecha scPageUp Ir a la página siguiente scPageDown Ir a la página siguiente scTop Ir a la posición de inicio scBottom Ir a la posición de fin scPosition Se ha desplazado el cursor a una posición absoluta scTrack Se está desplazando el cursor scEndScroll Se ha terminado de desplazar el cursor

3.IX. El control Bevel En la página Additional de la Paleta de componentes podremos encontrar el control cuyo nombre

es Bevel: . Mediante él podremos insertar en el form líneas, recuadros y bordes, que pueden aparecer hundidos en el form o sobresalir de él.

Forma y estilo

Mediante la propiedad Shape podemos seleccionar la figura que deseamos que tome el control, pudiendo ser cualquiera de los mostrados en la tabla siguiente. Cada uno de estos elementos puede aparecer hundido en el form o sobresaliendo de él, dependiendo de que a la propiedad Style le demos el valor bsLowered o bsRaised, respectivamente.

Constante Forma bsBox Rectángulo bsFrame Borde rectangular bsTopLine Línea horizontal superior bsBottomLine Línea horizontal inferior bsLeftLine Línea vertical izquierda

Page 33: Curso Basico de Delphi

bsRightLine Línea vertical derecha

3.X. El componente Timer Mediante el componente Timer, que encontramos en la página System de la Paleta de

componentes: , podremos programar un evento que se generará periódicamente en dos supuestos: cuando necesitemos repetir un mismo código cíclicamente, o bien para dividir un proceso muy extenso, no bloqueando así el programa.

Este es el primer componente no visual que vamos a conocer. Timer no tiene un elemento de interfaz, en tiempo de ejecución no aparece en el form, por lo que no es un control. Debido a esto el número de propiedades de este componente es mucho más reducido.

Frecuencia del evento

Para determinar el tiempo que transcurrirá entre dos eventos consecutivos generados por el componente Timer, tendremos que utilizar la propiedad Intervel. La magnitud de tiempo que indiquemos deberá ir expresada en milisegundos, siendo el valor por defecto 1000, es decir, el evento se generaría una vez por segundo.

Cada vez que transcurra el tiempo indicado en Interval, se generará un evento Ontimer, en el que podremos escribir el código que deseamos ejecutar.

La propiedad Enabled tiene un significado especial en el componente Timer. Si tiene el valor True, que es por defecto, el evento se generará según la frecuencia especificada.

Dándole el valor False, el evento dejará de producirse. De esta forma podemos activar y desactivar el funcionamiento del componente según nos interese.

3.XI. El control MaskEdit Delphi dispone de un campo de edición que nos permite aplicar un mayor control sobre los datos a introducir, sin necesidad de tener que escribir código para interceptar la pulsación de cada carácter. Este control aparece en la página Additional de la Paleta de componentes con el icono

y recibe el nombre de MaskEdit. Las propiedades de este nuevo control coinciden en gran parte con las del control Edit.

Máscara de entrada

La entrada de datos en un control MaskEdit será idéntica a la de un control Edit, a no ser que establezcamos una máscara de control. Dicha máscara es una cadena de caracteres, en la cual algunos tienen un significado especial. Esta cadena tendrá que asignarse a la propiedad EditMask. En tiempo de ejecución, la máscara que hayamos aplicado condicionará tanto la introducción de datos en el campo, como la visualización de éstos. Todos los caracteres, alfabéticos, alfanuméricos y símbolos, pueden formar parte de una máscara. Aquellos que tienen un significado especial, se muestran en la siguiente tabla; limitan la entrada de la información, mientras que todos los demás aparecen en el campo en tiempo de ejecución como parte fija de la información.

Carácter Significado C Requiere la entrada de un carácter c Permite la entrada de un carácter A Requiere la entrada de un carácter alfanumérico a Permite la entrada de un carácter alfanumérico L Requiere la entrada de un carácter alfabético

Page 34: Curso Basico de Delphi

l Permite la entrada de un carácter alfabético 0 Requiere la entrada de un carácter numérico 9 Permite la entrada de un carácter numérico # Permite la entrada de un carácter numérico o de signo < Los carácteres siguientes aparecerán en mayúsculas > Los carácteres siguientes aparecerán en minúsculas <> Desactiva la función de los dos carácteres anteriores \ Interpreta el carácter siguiente como no especial - Representa un espacio en blanco : Separador de horas y minutos / Separador de fechas ; Separador interno de la máscara

Para componer la máscara de edición en tiempo de diseño, bastará con que realicemos una doble pulsación sobre la propiedad EditMask, o bien pulsamos el botón con los puntos suspensivos que aparece en la parte derecha.

Contenido del control

Al igual que un control Edit, el control MaskEdit cuenta con la propiedad Text, en la que podemos encontrar el contenido actual del campo. En realidad el contenido dependerá de que la máscara sea salvada o no junto con la información introducida. Si marcamos la opción Save Literal Characters, o bien añadimos al final de la máscara un punto y coma y un 1, en la propiedad Text podremos encontrar el contenido actual, pero incluyendo el formato correspondiente a la máscara que hayamos utilizado.

4.I El control RichEdit Una de las grandes limitaciones del control TMemo, que usamos para permitir la entrada de texto por parte del usuario, es que no permite usar atributos diferentes para el texto, como tamaños o estilos, ni dispone de capacidad alguna de alineación, sangrado de párrafos, etc. Entre los controles de Windows 95 nos encontramos con uno, llamado TRichEdit, situado en la paleta de componentes

con este botón: , que en cierta manera funciona como un TMemo, con la diferencia de que permite editar texto en formato Rich Text Format, o RTF, en ql que es posible utilizar atributos en el texto, ajustar párrafos, etc.

En el inspector de objetos podremos apreciar la existencia de algunas propiedades y eventos exclusivos de este control. En la siguiente tabla se enumeran las propiedades.

Nombre Tipo Comentario DefAttributes TTexAttributes Atributos para el texto por defecto HideScrollBars Boolean Ocultar las barras de desplazamiento HideSelection Boolean Ocultar la selección actual de texto Paragraph TParaAttributes Atributos del párrafo actual o seleccionado PlainText Boolean Indica si el contenido es texto normal o RTFSelAttributes TTextAttributes Atributos del texto seleccionado

Atributos de texto

Page 35: Curso Basico de Delphi

Tanto la propiedad DefAttributes, que establece los atributos por defecto para el texto, como la propiedad SelAttributes, que nos permite conocer y modificar los atributos del texto actualmente, son de tipo TTextAtributes.

Mediante las propiedades Name, Style, Size y Pitch podemos conocer y modificar los atributos generales del texto. Estas propiedades son del mismo tipo y contienen la misma información que las propiedades del mismo nombre de un objeto TFont. Mediante la propiedad Color podremos manipular el color del texto, siendo de tipo TColor.

El texto seleccionado en un TRichEdit puede estar protegido contra escritura, atributo que podemos conocer y modificar mediante la propiedad Protected del objeto TTextAttributes, de forma similar a como podemos establecer el tipo o tamaño de letra.

Atributos de párrafo

También la propiedad Paragraph es una referencia a un objeto, en este caso del tipo TParaAttributes. Mediante este objeto podemos conocer y modificar los atributos del párrafo actual o los párrafos seleccionados en un determinado momento.

El texto de un párrafo puede estar ajustado a la izquierda, centrado o ajustado a la derecha, dependiendo del valor que demos a la propiedad Alignment, que puede ser uno de estos:

Valor Tipo de ajuste taLeftJustify Izquierda taCenter Centrado taRightJustify Derecha

Un párrafo se ajusta, según la propiedad anterior, dentro de los límites actuales del control y de los márgenes que se hayan establecido. Estos márgenes se definen mediante tres propiedades: FirstIndent, LeftIndent y RightIndent, pudiendo contener cada una de ellas un número entero cuya unidad de medida es el punto de pantalla. LeftIndent establece el margen izquierdo para la primera línea del párrafo, que será el relativo a FirstIndent. Mediante la propiedad RightMargin definiremos el margen derecho.

En caso de que sea posible utilizar el tabulador en el control, porque hayamos dado el valor True a la propiedad WantTabs del TRichEdit, la propiedad TabCount del objeto TParaAttributes contendrá el número de puntos de tabulación y la propiedad Tab, que es una matriz de enteros, almacenará las posiciones correspondientes a cada uno de esos puntos.

Cada inicio de párrafo del texto que se introduce en un TRichEdit puede ir precedido de lo que normalmente se denomina un bolo, una marca que resalta el comienzo del párrafo. La existencia o no de este elemento dependerá del color que asignemos a la propiedad Numbering, que será nsNone o nsBullet, siendo éste segundo el valor a usar para activar el uso de bolos.

Salvar, cargar e imprimir texto

Al igual que el control TMemo, un TRichEdit dispone de una propiedad Lines, en la que se almacenan las líneas que actualmente contiene el control. Se ha de tener en cuenta que estas líneas no contienen sólo el texto que nosotros vemos en el control sino que, además existen una serie de secuencias o controles especiales, que son los que establecen los atributos del texto y párrafo. Si queremos tener únicamente el texto, sin los caracteres especiales, hemos de acudir a la propiedad Text del TStrings que tiene las líneas del texto. Esta propiedad es una cadena que contiene todo el texto del TRichEdit.

La propiedad Lines es un objeto TStrings, por lo que disponemos de los habituales métodos SaveToFile y LoadFromFile, que nos facilitan las operaciones de entrada y salida a archivos en disco.

Además, este control incorpora un método Print, que se encarga de enviar a la impresora el texto contenido en él. Al llamar a este método deberemos facilitar una cadena de carácteres como único parámetro, que será el título del trabajo de impresión.

Page 36: Curso Basico de Delphi

Eventos de TRichEdit

Además de los eventos habituales de los controles de esta categoría, generados por el ratón, el teclado y otros elementos, el control TRichtEdit cuenta también con un evento, OnSelectionChange, que se produce cada vez que se desplaza el cursor por el contenido actual del control, o bien cuando se modifica la selección actual de texto. Esto nos da una oportunidad para obtener información acerca de los atributos del texto y el párrafo, mediante las propiedades SelAttributes y Paragraph, actualizando los indicadores, botones y, en general cualquier control cuyo estado o valor dependa de estos parámetros.

4.II El control StatusBar Se denomina barra de estado a un área de la ventana, normalmente situada en la parte inferior, que sirve para mostrar mensajes e indicadores de estado.

Se puede construir una barra de estado mediante un control TPanel, por ejemplo, dando un valor adecuado a la propiedad Align para que éste se sitúe en el lugar apropiado.

Delphi, sin embargo, incorpora en la página Win95 de la Paleta de componentes un control

llamado TStatusBar: . Al colocarlo en un form, automáticamente se situará en la parte inferior del form, ocupándolo de izquierda a derecha. En el extremo derecho inferior de la barra de estado, que tiene la altura precisa para mostrar una línea de texto, existe una esquina con varias líneas en diagonal, que indican que el form se puede coger por ese punto para ser redimensionado. Esta característica y algunas más, las podemos establecer mediante las propiedades de control TStatusBar. En la siguiente tabla se pueden ver algunas de ellas.

Propiedades Tipo Contenido Panels TStatusPanels Referencia a un objeto TStatusPanels

SimplePanel Boolean Indica si la barra de estado contiene sólo una línea de texto

SimpleText String Texto a mostrar en la barra de estado SizeGrip Boolean Indica si existe la esquina de cambio de tamaño

Una barra de estado simple

Si vamos a usar el control TStatusBar para crear una barra de estado simple, en la que sólo se muestra un mensaje, tan sólo hemos de dar el valor True a la propiedad SimplePanel, asignando el texto a mostrar a la propiedad SimpleText. En tiempo de ejecución bastará con modificar el valor de esta última propiedad para mostrar un texto diferente. También podemos hacer desaparecer el mensaje que está actualmente visualizando simplemente asignando el valor False a la propiedad SimplePanel, haciéndolo aparecer de nuevo devolviendo a esta propiedad el valor True.

La propiedad SizeGrip es la que establece la existencia o no en la barra de estado de la esquina con líneas en diagonal, que indica que es posible el cambio de tamaño del form. Por defecto esta propiedad tiene el valor True, indicando que sí es posible esa acción. Debemos dar el valor False a SizeGrip en caso de que la ventana que estamos usando sea de tamaño fijo.

Múltiples paneles en la barra de estado

Un control TStatusBar puede contener una o más secciones, a las que se denomina paneles.

La propiedad Panels del control TStatusPanel es un objeto de tipo TStatusPanels. Este objeto, en realidad, es una colección de objetos TStatusPanel y cuenta con una propiedad Count, que nos sirve para saber cuántos paneles existen, y los métodos precisos para poder añadir nuevos paneles, Add, y eliminar los existentes, Clear.

Además, el objeto TStatusPanels dispone de una propiedad indexada, llamada Items, que es la que permite acceder a cada uno de los elementos de la colección.

Page 37: Curso Basico de Delphi

Por lo tanto cada uno de los elementos TStatusPanels define una sección de la barra de estado, basándose en las propiedades que se comentan en la siguiente tabla. Si la propiedad Style contiene el valor psText, será alineado según indique la propiedad Alignment, que como en otros controles puede tomar los valores taLeftJustify, taCenter y taRightJustify. El ancho del panel se especificará en puntos en la propiedad Width, pero el último panel, el que quede en el extremo derecho, siempre ocupará el resto de la barra. Mediante la propiedad Bevel indicaremos si el panel debe aparecer hundido en la barra, pbLowered resaltado, pbRaised, o al mismo nivel, pbNone.

Propiedad Tipo Contenido Alignment TAlignment Alineación del texto en el panel Bevel TStatusPanelBevel Apariencia del panel en la barra Style TStatusPanelBevel Estilo del panel Text String Texto a mostrar en el panel Width Integer Anchura del panel

En caso de que asignemos el valor psOwnerDraw a la propiedad Style de un TStatusPanel, ese panel no contendrá un texto, sino que deberá ser dibujado por nuestro propio programa.

Cada vez que el panel deba ser dibujado, el control TStatusBar generará un evento OnDrawPanel, pasando tres parámetros al procedimiento correspondiente.

El primero de estos parámetros será de tipo TStatusBar y hará referencia al control TStatusBar que ha generado el evento. El segundo será de tipo TStatus, conteniendo una referencia al panel que debe ser dibujado. Por último encontramos un parámetro de tipo Rect, conteniendo los límites de la zona de dibujo.

Definir paneles en tiempo de diseño

En la mayoría de las ocasiones es posible definir los paneles de un control TStatusBar en tiempo de diseño, para lo cual deberemos hacer una doble pulsación sobre la propiedad Panels, abriendo el correspondiente editor.

En la ventana que aparece, tendremos que pulsar el botón Add por cada nuevo panel que deseemos crear, indicando a continuación el estilo, su anchura, aspecto y texto, en el Inspector de Objetos como cualquier otra propiedad.

Definir paneles en tiempo de ejecución

La creación de los paneles de una barra de estado en tiempo de ejecución, en lugar de hacerlo en tiempo de diseño, tiene la ventaja de que el usuario puede configurar la barra de estado. Para ello disponemos de dos métodos, Add y Clear. Cada vez que llamemos al método Add se creará un nuevo objeto de tipo TStatusPanel en la barra de estado. Si llamamos al método Clear, se eliminarán todos los paneles existentes en ese momento.

4.III El control TrackBar En muchas ocasiones, los valores que solicita un programa al usuario son numéricos y se encuentran entre unos ciertos límites conocidos. Aunque podemos utilizar un control TEdit para pedir datos de este tipo, existen bastantes posibilidades más, entre las que se encuentra el control

TTrackBar . Mediante este control, además, es posible seleccionar rangos de valores en lugar de un sólo valor. En apariencia un control TTrackBar es bastante similar a una barra de desplazamiento y de hecho su funcionamiento es muy parecido. Este control cuenta con unos límites y una posición actual, mostrada visualmente mediante un cursor. En el interior del control es posible disponer unas marcas a intervalos regulares, entre el mínimo y el máximo. Estas características y algunas más las podremos establecer mediante las propiedades de TTrackBar, algunas de las cuales las enumeramos en la siguiente tabla.

Propiedad Tipo Contenido

Page 38: Curso Basico de Delphi

Frecuency Integer Frecuencia de las marcas de medida LineSize Integer Incremento o decremento pequeño Max Integer Valor máximo Min Integer Valor mínimo Orientation TrackBarOrientation Orientación del control PageSize Integer Incremento o decremento grande

Position Integer Posición actual del cursor en el punto de control

SelEnd Integer Punto de inicio de la selección actual SelStart Integer Punto de fin de la selección actual TickMarks TTickMark Posición de las marcas de medida TickStyle TTickStyle Estilo de las marcas de medida

Límites y posición actual

Mediante las propiedades Min y Max fijaremos el valor mínimo y máximo de la medida, pudiendo también asignar una posición inicial modificando el valor de la propiedad Position, que por defecto tomará el mismo valor que asignemos a Min. El valor de la propiedad Position será lo único que cambie por una actuación del usuario en tiempo de ejecución, cuando el cursor del control se desplace a otro punto, ya sea mediante o con el teclado. En cualquiera de estos casos el TTrackBar generará un evento OnChange, que podemos aprovechar para actualizar cualquier parámetro que sea dependiendo de la posición actual en este control.

Apariencia del control

Un control TTrackBar puede aparecer en el form en sentido horizontal, que es el estado por defecto, o vertical, según el valor que asignemos a la propiedad Orientation, que será tbHorizontal o tbVertical.

A la izquierda y derecha o arriba y abajo, dependiendo de la orientación, el control puede mostrar unas marcas intermedias, que permitirán tener una idea aproximada del valor actual que se está usando. Mediante la propiedad TickMarks podemos determinar la situación de esas marcas en el control, pudiendo ser las siguientes:

Constante Posición de las marcas tmBottomRight Abajo o a la izquierda dependiendo de la orientación tmTopLeft Arriba o a la izquierda tmBoth Abajo y arriba o a la izquierda y derecha

La propiedad TickStyle nos servirá para fijar el estilo de las marcas, pudiendo tomar los siguientes valores:

Constante Estilo de las marcas tsAuto Automático, es el estilo por defecto tsNone Sin marcas tsManual Manual

El estilo tsAuto distribuye las marcas existentes entre los puntos de inicio y fin de una forma regular, según el valor que se haya asignado a la propiedad Frecuency, que por defecto es uno, lo que quiere decir que existirá una marca por cada unidad.

Page 39: Curso Basico de Delphi

Si asignamos el valor 100 a la propiedad Max, veremos que las marcas están tan juntas que forman una línea. Modificando el valor de Frecuency, asignándole por ejemplo 10, conseguiremos que se muestre una marca cada diez unidades.

En caso de que asignemos a la propiedad TickStyle el valor tsManual, el control sólo dispondrá de dos marcas, una en cada extremo. Cualquier otra marca que deseemos deberemos establecerla nosotros mismos, mediante el método SetTick, al que pasaremos como único parámetro un entero indicando la posición en la que deseamos disponer la marca.

Selección de rangos

Además de para mostrar o fijar una posición del cursor, lo que en definitiva se traduce en un cierto valor que obtendríamos de la propiedad Position, el control TTrackBar también nos permite seleccionar un rango o intervalo de valores, mediante las propiedades SelStart y SelEnd. Inicialmente estas dos propiedades tienen el valor cero, lo que indica que no hay seleccionado un intervalo.

Al asignar a SelStart y SelEnd un valor, podremos ver que en el control aparece de un color diferente el rango seleccionado y que, además aparecen dos marcas especiales, dos pequeños triángulos, que se delimitan perfectamente el intervalo.

4.IV Los controles ProgressBar, SpinButton, SpinEdit y UpDown

El control ProgressBar

Entre los componentes de Delphi encontramos uno llamado TProgressBar , cuya finalidad es mostrar de forma gráfica el estado actual del curso de un proceso. En apariencia este control es parecido a un TPanel, contando con propiedades similares a las de un control TTrackBar.

Antes de iniciar el proceso cuyo curso vamos a reflejar mediante el TProgressBar, deberemos asignar a las propiedades Min y Max de este control un valor mínimo y un valor máximo, que corresponderán al estado de inicio y fin del proceso.

A medida que el curso del proceso vaya avanzando, deberemos actualizar en consecuencia el valor de la propiedad Position, lo que tendrá un reflejo inmediato en el aspecto del control, que se irá llenando de bloques de color que indicarán la parte que ya se ha completado. En lugar de manipular directamente un valor de la propiedad Position, podemos asignar previamente un valor de incremento a la propiedad Step, llamando posteriormente, en cada paso, al método StepIt, que se encargará de realizar la actualización. También tenemos a nuestra disposición el método StepBy, que acepta como parámetro un valor de incremento, valor que se sumará al contenido que tenga en ese momento en la propiedad Position.

Los controles SpinButton y SpinEdit

En la hoja Samples de la paleta de componentes Delphi existen dos controles, TSpinButton y

TSpinEdit , que utilizan dos pequeños botones con unas flechas en su interior para facilitar el incremento y decremento de un valor, que en el segundo caso se almacena en un campo de edición.

En el caso del TSpinButton, podemos asociarlo a un control TEdit mediante su propiedad FocusControl. Además, si pulsamos el botón de la flecha hacia arriba se generará un evento OnUpClick, y si pulsamos el botón de la flecha hacia abajo se generará un evento OnDownClick. En respuesta a estos eventos podemos poner el código conveniente, por ejemplo, podemos poner código para aumentar o disminuir el valor del campo Edit al que esté asociado.

Si se trata de aumentar o disminuir valores numéricos, puede ser más conveniente usar el control TSpinEdit, pues viene con el campo de edición incorporado. Si cambiamos el valor de la propiedad MinValue cambiaremos el valor mínimo que puede tomar el campo de edición; por contra, si

Page 40: Curso Basico de Delphi

cambiamos el valor de la propiedad MaxValue cambiaremos el valor máximo que puede tomar el campo de edición (hablamos siempre de valores numéricos). El valor de la propiedad Increment nos dice de cuánto en cuánto se incrementarán los valores del campo de edición. Además, el valor del campo de edición lo tenemos en la propiedad Value.

El control UpDownEn en la página Win95 de la paleta de componenetes Delphi hay un control, llamado TUpDown

, que funciona de forma similar, con la diferencia de que puede ser asociado a cualquier otro control y dispone de alguna posibilidad más.

Mediante la propiedades del control TUpDown, que en parte se enumerarán en la siguiente tabla, podremos establecer los límites para el valor que se gestiona, así como el incremento o decremento que sea aplicará al pulsar el botón, su aspecto, control al que está asociado, etc.

Propiedad Tipo Contenido AlignButton TUDAlignButton Posición del control ArrowKeys Boolean Indica si se puede usar las flechas del teclado Associate TWinControl Control al que está asociado Increment Integer Incremento a aplicar Max Integer Valor máximo Min Integer Valor mínimo Orientation TUDOrientation Orientación del control Thousands Boolean Indica si se utilizan separadores de miles Position Integer Posición del cursor en el control Wrap Boolean Indica si se pone a cero al superar el máximo

Control del valor

Para usar un control TUpDown, uno de los primeros pasos que deberemos dar será el establecimiento del valor mínimo y máximo permitido, en las propiedades Min y Max, respectivamente. El valor actual será el contenido en la propiedad Position, que se verá incrementado o decrementado, según la flecha que se pulse, en una magnitud determinada por el valor de la propiedad Increment.

Si damos el valor True a la propiedad Wrap conseguiremos que el control funcione de forma circular, de tal manera que al pulsar el botón de incremento encontrándonos ya en el límite superior, el valor pase a ser el mínimo y viceversa.

Estilo y control asociado

Los botones de un control TUpDown, que tienen dibujadas unas flechas en su interior, pueden aparecer situados sobre el otro, o bien uno a la izquierda del otro, según el valor que se asigne a la propiedad Orientation. Por defecto esta propiedad tiene el valor udVertical, por lo cual los botones aparecen situados uno sobre otro. Asignando a Orientation el valor udHorizontal conseguiremos modificar el estilo del control, de tal forma que los botones se sitúen uno a la izquierda del otro.

En caso de que el valor que va a contener este control supere los tres dígitos, podemos dar el valor True a la propiedad Thousands para conseguir que se utilice un separador de miles.

Asignando el valor True a la propiedad ArrowKeys, indicaremos al TUpDown que estando el control asociado activo se pulsen las flechas arriba y abajo del teclado, se incremente o decremente automáticamente el valor. Esto es posible cuando el control asociado procesa estas pulsaciones de la tecla, como un TEdit, en lugar de pasar a otro control, como hace un TButton.

Page 41: Curso Basico de Delphi

4.V El control HotKey La tecla de acceso rápido a una opción de menú se almacena en la propiedad ShortCut del objeto TMenuItem que representa a cada opción de menú,la cual puede ser modificada en cualquier momento, incluso en tiempo de ejecución. El problema que nos encontramos es cómo saber cuál es el código a asignar a esta propiedad dependiendo de la combinación de teclas que se desee utilizar. Una posibilidad es utilizar la función TShortCut, que podemos asignar a la propiedad ShortCut. Sin embargo, aún deberemos llevar a cabo algún proceso complejo, ya que tendremos que preguntar al usuario qué combinación es la que desea establecer, detectando la pulsación de teclas como <Alt>, <Control>, teclas de función, etc. La solución al problema que se nos plantea la encontramos en el control THotKey, cuya finalidad básica es facilitar la entrada, por parte del usuario del programa, de una tecla de acceso rápido. La apariencia de este control es la de un TEdit, pero en él no es posible teclear texto, ya que en el momento en que se pulsa una tecla o combinación de teclas, lo que aparece en el control es una cadena descriptiva de esa combinación.

Uso de un control THotkey

Además de las propiedades habituales de todos los controles, que ya conocemos, un control

THotKey cuenta con tres propiedades clave, que le diferencian del resto. Estas propiedades son HotKey, InvalidKeys y Modifiers. La primera de ellas es de tipo TShortCut y contendrá el código correspondiente a la combinación de teclas que se hayan pulsado.

Esta propiedad puede ser modificada tanto en tiempo de diseño como en ejecución, pero lo habitual es que sea el usuario el que la modifique de forma indirecta.

Generalmente una tecla de acceso rápido es una combinación compuesta por una tecla normal, letra, número o de función, y una tecla modificadora, como puede ser <Control>, <Alt>, <Shift> o cualquier combinación de estas. Mediante la propiedad InvalidKey podemos establecer aquellos modificadores que no deseamos que sean válidos, impidiendo que el usuario los utilice.

En la siguiente tabla se muestran los valores posibles para asignar:

Constante Tecla representada hcAlt <Alt> hcCtrl <Control> hcCtrlAlt <Control> + <Alt> hcNone Ninguna hcShift <Mayúscula> hcShiftAlt <Mayúscula> + <Alt> hcShiftCtrl <Mayúscula> + <Control> hcShiftCtrlAlt <Mayúscula> + <Control> + <Alt>

Podemos saber qué teclas modificadoras se han usado en la combinación introducida por el usuario, o establecerlas mediante la propiedad Modifiers. Esta propiedad es de tipo THKModifiers, un conjunto que puede contener uno o más valores, enumerados en la siguiente tabla. En la práctica, suponiendo que usemos este control para personalizar un menú, será el valor de la propiedad HotKey el que nos interese.

Constantes Tecla a la que representa hkAlt <Alt> hkCtrl <Control> hkShift <Mayúscula> hkExt <Extra>

Page 42: Curso Basico de Delphi

4.VI El control HeaderControl Heredado de versiones anteriores de Delphi, existe un control, que ahora lo encontramos en la página Win 3.1, llamado THeader, que permite crear cabeceras para listas y elementos similares. Delphi cuenta, además, con el control TheaderControl, que es parecido a THeader, aunque cuenta con algunas posibilidades más. Lo encontramos en la página Win 95 de la paleta de componentes,

bajo la apariencia . Este control dispone de las propiedades habituales de todos los componentes visuales, contando, además, con la propiedad Align, que nos permite situarlo en el lugar del form que más nos convenga, y de la propiedad Sections, que nos servirá para definir las diferentes secciones en que se dividirá el control.

La propiedad Sections de este control es de tipo THeaderSection, que al igual que ocurre con la propiedad Panels del control TStatusBar, hace referencia a un objeto, que contiene un elemento por cada sección de la cabecera. Las propiedades de cada uno de estos elementos definen el texto que se mostrará en esa sección, su ajuste, límites, etc. En la siguiente tabla se enumeran algunas propiedades de un objeto THeaderSection:

Propiedad Tipo Contenido Alignment TAlignment Alineación del texto en la sección AllowClick Boolean Indica si la sección puede ser pulsada MaxWidth Integer Anchura máxima de la sección MinWidth Integer Anchura mínima de la sección Style THeaderSectionStyle Estilo de la sección Width Integer Anchura actual de la sección

Al igual que ocurre con los paneles de una línea de estado, las secciones de un control THeaderControl pueden contener un texto, si la propiedad Style tiene asignado el valor hsText, o bien ser dibujadas por el programa, si el estilo es hsOwnerDraw. El texto a mostrar lo facilitaremos en la propiedad Text. Si hemos optado por el estilo hsOwnerDraw deberemos responder adecuadamente al evento OnDrawSection, en el que recibiremos una referencia al THeaderControl, otra a la sección a dibujar, un objeto TRect con las coordenadas del área de dibujo y un parámetro de tipo Boolean que nos indicará si el botón está pulsado o no.

El ancho de cada una de las secciones de una cabecera es establecido por la propiedad Width de cada objeto THeaderSection. Este valor habrá de encontrarse entre los límites fijados por las propiedades MinWidth y MaxWidth.

Definir secciones de la cabecera

Las secciones de un control THeaderControl pueden ser definidas tanto en tiempo de diseño como durante la ejecución del programa. En el primer caso tendremos que usar la propiedad Sections, haciendo un doble clic sobre ella en el Inspector de Objetos, para acceder a la ventana de edición de secciones. Esta ventana es similar a la usada para definir paneles de una barra de estado. Tras pulsar el botón Add, podremos seleccionar el estilo de la sección, introducir el texto que deseamos mostrar en ella, establecer la anchura y sus límites o fijar la alineación del texto. También podremos indicar si es posible pulsar las secciones como si fuesen botones, generando el evento OnSectionClick correspondiente. Durante la ejecución del programa también es posible definir las secciones de una cabecera, de forma similar a como definíamos los paneles de un TStatusBar, ya que el funcionamiento de ambos controles es muy parecido.

4.VII El control PageControl A veces, la cantidad de información que es necesario solicitar o mostrar excede la capacidad habitual de una ventana, siendo preciso usar varias para poder gestionar todos los controles requeridos. Una alternativa a la creación de múltiples ventanas consiste en definir varias páginas en la misma ventana, lo cual es posible mediante varios de los controles incluidos en Delphi. Entre ellos existe uno que nos permite gestionar varias páginas en un form, en este caso con el nuevo

Page 43: Curso Basico de Delphi

aspecto de Windows 95. Este control se llama TPageControl y dispone de las siguientes propiedades:

Propiedades Tipo Contenido ActivePage TTabSheet Página actualmente activa MultiLine Boolean Indica si se permiten varias líneas PageCount Integer Número de páginas existentes Pages TTabSheet Matriz con las páginas existentes TabHeight SmallInt Altura de las pestañas de las páginas TabWidth SmallInt Anchura de las pestañas de las páginas

Cada una de las páginas contenidas en un control TPageControl es un objeto de tipo TTabSheet. Podemos acceder o modificar la página activa mediante la propiedad ActivePage y acceder a cada una de las páginas a través de la propiedad Pages, que es una matriz de objetos TTabSheet. Esta matriz contendrá tantos elementos como indique la propiedad PageCount, que está disponible sólo en tiempo de ejecución y, además, es de sólo lectura.

Definir las páginas de un TPageControl

Al insertar un control TPageControl en el form tan sólo tendremos una superficie con un borde, similar a un TPanel, pero en principio no existirá página alguna. Cada vez que deseemos añadir una página al control deberemos abrir el menú emergente, pulsando el botón derecho del ratón con el puntero sobre el control, y seleccionar la opción New Page. Al hacerlo aparecerá una página vacía con un título por defecto en la pestaña y en el Inspector de objetos podremos ver las propiedades del objeto TTabSheet que acabamos de crear.

Mediante las propiedades del TTabSheet podemos establecer el título que aparecerá en la pestaña (Caption), el tipo de letra (Font), su estado actual (Enabled y Visible), etc. Además de estas propiedades, habituales en todos los componentes visibles, al actuar como un contenedor para los controles, un TTabSheet cuenta también con las propiedades ComponentCount, Components, ControlCount y Control.

Por defecto la pestaña de acceso a una página está visible, lo que permite en tiempo de ejecución que el usuario pueda pulsarla activando esa página. Podemos dar el valor False a la propiedad TabVisible del TTabSheet para ocultar la pestaña correspondiente, desactivando así el acceso a esa página.

Propiedades comunes a todas las páginas

Por defecto, cada una de las pestañas ajusta su tamaño al necesario para contener el título que se haya asignado a la propiedad Caption. Esto es así porque inicialmente las propiedades TabHeight y TabWidth tienen el valor cero, pero asignando el valor que a nosotros nos interese podremos establecer un alto y ancho común para todas las pestañas.

Por regla general el número de páginas existentes en una ventana no es muy grande, por lo que todas las pestañas se pueden alinear en una sola fila. En caso de que esto no sea posible, automáticamente aparecerá en el extremo derecho un control con dos botones, que permitirán el desplazamiento de las pestañas a izquierda y derecha. Si no deseamos este funcionamiento, podemos dar el valor True a la propiedad MultiLine, lo que hará que las pestañas se distribuyan en tantas filas como sea necesario.

Métodos de TPageControl

Ya sabemos que en tiempo de ejecución el usuario puede cambiar la página activa de un TPageControl con tan solo una pulsación de ratón. Nosotros, desde el código de nuestro programa, también podemos cambiar de una página a otra, simplemente asignando a la propiedad ActivePage el nombre del TTabSheet correspondiente.

Otra forma de cambiar de una página a otra en utilizar el método SelectNextpage, que nos permite desplazarnos a la página siguiente o anterior, dependiendo de que pasemos como parámetro el

Page 44: Curso Basico de Delphi

valor True o False, respectivemente. También podemos usar el método FindNextPage, que facilita el desplazamiento a la página siguiente o anterior a una dada. Al llamar a este método pasaremos tres parámetros: el nombre de la página de referencia, un valor de tipo Boolean indicando si se desea ir a la siguiente, True, o a la anterior, False y por último otro valor de tipo Boolean, que en caso de ser True indicará al control que sólo devuelva páginas que estén activas.

TTabControl

El control TTabControl , es por el contrario un control simple, que muestra con una apariencia prácticamente idéntica a un TPageControl. Las diferencias, sin embargo, son muchas, ya que el TTabControl no actúa como un contenedor, ni intercambia automáticamente páginas. Su finalidad es, por lo tanto, servir simplemente como un conjunto de opciones que se muestran en forma de pestañas, de las cuales se puede seleccionar una en cada momento.

4.VIII El componente TImageList Algunos de los controles que veremos en los capítulos siguientes, como TListView y TTreeView, utilizan para visualizar sus elementos pequeñas imágenes, que deben estar accesibles mediante un tercer componente, llamado TImageList, que actúa como contenedor. Puesto que es necesario disponer de este contenedor de imágenes antes de poder utilizar los dos controles citados, vamos a tratar en primer lugar el funcionamiento de TImageList. Podemos encontrarlo en la pestaña 'Win95'

de la paleta de componentes, siendo el de la imagen: En la tabla siguiente vemos sus propiedades:

Nombre Tipo Contenido

AllocBy Integer Incremento cada vez que sea necesario aumentar el número de imágenes

BkColor TColor Color de fondo a usar al dibujar una imagen BlendColor TColor Color de combinación Count Integer Número de imágenes contenidas DrawingStyle TDrawingStyle Estilo para el dibujo de una imagen Height Integer Altura de las imágenes ImageType TImageType Tipo de imagen a utilizar para dibujar

Masked Boolean Indica si la ImageList contiene imágenes transparentes o no

ShareImages Boolean Indica si las imágenes son compartidas con otro control

Width Integer Anchura de las imágenes

Todas las imágenes que se almacenan en un TImageList deben tener exactamente el mismo tamaño, por lo que si pretendemos tener disponibles imágenes de distinto tamaño, tendremos que usar varios componentes TImageList, uno por cada tamaño.

Asignación de imágenes en tiempo de diseño

Tras insertar un componente TImageList en un form, haz doble clic sobre él, o bien despliega el menú emergente y selecciona la opción ImageList Editor, en la que podremos ir añadiendo imágenes mediante el botón Add, estableciendo algunos parámetros como el color que será transparente, o si la imagen se ajusta a las dimensiones por defecto, se corta o aparece centrada.

Asignación de imágenes en tiempo de ejecución

En caso de que la imagen a cargar esté almacenada en un archivo en forma de icono, archivos que normalmente usan la extensión ICO, deberemos crear un objeto TIcon y cargar dicho archivo, mediante el método LoadFromFile, añadiendo la imagen a continuación al TImageList mediante el

Page 45: Curso Basico de Delphi

método AddIcon, que toma como único parámetro una referencia al TIcon, devolviendo un entero indicando el índice, en la lista de imágenes, de la imagen recién añadida.

Cuando se dibuja un icono, además de los colores habituales de la paleta existe un color transparente, con el que se pueden pintar aquellas zonas del icono que no deseamos que alteren el fondo sobre el que posteriormente serán dibujados. Este "color" no existe en una imagen de mapa de bits normal, que se almacena en un archivo BMP. Por ello, al añadir una imagen de este tipo al TImageList, mediante el método AddMasked, además de una referencia al objeto TBitmap que contiene la imagen, también debemos facilitar, como segundo parámetro, un TColor, indicando el color de la imagen "máscara", que se usará a la hora de dibujar la imagen para evitar el borrado de aquellas zonas del fondo que sean ocupadas por el color transparente de la imagen.

Otra opción, a la hora de añadir una imagen, consiste en crear u obtener nosotros mismos la máscara para la imagen, pasando los dos parámetros, imagen original y máscara, al método Add, que al igual que los dos anteriores devolverá un entero facilitando el índice de la imagen añadida.

Ciertos recursos de una aplicación, como son las imágenes o iconos, pueden distribuirse de forma conjunta con el ejecutable, en lugar de en archivos separados. Para ello se debe crear un archivo de recursos cuyo nombre se facilita mediante la directiva $R al proyecto. Estos recursos pueden ser cargados posteriormente mediante diversas funciones, siendo una de ellas el método LoadResource del componente TImageList. Al llamar a este método debemos pasar tres parámetros: mediante el primero indicamos el tipo de recurso que se va a cargar, que será rtBitmap para una imagen de mapa de bits, rtCursor para un cursor o rtIcon para un icono; el segundo parámetro será un String con el nombre que tiene el recurso en el archivo y el tercero un TColor que servirá para crear la máscara correspondiente.

Uso de las imágenes de un TImageList

Podemos recuperar una imagen usando el método GetBitmap, pasando como primer parámetro el índice de dicha imagen, comprendido entre cero y el número de imágenes existentes menos uno, y como segundo una referencia a un objeto TBitmap, en el que obtendremos la imagen con su correspondiente máscara ya aplicada. En caso de que deseemos obtener la imagen en forma de icono y no de mapa de bits simple, el método a usar será GetIcon y los parámetros el índice de la imagen y un objeto TIcon.

Si lo que pretendemos es utilizar la imagen para dibujarla, por ejemplo en el Canvas del form, en lugar de obtenerla en un TBitmap y dibujarla a continuación, podemos usar el método Draw, al que pasaremos los parámetros siguientes: una referencia al objeto TCanvas en el que se va a dibujar, las coordenadas del punto a partir del cual se va a dibujar y, por último, un entero especificando cuál de las imágenes contenidas en el TImageList es la que se va a dibujar.

Mediante un objeto TImageList es fácil superponer una imagen a otra, usando dos de sus métodos. Lo primero que hemos de tener en cuenta es que las dos imágenes han de existir en el TImageList. El primer paso consistirá en llamar al método Overlay, pasando como primer parámetro un entero indicando el índice de la imagen que se va a superponer, y como segundo un TOverlay, que es un número comprendido entre 0 y 3, que servirá para identificar a esta imagen posteriormente. A continuación llamaremos al método DrawOverlay, pasando los primeros cuatro parámetros que se han citado para el método Draw y como quinto el índice, entre 0 y 3, que se utilizó en la llamada Overlay.

Otros métodos de TImageList

Además de las propiedades y métodos que hemos visto en los puntos anteriores, que son los habituales y seguramente los que nos serán más útiles, este componente cuenta con bastantes más métodos. Entre ellos existen varios métodos Insert, que funcionan de forma similar a Add pero que en lugar de añadir la nueva imagen al final la insertan en una determinada posición. También contamos con varios métodos Replace, que nos permiten reemplazar unas imágenes ya contenidas en el TImageList por otras nuevas.

5I. El control Main Menu Todos hemos usado menús en los programas: son las barras de opciones que suelen aparecer debajo de la barra de título de los programas, justo encima del área de trabajo del form. En Delphi

Page 46: Curso Basico de Delphi

podremos encontrarlo bajo el icono , en la pestaña Standard de la paleta de componentes. Con él, podremos insertar un componente Main Menu en el form.

La propiedad principal de este componente es Items, una matriz de objetos TMenuItem, cada uno de los cuales representa una opción del menú. La propiedad Items cuenta a su vez con una propiedad Count, mediante la cual podremos saber el número de opciones que tiene el menú. Cada uno de los elementos de la matriz Items tiene a su vez una propiedad Count, que nos servirá para saber el número de opciones existentes en cada lista pues, como sabemos, dentro de una opción podemos tener más subopciones y así sucesivamente.

Para facilitarnos la edición de un menú, Delphi dispone del Diseñador de menús. Podremos acceder a él haciendo doble click sobre el componente, o bien pulsando sobre la propiedad Items. Aparecerá una ventana en la que podremos ir introduciendo los títulos de las opciones, simplemente tecleándolas, y componiendo la estructura del menú desplazándonos, básicamente, mediante las teclas del cursor.

Edición de un Menú

Veamos un ejemplo de creación del menú. Para ello, partimos de un menú vacío recién insertado en el form. Introducimos la cadena &Bloque uno, que se irá mostrando en el inspector de objetos junto a la propiedad Caption, y pulsamos la tecla RETURN. Con esto ya tenemos la primera opción, cuya primera letra, la 'B' está subrayada, denotando así que además se trata de una tecla de acceso rápido.

A la derecha de esta opción y en la misma barra, aparecerá un borde punteado, que nos indicará la posición en la que se introducirá la siguiente opción principal, mientras que justo debajo de la opción que acabamos de crear también aparece un borde punteado en vídeo inverso indicándonos que podemos teclear la primera opción del menú Bloque uno. Si tras varias opciones queremos mostrar una separada del resto por una línea, tan sólo habrá que introducir un guión y pulsar <RETURN>. Aparecerá así en la ventana una línea horizontal separando las anteriores opciones de la siguiente.

Elementos del menú

Cada una de las opciones que hemos insertado en el menú anterior representa a un objeto del tipo TMenuItem. Este tipo cuenta con las propiedades necesarias para, además de conservar el título, activar o desactivar la opción, mostrarla como marcada o desmarcada, asociar teclas de acceso rápido, etc. En la siguiente tabla enumeramos algunas de sus propiedades.

Propiedad Tipo Comentario Break TMenuBreak Tipo de división en el menú Caption String Título de la opción Checked Boolean Indican si la opción está marcada o no Count Integer Número de opciones en este menú Enabled Boolean Indica si la opción está activa GroupIndex Byte Facilita la unión de múltiples menús Items TMenuItem[] Matriz con las opciones RadioItem Boolean Permite crear grupos de opciones exclusivas ShortCut TShortCut Tecla de acceso rapido

Teclas de acceso rápido

Para crear teclas de acceso rápido a cada una de las opciones, desplegaremos la lista de posibilidades correspondiente a la propiedad ShortCut, en el inspector de objetos, y seleccionaremos la combinación de teclas que queramos, que aparecerá a la derecha de la opción.

Opciones con más opciones

Page 47: Curso Basico de Delphi

Aunque una opción puede dar paso a una cierta acción en el programa, también puede abrir una nueva lista de opciones. La finalidad de la propiedad Items con la que cuenta cada objeto TMenuItem es precisamente esa, contener las opciones correspondientes a una cierta opción. Puesto que las opciones de ese nuevo menú también son objetos TMenuItem, cualquiera de ellas puede dar paso a otro menú, proceso que se puede repetir nivel tras nivel.

Para crear estas nuevas opciones pulsaremos sobre la opción que queramos que tenga las otras opciones las combinación de teclas <Control> + <Cursor derecho>. Aparecerá una nueva ventana, en la que podremos añadir las nuevas opciones.

Menús multicolumna

En caso de que la lista cuente con un gran número de opciones, resultando demasiado larga, podemos dividirla en dos o más columnas, mediante la propiedad Break. Esta propiedad puede tomar los valores que se muestran en la siguiente tabla.

Constante Tipo de división mbNone Ninguna división. Es el valor por defecto mbBreak División separada por un espacio mbBarBreak División separada por una línea vertical

Insertar y eliminar opciones en tiempo de diseño

La disposición de las opciones en un menú no es algo estático. Así, si en un momento nos interesa, podemos insertar una nueva opción entre otras ya existentes, eliminar alguna e incluso cambiar el orden de las ya existentes.

Para insertar una nueva opción seleccionaremos aquella que queramos desplazar hacia abajo o hacia la derecha y a continuación pulsaremos la tecla <Insert>. Podremos ver cómo se abre un espacio vacío, en el cual introduciremos la nueva opción.

Si lo que queremos es eliminar una opción de las ya existentes, lo único que hemos de hacer es seleccionarla y pulsar la tecla <Supr>. En caso de que la opción que borremos tenga otras en un nivel inferior, éstas también serán borradas.

Por último, también podemos alterar el orden de las opciones, tanto en la barra principal como en una lista de submenú. El método es muy simple, utilizando el cursor del ratón y el botón izquierdo para arrastrar y soltar la opción en su nueva posición.

El menú emergente del Diseñador de Menús

El Diseñador de menús cuenta con un menú emergente, al que podemos acceder mediante la pulsación del botón derecho del ratón. En él encontraremos algunas opciones que ya conocemos, como la de insertar o borrar una opción e insertar un nuevo menú. La opción Select menu nos permite pasar a editar otro que exista en el form, sin necesidad de salir del Diseñador de menús y volver a entrar. La opción Save as template nos permite salvar el menú que estamos diseñando como si fuese una plantilla, de tal forma que, posteriormente, podamos insertarlo en cualquier otro mediante la opción Insert from template. En último lugar encontramos la opción Insert from resource, que nos permite importar un menú que haya sido diseñado con cualquier otra herramienta de edición de recursos (siempre que se haya salvado en el formato habitual de los archivos de recursos de Windows).

Finalizar la edición

Cuando hayamos terminado el diseño de nuestro menú, tendremos que cerrar el Diseñador de menús para volver a la edición del form. Al hacerlo nos encontramos de nuevo con el componente MainMenu y sus propiedades, así como el menú que hemos diseñado situado en la parte superior del form. Si queremos acceder a las propiedades de cualquiera de los opciones existentes en el menú tenemos dos opciones: abrir de nuevo el Diseñador de menús, realizando un doble clic sobre el componente, o bien abrir la lista de componentes del Inspector de objetos, seleccionando el objeto TMenuItem correspondiente a la opción que deseamos manipular.

Page 48: Curso Basico de Delphi

5II. El control PopUp Menu Las similitudes entre un menú del form y un menú emergente son muchas, ya que en ambos casos se trata de listas de opciones, que pueden tener asociada una tecla de acceso y dar paso a otras opciones. La forma de diseñar un menú emergente es también muy similar, con la diferencia de que las opciones principales aparecen como una lista en el interior de una ventana, y no distribuidas en una barra como un menú del form.

Para crear un menú emergente tendremos que insertar en el form un componente PopupMenu,

representado en la Paleta de componentes con el icono , dentro de la pestaña Standard. En la siguiente tabla vemos las propiedades del componente PopupMenu.

Propiedad Tipo Comentario Alignment TPopupAlignment Determinará la posición de menú AutoPopup Boolean Indica si el menú se abrirá automáticamente PopupComponent TComponent Componente que ha hecho aparecer el menú

Activación del Menú

Podemos insertar en un form múltiples componentes PopupMenu, asociando cada uno de ellos al control que nos interese, mediante la propiedad PopupMenu de que disponen la mayoría de controles.

El método de activación del menú dependerá del valor que asignemos a la propiedad AutoPopup. Si le damos el valor True, el menú aparecerá automáticamente cuando se pulse el botón derecho del ratón sobre el componente al que está asociado. Si dicha propiedad tiene el valor False, para mostrar el menú tendremos que utilizar el método Popup del componente PopupMenu.

Si AutoPopup tiene el valor True, el menú aparecerá en la posición especificada por la propiedad Alignment, que puede tomar uno de los valores mostrados en la siguiente tabla:

Constante Posición del menú paLeft Esquina superior izquierda en el puntero del ratón paRight Esquina superior derecha en el puntero del ratón paCenter Parte central superior en el puntero del ratón

En el caso de que la activación del menú se produzca mediante el método Popup, se visualizará en la posición determinada por los parámetros pasados a dicho método.

Si estamos utilizando un determinado menú emergente para varios componentes, al producirse la activación necesitaremos saber cuál de ellos es el afectado por las acciones del menú. Para ello tenemos a nuestra disposición la propiedad PopupComponent, que es una referencia a dicho componente.

Opciones visibles, activas y marcadas

Cuando no queramos que el usuario pueda elegir una determinada opción tenemos dos posibilidades: desactivarla o hacerla no visible. Para ello utilizaremos las mismas propiedades Enabled y Visible que ya conocemos, asignándoles el valor True o False según nos interese.

Si alguna de las opciones de nuestro menú pueden tomar dos estados, activa o desactiva, podemos mostrar el estado actual mediante la propiedad Checked. Si damos el valor True a esta propiedad, a la izquierda de la opción aparecerá una pequeña marca, indicando que en ese momento está activada.

Page 49: Curso Basico de Delphi

Dando el valor True a la propiedad RadioItems, que por defecto es False, conseguiremos que las marcas anteriores aparezcan como pequeños círculos, al estilo de los botones de radio. Además, tan sólo podrá estar marcada en un determinado momento una opción del grupo. Los grupos de opciones se forman mediante la propiedad GroupIndex, de tal forma que todas aquellas opciones que tienen un mismo valor en esta propiedad, forman un grupo.

El código de las opciones

Para acceder al método que actuará como gestor del evento de cada opción, lo único que tenemos que hacer es elegirla en el menú, en tiempo de diseño. En caso de que estemos tratando con un menú emergente, primero tendremos que hacer aparecer en el Inspector de objetos la opción, para a continuación realizar un doble click sobre el evento OnClick.

Combinación de menús

Como sabemos, en un proyecto pueden existir múltiples forms, uno de los cuales actúa como principal. Cada uno de los forms existentes puede contar con su propio menú, que se mostrará en la parte superior del form al que corresponda.

Si lo queremos, podemos combinar automáticamente el menú del form principal y cualquiera de los forms secundarios, el que esté activo en cada momento, de tal forma que el menú de éste último sustituya en todo o en parte al menú de la ventana principal. Para ello nos serviremos básicamente de dos opciones: AutoMerge y GroupIndex.

Mediante la propiedad AutoMerge, con la que cuenta todo componente MainMenu, determinaremos qué menús se combinarán con el menú del form principal y cuáles no. Si disponemos en un form de un menú que nosotros queremos combinar con el del form principal, habrá que dar el valor True a esta propiedad. Si, por el contrario, queremos que el menú aparezca en su propio form, dejaremos el valor por defecto, que es False.

En principio, el menú del form secundario que esté activo sustituirá totalmente al menú del form principal, a no ser que nosotros indiquemos lo contrario, para lo cual tendremos que utilizar la propiedad GroupIndex.

Esta propiedad está presente en todos los objetos TMenuItem, aunque sólo es habitual utilizarla en aquellas opciones que forman parte de la barra principal. La norma general de funcionamiento es la siguiente: una opción del menú del form secundario que tenga un valor en GroupIndex igual al de una opción del form, sustituirá a dicha opción.

Aquellas opciones cuyo valor de GroupIndex no tengan correspondencia en el menú del form principal serán insertadas, en las posiciones que le correspondan según el orden establecido por el valor de esa propiedad. De igual forma, todas aquellas opciones del menú principal cuyo valor de GroupIndex no tenga correspondencia con ninguna opción del form secundario, permanecerán en el menú.

Añadir opciones en tiempo de ejecución

El primer paso que tendremos que dar será la creación del objeto TMenuItem. Para ello usaremos el constructor Create, que tomará como único parámetro una referencia al componente al que pertenecerá la opción. El siguiente paso será el establecimiento adecuado de las propiedades del nuevo objeto, fijando el título, estado inicial, el gestor del evento, etc. Por último añadiremos la nueva opción al menú que nos interese, para lo cual tenemos a nuestra disposición dos métodos: Add añadirá la nueva opción, cuyo objeto se pasa como parámetro, al final del menú correspondiente, e Insert, que nos permite insertar la nueva opción en una determinada posición, para lo cual el primer parámetro indicará dicha posición, sabiendo que el primer elemento del menú tiene índice cero. Podemos conocer el índice correspondiente a una opción dada mediante el método IndexOf, que tomará como parámetro la referencia a la opción cuya posición deseamos determinar.

6I. Algunas ventanas predefinidas Es bastante corriente necesitar en la aplicación de alguna ventana para solicitar datos, o para mostrar algún mensaje de error, de confirmación... según lo que el programa requiera. Podríamos

Page 50: Curso Basico de Delphi

diseñarnos nosotros los forms adecuados para cada caso, y luego usarlos en la aplicación, pero si se trata de entrada de datos básica o de un simple mensaje de información, puede ser más cómodo utilizar algunas de las funciones que pone Delphi a nuestra disposición para tal efecto, y que son las que comentamos en este apartado. Para usarlas, tendremos que asegurarnos de incluir la unit Dialogs en la clásula uses.

ShowMessage(Cadena);

Tal y como su nombre indica, muestra el mensaje 'Cadena', que debe ser un string, en una pequeña ventanita que se muestra en el centro de la pantalla, como la del dibujo:

Si no queremos que aparezca en el centro de la pantalla, podemos utilizar

ShowMessagePos(Cadena, x, y);

cuya única diferencia con el anterior es que toma dos parámetros adicionales, mediante los cuales especificaremos la posición de la esquina superior de la ventana. Estas coordenadas serán relativas a la pantalla y no a un form de la aplicación.

MessageDlg(Mensaje, Tipo, Botones, Ayuda): Word;

Esta función permite un poco más de juego que la simple ShowMessage, en el sentido de que nos permite especificar algunos detalles, y nos devuelve un valor que nos dice qué botón ha sido pulsado. Los parámetros que necesita la función son:

Una cadena conteniendo el mensaje que queremos visualizar en el interior de la ventana, con un máximo de 255 carácteres.

Una constante indicando el tipo de ventana que queremos mostrar. Las constantes disponibles son:

Constante Icono que aparecerá en el interior

mtCustom Ninguno. El título de la ventana será el nombre del programa

mtWarning

mtError

mtInformation

mtConfirmarion

Dependiendo de la que seleccionemos, en la ventana aparecerá un icono distinto y el título utilizado será acorde con dicho icono.

El tercer parámetro será un conjunto (un set), en el que indicaremos los botones que queramos que aparezcan en el interior de la ventana. Dicho conjunto puede estar vacío, contener un botón o más de un botón. En la siguiente tabla se enumeran las constantes que representan a cada uno de los botones. Cuando se quiera más de un botón, las constantes deben estar separadas por comas.

Constante Botón correspondiente

Page 51: Curso Basico de Delphi

mbYes Sí mbOk OK mbNO No mbCancel Cancelar mbHelp Ayuda mbAbort Abortar mbRetry Reintentar mbIgnore Ignorar mbAll Todo

Por último podremos facilitar un identificador asociado a una página de ayuda, que aparecerá en caso de que se pida ayuda estando activa la ventana mostrada por MessageDlg. Si no vamos a poner ayuda, simplemente escribiremos un 0.

Una vez que el usuario pulsa cualquiera de los botones existentes en la ventana, ésta se cierra y la función MessageDlg devuelve un valor que nos servirá para conocer qué botón ha sido el pulsado y, por lo tanto, qué acción tenemos que llevar a cabo. En la siguiente tabla se muestran las constantes que representan los distintos valores de retorno.

Constante Botón que se ha pulsado mrNone Ninguno, la ventana ha sido cerrada mrOk mbOk mrYes mbYes mrNo mbNo mrCancel mbCancel mrAbort mbAbort mrRetry mbRetry mrIgnore mbIgnore mrAll mbAll

Al igual que ocurre con ShowMessage, la ventana mostrada con MessageDlg aparecerá en el centro de la pantalla. Si queremos visualizarla en una cierta posición utilizaremos la función MessageDlgPos, que además de los parámetros descritos anteriormente, toma dos enteros especificando las coordenadas en la que se situará la ventana.

Application.MessageBox(Texto, Caption, Tipo): Integer;

Es una función similar a MessageDlg. En Texto le pasamos el texto que queremos que aparezca en la ventana, en Caption el que será el título de la ventana, y en Tipo le pasaremos una constante que definirá el tipo de la ventana, icono y botones. Si Texto o Caption son variables de tipo string será necesario convertirlas a PChar, si son constantes introducidas directamente en la función no. La función nos devolverá un entero, 0 si no ha conseguido abrir la ventana, o una de las siguientes constantes:

Constante Valor Significado IDABORT 3 El usuario pulsa el botón Abort IDCANCEL 2 El usuario pulsa el botón Cancel IDIGNORE 5 El usuario pulsa el botón Ignorar IDNO 7 El usuario pulsa el botón No IDOK 1 El usuario pulsa el botón Ok IDRETRY 4 El usuario pulsa el botón Reintentar IDYES 6 El usuario pulsa el botón Yes

Page 52: Curso Basico de Delphi

Algunos de los valores posibles para Tipo son:

MB_ABORTRETRYIGNORE La ventana contiene tres botones: Abortar, Reintentar e Ignorar.MB_ICONEXCLAMATION Aparece un icono de exclamación en la ventana.MB_ICONINFORMATION Se trata de un icono con una 'i' en un bocadillo.MB_ICONQUESTION Es un icono con una interrogación.MB_ICONSTOP Se trata de un icono con un signo de STOP.MB_OK La ventana contiene un botón de Aceptar.MB_OKCANCEL La ventana contiene dos botones: Aceptar y Cancelar.MB_RETRYCANCEL La ventana contiene dos botones: Reintentar y Cancelar.MB_YESNO La ventana contiene dos botones: Sí y No.MB_YESNOCANCEL La ventana contiene tres botones: Sí, No, y Cancelar.

Si, por ejemplo, queremos una vetana con un icono de exclamación y los botones correspondientes a la constante MB_YESNOCANCEL, pondremos en el parámetro Tipo de la función lo siguiente:

MB_ICONEXCLAMATION + MB_YESNOCANCEL

InputBox(Titulo, Mensaje, ValorPorDefecto): String;

Si lo que necesitamos es solicitar datos, tenemos disponible esta función. Los parámetros Titulo y Mensaje son dos cadenas en las que especificaremos el título de la ventana y el mensaje para solicitar los datos, respectivamente. El tercer parámetro es un valor por defecto como respuesta. Si se pulsa el botón Aceptar, la función devolverá una cadena con la respuesta introducida. Si se pulsa el botón Cancelar o la tecla <ESC>, el valor por defecto será la cadena que devuelva la función.

InputQuery(Titulo, Mensaje, VariableRespuesta): Boolean;

Si necesitamos saber cómo se ha cerrado la ventana, entonces usaremos esta función. Al igual que la anterior, esta función también toma tres parámetros, siendo los dos primeros idénticos en tipo y finalidad. Sin mebargo, el tercer parámetro habrá de ser necesariamente una variable de tipo String, en la que será devuelto el dato introducido por el usuario. A diferencia de InputBox, InputQuery devuelve True o False, dependiendo de que el usuario haya pulsado <Intro> o <Esc> respectivamente (o bien Aceptar o Cancelar).

6II. Uso de varios forms en la aplicación A pesar de que en el capítulo anterior vimos algunas funciones que nos facilita Delphi para no construir un form adrede pidiendo un dato o mostrando un mensaje, a buen seguro en nuestra aplicación vamos a necesitar tener más de un form, constituyendo cada uno las distintas pantallas de las que consta. En este punto vamos a ver cómo llevar a cabo una aplicación que gestione varios forms, como crearlos en tiempo de ejecución y como tenerlos accesibles desde el resto de los forms.

Los forms de un proyecto pueden ser creados al inicio del programa, cuando éste se carga en memoria, de tal forma que podamos hacer referencia a ellos desde cualquier punto en que nos convenga. La creación automática de los forms se determina en la página Forms de las opciones del proyecto. Inicialmente, todos los forms aparecerán en la lista de la izquierda, Auto-create forms, indicando así que serán creados al inicio de la ejecución sin intervención nuestra. Sirviéndonos de los botones situados en la parte central, entre las dos listas, podremos mover forms de una lista a otra. Los forms que desplacemos a la lista Avaible forms no serán creados al inicio de la aplicación, por lo que antes de poder usarlos en el programa habrá que crearlos.

Crear un form

Antes de poder hacer referencia a un form desde otra Unit, habrá que añadir a la cláusula Uses de dicha Unit la referencia, es decir, el nombre de la Unit asociada al form.

Page 53: Curso Basico de Delphi

Vamos a suponer que tenemos un proyecto con dos forms y sus dos Units, UPrincipal y USecundaria. Para poder hacer referencia al segundo form desde el código del primero, añadiríamos a la cláusula Uses de ésta el módulo USecundaria. Esta operación se puede realizar automáticamente, mediante la opción Use Unit del menú File. Al seleccionarla aparece una lista con los módulos disponibles en el proyecto, sólo aquellos que no estén ya en uso en el módulo actual, pudiendo seleccionar cualquiera de ellos.

Dada por supuesta la resolución de referencia anterior, para crear un form (que no esté en Auto-Create Forms, sino que esté en Available Forms) tendremos que utilizar el constructor Create, que actúa como el de cualquier otro componente, tomando un parámetro que será una referencia al objeto que se convertirá en padre del nuevo form.

Otro método que nos permite crear un form en tiempo de ejecución viene dado por el objeto Application, del tipo TApplication y que se crea al comenzar el programa. Este objeto cuenta con un método, llamado CreateForm, al que pasándole como parámetro el tipo del form a crear y ua variable donde almacenar la referencia, creará el form de forma similar a como lo haría el constructor Create.

Cuando el form que hemos creado no nos vaya a servir más, tendremos que liberar la memoria que se asignó al crearlo, para lo cual llamaremos al método Free con el que cuentan todos los forms.

Vamos a aclarar un poco el punto del tipo del form. Cuando estamos creando un form, en tiempo de edición, ese form tiene asociado un Name, que es como se le distingue de otros objetos. Ahora bien, si nos fijamos en el inspector de objetos, cuando tenemos seleccionado el form, supongamos que con Name=FrmPrincipal, veremos que pone FrmPrincipal: TFrmPrincipal. Precisamente, TFrmPrincipal es el tipo del form que estamos creando. Así, en el caso que estamos describiendo, para crear dinámicamente el form vía el método de TApplication, escribiremos:

Application.CreateForm(TFrmPrincipal, FrmPrincipal);

siendo TFrmPrincipal el tipo del form, y FrmPrincipal el nombre del form concreto que es de ese tipo.

Ventajas y desventajas

Si en una aplicación se cuenta con muchos forms y todos ellos son creados al inicio, está claro que el programa consumirá una cantidad de memoria muy superior a la que sería necesaria si los forms se fuesen creando y liberando a medida que fuesen precisos.

Otra de las desventajas que tiene la creación automática de todos los forms al inicio de la aplicación, es el tiempo que ésta tarda en cargarse y mostrarse activa. Obviamente, cuantos más forms se tengan que crear, el programa tardará más en ponerse en funcionamiento.

Ahora bien, si se trata de una aplicación con pocos forms, tres o cuatro, entonces es más recomendable que se creen automáticamente al principio, pues minimizaremos los riesgos de que se nos olvide liberar los forms cuando ya no vayamos a usarlos.

Mostrar un form

Independientemente del método que hayamos seleccionado para crear un form, a la hora de utilizarlo en nuestro programa tendremos que hacerlo visible, para lo cual podemos utilizar varios métodos. Uno de ellos consiste en dar el valor True a la propiedad Visible, lo que causará la aparición inmediata del form. El efecto será similar si llmamos al método Show, ya que éste básicamente lo que hace es dar el valor True a esa propiedad, aunque, además, se asegura de que el form esté sobre los demás, llamando si es necesario al método BringToFront.

Al mostrar el form mediante cualquiera de los dos métodos anteriores, estaremos visualizando una ventana no modal, lo que quiere decir que si el programa mantiene abiertas otras ventanas, podemos activarlas sin cerrar necesariamente aquella en la que nos encontramos actualmente.

Para ocultar una ventana no modal podemos también utilizar dos métodos: llamar al método Hide, o bien damos el valor False a la propiedad Visible.

Page 54: Curso Basico de Delphi

Cuadros de diálogo modales

Hay ocasiones en las que, al mostrar una ventana, lo que se persigue es que el usuario introduzca o tome alguna información y la cierre antes de continuar, no permitiendo el acceso a ninguna otra parte de la aplicación mientras tanto. A este tipo de ventanas se les llama cuadros modales, para lo que tendremos que mostrarla usando el método ShowModal.

Un form que se muestra como modal suele tener unas características que le diferencian de una ventana normal. Por ejemplo, la inexistencia de los botones para minimizar y maximizar, la imposibilidad de modificar su tamaño en tiempo de ejecución o la incorporación de algunos botones generales, como OK o Cancel. A las ventanas que cuentan con estas características y se muestran como modales se les conoce como cuadros de diálogo.

Para conseguir que cualquiera de nuestros forms se convierta en un cuadro de diálogo, tendremos que seguir por tanto las indicaciones anteriores. Para evitar la aparición de los botones de minimizar y maximizar y no permitir el cambio de tamaño durante la ejecución, bastará con que demos el valor bsDialog a la propiedad BorderStyle. Con el fin de hacerlo modal y que la aplicación no continúe su curso mientras no se cierre esta ventana, deberemos hacerla visible usando el método ShowModal. Por último, un cuadro de diálogo para cerrarse y ocultarse no utiliza el método Hide ni la propiedad Visible, sino que da un valor distinto de cero (o bien de la constante mrNone, que se define precisamente con el valor 0) a la propiedad ModalResult. Esto provoca la desaparición inmediata de la ventana y el valor asignado a la propiedad ModalResult será el mismo que devuelva la llamada al método ShowModal, que es una función. De esta forma al mostrar un cuadro de diálogo, el código que lleva a cabo esta operación puede obtener un valor de retorno que le servirá de información, de forma similar a como utilizábamos el valor de retorno devuelto por la función MessageDlg.

7I. Los cuadros OpenDialog y SaveDialog Los llamados Common Dialogs son una serie de cuadros de diálogo muy habituales en las aplicaciones bajo Windows (de ahí el nombre), que ya vienen, digamos, prefabricados, porque es tan común usarlos que no vale la pena obligar al programador a que los reinvente cuando tuviera la necesidad de utilizarlos en su programa. Estos cuadros son los típicos de abrir un archivo, guardarlo, imprimir, impresora, fuentes... y son los que vamos a ver en este último bloque de capítulos del curso.

Todos estos cuadros aparecen en la pestaña Dialogs de la paleta de omponentes, y tienen unas características comunes, como no disponer de un tamaño ni un elemento de interfaz en tiempo de diseño. Se trata de componentes que en tiempo de ejecución no son visibles en el form, de forma similar a lo que ocurría con el componente Timer.

Para hacer visible el cuadro de diálogo representado por uno de los controles, hemos de utilizar el método Execute, que no toma parámetro alguno y puede devolver True o False, indicando que el cuadro de diálogo se ha cerrado por la pulsación del botón OK o bien por otro método distinto, respectivamente.

Las características del cuadro de diálogo en el momento de la visualización dependerán de los valores que hayamos asignado previamente a sus propiedades.

El componente OpenDialog

Este componente aparece en la Paleta con el icono . Veamos algunas de las propiedades de las que disponemos para él.

Título de la ventana

Por, defecto el cuadro de diálogo tendrá un título genérico, que nosotros podemos personalizar utilizando la propiedad Title. La cadena que asignaremos a esta propiedad será la que aparezca como título en la parte superior de la ventana. La propiedad Title del componente OpenDialog sería equivalente a la propiedad Caption de un form.

Archivo seleccionado

Page 55: Curso Basico de Delphi

El nombre de archivo que aparezca inicialmente seleccionado, en el apartado Nombre de archivo, dependerá del valor que asignemos a la propiedad FileName. Asignando una cadena vacía dicho apartado aparecerá en blanco, mientras que si facilitamos una cadena conteniendo el nombre de un archivo éste aparecerá como el archivo elegido por defecto.

Una vez que el usuario haya seleccionado el archivo que desea abrir, tecleando su nombre o eligiéndolo de la lista, y cerrado el cuadro de diálogo, podremos obtener el nombre y todo el camino completo mediante la propiedad FileName.

Archivos que aparecen en la lista

Podemos facilitar una lista de tipos de archivos que deben aparecer en el cuadro de diálogo, mediante la propiedad Filter, a la que asignaremos una cadena que contiene una descripción del tipo de archivo y la referencia correspondiente, que normalmente se compone de un asterisco, un punto y la extensión. Estos dos componentes los separamos mediante el símbolo | (ASCII 124). Si queremos, podemos dar varios tipos de archivo, separando los datos de uno de los del siguiente mediante ese mismo carácter. En caso de que un determinado tipo de archivo esté asociado con varias extensiones distintas, éstas se facilitarán separándolas por punto y coma.

Por ejemplo, si asignamos la cadena

Archivos de texto | *.txt | Páginas web | *.htm; *.html

a la propiedad Filter de este cuadro de diálogo, aparecerían en la lista de archivo dos elementos, Archivos de texto y Páginas web.

Cuando se facilitan varios filtros para un cuadro de diálogo, por defecto aparece seleccionado el primero. Si queremos, podemos hacer aparecer cualquier otro modificando el valor de la propiedad FilterIndex, que por defecto es 1. Por ejemplo, si antes de mostrar el cuadro de diálogo en el que hemos establecido el filtro anterior damos el valor 2 a FilterIndex, en la lista aparecerán por defecto las Páginas web.

Extensión por defecto

La propiedad DefaultExt nos puede servir para añadir una extensión por defecto cuando el usuario no la haya especificado. Por defecto el valor de la propiedad DefaultExt es una cadena vacía, lo que indica que no se añadirá extensión alguna a los nombres de archivo.

Directorio inicial

Si lo queremos, podemos especificar una carpeta inicial mediante la propiedad InitialDir, a la que asignaremos una cadena conteniendo la unidad y camino completo de la carpeta que aparecerá inicialmente abierto.

Otras opciones

El aspecto y comportamiento del cuadro de diálogo OpenDialog puede ser modificado según las opciones que activemos en la propiedad Options, que es un conjunto del tipo TOpenOptions. Por defecto esta propiedad tiene como valor el conjunto vacío. Veamos las propiedades:

ofHideReadOnly: Oculta la caja de selección Abrir como sólo lectura, impidiendo así que el usuario abra un archivo en este modo.

ofFileMustExist: Aunque el cuadro de diálogo que estamos tratando tiene como finalidad solicitar un nombre de archivo a abrir, se permite introducir el nombre de un archivo inexistente, suponiendo que es posible crearlo. Activando esta acción forzaremos al usuario a que elija un archivo existente, avisándole si es necesario mediante un mensaje que el archivo que especifica no existe.

ofPathMustExist: Funciona de forma similar a la opción anterior, avisando al usuario mediante un mensaje en caso de que introduzca un camino de acceso inexistente.

ofNoChangeDir: Durante la selección de un archivo el usuario puede alterar el directorio establecido como actual, haciendo actual cualquier otro. Activando esta opción conseguiremos que al cerrar el cuadro de diálogo el directorio actual vuelva a ser el que era al principio, al mostrar la ventana.

Page 56: Curso Basico de Delphi

ofCreatePrompt: En caso de que el archivo especificado no exista, se mostrará una ventana preguntando si se desea crear.

ofExtensionDifferent: Cuando antes de visualizar el cuadro de diálogo se ha establecido una extensión por defecto, mediante la propiedad DefaultExt, y el usuario posteriormente ha introducido un nombre de archivo con una extensión distinta, esta opción se activa. Comprobando la existencia de ofExtensionDiferent en la propiedad Options, mediante el operador Is, podremos por lo tanto saber si la extensión del archivo es la establecida por defecto o no.

ofShowHelp: Activando esta opción forzaremos la aparición en el cuadro de diálogo de un botón de ayuda.

ofNoValidate: Por defecto el cuadro de diálogo comprueba que los caracteres introducidos por el usuario sean válidos en un nombre de archivo, avisando mediante un mensaje en caso contrario. Si activamos esta opción evitaremos la citada comprobación, permitiendo al usuario introducir cualquier carácter.

ofAllowMultiSelect: Mediante esta opción daremos al usuario la posibilidad de seleccionar varios archivos a abrir, utilizando el método habitual de selección múltiple de una lista. Para obtener los nombres de los archivos seleccionados, en lugar de usar la propiedad FileName tenemos a nuestra disposición la propiedad Files, que es un objeto del tipo TStrings de sólo lectura, en el cual cada elemento contiene un nombre junto con su camino completo.

Al utilizar cualquiera de estas opciones hay que recordar que la propiedad Options es un conjunto y que, por lo tanto, hemos de facilitar la lista de componentes de esas opciones entre corchetes.

El Componente SaveDialog

La operación complementaria a la carga de un archivo es su grabación, para la que dispone de un

componente llamado SaveDialog, que podemos encontrarlo bajo el icono . La apariencia y el funcionamiento de este cuadro de diálogo es muy similar al que acabamos de ver. De hecho, el componente SaveDialog tiene exactamente con las mismas propiedades que OpenDialog.

La propiedad Options

No todas las opciones que hemos visto para la propiedad Options tienen sentido cuando lo que se desea es salvar un archivo en lugar de cargarlo, por ejemplo la opción OfFileMustExit, pues perfectamente podemos grabar un archivo si no existe, lo crearíamos en primer lugar.

Además de las opciones vistas para el componente OpenDialog, en un cuadro de diálogo para salvar un archivo también podemos utilizar ofOverwritePrompt. Al hacerlo, el cuadro de diálogo comprobará si el archivo en el que se desea grabar ya existe y, en caso afirmativo, preguntará al usuario si desea o no sobreescribir el contenido actual de ese archivo.

7II. Los cuadros FontDialog, ColorDialog y PrintDialog FontDialog

Para facilitar la selección de un tipo y estilo de letra disponemos de l componente FontDialog, que

aparece en la Paleta de componentes como .

Tipo inicial y elegido

Al mostrar el cuadro de diálogo, el tipo de letra, estilo, tamaño y color seleccionados por defecto dependerán de los valores actuales de la propiedad Font, que como puede suponerse es un objeto del tipo TFont. Por tanto, esta propiedad cuenta con otro conjunto de propiedades, como Name, Size, Color y Style, que son las que nos permiten fijar las características de la fuente.

Una vez que el cuadro de diálogo es visualizado, el usuario puede alterar cualquiera de los componentes: tipo, tamaño, color y estilo. Al cerrar la ventana podremos obtener todos los datos del tipo seleccionado mediante la misma propiedad Font.

Dispositivo destino

Page 57: Curso Basico de Delphi

Básicamente existen dos dispositivos que pueden ser destino de un texto: la pantalla y la impresora. Estos dos dispositivos no funcionan de igual forma, por lo que puede ocurrir que un cierto tipo de letra que esté disponible en uno no lo esté en otro y viceversa. Obviamente también existen tipos de letra que están definidos para ambos dispositivos.

Utilizando la propiedad Device podremos indicar el dispositivo que será destino del tipo de letra, limitando así las fuentes que se listarán en el cuadro de diálogo a sólo aquellas que existan para ese dispositivo. Los valores que puede tomar esta propiedad son:

Constante Dispositivo destino fdScreen Pantalla fdPrinter Impresora fdBoth Ambos

Opciones

Al igual que en los cuadros de diálogo vistos anteriormente, en este también existe una propiedad Options que puede contener una o más opciones, siendo el valor por defecto [fdEffects]. Las opciones posibles y su finalidad son las siguientes:

fdTrueTypeOnly: En la lista aparecerán sólo fuentes TrueType, que se caracterizan por ser escalables y poder utilizarse tanto en pantalla como en impresora.

fdScalableOnly: En la lista de tipos sólo aparecerán fuentes que sean escalables, ya sean TrueType o no.

fdAnsiOnly: No se mostrarán en la lista aquellas fuentes que sean de símbolos, sólo aparecerán las que tengan el conjunto de caracteres estándar.

fdFixedPitchOnly: En la lista sólo apareceran tipos de letra de espaciado fijo. fdNoVectorFonts: En al lista no aparecerán los tipos de letra construidos con vectores. fdWysiwyg: En la lista sólo aparecerán aquellos tipos de letra que estén disponibles tanto

para pantalla como para la impresora. fdEffects: Esta opción está activa por defecto, haciendo aparecer en el cuadro de diálogo

los apartados de efectos, en los cuales es posible elegir el color de letra y si está aparecerá subrayada o tachada.

fdForceFontExist: Al activar esta opción no se permitirá la entrada directa de un nombre de tipo de letra que no exista.

fdNoFaceSel: Al mostrar el cuadrado de diálogo normalmente aparece seleccionado uno de los tipos de letra disponibles, cuyos nombres se muestran en la parte superior de la lista. Activando esta opción conseguiremos que ese campo de edición aparezca vacio.

fdNoSizeSel: Esta opción es similar a la anterior aplicándola al tamaño, de tal forma que al activarla no aparecerá preseleccionado un tamaño.

fdNoStyleSel: Similar a las dos anteriores, no mostrando un estilo seleccionado por defecto. fdLimitSize: El tamaño de letra a elegir por el usuario puede ser limitado, activando esta

opción y facilitando en las propiedades MinFontSize y MaxFontSize el tamaño mínimo y máximo permitidos.

fdShowHelp: Fuerza la aparición en el cuadro de diálogo de un botón de ayuda.

Una vez hayamos establecido todas las propiedades del cuadro de diálogo, bien en tiempo de diseño o en tiempo de ejecución, no tendremos mas que usar el método Execute para mostrarlo.

ColorDialog

Este cuadro de diálogo lo tendremos a nuestra disposición gracias al componente ColorDialog,

que en la Paleta de componentes aparece como .

Color seleccionado

La propiedad Color de este componente nos servirá para obtener el color que el usuario haya seleccionado en el cuadro de diálogo, pudiendo también usarla, antes de mostrar la ventana, para fijar un color por defecto. Además, podemos facilitar una serie de colores definidos a medida, aparte de los colores del sistema Windows. Para ello tendremos que utilizar la propiedad CustomColors, que es un objeto de tipo TString. A ella añadiremos una cadena por cada color que

Page 58: Curso Basico de Delphi

deseemos definir, conteniendo la palabra Color seguida de una letra, de la A a la P, un signo igual y una secuencia en hexadecimal, especificando los componentes BGR del color. Por ejemplo, podemos escribir algo así dentro del editor de líneas de la propiedad:

ColorA=FCDDDAColorB=BC875CColorC=E7BEAF

Opciones

Al igual que los anteriores componentes, éste también cuenta con una propiedad Options, que es un conjunto, en principio vacío, y puede contener una o más opciones de las siguientes:

cdPreventFullOpen: Cuando el cuadro de diálogo se muestra inicialmente, cuenta con un botón llamado Definir colores personalizados, que abre una extensión del cuadro, a la derecha, donde es posible seleccionar un color a partir de sus componentes RGB. Activando esta opción provocaremos que dicha extensión no sea accesible para el usuario.

cdFullOpen: En principio la parte derecha, citada antes, no aparece abierta, a no ser que utilicemos esta opción, lo cual causará que el cuadro de diálogo se muestra ya inicialmente completamente abierto.

cdShowHelp: Fuerza la aparición en la ventana de un botón de ayuda.

Impresión

Para dar las opciones comunes de imprimir algo podemos usar el cuadro que encontraremos en la

Paleta de componentes bajo el icono . El comportamiento de éste está controlado en parte por la propiedad Options, que en este caso puede tomar los valores:

poPageNums: Permite que el usuario seleccione una página de inicio y otra de fin de impresión. Podemos poner límites a los números de página posibles mediante las propiedades MinPage y MaxPage.

poSelection: Permite que el usuario elija imprimir la selección actual en el documento. poWarning: En caso de que no haya una impresora instalada, al especificar esta opción el

cuadro de diálogo avisará al usuario de esta circunstancia. poPrintToFile: Visualiza una opción por la cual el usuario puede elegir imprimir en un

archivo, en lugar de en la impresora. poHelp: Hace aparecer un botón de ayuda en el cuadro de diálogo.

Información a imprimir

El usuario puede elegir, si nosotros lo permitimos, entre imprimir la selección actual, un determinado número de páginas o bien todo el documento. Mediante la propiedad PrintRange podremos conocer cuál ha sido la opción elegida. En la tabla siguiente se muestran los posibles valores:

Constante Información a imprimir prSelection La selección actual prPageNums Las páginas especificadas prAllPages Todo el documento

Si una de las opciones del cuadro es poPageNums, en las propiedades FromPage y ToPage encontraremos la página de inicio y fin, respectivamente.

Por defecto, el número de copias a imprimir es uno, aunque nosotros podemos modificar este valor por defecto estableciendo el nuevo número en la propiedad Copies. En caso de que el usuario indique un número distinto de copias en el cuadro, esta misma propiedad nos servirá para conocer dicho número. El orden en que habrán de imprimirse las copias vendrá determinado por el valor de la propiedad Collate, que puede ser True o False, dependiendo de lo cual las copias serán consecutivas, de cada página, o bien se imprimirá una copia completa cada vez.

Page 59: Curso Basico de Delphi

Por último nos encontramos con la propiedad PrintToFile, que tomará el valor True en caso de que el usuario haya elegido realizar la impresión en un archivo, en lugar de en la impresora.

Debe quedar claro que este componente simplemente nos facilita la edición de las opciones que queremos dar al imprimir, y que nos va a devolver los valores adecuados para saber cómo hemos de imprimir, pero la tarea específica de imprimir el documento/imagen/etc la debemos realizar nosotros, no se imprime automáticamente por el mero hecho de usar este cuadro, sólo es una ayuda.

Configuración de la impresora

Aunque el cuadro de diálogo que contiene las opciones de impresión cuenta con un botón que permite el acceso a las propiedades de la impresora, nuestro programa también puede contar con una opción que dé acceso directamente a la ventana de configuración de impresión. Para ello existe el componente que es una impresora con una herramienta encima, y que recibe el nombre

de PrintSetupDialog, siendo este el icono que encontraremos en la Paleta de componentes . Este componente no cuenta con ninguna propiedad específica, por lo que para utilizarlo tan sólo habremos de llamar al método Execute.

7III. Los cuadros FindDialog y ReplaceDialog Para ayudarnos con las opciones que dar cuando queremos que el usuario pueda realizar una búsqueda en un texto, o una sustitución, tenemos dos cuadros de diálogo, el cuadro FindDialog, que es el que nos sirve para las opciones de búsqueda, y el cuadro ReplaceDialog, que es el que también nos da las opciones de búsqueda y sustitución.

El cuadro FindDialog

Podemos encontrarlo en la paleta de componentes bajo el icono , y cuenta con las siguientes opciones.

Opciones de búsqueda

La propiedad Options de este componente nos permitirá configurar las opciones que estarán disponibles en el cuadro de diálogo, antes de mostrarlo, así como conocer cuáles ha seleccionado el usuario, después de haberlo mostrado. Se trata de un conjunto que puede tomar los siguientes valores:

frHideMatchCase: Oculta la opción Match Case, cuya finalidad es indicar que la búsqueda se ha de realizar respetando el orden de mayúsculas y minúsculas.

frDisableMatchCase: Desactiva la misma opción anterior, de tal forma que aunque es visible el usuario no puede seleccionarla.

frMatchCase: Indica que la opción Match Case ha sido activada por el usuario. frHideWholeWord: Oculta la opción Match Whole Word Only, cuya finalidad es indicar

que la búsqueda se ha de realizar sobre palabras completas. frDisableWholeWord: Desactiva la opción anterior, dejándola visible pero inaccesible para el

usuario. frWholeWord: Indica que el usuario ha seleccionado la opción Match Whole Word Only en

el cuadro de diálogo. frHideUpDown: Oculta la opción Direction, cuya finalidad es facilitar la indicación de la

dirección de búsqueda. frDisableUpDown: Desactiva la opción anterior, no permitiendo que el usuario la seleccione. frDown: Cuando está activa inidica que el usuario ha seleccionado el botón Down, mientras

que si no lo está el botón elegido será Up. frFindNext: Indica que se ha pulsado el botón Find Next del cuadro de diálogo. frShowHelp: Fuerza la aparición de un botón de ayuda en la ventana.

Cada vez que el usuario pulse el botón Find Next, el componente generará un evento OnFind, en cuyo manejador podemos añadir el código necesario para obtener el texto a buscar, de la propiedad FindText, y poner en marcha el proceso según las opciones seleccionadas. El cuadro de diálogo no se oculta, de tal forma que el usuario puede volver a pulsar el botón Find Next para repetir la búsqueda, o bien modificar el texto y las opciones a buscar. Si lo deseamos podemos

Page 60: Curso Basico de Delphi

cerrar el cuadro de diálogo desde nuestro programa, utilizando el método CloseDialog, si no lo hacemos será el usuario el responsable de cerrarlo, para lo cual tendrá que pulsar el botón Cancel.

Mientras esté en marcha el proceso de búsqueda, en caso de que el cuadro de diálogo pueda interferir con la visualización de nuestro programa, podemos utilizar la propiedad Position para desplazarlo a otro punto. Esta propiedad toma como parámetro un TPoint, que es un registro conteniendo dos miembros, X e Y, correspondientes a la coordenada horizontal y vertical, respectivamente, del punto en el que deseamos posicionar la ventana.

Sustituciones

La apariencia y funcionamiento del cuadro de diálogo para búsqueda y sustitución es similar al

anterior. El componente está representado en la Paleta de componentes como el icono .

En este existe un campo adicional, en el que se introduce el texto que sustituirá al texto buscado, y otros dos botones, cuya finalidad es sustituir una vez o todas las veces que el texto aparezca.

Al igual que ocurre con el cuadro de diálogo de búsqueda, cada vez que el usuario pulsa el botón Find Next se genera un evento OnFind. De forma similar, al pulsar el botón Replace o Replace All se producirá un evento OnReplace. Para saber cuál de los dos botones ha sido pulsado nos servirá la propiedad Options, ya que dependiendo de ello en esta propiedad encontraremos activa la constante frReplace o frReplaceAll.

Tenemos en la ayuda de Delphi sobre estos componentes un ejemplo sobre cómo realizar la búsqueda de la palabra que nos hayan introducido. Hay que recordar que estos componentes no nos buscan la palabra, simplemente nos facilitan mostrar las opciones que hay que dar al usuario y la recogida de datos correspondiente.