Tecnicas de Programacion Visual Usando Delphi

185
UNIVERSIDAD CENTRO OCCIDENTAL “LISANDRO ALVARADO” Decanato de Ciencias y Tecnología Barquisimeto, 1999. T T É É C C N N I I C C A A S S D D E E P P R R O O G G R R A A M M A A C C I I Ó Ó N N V V I I S S U U A A L L U U S S A A N N D D O O D D E E L L P P H H I I Por Mauro J. Hernández D. Barquisimeto, 1999.

Transcript of Tecnicas de Programacion Visual Usando Delphi

Page 1: Tecnicas de Programacion Visual Usando Delphi

UNIVERSIDAD CENTRO OCCIDENTAL “LISANDRO ALVARADO”

Decanato de Ciencias y Tecnología

Barquisimeto, 1999.

TTTÉÉÉCCCNNNIIICCCAAASSS DDDEEE PPPRRROOOGGGRRRAAAMMMAAACCCIIIÓÓÓNNN VVVIIISSSUUUAAALLL UUUSSSAAANNNDDDOOO DDDEEELLLPPPHHHIII

Por Mauro J. Hernández D.

Barquisimeto, 1999.

Page 2: Tecnicas de Programacion Visual Usando Delphi

TÉCNICAS DE PROGRAMACIÓN VISUAL USANDO DELPHI

Por Mauro J. Hernández D.

TRABAJO DE ASCESO PRESENTADO PARA OBTAR A LA

CATEGORIA DE ASOCIADO EN EL ESCALAFÓN DEL PERSONAL DOCENTE Y DE INVESTIGACIÓN

UNIVERSIDAD CENTRO OCCIDENTAL “LISANDRO ALVARADO”

Decanato de Ciencias y Tecnología

Barquisimeto, 1999.

Page 3: Tecnicas de Programacion Visual Usando Delphi

TÉCNICAS DE PROGRAMACIÓN VISUAL USANDO DELPHI

Por Mauro J. Hernández D.

Trabajo Aprobado

___________________________ __________________________ Coordinador

__________________________

Barquisimeto, Octubre de 1999.

Page 4: Tecnicas de Programacion Visual Usando Delphi

AAggrraaddeecciimmiieennttoo A mis alumnos quienes contribuyeron a ser posible la realización de este trabajo, a mis colegas y amigos profesores cuya asesoría constituyo un valioso aporte en el desarrollo de este trabajo. Al Prof.Manuel Crespo, por su motivación y empujé para tener una mejor universidad. A mi familia Monica, Mauro Alejandro, Marco Aurelio y Mario Fernando quienes crearon el ambiente adecuado para poder terminar el trabajo. A la Universidad Centro Occidental “Lisandro Alvarado” por permitirme ser mejor profesional... gracias por revisar los papeles previos.

Page 5: Tecnicas de Programacion Visual Usando Delphi

DDeeddiiccaattoorriiaa

AAA mmmiiisss hhhiiijjjooosss,,, aaa mmmiii eeessspppooosssaaa yyy aaa mmmiiisss cccooollleeegggaaasss aaa qqquuuiiieeennneeesss sssuuu mmmoootttiiivvvaaaccciiióóónnn hhhaaannn hhheeeccchhhooo pppooosssiiibbbllleee lllaaa cccuuulllmmmiiinnnaaaccciiióóónnn dddeee eeesssttteee tttrrraaabbbaaajjjooo

Page 6: Tecnicas de Programacion Visual Usando Delphi

Resumen

El producto de este trabajo se utilizará como material didáctico en la enseñanza de Laboratorio II del programa de Ingeniería en Informática. El objetivo general es “presentar una alternativa de apoyo a las cátedras de Base de Datos y Sistemas de Información en cuanto a técnicas modernas de programación visual”. El análisis y diseño de sistemas informáticos debe tener un final en la implementación materializada en una pieza de software/hardware, usando herramientas de programación sólidas que den una garantía aceptable en cuanto a confiabilidad en la puesta en marcha y productividad deseada. Las técnicas de manipulación de bases de datos expuestas en este trabajo, más el ejemplo de desarrollo de una aplicación, representan un camino sólido en la aplicación de conceptos actuales de programación visual. Delphi surge como una herramienta de programación adecuada para desarrollar aplicaciones informáticas a nivel del cliente y servidor. El uso de conceptos sobre programación orientada a objetos, más una gran variedad de componentes de manejo de base de datos, determinan que Delphi puede ser fácilmente aprovechado en la Universidad Centro Occidental “Lisandro Alvarado” en los últimos semestres del programa de Ingeniería en Informática. Este trabajo trata de resaltar algunos aspectos de esta herramienta que serian fácilmente aplicables por los alumnos de estos semestres.

Page 7: Tecnicas de Programacion Visual Usando Delphi

Bibliografía

Calver, Charlie. Delphi 4 Unleashed. Sams 1998. Aguilar, Luis Joyanes / Muños Antonio. Borland Delphi, Osborne McGraw Hill 1999 Pacheco, Xavier y Teyseira, Steve. Delphi 4 Develpers’s Guide, Sams 1998 Cantu, Marco. Mastering Delphi 4, Sysbex, 1998 Reisdoph, Kent. Teach Yourself Borland Delphi in 21 Days. Sams, 1998 Swan, Tom. Delphi 4 Bible, IDG Books Worldwide, 1998

Sitios WEB Consultados. Borland Inc. www.borland.com Imprise / Borland Inc. www.imprise.com Delphi Super Page. www.delphi32.com Delphi Developers’s Guide Homepage. www.xapware.com

Page 8: Tecnicas de Programacion Visual Usando Delphi
Page 9: Tecnicas de Programacion Visual Usando Delphi

Contenido

Prof. Mauro J. Hernández D.

1 Fundamentos de Delphi 1

Ambiente de Desarrollo Integrado (IDE) 3 Otros Conceptos 6 Desarrollo de una Aplicación en Delphi 6

2 Primeros Pasos en Delphi 12

Propiedades 12 Eventos 15 Metodología del desarrollo de aplicaciones Delphi 19 Componente TApplication 21 Componente TForm. 22

3 Componentes Básicos 32

Paleta de componentes “Estándar” 32 Paleta de componentes “Adittional” 41

4 Manejo Básico de Base de Datos 46

Objetos de Acceso de Datos (Data Access) 46 Objetos de Control de Datos (Data Controls) 51 Asistente para la Creación de Formularios de Manejo de

Base de Datos 59

Manejo de Tablas Usando Instrucciones SQL 63 Creación y Ejecución de Instrucciones SQL en Tiempo Real 68

5 Manejo Avanzado de Base de Datos 72

Modificación de Registros con SQL 72 Enlaces Dinámicos - Aplicaciones Maestro - Detalle 74 Control de Integridad de Referencia 77 Búsqueda Rápida de Información 86 Uso de Catalogos en Formularios 87 Arquitecturas de Manejo de Base de Datos - Delphi 97

6 Creación de Componentes 100

Creación de Componentes “Delphi” 100 Creación de Componentes “Active-X” 106 Apendices 109

Page 10: Tecnicas de Programacion Visual Usando Delphi
Page 11: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 1

Fundamentos de Delphi.

Delphi es una herramienta de programación perteneciente a la familia de los actualmente llamados ambientes RAD (Desarrollo Rápido de Aplicaciones). Los ambiente RAD modernos poseen la característica que utilizando el ratón, visualmente, se seleccionan objetos que representan componentes utilizados para la comunicación entre el computador y los usuarios intermedios (programadores) o usuarios finales. El ciclo de desarrollo de sistemas por prototipos dinámicos es el que mas se acopla a este tipo de herramientas. Iterativamente se pueden definir una gran cantidad de requerimientos del sistema estando el usuario final presente, y participando durante el proceso. Las ventajas que posee esta tecnología son:

q Participación directa del usuario en el desarrollo del sistema. q Aumento de la motivación del usuario en la futura implantación de un nuevo

sistema. q Disminución de errores de implementación de sistemas q Simplificación del ciclo de desarrollo de sistemas. q Disminución de costos de diseño y desarrollo de sistemas. q Utilización de interfaces GUI. q Incremento de la integridad de los datos manipulados.

Las herramientas RAD también tienen sus desventajas. Entre ellas tenemos las siguientes: q Aumento del uso de recursos de hardware y software. q Aumento de las exigencias en las interfaces de manipulación de datos. q Aumento de la posibilidad de dejar un “prototipo” como el sistema “final”.

Durante la etapa proceso de definición de requerimientos se puede decidir que el prototipo en desarrollo es suficiente para solucionar los problemas existentes, obviando la terminación de las etapas de análisis y diseño adecuado del sistema. El desarrollo de aplicaciones, utilizando Delphi, se simplifica

dramáticamente. Muchos de los detalles de bajo nivel de la programación en Windows que debían ser tomados en cuenta están ocultos en Delphi. Claro esta, esta herramienta no sustituye a un programador, pero minimiza en gran escala la complejidad de la codificación en ambientes orientados a eventos como lo es Windows.

Page 12: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 2

Delphi posee tres características importantes que lo ubican entre las

herramientas de desarrollo de software mas eficientes y efectivos existentes en el mercado actual. Estas características se mencionan a continuación:

1. Flujo de Control Orientado a Eventos. Las acciones del usuario, otros

programas o el sistema operativo determinan las acciones a ser ejecutadas.

2. Manejo Visual de Objetos. El uso de componentes (objetos) estándares

por medio de técnicas de “Arrastrar y Soltar” facilitan el diseño de interfaces GUI.

3. Programación en el lenguaje Pascal. Las respuestas del sistema a los

eventos se realizan a través del lenguaje Pascal.

Una de las fortalezas mas relevantes de Delphi es la capacidad de desarrollar

aplicaciones de manejo de base de datos con extrema facilidad. Un conjunto de componentes y manejadores nativos de acceso a una gran variedad de manejadores de bases de datos actuales permite la creación rápida de programas para mantener los datos en medios secundarios de almacenamiento. Delphi también puede manipular datos por medio de mecanismos ODBC pero sus manejadores nativos (SQL-Links) son mas eficientes.

Programación en Pascal

Orientado a Eventos

Manejo Visual

Delphi

Page 13: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 3

Ambiente de Desarrollo Integrado (IDE). Delphi provee al usuario de un conjunto de ventanas que conforman el

ambiente de desarrollo integrado. Cada ventana realiza un grupo de funciones especificas que facilitan el diseño, ejecución y depuración de aplicaciones en Windows . El IDE (integrated development environment) esta constituido por tres partes. El siguiente gráfico muestra como se despliegan estas tres partes (ventanas) cuando se ejecuta Delphi.

Ventana Principal. Contiene tres áreas: ü Menú de Opciones ü Botones Rápidos. ü Paleta de Componentes

Ventana del Inspector de Objetos. Ventana de Area de Trabajo. (Editor de Formas o Editor de Código).

Page 14: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 4

1. Ventana Principal de Delphi: Esta ventana se encuentra dividida en tres áreas: Ø Menú Principal de Opciones: Permite realizar tanto operaciones

generales de Delphi como también especificas del proyecto (programa) que se este desarrollando en un momento determinado. En el Apéndice A se encuentra un breve descripción de cada uno de los elementos de este menú.

Ø Botones Rápidos: Estos botones se encuentran ubicados en la parte

izquierda de la venta. Las operaciones que realizan son equivalentes a las opciones del Menú Principal con la diferencia que es mas fácil usuarlos (acceso directo). Este panel de botones puede ser configurado y personalizado por el usuario a su conveniencia (presionando el botón derecho del ratón cuando el cursor esta sobre el panel). El siguiente gráfico muestra la función de cada botón rápido en Delphi 3. En Delphi 4 se presentan los mismos botones pero organizados de una manera diferente.

Abrir archivo

Abrir proyecto

Guardar archivo

Remover Archivo

Cambiar Formulario / Unidad

Nuevo Formulario

Depurar detalle

Guardar Todo

Añadir Formulario y/o Unidad

Seleccionar Unidad

Seleccionar Formulario

Ejecutar programa

Suspender ejecución

Depurar general

Page 15: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 5

Ø Paleta de Componentes: Todos los componentes que se pueden utilizar en un programa se encuentran en esta paleta. Los componentes están agrupados en diferentes carpetas. Por ejemplo, al hacer click en la pestaña llamada “Data Controls” se muestra la carpeta que posee los componentes utilizados para manipulación de campos de tablas de base de datos (ver siguiente figura). Muchos de estos componentes son explicados mas adelante.

Nota: Un componente se convierte en un objeto cuando se utiliza. Por ejemplo, cuando el componente “TLabel” (etiqueta) se selecciona de la pestaña “Standard” y se suelta en un formulario (Ventana de Area de Trabajo), este se convierte en la ocurrencia de un componente, o sea un objeto con características (nombre, posición, color, etc.) propias.

2. Ventana del Inspector de Objetos. El Inspector de Objetos muestran las

propiedades y eventos relacionados con el objeto actualmente seleccionado. Las características de un objeto se le denominan “propiedades” y acciones a las cuales puede responder el objeto se llaman "“eventos". En el gráfico anteriormente mostrado se despliegan las propiedades del objeto “Form1” (formulario). Al presionar la pestaña “Events” se presentaran todos los posibles eventos a los cuales puede reaccionar el objeto “Form1”. El Inspector de Objetos se puede invocar rápidamente presionando la tecla de función F11 cuando se encuentra seleccionado un objeto.

3. Ventana de Area de Trabajo. Para crear o cambiar un formulario se utiliza el

Area de Trabajo. En esta área se puede presentar tanto el Editor de Formularios para cambiar formularios como también el Editor de Código para cambiar los programas en Pascal que interactuan con el formulario (por ejemplo, definición de eventos). Utilizando el botón rápido podemos cambiar de un editor a otro (formulario / unidad). El usuario puede abrir varias ventanas del Editor de Código seleccionando del menú “View” la opción “New Edit Window”. Esta opción es útil cuando queremos estar viendo (o editando) simultáneamente diferentes segmentos de una misma unidad o diferentes unidades.

Page 16: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 6

Otros Conceptos

El ambiente de desarrollo integrado (IDE) de Delphi permite crear aplicaciones en Windows rápidamente. Antes de desarrollar nuestra primera aplicación es importante establecer o recordar varios conceptos:

Ø En el mundo de las herramientas visuales existe siempre un formulario como el

máximo contenedor de objetos. Un formulario es también un objeto pero es el mecanismo de mostrar otros objetos al usuario final. La actividad más común en el proceso de escribir programas es seleccionar componentes, arrastrarlos y soltarlos en un formulario.

Ø Un objeto es la ocurrencia de un componente. Ø Un Objeto posee tres aspectos importantes: § Propiedades: Características propias del objeto, por ejemplo; nombre,

contenido, posición en el formulario, color, fuente, etc.. Estas propiedades varían dependiendo del tipo de objeto. El tipo de objeto se le denomina “Clase”.

§ Eventos: Reacción de un objeto a un estimulo externo. Estos eventos varían dependiendo de la clase del objeto.

§ Métodos: Procedimientos o funciones que pueden modificar las propiedades del objeto o permiten la comunicación con el usuario o sistema operativo. Estos métodos varían dependiendo de la clase (tipo) del objeto.

Ø La programación en la mayoría de las herramientas visuales actuales no siguen

un flujo de control predeterminado. Las acciones de un programa son determinadas por respuesta a eventos generados por el usuario. La forma de diseñar programas cambia dramáticamente. Se deben tomar en cuenta un mayor numero de alternativas de respuesta al usuario o al sistema operativo.

Ø Ninguna herramienta de programación va a realizar todo el trabajo del

programador. Muchas de las tareas se simplifican pero el programador sigue siendo determinante en el desarrollo satisfactorio de la aplicación.

Ø Cada formulario tiene su correspondiente unidad (modulo) de programa en

Pascal que define sus componentes y eventos.

Page 17: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 7

Ø Los siguientes gráficos muestran un formulario (Form1) con dos objetos, un panel y una etiqueta en color rojo y la estructura de la unidad (unit1.pas) en Delphi correspondiente a este formulario. Los comentarios sobre la estructura de la unidad están en color azul. Una unidad en Delphi consiste en dos grandes áreas: La sección de Inteface y la de Implementación. Los objetos (componentes) que se arrastran a un formulario son automáticamente declaradas por Delphi en su respectiva unidad. Al crear un formulario, opción “File - New Form”, Delphi crea un archivo de pascal (la unidad con todas las declaraciones básicas) y un archivo con terminación .DFM (el formulario) automáticamente.

Page 18: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 8

Desarrollo de una Aplicación en Delphi. La gran mayoría de aplicaciones en Windows consiste en uno o varios

formularios. En este caso vamos a crear un programa con un formulario que posea un botón y muestre un mensaje al ser este botón pulsado con el ratón. Los pasos serian los siguientes:

1. Tomar la opción “File – New Application”. Delphi. Creara una aplicación con

un formulario en blanco con su respectiva unidad. En este momento ya se tiene un programa completo pero con posibilidades muy limitadas de interacción con el usuario. Si usted compila y ejecuta este programa (botón rápido ), se mostrara un formulario en blanco.

Nota: Si se guarda esta aplicación (botón rápido ), Delphi crea, entre otros, los siguientes archivos : § Unit1.PAS. Unidad en Pascal con las definiciones del formulario. § Unit1.DFM. Definición gráfica del formulario (Delphi Form Module). § Proyect1.DPR. Proyecto o programa principal de la aplicación. Una

aplicación en Delphi posee un solo archivo .DPR y uno o varios .DFM con sus respectivos archivos .PAS.

§ Proyect1.RES. Archivo de recursos del proyecto. En un archivo de recursos se puede almacenar el icono del programa, cursores, imágenes bitmaps, lista de strings, etc.

Los nombres de los archivos se pueden cambiar en el momento de guardar el proyecto. La nueva aplicación tendría el aspecto mostrado en el gráfico de la derecha. Note que se presentan el Editor de Formularios y el Editor de Código junto a las propiedades del objeto seleccionado, en este caso el formulario.

Page 19: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 9

2. Un objeto tiene asociado una variedad de propiedades (características) y eventos a los que puede, opcionalmente, reaccionar. Según el gráfico anterior, el Inspector de Objetos muestra las propiedades del objeto seleccionado, el formulario. Vamos a cambiar la propiedad “Caption” que representa el titulo del formulario. Por defecto, cuando se crea un formulario, el titulo del formulario es el nombre del objeto. Utilizando el ratón se selecciona la propiedad “Caption” y se escribe un nuevo titulo, en este caso “Formulario Uno”. Si no se encuentra el Inspector de Objetos desplegado en pantalla, se puede abrir pulsando la tecla F11 después de seleccionar el formulario. El siguiente gráfico muestra el resultado de este cambio:

3. El siguiente paso consiste en colocar un botón en el formulario.

Seleccione de la Paleta de Componentes la pestaña “Standard”. En esta hoja de la paleta se encuentran agrupados los componentes mas comunes de una aplicación en Windows. Usando el ratón, seleccione el componente de botón que se encuentra en esta hoja y arrástrelo al formulario. Al soltar este componente, Delphi crea un objeto de clase TButton en el formulario. Este objeto tiene sus propios atributos y eventos a los cuales puede reaccionar. El siguiente gráfico muestra el resultado de esta operación.

Page 20: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 10

Note que el Editor de Código refleja la declaración del nuevo objeto en la definición del formulario.

4. Uno de los eventos mas comunes de los componente es “OnClick”. Este

evento define la respuesta de un componente a la acción de pulsar un botón del ratón cuando el cursor se encuentra sobre el mismo. Podemos crear un evento de este tipo al objeto botón siguiendo los siguientes pasos: § Seleccione con el ratón el objeto botón. § Presione la tecla F11 para mostrar el Inspector de

Objetos. § Seleccione la pestaña “Events” del Inspector de

Objetos. Todos los posibles eventos relacionados con esta clase de componente se mostraran.

Arrastrar y Soltar

Definición del formulario y botón

Page 21: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 11

§ Presione el botón derecho del ratón dos veces (“doble click”) sobre el evento “OnClick”.

§ La ventana del Editor de Código se desplegara en pantalla mostrando la estructura vacía de un procedimiento en Pascal (ver siguiente gráfico).

§ Entre las líneas de “Begin” y “End” se escribe la siguiente línea de código: “ShowMessage(‘Hola desde el mundo Delphi’)”. Esta línea de código mostrara en pantalla la línea de texto que recibe como parámetro el procedimiento ShowMessage.

Page 22: Tecnicas de Programacion Visual Usando Delphi

Fundamentos de Delphi. 12

5. El programa esta listo para ser ejecutado. Pulse el botón para compilar y ejecutar el programa. Usando el ratón, presione el botón “Buton1” que se encuentra en el formulario y se mostrara el mensaje “Hola desde el mundo Delphi”.

Nota: El titulo de este botón se puede cambiar modificando la

propiedad “Caption” del objeto.

Page 23: Tecnicas de Programacion Visual Usando Delphi
Page 24: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 12

En este capítulo profundizaremos en el conocimiento de las propiedades y eventos resaltando aquellos que más comúnmente utilizaremos en nuestras aplicaciones, hablaremos de la metodología de trabajo y veremos en profundidad el componente principal de cualquier aplicación en Delphi, el formulario o TForm.

Propiedades

El concepto de propiedad ya ha sido tratado en temas precedentes y puede entenderse como una tributo del objeto al que pertenece, es decir, es como una variable que contiene un dato que hace referencia a alguna característica que define el aspecto o funcionamiento del objeto, con la peculiaridad de que al acceder a una propiedad o cambiar su valor podemos estar provocando la ejecución de algún método de forma indirecta. Como también sabemos, la manipulación y uso de las propiedades de los componentes y objetos suministrados por Delphi es una de las bases en el desarrollo aplicaciones con este entorno y por ello un buen conocimiento de las mismas nos permitirá obtener un mayor rendimiento de esta herramienta, facilitando enormemente todas las tareas del programador. Existen diversos tipos de propiedades, cada una de las cuales tiene su propio mecanismo para su edición y manipulación en tiempo de diseño a la vez que nos determinara el mecanismo de acceso y las operaciones posibles a realizar en tiempo de ejecución. Cabe mencionar que hay propiedades que sólo son accesibles en tiempo de diseño o ejecución, o bien son de sólo lectura o sólo escritura. Todos los componentes suministrados por Delphi disponen de una serie de propiedades, cada una de las cuales pueden estar presente en todos ellos, ser específicas de un grupo o incluso particulares. En este apartado se presenta un conjunto de propiedades que están incluidas en la mayoría de los componentes y cuyo valor que es generalmente modificado directa o indirectamente para ajustar el control a nuestras necesidades de diseño. Nombre, posición y tamaño. Todo componente incluido en un formulario de nuestros proyectos debe detener un nombre único que se establece mediante su propiedad Name, por defecto su valor está constituido por una concatenación del nombre del control y un número indica el orden en el que hemos incluido ese control o componente

Page 25: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 13

en el formulario en relación con los componentes de su misma clase; así, en el caso que hayamos insertado dos controles de la clase TLabel (etiqueta), sus propiedades Name tendrán como valor por defecto Label1 y Label2 respectivamente. No obstante, el valor de la propiedad Name suele ser lo primero que modifiquemos, de forma que el nombre del componente sea más intuitivo que el asignado automáticamente. Esta operación sólo se puede realizar en tiempo de diseño, asignando el nuevo identificador a través del inspector de objetos. Otra de las primeras cosas que habitualmente haremos al incluir un nuevo componente en un formulario es definir su posición y tamaño. Estas características vienen determinadas por las siguientes propiedades. Top y Left nos determinan la posición de la esquina superior izquierdo, es decir, la altura y el margen izquierdo en que se encuentra el componente en el formulario. Width y Height nos determinan, respectivamente, el ancho y el alto del componente, es decir, su tamaño.

Nota: Los valores de estas cuatro propiedades pueden ser modificados tanto en tiempo de diseño como de ejecución, en el primer caso podremos cambiar sus valores través del inspector de objetos o bien seleccionándolos y redimencionando el control por medio del ratón, mientras que en ejecución basta, con asignar un nuevo valor a estas propiedades. Aspecto Existe un conjunto de propiedades que determinan el aspecto general de la presentación visual de los componentes dentro de una aplicación, por lo tanto y como es lógico, estas propiedades sólo tienen sentido en componentes visuales.

El borde de un componente se establece mediante su propiedad BorderStyle, la cual básicamente puede tomar dos valores BsNone o BsSingle, indicando la presencia o no de un borde negro en el componente, aunque en el caso de los formularios esta propiedad admite un conjunto de valores posibles mucho más amplio. Una propiedad que complementa a la anterior es Ctrl3D y qué contiene un valor booleano para indicar si se le da un aspecto tridimensional al borde del control. Para establecer el color de los controles usaremos generalmente la propiedad Color, que admite un amplio conjunto de posibles valores en forma de constantes con la codificación del color en formato RGB mediante seis dígitos hexadecimales, los cuales expresan en grupos de dos dígitos la intensidad en rojo, verde y azul del color,

Page 26: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 14

respectivamente. Cuando lo que deseamos es definir las características del tipo de letra a usar contamos con la propiedad Font que es un objeto de tipo TFont que cuentan con sus propias propiedades y es donde se almacena realmente la información para determinar el tipo de letra. Un objeto de tipo TFont usa su propiedad Name para definir el nombre de la Fuente, Size, para el tamaño, Color, para el color y Style para determinar atributos como negritas o cursiva. Herencia de propiedades. Mediante las propiedades ParentColor, ParentFont y ParentCtrl3D que admiten los valores True o False podemos conseguir que un control adopte automáticamente los valores de las propiedades Color, Font y Ctrl3D del componente que lo contiene, para lo cual bastará con asignar el valor True a cada una de las propiedades mencionadas. Si usted modifica con posterioridad el valor de Color, Font o Ctrl3D del componente, la propiedad asociada tomara automáticamente el valor False y la herencia dejará de tener efecto. Drag & Drop (Arrastrar y Soltar). Para controlar las operaciones de arrastrar y soltar disponemos de dos propiedades. Así, DragMode determina el mecanismo para iniciar la operación, si su valor es dmManual será necesario realizar una llamada al método BeginDrag para iniciar el arrastre, mientras que si es dmAutomatic la operación comenzará automáticamente al pulsar el botón izquierdo del ratón. La otra propiedad es DragCursor y nos sirve para determinar la forma del puntero del ratón mientras se realiza la operación de arrastre, siendo sus valores posibles los puntero definidos en el sistema. Desplazamiento entre los componentes de una ventana. Una ventana de nuestra aplicación contendrá generalmente varios componentes. Para pasar el foco de un control a otro, es decir cambiar el control que está activo, podemos usar la tecla <TAB>. El orden en que se irá pasando el control será por defecto el orden de introducción de los componentes en el formulario pero podemos cambiarlo a través de la propiedad TabOrder que contiene un número de 0 a n-1 (siendo “n” el numero de componentes presente) que indica el orden de activación del control. También podemos presionar el botón derecho del ratón, un menú emergente mostrara varias opciones dónde se encuentra la opción "Tab Order". Por medio

Page 27: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 15

de esta opción y utilizando el ratón es posible cambiar fácilmente el orden preestablecido, y por ende el contenido de la propiedad TabOrder. Para activar la capacidad de transferir el foco aún control y que por lo tanto tenga relevancia el valor de dicho control se tiene una propiedad llamada TabStop. En momento de ejecución podemos invocar el método "SetFocus". Por ejemplo; si tenemos un componente llamado Boton_Inicio, para transferir el foco a este componente escribiremos la siguiente instrucción: “Boton_Inicio.SetFocus”. Otras propiedades generales. Es posible crear menús desplegables (emergentes) y asociados a diversos controles en un formulario. Esta característica se activa a través de la propiedad PopUpMenu de los componentes, en donde indicaremos el nombre del menú que deseamos asociar. Otra de las propiedades que nos encontraremos generalmente en los componentes de un formulario es en el Cursor que indicará el tipo de puntero que deseamos que aparezca en pantalla al mover el ratón sobre dicho control. La propiedad Tag, que no tiene ningún significado específico y estará a nuestra disposición para poder asignarle un valor numérico que nos puede servir para guardar cierta información sobre el control o como señal para realizar una acción determinada.

Eventos.

Un evento es una señal que puede ser interna o externa a nuestra aplicación y que es detectada por esta última, pudiendo aprovechar esta circunstancia para provocar la ejecución desierto código asociado, al que se le denomina usualmente "Manejador de Eventos". Como ya hemos mencionado anteriormente, la realización de aplicaciones en Delphi se basa en asociar fragmentos del código a la ocurrencia de determinados eventos, es decir, crear manejadores de eventos, de forma que cuando se produzca uno de ellos se inicia la ejecución del código que tenga asociado y no realizando ninguna acción si ocurre un evento para el cual no hemos definido ningún bloque de código. Lo importante que usted tiene que darse cuenta es cuando se realiza una aplicación en Delphi, el flujo ejecución del código no es secuencial sino que dependerá de los segmentos concretos durante cada ejecución de la aplicación, no obstante y como es lógico y mientras más crece el tamaño de nuestra aplicación, también será

Page 28: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 16

necesario escribir cierto código que realice determinadas funciones más complejas y que no entren en conflictos con las ya existentes. Todos los componentes tienen definido un evento por defecto que es el que más usa dicho componente. Una vez incluido el componente en el formulario bastará con hacer doble-click sobre dicho componente para crear un acceso al manejador de este evento por defecto, teniendo que usar el Inspector de Objetos para realizar la misma función con el resto de los eventos que tenga disponible el componente. El Inspector de Objetos es desplegado presionando la tecla F11. Es importante señalar que los procedimientos asociados a un evento reciben una serie de parámetros, a través de los cuales obtenemos información que nos puede ser útil para gestionar satisfactoriamente la respuesta a dicho evento. Eventos generales del ratón. En los entornos visuales como Windows uno de los dispositivos más usados para interactuar con cualquier aplicación es el ratón y será generalmente los eventos asociados con este dispositivo los que más usemos en nuestras aplicaciones. En Delphi podremos encontrar los siguientes eventos generados por el ratón: OnMouseDown(Sender : TObjet;Button : TMouseButton; Shift : TShiftState; X,Y : Integer). Se genera cuando se pulsar cualquiera de los botones del ratón y lo recibe el componente sobre el cual está el foco en dicho momento. OnMouseUp(Sender : TObjet;Button : TMouseButton; Shift : TShiftState; X,Y : Integer). Se genera al liberar cualquiera de los botones del ratón y al igual que en el caso anterior lo recibe el componente que esté activado en ese momento . OnMouseMove(Sender : TObjet; Shift : TShiftState; X,Y : Integer). Es recibido por un componente a medida que el cursor se desplaza en su interior. El significado de los parámetros que utilizan estos eventos son los siguientes: Sender: Este parámetro lo podremos encontrar en casi todos los procedimientos que gestionan un evento y se corresponde con el objeto que ha

Page 29: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 17

detectado la ocurrencia del mismo, en este caso en concreto hará referencia al componente que ha detectado la acción del ratón. Button: este parámetro nos indica que botón se ha visto involucrado en la acción y puede tomar los valores mbLeft, mbMiddle o mbRight, indicando que ha sido el botón izquierdo, central o derecho que sea presionado. Shift: este parámetro nos indica el estado de diversas teclas que son de uso habitual con el ratón y los botones del mismo, puede tener los siguientes valores :

• ssShift: La tecla Shift esta presionada. • ssAlt: La tecla Alt esta presionada. • ssRight: El botón derecho del ratón esta presionado. • ssLeft: El botón izquierdo del ratón esta presionado. • ssMiddle: El botón del centro del ratón esta presionado. • ssDouble: El botón izquierdo y derecho del ratón están presionados

simultáneamente. X y Y: Estos dos parámetros nos suministran la posición del puntero del ratón en el momento de producirse el evento.

Aunque los eventos vistos hasta ahora puedan resultar interesantes en determinadas ocasiones los que también normalmente utilizamos en nuestras aplicaciones bajo Windows son los siguientes: OnClick(Sender:TObject): este evento no esta asociado únicamente a la acción del ratón pero sin embargo, es con este dispositivo con el que lo usaremos generalmente, indicando que se ha producido una pulsación del botón del ratón sobre el componente. Las otras circunstancias que produce este evento son la pulsación de la barra espaciadora, la tecla <Enter> o la tecla <Escape>. Cabe destacar que además del parámetro Sender ya conocido, en diversos componentes, el evento OnClick tendrá asociado parámetros adicionales para poder realizar una completa gestión del mismo. OnDblClick(Sender:TObject): Este evento es recibido por un componente cuando se realiza una doble pulsación del botón izquierdo del ratón estando el curso sobre el mismo.

Page 30: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 18

Eventos generales del teclado.

Aunque su uso es mucho menos habitual que el de eventos generados por el ratón, Delphi nos proporciona tres eventos que nos servirán para interceptar las pulsaciones de las teclas. Estos tres eventos son: OnKeyPress(Sender:TObject; var Key : Char): Este evento se produce cuando se pulsa una de las teclas de caracteres o numéricas, excluyendo las de función o edición. A través del parámetro Key se recibe el código ASCII de la tecla pulsada. OnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState): Este evento se produce al pulsar cualquiera de las teclas del teclado incluyendo en este caso todas las del función y edición. El valor del parámetro Key nos sigue identificando la tecla pulsada, que viene codificada mediante los valores de las teclas virtuales de Windows, el parámetro Shift de nuevo nos indica si hay otras teclas (Shift o Alt) simultáneamente en pulsadas. OnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState): Este evento se produce cuando se suelta una tecla que previamente había sido pulsada, sus parámetros son semejantes al evento anterior. Eventos en de arrastrar y soltar (Drag & Drop).

Otros de los eventos que con más frecuencia podremos encontrar en los diversos componentes están relacionados con las operaciones de arrastrar y soltar en Windows. OnDragDrop(Sender, Source : TObjet; X,Y Integer): Esté evento se produce cuando un objeto que está siendo arrastrado se suelta sobre el componente que recibe el evento. El parámetro Sender hace referencia al componente que recibe el evento mientras que Source hace lo propio con el objeto sobre el que se realiza la operación de arrastre. Por su parte, los parámetros X e Y nos proporcionan la posición donde el objeto fue soltado . OnDragOver(Sender, Source : TObjet; X,Y Integer; State: TDragState; var Accept : Boolean): este evento se produce a medida que desplazamos un objeto en una operación de arrastre sobre el componente. Los parámetros Sender, Source, X e Y tienen el mismo significado que en el evento anterior, incluyendo

Page 31: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 19

adicionalmente los parámetros State para obtener información acerca del estado de la operación y Accept con el que indicaremos si el objeto puede o no ser soltado sobre componente que recibe el evento. Los valores posibles del parámetro State son los siguientes :

• dsDragEnter: Se acaba de entrar en el componente que recibe el evento. • dsDragMove: Se esta moviendo por el interior del componente. • dsDragLeave: Se acaba de producir la salida del componente.

Metodología del desarrollo de aplicaciones en Delphi.

Cuando deseamos crear una aplicación, lo primero que debemos hacer es crear un nuevo proyecto, cosa que ocurre por defecto cuando iniciamos una nueva sesión con Delphi o mediante la opción "New Application" del menú "File", en caso de que se deseamos realizar la operación (crear una nueva aplicación) con posterioridad al inicio del sistema. Lo normal en este momento es que usted ya tenga preparado un directorio dónde almacenar posteriormente todos los archivos involucrados en el proyecto., si bien, es posible que dichos archivos estén ubicados en diferentes directorio, lo que conlleva un mantenimiento más complejo de la aplicación. Como podrá observar, inmediatamente después de iniciar Delphi, un nuevo proyecto se crea y aparece una ventana de Windows con el nombre de Form1, esta ventana es un formulario o, como se conoce bien en Delphi, un componente TForm, el cual estudiaremos a continuación. Esta será la ventana que usaremos en nuestra aplicación para comunicarse con el usuario y constituye la base sobre la que crearemos la interfaz con el usuario. Para establecer la comunicación con el usuario insertaremos los componentes adecuados en este formulario, realizando las oportunas modificaciones en sus propiedades, de forma que se adecue a nuestras necesidades. Analicemos más detenidamente este punto. Al proceso de inclusión de componentes en un formulario y la personalización de todos los elementos para que se ajuste a nuestras aplicaciones se le denomina "etapa de diseño". Este proceso puede empezar con las oportunas modificaciones de las propiedades del formulario, y hecho esto, debemos ir eligiendo de entre todos los componentes disponibles aquellos que más se adecuen a nuestras necesidades, de ahí la importancia de su conocimiento, e irlos insertan en el formulario con la consiguiente modificación de las propiedades necesarias en cada uno de ellos. Para insertar un componente en el formulario bastará con hacer doble-click sobre la paleta de

Page 32: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 20

componentes, o pulsar sobre él para seleccionarlo y posteriormente realizar una segunda pulsación sobre la posición del formulario en donde queremos insertarlo. Una vez que el componente se encuentra en el formulario podemos desplazarlo, por medio del ratón, sobre la superficie o área de trabajo del formulario. También podemos redimensionarlo, borrarlo o copiarlo al porta papeles, de la misma forma como se realizan todas las operaciones en las aplicaciones bajo Windows. Si queremos insertar múltiples instancias de un mismo componente, una forma muy cómoda de hacerlo es añadir el primero de ellos al formulario, modificar las propiedades comunes, seleccionarlo y copiarlo al portar papeles, y por último pegarlo en el formulario, tantas veces como instancias queramos, ahora sólo tendremos que modificar las propiedades que sean diferentes entre ellos. Existen dos tipos diferentes componentes que podemos insertar en un formulario. Un componente puede ser visible para el usuario o también visible en el momento de diseño pero no para el usuario en momento de ejecución. Un componente no visible, por ejemplo, es la definición de un archivo o tabla de base de datos. Podemos incluir los componentes no visuales en un módulo de datos en lugar de hacerlo en el formulario. Más adelante hablaremos en detalle sobre los módulos de datos. El siguiente paso es detectar o definir los diversos eventos a los que tendrá que responder nuestra aplicación y asociarles las líneas fuentes de código que realicen las operaciones deseadas cuando cada uno de los eventos se produzcan. La ventana llamada inspector de objetos se utiliza para cambiar las propiedades de los componentes y asignar las respuestas a los eventos. Una vez que hemos definido la interfaz de nuestra aplicación a través de la inserción de componentes en la ficha o formulario con la oportuna modificación de sus propiedades y haber escrito el código asociado a los eventos elegidos, estamos en disposición de pasar a la etapa de prueba y depuración de nuestra aplicación. Para ello ejecutaremos el programa sucesivas veces, a través de las opciones del menú "Run" o con los botones rápidos que para ello se encuentran en la barra de acceso rápido, hasta conseguir los resultados deseados. Para la localización de errores en el programa podemos hacer uso del Debugger (depurador), que nos permitirá ver el valor de las variables y las propiedades en tiempo de ejecución, establecer puntos de ruptura, ejecución paso a paso, etc. Una vez que hayamos corregido todos los errores, crearemos el archivo ejecutable de la aplicación con las opciones "Compile" y "Build" del menú "Proyect". Para guardar la información referente a cualquiera de nuestras aplicaciones podemos distinguir tres archivos distintos. El punto central lo

Page 33: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 21

constituye el archivo del proyecto donde se guarda la información del resto de archivos usados y desde donde se iniciará la aplicación; el contenido de este archivo es generado automáticamente por Delphi el cual le asigna por defecto la extensión DPR. Cuando compilemos el proyecto para crear el archivo ejecutable o un archivo de enlace dinámico (DLL), el nombre de este último se tomará del archivo de proyecto cambiando la extensión a EXE o DLL respectivamente. Por otro lado, cada formulario de nuestra aplicación dará lugar a un archivo con extensión .PAS al que denominaremos módulo de formulario, que contiene la definición de todos los objetos contenidos en ella y los manejadores de sucesos que hayamos definido, siendo el propio Delphi el que incorpora todas las definiciones, mientras que nosotros sólo tendremos que escribir el código de respuesta. Los valores correspondientes a las propiedades del formulario y todos los componentes que contengan se almacenan en un archivo con el mismo nombre que el módulo de formulario pero con extensión .DFM y que a diferencia del resto de archivos vistos hasta ahora, que están en formato de texto ASCII, contiene información binaria que no es legible directamente, aunque sí podremos ver su contenido en el editor de formularios de Delphi. Por cada formulario incluido en nuestra aplicación nos encontramos con este tipo de archivos para guardar su información. Además de estos archivos básicos podemos incluir en nuestro proyecto módulos independientes de los formularios que contengan procedimientos funciones, es decir, UNIT, siendo su extensión PAS si no está compilado, DCU en caso contrario. Por último nos encontramos con un archivo recursos donde se guardan los gráficos, cursores, iconos, etc. usados por nuestra aplicación y cuya extensión es RES.

El componente TApplication. Todas las aplicaciones desarrolladas en Delphi utilizan un componente TApplication el cual será creado automáticamente al ejecutar el programa. Generalmente no será necesario trabajar directamente con este objeto, sin embargo usted debe saber que cuenta con una serie de propiedades para almacenar información generalmente sobre la aplicación, métodos y eventos que nos permitirán realizar operaciones sobre la misma. Entre las propiedades que posee este componente podemos resaltar la propiedad "Active" que contiene un valor booleano que indica si la aplicación está activa o no, ExeName para almacenar el nombre del programa ejecutable, Icon y Title

Page 34: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 22

contienen respectivamente el icono y el título que presentará la aplicación cuando esté minimizada. Todos estos parámetros son configurables en tiempo de diseño a través de las opciones del proyecto. Entre los métodos más interesantes podemos mencionar Create, RUN, Terminate y Destroy para crear la variable o componente del tipo TApplication, ejecutar la aplicación, terminar la aplicación y destruir el objeto TApplication respectivamente. Tenga en cuenta que normalmente y de forma inadvertida por el usuario sera el propio Delphi el que realice estas llamadas a estos metodos cuando sea oportuno . Existen muchas otras propiedades, métodos y eventos asociados a un objeto del tipo TApplicaction, sin embargo y como ya hemos mencionado, normalmente no será necesario su uso, por ello tenga presente que lo que se pretendía en este apartado es que usted conozca su existencia y no dar una información exhaustiva del mismo; si desea más información sobre este objeto puede acudir a la ayuda en línea de Delphi o consultar con otros manuales que profundiza en más sobre el tema .

El componente TForm. El control (componente) TForm, también denominado comúnmente formulario o ficha, constituye el centro de cualquier aplicación desarrollada en Delphi y cuenta con una serie de características especiales que lo distingue del resto de componentes. Este control representa las ventanas de nuestro programa mediante las cuales se permite la interacción con el usuario y cuenta con múltiples propiedades, eventos y métodos asociados, sin embargo, por lo que realmente se caracteriza es por su capacidad para contener otros controles en su interior, siendo esta propiedad la que le dota de importancia y funcionalidad, aunque como veremos posteriormente existen otros componentes que también tienen esta característica. Propiedades generales de uso común (TForm). A través de la propiedad Name le asignamos el identificador válido (nombre) con el que se conocerá al componente en nuestra aplicación, siendo sólo modificacable en tiempo de diseño. Con la propiedad Caption podemos indicar el título del formulario, el cual, y como se puede apreciar en el aspecto general del mismo, está situado en la barra superior de la misma, pudiendo

Page 35: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 23

variar el valor de esta propiedad tanto en tiempo de diseño como en tiempo de ejecución. Ver lado derecho de la siguiente pagina. Mediante las propiedades Enable y Visible que admiten como valores posibles True y False, se establecen si el formulario estará activo y visible respectivamente. El valor por defecto de estas propiedades es True y debe tener en cuenta que si la propiedad Enable tiene como valor False el formulario y todos los componentes que contenga no podrán recibir ningún evento, así mismo si la propiedad Visible tiene el valor False el formulario permanecerá oculto. Cuando no es posible la visualización completa de todos los controles incluidos en un formulario, debido por ejemplo al tamaño de mismo, aparecerán por defecto unas barras de desplazamiento que nos permitirán movernos por la superficie del formulario y poder manipular los otros componentes o controles que se encuentren depositados en el mismo. Esto es debido a que por defecto la propiedad (del formulario) AutoScroll tiene el valor True, si por el contrario usted no desea que la aparición y desaparición de las barras de scroll sean gestionadas de forma automática, deberá asignar el valor False a dicha propiedad. Las características de la barra de desplazamiento horizontal y vertical están definidas en las propiedades HorzScrollBar y VertScrollBar respectivamente, ambas se corresponden con un objeto de tipo TControlScrollBar que dispone de las propiedades necesarias para definir dichas barras de

Page 36: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 24

desplazamiento, entre las que cabe destacar la propiedad Visible a la que tendremos que asignar los valores True o False para mostrar u ocultar las barras en el caso de que hayamos dado el valor False a la propiedad AutoScroll. Propiedades para la posición y dimensiones del formulario (TForm). Para situar el formulario en una posición de la pantalla ursaremos las propiedades Top y Left a través de las cuales indicaremos las coordenadas de la esquina superior izquierda. El valor de estas propiedades en tiempo de diseño pueden modificarse a través del inspector de objetos o simplemente desplazando el formulario mediante el uso del ratón. Es importante mencionar que estas propiedades hacen referencia a las coordenadas globales de la pantalla, mientras que en el resto de los componentes hacen referencia a posiciones relativas del objeto que las contiene. Cuando se ejecuta una aplicación, el formulario aparecerá en la misma posición y dimensiones que tenía en tiempo de diseño a no ser que le indicamos lo contrario mediante la propiedad Position, la cual puede tomar uno de los siguientes valores: • poDesigned: El formulario aparecera en la misma posicion y tamaño que en

tiempo de diseño. • poDefault: En cada ejecucion se varia la posicion y tamaño del formulario. • poDefaultPostOnly: La posicion del formulario varia en cada ejecucion pero

su tamaño permanece fijo. • PoDefaultSizeOnly: El tamaño del formulario varia en cada ejecucion pero

se mantiene su posicion. • poScreenCenter: El formulario aparecera en el centro de la pantalla y con el

tamaño que tenia en tiempo de diseño. Para definir las dimensiones del formulario usaremos sus propiedades Width y Height para indicar la anchura y altura de la misma. Estas propiedades, al igual que Top y Left cambiaran sus valores deforma automática si redimencionamos el formulario mediante el uso del ratón. En el caso particular de los formularios, existen dos propiedades adicionales que son ClientWidth y ClientHeight que nos define la dimensión real de espacio disponible para la inserción de componentes o la visualización de datos, y que obviamente son menores que sus homonimas Width y Height. Para establecer o determinar la superficie caliente del formulario de una sola vez podemos hacer uso de la propiedad ClientRect que corresponde con un objeto tipo

Page 37: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 25

TRect en el que los dos primeros puntos nos determinan la esquina superior izquierda y los dos segundos corresponden con las propiedades ClientWidth y ClientHeight, respectivamente. El tamaño inicial del formulario puede fijarse mediante la propiedad WindowState la cual puede tomar los valores wsNormal, wsMinimize, wsMaximize indicando, respectivamente, que el formulario aparecerá igual que en tiempo de diseño, minimizada o maximizada. no obstante recuerde que usted puede variar el tamaño y posición del formulario en tiempo de ejecución mediante las propiedades Top, Left, Width, Height y WindowState que acabamos de ver. La propiedad Scaled admite como valores posible True y False. Si designamos el primero de ellos conseguiremos que cuando se redimencione el formulario todos los controles contenidos en la misma sufran un escalado en sus dimensiones de forma que se ajusten al nuevo tamaño. La escala se indica en la propiedad PixelperInch, representa el número de puntos a dibujar por pulgada. Propiedades para el aspecto y estilo del formulario (TForm). Como se puede apreciar en un formulario, en la parte superior, existe una barra en la que podemos encontrar de izquierda a derecha los siguientes elementos: un icono, el título de la ventana, y tres botones que nos permiten minimizar, maximizar o cerrar el formulario. en ciertas ocasiones nos puede interesar que alguno de estos botones no esté disponible para su uso por parte del usuario. Para gestionar la presencia de los mismos tenemos la propiedad BorderIcons, que es un conjunto que puede contener los valores biMinimize, biMaximize, biSystemMenu. en tiempo de diseño podemos indicar la presencia ausencia de cada uno de estos elementos desplegando la propiedad BorderIcons y asignando los valores True o False según nos interese, aunque los cambios no serán apreciables hasta que ejecutemos la aplicación, mientras que en tiempo de ejecución deberemos hacer uso de las operaciones sobre conjuntos como “Include” y “Exclude”. Otra propiedad que nos puede resultar muy interesante es BorderStyle, cuyo valor afecta tanto al borde del formulario como la posibilidad de redimensionarla en tiempo de ejecución. Los valores posibles de esta propiedad son los siguientes:

Page 38: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 26

• bsSizeable: Muestra el borde estandar y permite la redimension del formula en tiempo de ejecución (valor por defecto).

• bsSingle: No permite redimensionamiento del formulario y el borde aparece con un grosor mayor.

• bsDialog: no permite redimensionamiento pero no influye en el grosor del borde .

• bsNone: elimina el borde y barra de título de la ventana, no permitiendo redimensionamiento ni desplazamiento por la pantalla.

• bsToolWindow: Idéntico al generado por opción bsSingle pero con una barra de título más pequeña .

• bsSizeToolWin: Idéntico al generado por la opción bsSizeable pero con una barra del título más pequeña .

Con la propiedad Icon, que son objetos de tipo TIcon, podemos asignar un icono diferente al que por defecto muestra la ventana en su borde superior. Mediante la propiedad Cursor se establece el puntero que aparecerá al desplazar el ratón por la superficie del formulario. Con las propiedades Color y Font indicamos el color del fondo del formulario y el tipo de fuente que se usará al escribir sobre el mismo. la propiedad Color, como ya lo mencionamos anteriormente, permite un amplio conjunto de valores definidos como constantes. Otras propiedades de los formularios (TForm). La propiedad Active contiene un valor booleano que nos indica si la ventana del formulario está activa o no activa, mientras que con la propiedad ActiveControl indicaremos cual es el componente que tomará el foco inicialmente al desplegarse el formulario, siendo éste por efecto el primer componente que incluyamos en el formulario. La propiedad Canvas sólo está disponible en tiempo de ejecución y se corresponde con la superficie del formulario sobre la que nos es posible escribir, dibujar, etc. Asociada de alguna forma con el Canvas del formulario nos encontramos con su propiedad Brush su propiedad que nos permite definir el relleno del área.

En tiempo de ejecución podemos usar la propiedad ComponentCount podemos usar la propiedad para determinar el número de componentes incluidos en el fórmulario, Estando estos últimos almacenados en la propiedad Components esta propiedad es una matriz de componentes. Mediante las

Page 39: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 27

propiedades ComponentIndex y ComponentState podremos determinar el índice en la matriz Components y el estado del componente que tiene el foco. Si por contrario estamos interesados en la gestión de los controles visuales usaremos el conjunto de cuatro propiedades equivalentes, las cuales se identifican por los nombres ControlCount, Controls, ControlIndex y ControlState.

También existe la propiedad PrintScale que determina La escala en que se imprimía El formulario usando el método Print. La propiedad KeyPreview Que permitirá que el formulario interesen las pulsaciones de las teclas, Si le

le asignanos el valor True.

Tipos Generales de Formularios. Existen dos tipos básicos de formularios. El primero se corresponde a las ventanas comunes de captura o manipulación de datos, el segundo es un tipo especial de formulario utilizado por Delphi llamado módulo de datos. Este tipo especial de formularios tiene como finalidad el agrupar componentes no visuales, por lo tanto este formulario no es tampoco visible para el usuario en momento de ejecución. Uno proyectos puede tener un gran número de formularios comunes y formularios de módulos de datos. En proyectos de mediano tamaño cobra una gran importancia el uso de los módulos de datos. por ejemplo; si vamos a utilizar un componente no visual como la definición de una tabla de clientes en varios formularios, podemos crear el componente una sola vez en el módulo de datos y utilizarlo a través de varios formularios en nuestra aplicación. La centralización de la definición de componentes en un solo lugar nos permite tener un mejor control del uso de los mismos. Un módulo de datos se crea tomando la opción "New" del menú "File" y seleccionando "Data Module".El uso de un módulo de datos desde un formulario se realiza a través de la inclusión de una directiva en el formulario que necesita dicho módulo, de la siguiente forma:

Uses Nombre_Modulo_de_Datos Estilos de Formulario (TForm). Un proyecto puede estar configurado de dos formas diferentes. El primero utiliza un formulario inicial y puede o no mostrar otros formularios independientes. Este tipo de proyecto se denomina SDI (Standard Document Interface). Delphi es un ejemplo de una aplicación con este estilo. Por otro lado

Page 40: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 28

existen aplicaciones, como por ejemplo Word o Excel, donde se despliega un formulario maestro (o padre) y otros formularios secundarios (o hijos) que dependen del formulario maestro. Este tipo de proyectos se denomina MDI (Multiple Document Interface). la propiedad FormStyle se utiliza para definir el estilo de formulario y puede tomar los siguientes valores:

• fsMDIChild: El formulario es un hijo del proyecto MDI. • fsMDIForm: El formulario es el padre del proyecto MDI. • fsMDINormal: El formulario es SDI. • fsStayOnTop: El formulario es SDI y siempre es desplegado sobre otros

formularios. Nota: siempre debe existir un sólo formulario padre, en un proyecto MDI, y uno o varios formularios hijo . Métodos del componente formulario (TForm). El componente TForm dispone de una gran cantidad de métodos, por lo que vamos a centrarnos en aquellos que son más importantes o que sabemos que usuaremos más frecuentemente. Algunos de estos métodos serán tratados con detalle en capítulos siguientes. No obstante, los métodos presentados en este apartado son suficientes para realizar la mayoría de las aplicaciones con un nivel medio de complejidad, y como siempre, recuerde que puede obtener mas información detallada de todos los métodos del componente TForm en la ayuda en linea de Delphi. Cuando iniciamos la ejecución de una aplicación, la ventana o formulario principal de la misma se visualiza, sin embargo y como veremos más adelante, lo normal cuando se realiza una aplicación de tamaño medio es que necesitamos varios formularios y tengamos que ser nosotros, mediante el código los que indicamos la visualización o no de las diversas ventanas o formularios que constituyen la aplicación. Para ello disponemos básicamente de los métodos Hide para ocultar un formulario y Show ó ShowModal para visualizarlos. La diferencia entre los métodos Show y ShowModal es que el segundo de estos métodos realiza la visualización de una ventana Modal, lo que implica que no podemos continuar con la ejecución del aplicación hasta que cerremos dicha ventana, además, para cerrar una ventana modal no utilizaremos el método Hide, sino que debemos asignar un valor distinto de cero a la propiedad ModalResult del formulario. más adelante veremos que

Page 41: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 29

existen ciertos componentes (botones) que pueden asignar valores para propiedad Modal Result automáticamente. Para crear una instancia de un objeto TForm usaremos el método Create, mientras que para destruirlo y liberar los recursos consumidos por un formulario podemos usar los métodos Free, Destroy y Release . Estos métodos son invocado directamente y automáticamente cuando iniciamos o finalizamos la ejecución de un programa desarrollado en Delphi. Para cerrar una ventana o formulario usaremos el método Close el cual a su vez hace uso del evento CloseQuery para determinar si el formulario puede ser cerrado. Generalmente usaremos el método Close en la ventana principal de nuestra aplicación lo que provocara que la ejecución de la misma termine y se liberen todos los recursos que consumía, es decir, el uso de Close en la ventana principal hace que se cierren todas los formularios existentes y se termine la ejecución, lo que es equivalente a usar el método Terminate del objeto TApplication. Los métodos Free, Destroy y Release son automáticamente invocados por el método Close. Para redibujar o actualizar un formulario y todos sus componentes, podemos hacer uso de los métodos Refresh (refrescar), Repaint (redibujar) ó Update (actualizar), los cuales nos permiten por ejemplo volver a mostrar un formulario cuando se halla dañado la parte visual por la superposición de otra ventana. Mediante los el métodos BringToFront y SendToBack podemos forzar a que el formulario aparezca encima de cualquier otra ventana o debajo de todas las existentes, respectivamente. Mediante el método Print podemos obtener una copia impresa de la ventana, mientras que si deseamos obtener una imagen de la misma para su posterior manipulación o almacenamiento en un archivo usaremos el método GetFormImage que nos devuelve una imagen en formato de mapa de bits o BitMap. Eventos del componente formulario (TForm) . El componente TForm dispone también de una gran cantidad de eventos asociados entre los que se incluyen los del ratón, teclado y los generales vistos anteriormente. Veamos otros eventos que todavía no conocemos y cuya explicación será válida para el resto de componentes que también dispongan de los mismos.

Page 42: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 30

OnCreate(Sender : TObject): Este evento se genera cuando el formulario es creado, siendo el evento por defecto del componente. Generalmente se utiliza para realizar las inicialisaciones de valores o la creacion de otros objetos. El parámetro Sender que recibe el procedimiento asociado se corresponde, como ya sabemos, con el objeto que ha generado el evento. OnDestroy(Sender : TObject): esa que el evento complementario a OnCreate y se produce justo antes de que el formulario sea destruido . OnActivate(Sender : TObject): este evento se produce cuando el formulario se convierte en la ventana activa de Windows . OnDeactivate(Sender : TObject): es el evento complementario a OnActivate, produciéndose en el momento en que la ventana deja de estar activa . OnShow(Sender : TObject): este evento se produce justo antes de que la ventana sea visualizar y generalmente se usará para establecer los valores adecuados para dicha visualización. OnHide(Sender : TObject): Evento complementario a OnShow, se produce justo antes de que la ventana se oculte . OnResize(Sender : TObject): este evento se produce cuando se modifica el tamaño de la ventana, sin importar el mecanismo usado para ello. usualmente lo podremos utilizar para el ajuste de las posiciones y dimensiones de los componentes incluidos en el formulario. OnPaint(Sender : TObject): Este evento se produce cuando es necesario dibujar la ventana, lo que podemos hacer mediante los métodos Update y Paint. OnClose(Sender : TObject; var Action : TCloseAction): Este evento se produce justo antes de que el formulario sea cerrado, permitiendonos tomar el control de la acción a realizar gracias al parámetro Action que recibirá el procedimiento asociado y cuyos valores son los siguientes: • caFree: El formulario es cerrado. • caMinimize: El formulario no es cerrado pero minimizado. • caHide: El formulario no es cerrado pero ocultado.

Page 43: Tecnicas de Programacion Visual Usando Delphi

Primeros Pasos en Delphi. 31

• caNone: El formulario no es cerrado. OnCloseQuery(Sender : TObject; var CanClose : Boolean): este evento se puede considerar una variante del evento OnClose ya que también se produce justo antes de que la ventana se hace ráfaga, cuestión que podemos controlar mediante el parámetro CanClose que recibirá el procedimiento asociado y que indicará si se realiza finalmente el cierre del formulario. El siguiente grafico muestra el inspector de objetos con la lista de los eventos a los cuales puede reaccionar el componente Tform.

Page 44: Tecnicas de Programacion Visual Usando Delphi
Page 45: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 32

Uno de los elementos o ventanas más importantes del ambiente integrado (IDE) de Delphi es la paleta de componentes. En esta ventana se encuentran agrupados los diferentes objetos o componentes que pueden ser utilizados (insertados) en un formulario. Esta ventana se encuentra organizada en forma de pestañas que agrupan componentes que tienen en común ciertas características u objetivos. Dependiendo de la versión de Delphi, pueden existir diferentes pestañas.

Es importante destacar que un componente además de tener simples propiedades, eventos y métodos también puede tener varios subobjetos asociados o de uso interno. Estos subcomponentes a la vez tienen propiedades y métodos que están disponibles al usuario. Los subcomponentes se presentan como propiedades del componente mayor y para utilizar sus propiedades y métodos tenemos que referenciarlos de la siguiente forma:

Componente_Principal.SubComponente.Propiedad_o_Método Donde: Componente_Principal : El nombre del componente mayor. SubComponente : El nombre del su-Componente. Propiedad_o_Metodo : El nombre de la propiedad o método del sub-componente.

Un tratamiento extenso de todos los componentes con sus propiedades, métodos y eventos que provee Delphi seria una tarea muy laboriosa. Lo saludable seria presentar un tratamiento de un subconjunto de ellos y a la medida que el usuario se sienta confortable y seguro de su funcionamiento, profundizara sobre otros componentes, propiedades, métodos y eventos utilizando la amplia ayuda en línea con que dispone el sistema. El soporte de la ayuda en línea más largas sesiones de ensayos y pruebas de los mismos es a la larga el único procedimiento que puede garantizar el obtener la experticia necesaria para ser un buen programador en esta gran herramienta de programación de tecnología de punta. A continuación discutiremos el contenido de alguna de estas pestañas de la paleta de componentes y algunos de los componentes que en ellas se encuentran para poder ser utilizados en nuestros formularios. La paleta de componentes “Estándar”.

La paleta de componentes “Estándard” es una de las más importantes de las usadas en Delphi. El siguiente gráfico muestra la paleta de componentes “Estándard” y a continuación describiremos algunos de sus objetos.

Page 46: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 33

Etiqueta (Label): Este componente es nos permite introducir texto en nuestras aplicaciones, es decir, con el componente Label añadimos etiquetas que bien pueden ser explicativas de otros controles (componentes) o bien puede ser mera información de la aplicación al usuario. Posee una propiedad llamada Caption donde se almacena, por medio del inspector de objetos, el texto a ser mostrado. También las propiedades Fuente (Font) y Color para personalizar su apariencia.

Caja de Texto (EditBox): Nos permite introducir datos en nuestra

aplicación (formulario). Es la forma más básica de capturar datos suministrados por el usuario para poder ser usados en un programa. Posee, entre otras, una propiedad llamada Text donde se recoge el valor introducido por el usuario, es decir, ese será el valor del componente en ese momento.

Memo : al igual que la caja de texto componente Memo nos permite

capturar texto pero en múltiples. La propiedad Lines (un subobjeto del componente) nos permite almacenar múltiples líneas de texto. Este componente cuenta con varios métodos de relevancia:

LoadFromFile: Cargar el contenido de un archivo al subobjeto Lines. SaveToFile: Grabar el texto escrito a un archivo. Clear : Borrar el contenido (texto) del componente. Es método por defecto del componente memo. Add: Añadir una línea de texto al su objeto Lines.

Por ejemplo si tenemos el componente Memo1 en un formulario, y queremos almacenar dos líneas de texto en él, limpiando el contenido del mismo previamente, y luego grabar el texto un archivo, el código necesario sería siguiente:

Memo1.Clear; Memo1.Lines.Add('La dirección es incorrecta !'); Memo1.Lines.Add('Intente en otra ocasión'); Memo1. SaveToFile('Respuesta.Text');

Botón (Button): Este componente, aunque ya nos hemos referido a él, es

de los más importantes para el desarrollo aplicaciones. Mediante componente

Page 47: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 34

Button podremos relacionada los eventos con la interacción del usuario. Es fundamental, por lo tanto, asociar bien el código relativo a los eventos de un botón. Una de las propiedades que más se suelen modificar es la propiedad Caption, que refleja el título del botón. Con la propiedad Enabled podremos activar o desactivar el botón, para desencadenar o no las acciones definida en su evento OnClick. Por ultimo, la propiedad ModalResult almacena el valor del resultado de presionar el botón cuando está en un formulario mostrado de forma Modal. Por ejemplo si tenemos un botón llamado "Ver", cambiando su propiedad ModalResult a "mrOk", al presionar el botón "Ver", el formulario se cerrara y el valor de la propiedad ModalResult del formulario tendrá el valor "mrOk". En este caso no es necesario definir el evento OnClick para el Boston, ya que Delphi interpreta que el botón es para cerrar un formulario Modal (diálogo) y que el resultado de cerrar el formulario se encuentra almacenado en la propiedad ModalResult del botón.

Casilla de Verificación (CheckBox): este componente sirve para

marcar (activar) una opción, es decir, solamente existen dos opciones posibles: marcado y no marcado. Cada componente CheckBox posee una propiedad Checked, cuyo valor, al igual que el de un RadioButton, puede ser True (verdadero) o False (falso). A partir de este valor es posible saber si una opción está marcada o no. El siguiente gráfico muestra un componente de

tipo TCheckBox donde describe el status de un cliente (cliente activo o inactivo):

La propiedad Caption se utiliza para contener el titulo desplegada en el lado derecho del componente. En este caso esta propiedad posee el valor “Cliente Activo”.

Botón de Radio (RadioButtom): Los botones de radio o de opción se usan cuando de una serie de opciones o alternativas podemos seleccionar una y sólo una, es decir, la selección de una impide que el resto de las otras alternativas. Si se intenta seleccionar otro botón de opción de un RadioButtom se deselecciona el anterior y se selecciona el pulsado. Este tipo de componentes suelen agruparce en otro componente que se encuentran en esta pestaña (Estandard), el RadioGroup. El procedimiento es: primero, insertar un componente RadioGroup en el formulario, y luego insertar tanto RadioButtons como sea necesario, dentro del RadioGroup. Por ejemplo, si deseamos tener un grupo de botones de radio para definir el status de un cliente (activo o no activo), podemos primero incluir un RadioGroup en el formulario y luego dos componentes RadioButtom dentro del RadioGroup.

Page 48: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 35

Por ultimo cambiamos la propiedad Caption de cada RadioButtom para describir adecuadamente cada una de las opciones o alternativas. El gráfico a

la izquierda muestra estos componentes. El marco que se encuentra alrededor de los dos RadioButtoms representa el RadioGroup. Un RadioGroup posee la propiedad Caption donde se almacena un posible titulo para el grupo de botones de radio. En este caso esta propiedad (Caption) posee la tira

de caracteres “Estado del Cliente”. La propiedad Checked de un RadioButtom se utiliza para saber si el botón esta marcado o no.

Lista de Texto ( ListBox): Nos permite introducir datos en nuestra

aplicación desde una lista de elementos previamente introducidas por el programador o la aplicación. Mediante la propiedad Items, representando las líneas de la lista, podemos introducir elementos a la lista, utilizando el inspector de objetos. También podemos en momento de ejecución limpiar (borrar) y cargar la lista en Items (que también es un subobjeto del componente ListBox). Por ejemplo si tenemos un componente tipo TListBox llamado Tipo_Cliente cuya lista debe tener los valores 'A', 'B' y 'C', de siguiente código sería necesario para que en momento de ejecución se cargara la lista:

Tipo_Cliente.Clear; {Limpiar lista de Items} Tipo_Cliente.Items.Add('A'); {Agregar Lista 0 con valor 'A'} Tipo_Cliente.Items.Add('B'); {Agregar Lista 1 con valor 'B'} Tipo_Cliente.Items.Add('C'); {Agregar Lista 2 con valor 'C'}

Cada elemento de una lista, es decir, cada Item, tiene un número de

orden. El número de orden del elemento seleccionado se obtiene a través de la propiedad ItemIndex del componente ListBox. ItemIndex puede tener un valor de cero (primer ítem) hasta n-1 (último ítem). En este caso el ultimo elemento de la lista, cuando esta seleccionado, tiene el valor del ItemIndex igual a tres (3). Cuando no exista ningún elemento seleccionado el valor de ItemIndex será igual a –1 (menos uno). Si el número de líneas (ítems) no puede ser mostrado dentro del componente, una barra de desplazamiento (scroll) será mostrada en el lado derecho del componente. Este componente no tiene una propiedad Text para averiguar cual es el valor del componente en momento de ejecución, por lo tanto utilizaremos la propiedad ItemIndex para controlar el elemento seleccionado. Por ejemplo, en el caso del componente

Page 49: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 36

Tipo_Cliente, si deseamos saber cual elemento esta seleccionado y mostrarlo en pantalla con la función de Delphi “ShowMessage” que despliega en pantalla una ventana con un mensaje suministrado como parámetro, escribiríamos las siguientes líneas de código:

If Tipo_Cliente.ItemIndex <> -1 Then ShowMessage(Tipo_Cliente.Items[Tipo_Cliente.ItemIndex]) Else ShowMessage('No hay elementos seleccionados'); Los siguientes gráficos muestran el resultado de las dos alternativas de

la sentencia “If” anterior.

Lista de Texto Desplegables (ComboBox): Este componente, al igual

que el componente ListBox, nos permite introducir datos en nuestra aplicación desde una lista de elementos previamente introducidas por el programador, pero con la diferencia que la lista de elementos no se encuentra constantemente desplegada. Un botón en el lado derecho de una caja simple de texto se muestra para que el usuario al pulsarlo despliegue la lista de elementos. Mediante la propiedad Items, representando las líneas de la lista, podemos introducir elementos a la lista, utilizando el inspector de objetos y la propiedad Text, en momento de ejecución, tendrá el valor seleccionado por el usuario. El gráfico a la derecha muestra un componente ComboBox con la lista de elementos desplegados. Este componente, al igual que ListBox, posee la propiedad booleana Sorted. Al ser verdadera esta propiedad, Delphi automáticamente clasifica alfabéticamente en forma ascendente la lista de elementos almacenados en el componente. Un ComboBox también posee una propiedad muy importante que determina el estilo de presentación y funcionamiento. La propiedad Style puede tomar los siguientes valores:

Page 50: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 37

CsDropDown : Muestra una lista desde donde el usuario puede seleccionar un elemento u opcionalmente introducir un dato diferente en la caja de texto. CsSimple : Muestra solo la caja de texto para la captura de datos. csDropDownList : Muestra una lista desde donde el usuario puede seleccionar un elemento pero no puede introducir datos en la caja de texto. CsOwnerDrawFixed : Muestra una lista personalizada de elementos. El evento OnDrawItem ocurre para que el usuario cree su propio procedimiento de dibujo o presentación de la lista. Todos los elementos de la lista tienen que tener la misma altura. CsOwnerDrawVariable : Muestra una lista personalizada de elementos. El evento OnDrawItem ocurre para que el usuario cree su propio procedimiento de dibujo o presentación de la lista. Los elementos de la lista NO tienen que tener la misma altura. El evento OnMeasureItem también ocurre para establecer la altura de cada elemento de la lista.

Caja de Grupo (GroupBox) : Este componente nos sirve para agrupar

componentes que tengan cierta relación para el usuario en un formulario. La propiedad Caption es utilizada para opcionalmente suministrar un titulo para el marco de la caja de grupo. El siguiente gráfico presenta un formulario con dos GroupBox. El primero se utiliza para delimitar la información personal de un empleado y el segundo para información relativa al área de trabajo.

Panel : El componente Panel, al igual que GroupBox, se utiliza para agrupar otros componentes que posean características lógicas para el

usuario en común. La propiedad Caption del componente Panel muestra su contenido dentro del marco o borde del panel. Esta propiedad es poco utilizada puesto que la utilidad principal es colocar otros componentes dentro

Page 51: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 38

del panel (marco) para diferenciarlos de otros componentes del formulario. Después de colocar varios componentes dentro de un Panel o GroupBox podemos tratar todos estos componentes como uno solo. Por ejemplo, podemos marcar solo el componente mayor (Panel o GroupBox) y moverlo sobre el formulario. El componente panel ofrece tres propiedades, entre otras, que nos permite personalizar el borde interior, exterior y el ancho del marco. Estas propiedades son BevelInner, BevelOuter y BevelWidth respectivamente. El Siguiente formulario muestra la combinación de diferentes valores para estas propiedades.

Nota: Por medio del Inspector de Objetos o en momento de ejecución del programa, modificando directamente estas propiedades, podemos darle diferentes efectos visuales a la presentación de nuestros formularios.

Otros de los componentes importantes que se encuentran en la pestaña “Estándard” de la paleta de componentes son los utilizados para la creación de

Page 52: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 39

sistemas de menús para nuestros formularios. El menú es un elemento que permite expresar al usuario lo que desea por medio de mandatos. Podemos diferenciar los menús en dos tipos:

Los menús tradicionales, es decir, aquellos que nos encontramos en todas las aplicaciones Windows. Este componente se le denomina MainMenu en Delphi. Los menús Emergentes, también llamados menús flotantes que aparecen según la necesidad presionando el botón derecho del ratón cuando estamos sobre un componente determinado. Este componente se le denomina PopUpMenu en Delphi. Un componente MainMenu se incluye normalmente en lo que debe ser

el formulario principal de la aplicación. El componente MainMenu debe ser colocado en el formulario donde el menú va a ejecutar su trabajo. Es aconsejable diseñar bien el sistema de menús antes de incluirlo en la aplicación. Un menú bien diseñado y estructurado nos permite ver y comprender claramente las funciones comunes de una aplicación.

Con este componente Delphi no genera inmediatamente el menú, sino que espera a que insertemos las distintas opciones en él. Para representar las opciones del menú tenemos dos posibilidades:

• Mediante la propiedad Items del componente, que representa cada uno de los elementos del menú, accedemos a la ventana de edición de menús (Editor de Menús).

• Haciendo “doble click” sobre el componente, accederemos sin más a la ventana del Editor de Menús.

Al editar el menú por primera vez, estará vacío, a excepción de un rectángulo punteado indicando la primera entrada a definir (ver siguiente gráfico). Un componente MainMenu tiene tantos subcomponentes Items como opciones tenga el menú. El nombre de las opciones se escribe en la propiedad Caption de cada subcomponente Items. Después de escribir el “Caption” de un subcomponente Items,

Page 53: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 40

Delphi automáticamente crea una opción de menú. En el gráfico anterior se muestra tanto el formulario principal, donde se encuentra el componente MainMenu, como también el Editor de Menús.

Después de actualizar la propiedad Caption de la primera entrada del menú podemos, con el uso del ratón o las flechas de dirección del teclado, ir al próximo elemento de opción, sea en sentido horizontal o vertical en el sistema de menú. Presionando simultáneamente la tecla Ctrl (control) y flecha a la derecha crearemos un submenú de una opción. El siguiente gráfico muestra varias opciones de un menú con un submenu para la opción “Facturas”, en momento de edición utilizando el Editor de Menú.

Otra alternativa para construir submenús es situarnos sobre el mandato del menú correspondiente y pulsamos el botón derecho del ratón. De las opciones disponibles debemos seleccionar Create Submenú. Entonces aparecerá a la derecha un rectángulo punteado donde insertaremos la primera subopción de este nuevo submenú.

En la propiedad Caption podemos subrayar y definir la letra que sirve de acelerador de teclado para la opción de menú con el símbolo “&”. Es fundamental poder usar el menú desde el teclado. Para introducir una barra de separación entre opciones basta crear, en el lugar deseado para la separación, una nueva entrada que tenga como valor de la propiedad Caption el símbolo menos “-“. Al introducir las opciones de menú nos encontramos con una propiedad muy interesante. Se trata de la propiedad ShortCut (atajo) que servirá para introducir una combinación de teclas y que realizara el mandato correspondiente.

Page 54: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 41

Es importante resaltar, en cuanto al aspecto de diseño de menús, que es recomendable no crear un menú con demasiados submenús. Es preferible un menú largo a un menú en el que para acceder a una opción haya que navegar por cientos de etiquetas.

Una vez confeccionado el menú tendremos que asociarle a cada opcion su función. Para editar un método (OnClick) que reaccione a cualquiera de las opciones del menú, basta con pulsar con el ratón sobre la opció deseada y escribir el código necesario. Como es logico pensar el nombre del procedimiento que Delphi creara se llamara “OnClick”. La reaccion de este evento es normalmente mostrar un formulario. El método Show, precedido del nombre del formulario, es usualmente utilizado para tal funcion.

Los menús flotantes es el siguiente tipo de menús que pueden existir en una placion en Delphi. Como podremos recordar, un menú flotante es aquel que colocando el puntero del raton sobre un componente (control) y pulsamos el botón derecho nos presenta una ventana (menú) con una serie de opciones para tomar una medida de acción. El componente PopUpMenu se utiliza en un formulario para tal acción. Cada componente presente en un formulario puede tener asociado un menu flotante o emergente.

La paleta de componentes “Adittional”.

La paleta de componentes “Adittional” esta ubicada en la segunda pestaña de la paleta de componentes. El siguiente gráfico muestra la paleta de componentes “Adittional” y a continuación describiremos algunos de sus objetos más relevantes.

Botón con Imagen (BitBtn): Este componente presenta el mismo objetivo que el componente Button de la paleta Estándar pero con la posibilidad de mostrar un gráfico BMP dentro del botón. Cuando se instala Delphi – 4 una serie de imágenes son grabadas en el disco duro. En el subdirectorio “Archivos de Programas \ Archivos Comunes \ Borland Shared \ Images \ Buttons” se encuentran archivos BMP con el tamaño adecuados para ser utilizados con este componente. El evento OnClick es el mas comúnmente usado para relacionar una acción con este componente. El siguiente gráfico

Page 55: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 42

muestra al Inspector d Objetos con las propiedades Caption (titulo del botón) y Gliph (imagen). En la parte izquierda también se muestra un formulario con este componente utilizando la imagen Abort.BMP que se encuentra en el subdirectorio antes mencionado.

Botón Rápido (SpeedButton): Este componente es también utilizado

para mostrar botones con gráficos. No posee la propiedad Caption como los componente tipo botón anterior. Es frecuentemente agrupado con otros componentes del mismo tipo para presentar barras de opciones rápidas en un formulario. Este componente también tiene una serie de propiedades que ayuda a mostrar gráficos en diferentes estados (seleccionando, deseleccionado, activo, etc..). La propiedad GroupIndex sirve para agrupar (asociar) botones del mismo tipo y que actúen en conjunto. Por ejemplo, los siguientes formularios muestran tres (3) botones rápidos en un componente Panel. Los tres botones poseen la propiedad GroupIndex con el mismo valor (en este caso el valor uno “1”). Al iniciarce la ejecución del formulario (lado izquierdo) ningún botón a sido pulsado. Cuando se pulsa cualquiera de los botones, se mantiene seleccionado (lado derecho), y si había otro seleccionado se deselecciona. Los tres botones están actuando en conjunto.

Page 56: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 43

Caja de Texto de Edición (MaskEdit): Al igual que el componente EditBox, este componente nos permite introducir datos en nuestra aplicación (formulario). Solo se diferencia del EditBox en que podemos forzar al usuario a que introduzca datos conforme a un formato determinado. Por ejemplo, si queremos que el usuario introduzca siempre un numero de teléfono con un código de área con separador basta con inicializar el atributo MaskEdit con la siguiente tira de caracteres: “###-######;1;_” (sin las comillas) escribiéndola directamente en el Inspector de Objetos o utilizando el Editor de Mascaras (ver siguiente gráfico). El Editor de Mascaras se invoca pulsado el botón de elipses que presenta el Inspector de Objetos en la propiedad EditMask de un componente MaskEdit.

Una mascara de edición esta constituida por tres partes. La primera es la mascara en sí. Un símbolo de “#” representa una entrada tipo numérica, un “A” solo aceptara valores alfabéticos, etc. Para mas información ver la ayuda en línea de Delphi. La segunda parte indica si caracteres literales (el “-” en nuestro ejemplo anterior) se deben incluir y guardar como parte de los caracteres introducidos por el usuario. Un valor de “0” significa que los literales no deben ser almacenado, un numero diferente de “0” incluiría todos los valores literales como parte de la cadena de caracteres. La ultima parte de una mascara de edición representa el carácter que se utilizara para espacios en blancos durante el momento de edición. Este caracteres puede ser inclusive el carácter “blanco”. Por medio del Editor de Mascaras se pueden actualizar estas tres áreas. Delphi suministra una serie de mascaras predeterminadas que se muestran en el lado derecho del Editor de Mascaras. Es importante resaltar que las mascaras editadas pueden ser probadas en la caja de texto “Test Input” que se encuentra en el lado izquierdo del Editor de Mascaras.

Page 57: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 44

Rejilla de Caracteres (StringGrid): Este componente esta diseñado específicamente para albergar tira de caracteres en celdas independientes. Este componente simula, en apariencia, el comportamiento de una hoja de calculo donde podemos mantener unas columnas y filas con datos almacenados en él. El siguiente gráfico muestra este componente en un formulario y las propiedades que definen el numero de columnas y filas. La(s) primera(s) fila(s) pueden ser fijas (siempre se mostrarán).

La propiedad Cells se utiliza para en momento de ejecución almacenar valores en una de las celdas del componente. Por ejemplo, si queremos inicializar la celda de la columna 3 y fila 2 con la tira de caracteres “5 de abril” se escribiría, en el evento adecuado, la siguiente instrucción:

StringGrid1.Cells[3,2] := “5 de abril”;

Numero de columnas

Numero de Filas

Page 58: Tecnicas de Programacion Visual Usando Delphi

Componentes Básicos 45

Figura (Shape): Usando este control podemos crear círculos, rectángulos, óvalos, cuadros, es decir dibujos muy simples pero a la vez muy útiles. En este componente la propiedad Shape es la que define que tipo de figura se dibujara. El siguiente gráfico muestra varios componentes Shape variando las propiedades Shape, Brush y Pen.

Caja de Desplazamiento (ScrollBox): este componente se utiliza para crear barras de desplazamiento en un formulario. Delphi introduce

automáticamente este componente cuando no se pueden mostrar todos los componentes de un formulario. El siguiente gráfico muestra este componente con barras de desplazamiento horizontales y verticales.

Bevel: Este componente es utilizado para dar aspecto tridimensional a formularios y otros componentes en él. En sí, este componente, es muy

similar al componente Panel, prácticamente igual, con la salvedad de que los componentes Bevel no actúan como contenedor de otros componentes, sino solo ofrecen el aspecto, es decir, el viselado. Las propiedades Shape y Style se utiliza para definir la forma, el primero, y modificar el aspecto de un efecto hacia adentro o hacia fuera se tratara, el segundo. El siguiente gráfico muestra el efecto de la propiedad Style.

Page 59: Tecnicas de Programacion Visual Usando Delphi
Page 60: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 46

Objetos de Acceso de Datos (Data Access).

En la pestaña “Data Access” de la Paleta de Objetos se encuentran los objetos utilizados para mantener la comunicación entre una base de datos y los formularios de una aplicación Delphi. Dependiendo del tipo de base de datos y las operaciones que se desean realizar sobre una o varias de las tablas se utilizara un subconjunto de estos objetos. Después de seleccionar los objetos de “Data Access” adecuados se deben seleccionar los objetos de “Data Controls” para completar una interface adecuada que permita la manipulación de datos almacenados en medios secundarios.

Fuente de Datos (Data Source) permite establecer la relación entre el objeto Tabla (Table) y otros objetos de manipulación de datos (pestaña

“Data Controls” de la paleta de objetos).

Tabla (Table) establece la relación entre una tabla física de un manejador de base de datos y una aplicación Delphi. Las propiedades

“DataBaseName” y “TableName” identificarían el nombre de la base de datos (o subdirectorio) y el nombre de la tabla respectivamente. Por ejemplo, para manipular datos en una caja de texto de base de datos (DBEditBox) en un formulario se realizaría de la siguiente forma: Nota: Las relaciones entre los objetos Tabla y Fuente de Datos con otros objetos de manipulación de datos se establece por medio de las propiedades de los objetos. Mas adelante se explicara la forma de utilizar las propiedades más importantes para conectar estos objetos.

Tabla Física

Page 61: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 47

Consulta en SQL (Query). Almacena en una de sus propiedades una instrucción en SQL sobre una o varias tablas de una base de datos. Base

de datos remotas (Sybase, SQL Server, Oracle, Informix, DB2, InterBase) y bases de datos locales (Paradox, dBASE, Access y FoxPro) pueden ser actualizas usando este objeto. También se pueden utilizar en bases de datos que cumplan con el tipo de conexión ODBC. Una instrucción en SQL puede ser de dos tipos:

• “RequestLive”: El resultado de la consulta es de lectura y / o escritura. La consulta se comporta como una tabla donde se pueden actualizar o cambiar los datos.

• No “RequestLive”: El resultado de la consulta es solo de lectura.

Nota: Al igual que el Objeto Tabla (Table), el objeto Consulta SQL

(Query) necesita de un objeto de Fuente de Datos (DataSource) para poder establecer la conexión entre la tabla física y los objetos de manipulación de datos que se encuentran en la pestaña “Data Controls” de la paleta de objetos.

Procedimientos Almacenados (StoredProc.). Este tipo de objeto se utiliza para ejecutar un grupo de instrucciones (SQL) guardados en una

base de datos que son parte del metadata (como lo son tablas, índices, definiciones de dominio). Estas tareas pueden ejecutar operaciones frecuentes que estan relacionadas con el mantenimiento de las tablas de la base de datos. En algunos manejadores de bases de datos populares este tipo de instrucciones almacenadas se conocen como “triggers”.

Nota: Al igual que el Objeto Tabla (Table), el objeto Procedimiento Almacenado (StoredProc) necesita de un objeto de Fuente de Datos (DataSource) para poder establecer la conexión entre la tabla física y los objetos de manipulación de datos que se encuentran en la pestaña “Data Controls” de la paleta de objetos.

Base de Datos (DataBase). Este objeto se utiliza cuando en una aplicación se requiere poseer controles discretos sobre una base de

datos. Los tipos de controles que provee este objeto son sobre: • Conexiones persistentes.

Page 62: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 48

• Tipos personalizados de conexión (login). • Control de transacciones lógicas. • Selección de diferentes bases de datos dependiendo de los requerimientos

de la aplicación.

El objeto DataBase es de particular importancia cuando se trabaja con bases de datos remotas (Sybase, SQL Server, Oracle, Informix, DB2, InterBase). Delphi automáticamente crea un objeto DataBase en momento de ejecución de la aplicación si explícitamente no se creo en un formulario.

Sesión (Session). Cuando se estan utilizando varias bases de datos diferentes en una aplicación, el objeto Session provee un control

administrativo global de la conexión de las bases de datos en los formularios de la aplicación. Operaciones de multiples hilos y control de concurrencia (por ejemplo, dos consultas de SQL a una misma tabla o base de datos) pueden utilizar este objeto para mantener altos niveles de integridad de datos. Delphi automáticamente crea un objeto Session en momento de ejecución de la aplicación si explícitamente no se creo en un formulario.

Proceso en Lote (BatchMove). Permite ejecutar procesos en lote, y de mantenimiento, a una tabla de una base de datos. Las operaciones que

pueden que se contemplan son: • Añadir registros de una tabla (fuente) a otra tabla (destino) de una base de

datos. Si registros iguales existen NO son remplazados. (Modo Append). • Añadir registros de una tabla (fuente) a otra tabla (destino) de una base de

datos. Si registros iguales existen son remplazados. (Modo AppendUpDate).

• Actualizar registros de una tabla (fuente) a otra tabla (destino) de una base

de datos. Registros iguales en la tabla destino son remplazados por registros de la tabla fuente (Modo UpDate).

Page 63: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 49

• Copiar registros de una tabla (fuente) a otra tabla (destino) de una base de datos. La tabla destino es borrada y completamente remplazada por la nueva tabla destino (Modo Copy).

• Borrar registros de una tabla (fuente) a otra tabla (destino) de una base de

datos. Los registros que sean iguales en la tabla fuente y destino son borrados de la tabla destino (Modo Delete).

Nota: Las áreas de índices son utilizadas para determinar cuando dos

registros son iguales. También existen otras alternativas de procesamiento en lote de tablas. Un conjunto variado de métodos (procedimientos o funciones) pueden ser utilizados para recorrer un objeto Tabla (Table) o Consulta de SQL (Query) y aplicar operaciones de actualizaciones sobre registros determinados.

Advertencia: Los próximos objetos mencionados pueden ser utilizados en aplicaciones avanzadas de manejo de base de datos donde el equilibrio de la comunicación entre los clientes y el servidor de datos son criticas.

Actualizaciones de Datos en Operaciones de SQL (UpDateSQL). Aunque un conjunto de datos se reporte como “solo de lectura”, es

posible aplicar cambios a las tablas que son transparentes al usuario final. Operaciones de inclusión (INSERT), actualización (UPDATE) o eliminación (DELETE) de registros por medio de instrucciones de SQL se puede realizar automáticamente (in sin intervención del usuario) sin importar que una Consulta de SQL sea solamente de lectura.

Proveedor de Datos (Provider). Engloba mecanismos para proveer datos a una aplicación multi – hilos en una aplicación Cliente –

Servidor. Este objeto empaqueta datos desde el servidor y los transmite al cliente.

Cliente de Datos (ClientDataSet). Objeto utilizado para leer y escribir datos directamente al disco duro del cliente. Comúnmente utilizado en

conjunto con el Proveedor de Datos (Provider).

Servidor Remoto de Datos (RemoteServer). Describe la conexión remota del servidor con la aplicación cliente en un proceso multi – hilo. Objeto usuado en combinación con el Proveedor de Datos (Provider) y

Cliente de Datos (ClientDataSet).

Page 64: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 50

Los objetos disponibles en la pestaña “Data Access” de la Paleta de Objetos representan la puerta de entrada para una optima manipulación de datos. En la mayoría de las aplicaciones pequeñas a medianas solo el uso de un conjunto limitado de ellos es requerido para tener un procesamiento de datos adecuado. Los sistemas de procesamiento de datos avanzadas que requieren sofisticadas herramientas para el mantenimiento de estructuras cliente – servidor encuentran los objetos convenientes en esta paleta para garantizar su persistencia en el tiempo.

La pestaña “Data Controls” de la Paleta de Objetos o Componentes posee los objetos disponibles para hacer que una aplicación tome vida. En esta se encuentran las interfaces que hacen posible la comunicación entre un usuario y los datos almacenados en una o varias bases de datos. Es conveniente recordar que los objetos brevemente descritos en esta sección son no – visibles y normalmente se depositan en un Modulo de Datos. Los próximos objetos se utilizan exclusivamente en formularios que son visibles a los usuarios finales.

Page 65: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 51

Objetos de Control de Datos (Data Controls).

En la pestaña “Data Controls” de la Paleta de Objetos se encuentran los objetos utilizados para mantener la comunicación entre una base de datos, los componentes de acceso de datos (Data Access) y los formularios de manipulación de datos. Delphi ofrece en esta hoja de la paleta de objetos una buena variedad de componentes que permiten desarrollar una aplicación con formularios robustos de manejo de base de datos. La definición de objetos como Table, Query y datasource, preferiblemente en un Modulo de Datos, son necesarios para establecer la comunicación entre las tablas físicas de una B.D. y los componentes de Manipulación de Datos (Data Controls). La hoja de componentes se presenta a continuación seguido de una breve explicación de los objetivos de cada componente.

Cuadricula de B.D. (DBGrid). Permite la manipulación de datos de una tabla o consulta SQL en una forma parecida a una hoja de calculo. Una

matriz gráfica se presenta donde cada fila representa un registro de la tabla y cada columna en un campo de un registro. El siguiente gráfico muestra un DBGrid en el formulario “Form2”. La ventana del Inspector de Objetos (“Object Inspector”) muestra la propiedad “DataSource” con el nombre del objeto de Fuente de Datos (DataModule1) que suministra la conexión con la tabla física (señalado atraves de las flechas punteadas azules). El DBGrid esta mostrando tres registros donde cada registro esta constituido por tres campos (Código, Descripción y Saldo).

Page 66: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 52

Es importante destacar que ya tenemos un formulario de manipulación de datos completamente funcional. Dependiendo de la configuración (valores) de las propiedades del objeto DBGrid podemos incluir, modificar o eliminar registros de la tabla en momento de ejecución.

NOTA: Todos los objetos que se encuentran en la hoja de “Data Controls” poseen la propiedad “DataSource” para establecer el origen de los datos a ser manipulados y mayoría posee la propiedad “DataField” que determina que campo de la tabla se manejara por medio del objeto o componente.

Navegador de B.D. (DBNavigator). Al soltar este componente en un formulario e inicializar su propiedad de fuente de datos (DataSource) se puede navegar atraves de los registros de una tabla (table) o consulta de

SQL (Query). Botones para actualizar los datos también se muestran. Por defecto se presentan todos los botones mostrados en el siguiente gráfico pero es posible configurar el objeto (por medio de las propiedades) para que solo presente los botones particulares a una aplicación.

Etiquetas de B.D. (DBLabel). La característica fundamental de una etiqueta es que mantiene (en tiempo de ejecución) permanentemente su

contenido. Una Etiqueta de Base de Datos muestra el contenido de un campo en particular en modo solo de lectura, el usuario no podrá cambiar el contenido de ese campo por medio de este objeto. Además de poseer propiedad “DataSource” que define la fuente de datos, también existe la

Primero

Anterior

Próximo

Ultimo

Incluir

Eliminar

Editar

Aceptar Refrescar

Cancelar

Page 67: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 53

propiedad “DataField” que determina que campo de la tabla se mostrara por medio de este objeto o componente.

Caja de Texto de B.D. (DBEdit). Este componente es el mas utilizado en formularios de B.D..Un campo tipo carácter, numérico o fecha puede

ser actualizado por medio de este componente. También existe la propiedad “DataField” (entre otros) que define que campo de la tabla se manipulara por medio de este objeto o componente. El siguiente gráfico muestra tres (3) DBEdit correspondientes a la tabla Maestro. Cada DBEdit corresponde a un campo de dicha tabla: Código, Descripción y Saldo. Un DBEdit puede simular un DBLabel inicializando la propiedad “ReadOnly” (solo de lectura) a “True”.

Memo de B.D. (DBMemo). Muchos manejadores de base de datos pueden manejar campos tipo memo. Estos tipos de campo son cajas de

texto grandes y multi – líneas en formato libre. Delphi utiliza este formato para manejar campos tipo memo.

Imagen de BD. (DBImage). Muchos manejadores de base de datos pueden manejar campos tipo BLOB (binary large object). Con este

objeto se puede mostrar en un formulario imágenes de un campo BLOB de una tabla o Consulta SQL.

Caja de Lista de B.D. (DBListBox). Un campo de una tabla puede estar relacionado con un conjunto finito de posibles valores. El objeto

DBListBox puede ser utilizado para restringir al usuario a seleccionar uno de los posible valores que debe tener el campo. El formulario “Form2” que se presenta a continuación tiene un campo descripción que puede tener solo los valores “Jamón Tipo A”, “Jamón de Pierna”, Fiambre, etc. Esta lista de valores es comúnmente definida en momento de diseño del formulario. El ratón se utiliza para determinar que valor tendrá este campo. Delphi se

Page 68: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 54

encarga de mostrar que tipo de descripción corresponde al registro que esta siendo mostrado en el formulario. Por ejemplo, el código “00000”

corresponde al Jamón de Pierna y por lo tanto la lista de posibles valores se muestra esta descripción. Pero cuando se utilice el navegador de base de datos para ir a otro registro de la tabla, el correspondiente valor del código se mostrara en el

DBListBox. Cada línea mostrada en la caja se almacena en la propiedad “Items” del objeto.

Caja Combo de B.D. (DBComboBox). Este componente posee las mismas características que el objeto anterior (DBListBox) con la

salvedad que es su presentación es como una caja de texto donde solo se muestra una sola de las opciones. Un pequeño botón en la parte derecha permite que se desplegué la lista de las

otras alternativas posibles para el valor del campo al cual esta relacionado. Cada línea mostrada en la lista desplegable se almacena en la propiedad “Items” del objeto.

Caja de Status o Condición de B.D. (DBCheckBox). Cuando un campo de un registro solo puede tener dos (2) valores (“True” o

“False”, “Si” o “No”. Etc.), este objeto puede manejar la actualización correcta en la base de datos. Como ya se menciono las propiedades DataSource y FieldName deben tener valores apropiados para la correcta actualización del campo de datos. El siguiente gráfico muestra como la condición de un cliente puede ser cambiado (y mostrada) usando el objeto DBCheckBox.

Propiedad que define la etiqueta del objeto DBCheckBox.

Area donde se actualiza el valor del campo.

Page 69: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 55

Grupo de Botones de Radio de B.D. (DBRadioGroup). Algunas aplicaciones de B.D. actualizan campos de una tabla donde más de dos

valores (pero uno solo de ellos en un momento dado) puede ser almacenados. Normalmente un conjunto muy pequeño de valores son los validos para el

campo (Ver gráfico a la izquierda de la pagina). En estos casos el uso de un objeto DBRadioGroup es conveniente. Una lista (grupo) de una o varias columnas (configurable por medio de las propiedades) se pueden mostrar con los posibles valores para el campo. Por medio del uso del

ratón el usuario seleccionara la condición adecuada. Los títulos y valores para cada categoría son asignados en las propiedades del objeto. Por ejemplo, la propiedad “Values” del objeto puede tener los valores “A”, “I” y “E” que corresponderían con cada una de las líneas del tipo de condición que se desea actualizar. Cada titulo o etiqueta de las condiciones se almacenan en la propiedad “Items” del objeto.

Caja de Lista de Claves Foráneas B.D. (DBLookUpListBox). La aplicación de los conceptos de normalización y centralización de datos

implica el uso de claves foráneas. Por ejemplo, el Código del cliente se utiliza en una tabla de facturas para establecer la relación entre un registro de cliente y las facturas que le pertenecen. El objeto DBLookUpListBox se utiliza para facilitar la integridad de referencia entre dos (2) tablas. Este objeto actúa como un DBListBox con la diferencia que la lista de opciones pertenece a otra tabla. La siguiente figura muestra un formulario (Transacciones) usando un objeto DBLookUpListBox para actualizar el campo Código.

Campos mostrados por el objeto DBLookUpListBox

Page 70: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 56

Los ítems desplegados en el objeto son tomados de la tabla maestro (mostrados en el lado izquierdo en un DBGrid). Cada vez que se actualice la tabla maestro cambiara el contenido del DBLookUpListBox en el formulario de Transacciones. El código “00001” tiene una descripción de “Fiambre” y pertenece a la transacción “111111”. El campo Descripción que aparece en el rectángulo blanco representa una “nota” o aclaratoria de la línea de transacción y no la descripción de la tabla maestro. El siguiente gráfico muestra la ventana del inspector de objetos con las propiedades del DBLookUpListBox que se utiliza en el formulario anterior.

La lista parcial de atributos del objeto muestra los elementos más

relevantes para establecer la relación entre la tabla fuente (DataSource) y la tabla (ListSource) que suministrara la lista de valores para la selección. Como la lista de valores puede tener varias columnas (campos) es importante establecer el ListFieldIndex donde se define la posición de la columna que retornara el valor al DataField. En este caso el ListFieldIndex “0” corresponde al primer campo (Código) que se encuentra en la propiedad ListField. La propiedad KeyField define el nombre que tiene la clave foránea en el ListSource (Tabla Maestro). El nombre del campo en la tabla Maestro y Transacciones no tienen que ser iguales, pero si su contenido.

Nombre del Campo a ser actualizado

Nombre del campo (de la tabla Maestro) que debe concordar con el contenido del campo a ser actualizado (código de la tabla Transacciones).

Campos de la tabla Maestro que se desplegaran en la lista del objeto. Los nombres de los campos separados por ; .

Numero (o posición) del campo de ListField cuyo valor será retornado al campo definido en DataField (Código de la tabla Transacciones).

DataSource de donde se leerán los valores para el DBLookUpListBox.

Page 71: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 57

Caja Combo de Claves Foráneas B.D. (DBLookUPComboBox). Este componente actúa de una manera muy similar al objeto anterior (DBLookUpListBox) con la diferencia que presenta una recuadro o

lista desplegable en vez de un recuadro de dimensiones fijas. Use este objeto cuando desee proveer al usuario una alternativa conveniente de buscar y utilizar valores para un campo (normalmente una clave foránea) por medio de una lista desplegable. El siguiente gráfico muestra un DBLookUPComboBox

para actualizar el campo Código. Observe que el espacio utilizado es menor que un DBLookUPListBox. También se necesita un componente DBEdit adicional para desplegar la descripción del código del maestro. Este DBEdit tendrá las propiedades DataSource y DataField correspondientes a la tabla Maestro. Los atributos usados en el DBLookUpListField (KeyField, ListField, ListFieldIndex y ListSource) tienen las mismas funciones descritas anteriormente.

Memo de B.D. en Formato RTF (DBRichEdit). Al igual que el componente DBMemo, este objeto puede manejar campos tipo “memo”

pero en formato RTF. Este formato permite establecer diferentes tipos de efectos especiales, tamaños y colores de fuentes en un mismo párrafo. Este formato es compatible con el Word y WordPad de Windows.

Page 72: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 58

Cuadricula de B.D. Libre (DBCtrlGrid). Como se menciono anteriormente, el componente DBGrid despliega una matriz con

columnas (campos) y filas (Líneas). El objeto DBCtrlGrid también muestra una matriz donde las filas representan los registros de una tabla pero no existen columnas fijas. Un formato libre por cada fila se presenta donde el usuario coloca objeto para manipular los campos de un registro. Por Ejemplo, el siguiente gráfico muestra el diseño de un formulario con un DBCtrlGrid y otros componentes.

Un DBCtrlGrid posee un numero determinado de paneles (tres en este caso) que son definidos por una propiedad del objeto. En momento de diseño se colocan los componentes de manipulación de datos en el primer panel, los otros paneles

están sombreados. Cuando se ejecute el formulario, Delphi duplicara el formato del primer panel en el resto de los paneles. La siguiente figura muestra el formulario en momento de ejecución. El DBNavigator se utiliza para contralar la navegación y actualizaciones de la tabla.

DBCtrlGrid DBEdit

Label

Page 73: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 59

Asistente para la Creación de Formularios de Manejo de Base de Datos. Un formulario que actualice una o varias tablas de una base de datos puede ser desarrollado por un programador, colocando cada componente manualmente, o también por medio del Asistentes de Formularios. El Asistente de Formularios crea rápidamente la estructura fundamental para la manipulación de datos de una o varias tablas, pero es responsabilidad del programador incluir posteriormente todas las validaciones necesarias para mantener la integridad de los datos. La opción Database à Form Wizard del menú principal es utilizada para invocar el Asistente de formularios de B.D.. La siguiente secuencia de ventanas muestra los pasos a seguir para la generación asistida de un formulario de B.D.: 1. Ventana “Tipo de Formulario”. En esta ventana existen dos preguntas

básicas: Numero de fuentes de datos involucradas: ü Crear un formulario

sencillo (manejo de una sola fuente).

ü Crear un formulario Maestro – Detalle (manejo de dos fuentes).

Tipo de Fuente de datos: ü Usando componentes tipo

Tabla. Recomendado para aplicaciones de manejo local de datos (poco volumen de datos).

ü Usando componentes tipo Query (instrucciones SQL). Recomendado para aplicaciones de manejo distribuido y remoto de datos (gran volumen de datos).

2. Ventana “Fuente de Datos”.

En esta ventana se selecciona el nombre de la Base de Datos y tabla(s) que se utilizara(n) en el formulario. El numero (cantidad) de tablas depende de la

Page 74: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 60

respuesta suministrada en la ventana anterior. Si el formulario a ser creado es sencillo, el Asistente pedirá el nombre de una sola tabla. Si se desea crear un formulario tipo “Maestro – Detalle”, el Asistente pedirá el nombre de la tabla “Maestro” y el nombre de la tabla “Detalle”.

3. Ventana “Campos de la Fuente de Datos”. Por cada tabla seleccionada (una

o dos tablas, dependiendo del tipo de formulario) el Asistente pedirá que se seleccionen los campos que se mostraran y manipularan en el formulario a ser creado. En el lado izquierdo se muestran los campos disponibles y en el lado derecho los campos que están seleccionados.

4. Ventana “Organización de los Campos”. Después de seleccionar los

campos que se utilizaran en el formulario hay que definir la posición donde se ubicaran en pantalla. Existen tres (3) alternativas: ü Horizontalmente. ü Verticalmente. ü En una objeto DBGrid

(Matriz tipo hoja de calculo).

5. Ventana “Relación de

Campos”. Si el tipo de formulario es “Maestro – Detalle” el Asistente debe tener información sobre como establecer la relación entre la tabla Maestro y la tabla Detalle. Esta ventana se muestra en la parte derecha de esta pagina. Por cada registro

Page 75: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 61

que es leído de la fuente de datos Maestro se debe leer uno o más registros de la fuente de datos Detalle. Los campos de la tabla Maestra se muestran en el lado izquierdo y los campos de la tabla Detalle en el lado derecho de esta ventana. Esta relación se establece seleccionando uno o más campos de la parte izquierda y derecha de la ventana y pulsando en botón “Add”.

6. Ventana “Final”. En esta ventana se debe seleccionar sí el formulario será

“principal” o no. Si se desea que al ejecutar el programa el formulario sea el primero en ser mostrado se debe seleccionar “Generate a main form”. También en esta ventana se determina si se incluye un “Modulo de Datos”. Es importante recordar que un Modulo de Datos en un formulario especial donde se definen componentes comunes y no visibles de una aplicación. En este caso los componentes serian la definición de las fuentes de datos (tablas simples o consultas en SQL). Varios formularios podrían utilizar la misma fuente de datos y su definición estaría centralizada en un solo Modulo de Datos. Es más conveniente cambiar cualquier característica de las fuentes de datos cuando estas se encuentran en un solo sitio y no diseminadas en diferentes formularios. Los Módulos de Datos son invisibles durante la ejecución del programa. En momento de diseño es cuando se pueden manipular. En estos formularios también se pueden definir reglas de integridad y validación de datos por medio de eventos. Estos conceptos serán posteriormente ejemplificados, pero el aspecto más relevante es que un Modulo de Datos serviría como un contenedor de todas las reglas de manipulación de datos de las tablas de un sistema. Cuando se necesite la definición de una tabla también se puede suministrar, conjuntamente, todas las validaciones de integridad relacionadas.

Después de generar un formulario de manejo de base de datos se

procede a definir las reglas de validación. Por cada fuente de datos se crean respuestas a eventos que apoyarían el mantenimiento de la integridad de los datos. Por ejemplo, para validar que el campo “Saldo” de una tabla no sea negativo sé definiría el evento “OnValidate” de la fuente de datos. Mas sobre esto en los próximos capítulos. El siguiente gráfico muestra el

Page 76: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 62

resultado de generar un formulario sencillo de manipulación de datos sobre la tabla Maestro.

Page 77: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 63

Manejo de Tablas Usando Instrucciones SQL. Una instrucción SQL puede utilizar una o varias tablas de una base de datos. Delphi es capaz de procesar o dejar que un manejador de base de datos, basado, en la estructura Cliente – Servidor, procese la instrucción y devuelva un conjunto de datos como resultado. Los componentes de la pestaña “Data Access” y “Data Controls” están disponibles para manipular el resultado de una instrucción SQL. Recordemos la estructura de las tablas de nuestra base de datos ejemplo. Maestro Cabeza Cuerpo Código Descripción Saldo

Número_Transacción Fecha Descrip_Transacción

Número_Transacción Código Descripción_Linea Tipo Monto

Ahora, podemos crear una consulta en SQL para obtener la descripción de todos los registros de la tabla Maestro que tienen monto de transacciones mayores a 1,000. La instrucción en SQL seria la siguiente: Select Descripción From Maestro, Cuerpo Where Maestro.Codigo = Cuerpo.Codigo AND Monto > 1000; Los pasos para crear y ver esta consulta serian los siguientes: 1. Crear una aplicación con un formulario nuevo.

• Opción File – New Aplicación. • Hacer click (seleccionar) el formulario nuevo. • Presionar F11 para que aparezca la ventana del Inspector de Objetos y

cambiar el titulo (propiedad Caption) de del formulario por “Consulta en SQL”.

Page 78: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 64

2. Seleccionar un componente DataSource y un Query de la Paleta de Objetos (pestaña de Data Access) y soltarlos en un formulario nuevo. El siguiente formulario es el que debe tener en pantalla:

3. Ajustar las propiedades de los objetos DataSource y Query para establecer una conexión con la base de datos. En este caso la base de datos es en Paradox por lo tanto solo establecemos la propiedad DataBaseName del objeto Query con el nombre del subdirectorio donde se encuentran las tablas (por ejemplo “C: \Base”). • Seleccionar el objeto Query usando el

ratón y haciendo “click” sobre él. • Presionar F11 para que aparezca la

ventana del Inspector de Objetos. • Cambiar la propiedad DataBaseName por

“C:\Base”. La siguiente ventana (lado dereccho de la pagina) muestra a el “Inspector de Objetos”.

• Seleccionar el objeto DataSource y cambie el atributo DataSet por “Query1”, de esta forma los componentes de manipulación de datos sabrán cual es la “fuente de datos”. El Inspector de Objetos se muestra en la parte derecha de esta pagina. Ahora procederemos a definir la instrucción de SQL adecuada para obtener la consulta deseada.

4. Escribir la instrucción SQL en la propiedad “SQL” del objeto Query. • Seleccionar el objeto Query usando el ratón haciendo “click” sobre él. • Presionar F11 para que aparezca la ventana del Inspector de Objetos.

Las propiedades y eventos del objeto Query de mostraran en esta ventana.

Page 79: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 65

• Buscar la propiedad “SQL”, seleccionarla y pulsar el botón que aparece en el lado derecho de la caja de texto (botón con tres puntos suspensivos). La ventana de dialogo “String list editor” se desplegara en pantalla.

• Escribir la instrucción en la ventana de dialogo que se muestra en pantalla y luego pulsar OK. Esta ventana de dialogo se muestra a continuación.

5. Hasta este momento esta parcialmente definido el enlace entre la base de

dados física (C:\Base) y el formulario (Query y DataSource). Ahora debemos buscar una forma de mostrar los datos resultantes de la instrucción SQL. Un DBGrid se puede utilizar para manipular el dataset (datos). • Seleccione de la paleta de objetos, la pestaña “Data Controls”. • Seleccione el objeto DBGrid y suéltelo en el formulario. Cambie el

tamaño del DBGrid, usando el ratón, para ajustarlo a la medida que desee. El siguiente gráfico muestra de donde obtuvo el objeto DBGrid, el inspector de objetos y la apariencia que posee en el formulario.

Page 80: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 66

• Seleccionar el objeto DBGrid usando el ratón haciendo “click” sobre él. Presionar F11 para que aparezca la ventana del Inspector de Objetos. Las propiedades y eventos del objeto DBGrid se mostraran en esta ventana.

• Busque la propiedad DataSource y cambie la fuente de datos por el nombre del DataSource que corresponde al objeto Query definido. De esta forma completamos la conexión a un objeto de manipulación de datos (DBGrid).

6. El siguiente paso seria ejecutar la aplicación. Ya se definió la instrucción

SQL (Objeto Query), su fuente de datos (Objeto DataSource) y como manipular los datos (objeto DBGrid), pero la consulta (instrucción SQL) en si no esta abierta. Hay dos formas de abrir una consulta. La primera es en momento de diseño y la segunda en momento de ejecución (método Query1.Open). Utilizaremos la primera alternativa para abrir la consulta. • Seleccionar el objeto Query usando el ratón haciendo “click” sobre él.

Presionar F11 para que aparezca la ventana del Inspector de Objetos. Las propiedades y eventos del objeto Query de mostraran en esta ventana.

DBGrid

Fuente de Datos

Page 81: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 67

• Busque la propiedad Activo (Active) y cámbiela por el “True”. De esta forma Delphi abre y muestra los resultados en los objetos de manipulación de datos que este relacionados con su DataSource. El siguiente gráfico muestra el formulario y el Inspector de Objetos en momento de diseño.

En momento de ejecución los objetos DataSource y Query no aparecerán

en pantalla. Estos objetos son visibles solo cuando sé esta diseñando la aplicación. Por ejemplo, el siguiente gráfico representa como se vería el formulario cuando sé esta ejecutando el programa:

Nota: No confundir la

propiedad DataSource de un objeto Query con la propiedad DataSource de los objetos de manipulación de datos que se encuentran en la pestaña de Data Controls de la paleta de objetos (Por ejemplo, la del objeto DBGrid). La propiedad DataSource de un objeto Query es utilizado para establecer Enlaces Dinámicos (“Late Binding”) en instrucciones SQL. El concepto de Enlaces Dinámicos será ampliado posteriormente.

Page 82: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 68

Creación y Ejecución de Instrucciones SQL en Tiempo Real. Una instrucción SQL puede ser creada en momento del diseño de un formulario o dinámicamente (no se confunda con el concepto de Enlaces Dinámicos) en momento de ejecución de la aplicación. Vamos a modificar el formulario desarrollado anteriormente para poder editar y ejecutar una instrucción SQL dinámicamente. Se tomara el formulario usado en la sección anterior y añadimos dos componentes adicionales; un objeto Memo para editar una instrucción SQL y un botón para ejecutar la dicha instrucción.

El siguiente gráfico muestra el formulario con los dos nuevos objetos y segmentos de las paletas de donde se seleccionaron los objetos. En el componente Memo se escribirá cualquier instrucción en SQL que utilice las tablas Maestro, Cabeza o Cuerpo y luego se presionará el botón “Ok” para ejecutar la instrucción.

En momento de ejecución del programa se evaluara la instrucción escrita en el objeto memo. Si cumple con las reglas de sintaxis del manejador de base de datos utilizado, el resultado será depositado en el objeto DbGrid.

Page 83: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 69

Después de seleccionar y soltar el botón rápido OK en el formulario hay una propiedad que debe ser modificada. Un botón puede tener diferentes tipos dependiendo de la función que realizara. Delphi posee varios tipos de botones predefinidos que podemos utilizar. También podemos definir nuestros propios tipos. En este caso se desea que cumpla con el objetivo de aceptar y ejecutar la instrucción de SQL. Seleccionemos el botón del formulario y presionemos F11 para ver la ventana del Inspector de Objetos (mostrada a continuación). En la pestaña de propiedades modificamos la propiedad “Kind” por “bkOK”. El icono y leyenda del botón cambiaran automáticamente. La apariencia del botón cambio pero falta por decirle a Delphi que se debe hacer en el evento de un click del ratón (ejecutar la instrucción SQL). El botón Ok debe realizar varias operaciones. Estas funciones serian: 1. Cerrar cualquier consulta previa del objeto Query1 (Método Close). 2. Limpiar el contenido de la propiedad SQL (Método Clear). 3. Asignar el contenido del objeto Memo1 (propiedad Lines) a la propiedad

SQL del objeto Query1. 4. Ejecutar la nueva instrucción en SQL (Método

Open). Seleccionamos el objeto botón y presionamos F11. En la pestaña Eventos de la ventana del Inspector de Objetos se encuentran todos los eventos posibles de este objeto. Hacemos doble click en el primer evento (“OnClick”). La ventana del Editor de Código se desplegara en pantalla con un procedimiento de Pascal en blanco. En este procedimiento escribimos las instrucciones necesarias para ejecutar las operaciones. El siguiente gráfico muestra el código necesario. Cada numero corresponde a las operaciones mencionadas anteriormente.

Page 84: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 70

Ç

Otra alternativa de ejecución dinámica de instrucciones SQL es el de formar la instrucción por medio de la programación. Por ejemplo, un formulario podría pedir un valor del campo “descripción” para filtrar sola los registros que cumplan con el criterio. Supongamos que el usuario desea todos los registros cuya descripción comienzan con la palabra “Jamón”. En momento de ejecución se creara la instrucción SQL. La tira de caracteres puede ser leída en un objeto de Caja de Texto (Edit) y al pulsar un objeto de botón se procesa la instrucción. El siguiente gráfico muestra el formulario en momento de diseño. El evento “OnClick” del objeto botón es donde se escribirán las instrucciones para ensamblar y abrir la consulta en SQL. El siguiente gráfico muestra las instrucciones necesarias para cumplir con los requerimientos.

1 2

4 3

Page 85: Tecnicas de Programacion Visual Usando Delphi

Manejo Básico de Base de Datos 71

El botón Ok realiza varias operaciones: 1. Cerrar cualquier consulta previa

del objeto Query1 (Método Close).

2. Limpiar el contenido de la

propiedad SQL (Método Clear). 3. Asignar, al contenido de la

propiedad SQL del objeto Query1, la instrucción en SQL (Método ADD). Desde la línea numero tres (3) hasta la cinco (5) se realiza esta asignación. El símbolo $ se utiliza como comodín para denotar que cualquier secuencia de caracteres puede existir después del contenido de la caja de texto. La instrucción a introducir es la siguiente:

Select * From Maestro Where Descripcion Like ‘Contenido de la Caja de Texto%’;

4. Ejecutar la nueva instrucción en SQL (Método Open).

Page 86: Tecnicas de Programacion Visual Usando Delphi
Page 87: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 72

Modificación de Registros con SQL. Un objeto Query puede actuar como una simple manipulación de

tabla(s) o como una consulta de una tabla pero sin poder modificar la(s) tabla(s) de las cuales se obtienen los datos. Cuando existe la posibilidad de poder modificar los registros presentados por un objeto Query se denomina Resultado Vivo (“Live Result”). No se confunda esta característica de un objeto Query con la propiedad “ReadOnly”. Una consulta de SQL puede ser capaz de actualizar los registros obtenidos, pero si la propiedad “ReadOnly” fue establecida como “True” no es posible modificar, eliminar o incluir registros. También existe la propiedad “RequestLive” de un Query. Esta propiedad adicional determina que Delphi trata de obtener o no un Resultado Vivo para la consulta dependiendo de las características de la consulta y el estado de las tablas de la base de datos.

En resumen, para poder obtener una instrucción en SQL que

pueda ser modificados los registros, se tiene que cumplir las siguientes premisas.

• La propiedad ReadOnly del objeto Query debe ser igual a

“False”.

• La propiedad RequestLive del objeto Query debe ser igual a “True”.

• Las características de la instrucción SQL. Para consultas sobre

una sola tabla local (Dbase – Paradox) deben usar:

• Cláusulas JOIN, UNION, MINUS, GROUP BY, HAVING o DISTINTICT.

• Funciones Agregadas. • Subconsultas.

Page 88: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 73

• Cláusula ORDER BY basada en campos que no son índices. • Tablas que sean solo de lectura.

• Las características de la instrucción SQL. Para consultas sobre

mas de una tabla local (Dbase – Paradox) deben usar:

• Solo dos tablas bases (no otro Query). • La mezcla (Join) entre las dos tablas se puede realizar

usando áreas de índices existentes. • “Outer Joins” de izquierda a derecha. • Ningún ordenamiento de los registros.

• Las características de la instrucción SQL. Para consultas sobre

una sola tabla remota (Oracle, SysBase, etc.) no deben usar:

• Cláusula DISTINCT, GROUP BY o HAVING. • Funciones Agregadas. • SubConsultas. • Mas de una tabla. • Restricciones propias del Manejador de Base de Datos

remoto. Nota: Estas son restricciones establecidas por el estándar de SQL-92.

Si no se cumplen con estas condiciones el BDE (Borland Database Engine) devuelve una condición de solo lectura para la consulta. Cualquier intento de incluir, modificar o eliminar un registro de la consulta genera un error en tiempo de ejecución. Es importante resaltar que son pocos los momentos en los cuales se trata de modificar registros que son el resultado de una instrucción que no cumplan con la sintaxis arriba descrita. La mayoría de las actualizaciones involucran la utilización de tablas donde las validaciones de integridad de los datos determinan un control estricto de manipulación a nivel de la aplicación cliente y / o el servidor de datos.

Page 89: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 74

Enlaces Dinámicos en Aplicaciones Maestro - Detalle. En muchas aplicaciones de manejo de datos ocurre que no se conocen todos los parámetros para construir una consulta en SQL. Por ejemplo, para crear un formulario donde por cada registro de una tabla debemos mostrar solo todos los registros relacionados de otra tabla, debemos crear enlaces dinámicos (late binding) de registros. Estas situaciones ocurren en formularios donde existe manejo de tablas tipo maestro – detalle. Por cada lectura de un registro de la tabla maestro se tienen que leer solo los registros que están asociados en la tabla detalle. Usando la base de datos ejemplo podemos crear un formulario donde la tabla Cabezas representa el maestro (o tabla principal) y la tabla Cuerpo representa el detalle (o tabla esclava). El siguiente gráfico muestra el formulario en etapa de diseño:

Cuando se lea (y muestre) la transacción numero “00000” también deben ser mostrados solo registros de la tabla Cuerpo que posean el numero de transacción igual. Este formulario utiliza dos (2) consultas (Query) para manejar las tablas. La primera consulta (Query1) lee registros de la tabla Cabeza y la segunda consulta registros de la tabla

Cabeza -DataSource1

Cuerpo -DataSource2

Page 90: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 75

Cuerpo. La siguiente tabla tiene las dos instrucciones en SQL para manipular los datos: Query1 Query2

Select * From Cabeza;

Select Numero_Tran, Codigo, Tipo, Descrip_Tran, Saldo From Cuerpo, Cabeza Where Cuerpo.Numero_Tran = Cabeza.Numero_Tran;

Al ejecutar la aplicación vemos que el resultado es incorrecto. El DBGrid, al final del formulario, contiene todos los registros de la tabla Cuerpo. Solo debía mostrar los registros que posean igual numero de transacción en la tabla Cabeza y Cuerpo. Las dos ultimas líneas de transacciones (Numero_Tran igual a 11111) del DBGrid no deberían ser mostradas.

La solución para este problema es utilizar el concepto de “Late Binding”. En momento de ejecución es cuando se establece correctamente el criterio de selección (cláusula WHERE) de la instrucción SQL. La lógica deseada, para el primer registro de la tabla Cabeza, seria: SELECT * From Cuerpo, Cabeza Where Cuerpo.Numero_Tran = ‘00000’

Page 91: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 76

Claro esta que no podemos tener una instrucción SQL para cada registro de la tabla cabeza. El concepto de Enlaces Dinámicos de registros se establece en Delphi utilizando la propiedad DataSource del objeto Query y una sintaxis especial en la instrucción SQL. El siguiente gráfico muestra la ventana del inspector de objetos con las propiedades de Query2 y la instrucción en SQL adecuada. Note los dos puntos (:) que están antes del campo “Numero_Tran”. Los dos puntos determinan que el contenido del numero de la transacción se obtendrá de la fuente de datos escrita en la propiedad DataSource del objeto Query2.

Resultado de la ejecución del programa.

Contenido de la propiedad SQL (no mostrada): SELECT * From Cuerpo Where Numero_Tran = :Numero_Tran;

Fuente de datos para la tabla tipo “Maestro”. En este caso la tabla Cabeza.

Page 92: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 77

Control de Integridad de Referencia. La integridad de referencia es fundamental para un buen procesamiento de datos. El mantenimiento de un alto nivel de integridad de los datos es logrado aplicando este concepto en el diseño y manipulación de tablas. La integridad de referencia “consiste en garantizar que cualquier clave foránea se corresponde con una clave primaria”1 en otra tabla. El control de integridad de referencia “lo ha de conseguir el Gestor sin el concurso de la aplicación y es particularmente importante en una Base de Datos relacional ya que los accesos con SQL iteractivo desde un terminal no están sujetos a ningún control”2. La situación ideal es que el manejadores de bases de datos (MBD) realice las operaciones de control sobre los datos. Si el control se ejecuta solo desde la aplicación, existen posibilidades que un usuario no autorizado, utilizando herramientas fuera del sistema, puede violar los controles de integridad y actualizar datos equivocadamente. En la mayoría de los manejadores de bases de datos (MBD) actuales existen herramientas para reforzar el concepto de integridad de referencia cuando se diseña la estructura de datos, por medio de comandos de definición de datos (DDL). Pero existen algunos MBD que no tiene la capacidad de definir y controlar la integridad de los datos. En este ultimo caso Delphi ofrece comandos (métodos) que por medio de eventos pueden mantener el control de la integridad. En el caso de nuestra base de datos ejemplo, podemos controlar la integridad de referencia cuando se esta actualizando un Código de la tabla Maestro en el formulario de actualización de transacciones (tabla Cuerpo). Al incluir o modificar un registro en la tabla Cuerpo, debemos verificar que ese Código exista en la tabla Maestro. De igual forma, la actualización de un Código en la tabla Maestro debe ser evaluada para evitar que transacciones queden con códigos equivocados.

Page 93: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 78

La implementación de rutinas para validar la integridad de datos al nivel de la aplicación también nos sirve para ejemplificar el uso de los eventos relacionados con los objetos Table y Query. La ventana del inspector de objetos, mostrando los eventos del objeto Table, se presenta a continuación.

Después de cancelar una operación. Después de cerrar una tabla. Después de eliminar un registro. Después de entrar en el modo de edición. Después de insertar un registro Después de abrir la tabla Después de grabar un registro. Después de cambiar (navegar) de registro. Antes de cancelar una operación. Antes de cerrar una tabla. Antes de eliminar un registro. Antes de editar un registro Antes de insertar un registro. Antes de abrir una tabla. Antes de grabar un registro. Antes de cambiar (navegar) de registro. En momento de calcular campos. En momento de un error de eliminación. En momento de un error de editar registro. En momento de filtrar registros. En momento de añadir un registro. En momento de un error de actualización. En momento de responder al servidor. En momento de errores de cambios en lote. En momento de cambiar registros en lote.

Responder “Después”, “Antes” ó “Durante” la ocurrencia de un evento (acción) sobre una tabla.

Page 94: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 79

Es importante resaltar el hecho de que un objeto puede estar relacionado con otros objetos. Por ejemplo, el objeto Tabla_Maestro representa la tabla Maestro y él a su vez tiene asociados otros objetos. Estos objetos internos son todos los campos que tiene la tabla Maestro. Cuando se inserta el objeto Tabla_Maestro en el formulario (modulo de datos) también se incluyen los objetos que representan a los campos de la tabla. En este caso el objeto Maestro posee tres campos y por lo tanto Delphi declara los siguientes objetos de campos:

• Tabla_MaestroCodigo: Campo Código. • Tabla_MaestroDescripcion: Campo Descripción. • Tabla_MaestroSaldo: Campo Saldo.

Al igual que el objeto Tabla_Maestro, los objetos de campos también poseen un grupo de propiedades, eventos y métodos. Las validaciones de integridad que se realizaran contemplan el uso de los siguientes eventos:

• BeforePost (Objeto tabla Transacciones): Antes de intentar grabar (incluir o modificar) un registro en la tabla de transacciones se debe buscar y verificar la existencia del campo Código en la tabla Maestro.

• BeforeDelete (Objeto tabla Maestro): Antes de intentar eliminar un registro de la tabla Maestro se debe verificar que no hay transacciones en la tabla Cuerpo que posean ese código.

• BeforeEdit (Objeto tabla Maestro): Antes de modificar un registro de la tabla Maestro se debe guardar temporalmente el valor del código actual (el que va ser cambiado) para usarlo en el evento OnValidate del objeto Tabla_MaestroCodigo (el campo Código de la tabla Maestro). La variable “Codigo_Anterior” se utilizara para almacenar temporalmente el valor del campo código antes de cualquier edición.

• OnValidate (Objeto Tabla_MaestroCodigo del objeto tabla Maestro): En el proceso de validación de un registro de la tabla Maestro se debe verificar que si cambio el código del maestro, el código anterior no tenga transacciones. Si hubo una modificación del campo, se debe

Page 95: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 80

utilizar el código anterior para validar (que ese código anterior) no tenga transacciones.

La implementacion de estos eventos clarificara cualquier duda que se

tenga sobre ellos. El siguiente gráfico muestra el modulo de datos donde se declararon las tablas y fuentes de datos, el inspector de objetos con información sobre el objeto Tabla_Cuerpo y el formulario de manipulación de transacciones.

El inspector de objetos muestra la asignación del evento BeforePost. Para seleccionar y utilizar un evento, posiciones el ratón sobre el nombre del evento deseado y pulse doble click. Delphi asignara y creara un procedimiento vacío en Pascal. El nombre del procedimiento es la

Page 96: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 81

concatenación del nombre del objeto (en este caso Tabla_Cuerpo) y el nombre de evento (BeforePost). El nuevo procedimiento (Tabla_CuerpoBeforePost) se muestra a continuación. Las líneas de programación necesarias para validar la existencia del código en la tabla maestro cuando se actualiza la tabla cuerpo se encuentra escrito. Secuencias de programación: 1. Asignación temporal del nuevo contenido del campo código a la

variable “Clave”. El nombre del objeto Tabla_CuerpoCodigo representa el campo código. La propiedad “Value” es el contenido actual de ese campo.

2. Utilizar el método “Locate” (localizar) del objeto Table para buscar

en la tabla maestro el nuevo código. El método retorna “True” si encontró la clave en la tabla. Los parámetros de entrada del método son: • Lista de los nombres (separados por “;”) de campos a buscar. • Lista de contenidos de campos a buscar. • Conjunto que define el tipo de búsqueda. ü Sensitivo a mayúsculas. [loCaseInsensitive]. ü Búsquedas parciales. [loPartialKey].

1

2

3

Page 97: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 82

3. Si la clave (código) no existe, mostrar un mensaje de error y abortar la actualización del registro de la tabla cuerpo. La implementación del evento BeforePost (antes de grabar o

actualizar) garantiza que cualquier acción de incluir o editar un registro de transacciones, exista una validación de integridad con respecto a la tabla maestro. También hay que implementar la verificación de integridad en sentido contrario, desde la tabla maestro a la tabla de transacciones (cuerpo).

El nuevo procedimiento (Tabla_MaestroBeforeDelete) se muestra a

continuación. Cuando se trata de eliminar un registro del maestro, el evento BeforeDelete se activa. En este evento se verifica que no exista el código del maestro en un registro de transacciones (tabla Cuerpo). Las líneas de programación necesarias para validar la existencia del código en la tabla cuerpo cuando se actualiza la tabla maestro se muestran a continuación:

1. Asignación temporal del contenido del campo código (del maestro) a

la variable “Clave”. El nombre del objeto Tabla_MaestroCodigo representa el campo código del registro de la tabla maestro que se

1

2

3

Page 98: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 83

intenta eliminar. La propiedad “Value” es el contenido actual de ese campo.

2. El método “Locate” (localizar), del objeto Table, busca en la tabla cuerpo el código, contenido en la variable “Clave”. El método retorna “True” si encontró la clave en la tabla cuerpo.

3. Si la clave (código) no existe, mostrar un mensaje de error y abortar la actualización del registro de la tabla cuerpo. El próximo paso seria validar que la modificación de un código del

maestro no genere inconsistencias con la tabla maestro. Por ejemplo, no podemos cambiar el código “00000” por “10101” por el hecho de que existen registros de transacciones asociados. La lógica de implementación puede ser guardar provisionalmente el contenido del campo código antes de ser modificado. En el momento que se trata de editar una tabla se genera el evento BeforeEdit. En este evento almacenamos el contenido del campo Código en una variable local al formulario (Codigo_Anterior). Esta variable se declara al principio del programa (cuerpo principal), donde se declara el formulario DataModule. El siguiente gráfico muestra el segmento de código donde se declara la

Page 99: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 84

variable Codigo_Anterior y la ventana donde se define el evento BeforeEdit para la tabla maestro.

El proceso de actualización (edición) de un registro de una tabla en

Delphi cumple con la invocación de los siguientes eventos (si están implementados por el usuario): ü Ejecutar evento BeforeEdit. ü Ejecutar AfterEdit. ü Ejecutar OnCalcFields. ü Ejecutar validaciones (OnValidate) por cada campo del registro.

Si se actualiza el registro: ü Ejecutar BeforePost. ü Ejecutar AfterPost.

Si NO se actualiza el registro ü Ejecutar BeforeCancel ü Ejecutar AfterCancel El evento importante en este momento para nosotros es la validación

de cada campo del registro. En este caso la verificación del campo Código es determinante. En este evento de validación del campo Código se implementara la consistencia entre las tablas Maestro y Cuerpo. Si existen transacciones para el código que se desea cambiar, se abortara el proceso de actualización. Los siguientes segmentos de pantallas muestran

Page 100: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 85

como ver y seleccionar el evento Validate para el campo código. Al pulsar doble “Click” sobre el objeto tipo tabla “Tabla_Maestro” del formulario DataModule, se despliegan todos los campos de la tabla, luego se selecciona el campo código y presionando F11 se puede ver el inspector de objetos para ese objeto seleccionado. En la pestaña correspondiente se observan los diferentes eventos que pueden existir para el objeto Tabla_MaestroCodigo. El contenido que debe tener este evento para validar la integridad de referencia se muestra a continuación.

En la implementación del evento se puede observar que la secuencia

de instrucciones son muy parecidas a las anteriores. Es importante resaltar que en este evento también se puede escribir el código necesario para realizar cualquier otro tipo de validación que la aplicación requiera. Por ejemplo, si deseamos validar que el campo código tenga como primer carácter una letra en mayúscula y no un numero podemos escribir las siguientes instrucciones:

Valor := Sender.Value {contenido del campo} If NOT (Valor[1] IN [‘A’..’Z’]) Then Begin ShowMessage(‘Mensaje de error.....’); Abort End;

Page 101: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 86

Búsqueda Rápida de Información. En ciertas aplicaciones es conveniente navegar o revisar registros de una tabla. Delphi ofrece alternativas sencillas de buscar registros utilizando datos introducidos por el usuario. Por ejemplo, el siguiente formulario fue generado por el asistente de formularios “Form Wizard”. Para revisar el contenido de cada transacción se utiliza el objeto navegador de base de datos. Para ir al cuarto registro es necesario pulsar el botón de “próximo” registro varias veces. Una alternativa es utilizar un objeto que nos permita ir a un registro en especifico cuando el usuario introduzca datos que identifiquen al mismo. El siguiente formulario presenta el mismo formulario pero con un objeto MaskEdit. Cuando el usuario introduce información en este objeto, el evento OnChange se activa y busca en la tabla cabeza un registro cuya clave sea igual o parecida a la información almacenada en el objeto MaskEdit. El método Locate del objeto Tabla_Cabeza utiliza búsquedas parciales (loPartialKey) y no sensitivo a mayúsculas (loCaseInsensitive).

Page 102: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 87

Uso de Catalogos en Formularios.

Cualquier aplicación de manejo de datos debe utilizar técnicas de selección de datos desde tablas foráneas. Por ejemplo, en el formulario de Transacciones antes mostrado es conveniente poder seleccionar un registro de la tabla Maestro para utilizarlo en la tabla de cuerpo o detalle de transacciones. Existen varias alternativas en la implementacion de catálogos, entre ellas tenemos las siguientes opciones en nuestro formulario de transacciones para el objeto celdas (DBGrid del cuerpo o detalle de transacciones) : Ø Definición estática del rango de valores a ser seleccionados. Ø Definición dinámica del rango de valores a ser seleccionados. Ø Uso de formularios como “dialogo” para seleccionar valores. Definición estática del rango de valores a ser seleccionados. Esta alternativa sugiere que el usuario selecciona de un conjunto finito de valores. El conjunto de valores es previamente introducido en momento de diseño del formulario. Por ejemplo, el siguiente gráfico muestra el formulario de transacciones donde en el momento de tratar de editar el campo “Codigo” del DBGrid un botón es dibujado por donde el usuario puede seleccionar un rango de valores para este campo. Los valores “00002” y “00003” fueron previamente definidos como los datos que puede ser seleccionados. Al pulsar el botón una lista con los valores predefinidos es desplegado. El siguiente gráfico muestra esta acción:

Page 103: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 88

Las operaciones que deben realizarce para definir esta característica en el DBGrid de la tabla Cuerpo del formulario de transacciones son las siguientes: Ø Seleccionar el objeto DBGrid. Ø Doble “Click” sobre el objeto DBGrid o pulsar el botón derecho del

ratón cuando se este sobre el objeto y seleccionar la opción del menú “Column Editor” (Editor de Columnas). En ambos casos se muestra el editor una ventana con los nombres de las columnas que conforman el DBGrid. Si no aparecen los nombres de las columnas pulsar el botón de añadir campos. Seguidamente se muestra la ventana del Editor de Columnas (Delphi 4).

Valores Predefinidos

Borrar Columnas Nueva Columna Añadir Columnas Restaurar Valores

Columna seleccionada

Page 104: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 89

Ø Cada columna es un sub-objeto (objeto de la clase Tcolumn) del objeto principal DBGrid, por lo tanto una columna posee propiedades como cualquier otro objeto. Una de las propiedades de los objetos “Column” es “PickList” (Lista de Selección). En esta propiedad se pueden almacenar valores para ser desplegados en momento de ejecución. Seguidamente se muestra la lista de propiedades del objeto “Columna Codigo” que esta seleccionado en la ventana anterior (Editor de Columnas). Al seleccionar el atributo “PickList” se despliega un editor para modificar o incluir los valores que tendrá la lista de selección. La ventana del Inspector de objetos y la ventana del Editor de “Strings” se muestran a continuación. Los valores “00002” y “00003” se encuentran ya incluidos (escritos por el programador).

Nota: La propiedad “ButtonStyle” que se encuentra en el inspector de objetos define el estilo del botón que se mostrara si la columna tiene valores en la propiedad “PickList”. Los valores pueden ser: 1. CbsAuto : Un “combobox” se despliega con los valores predefinidos. 2. CbsEllipsis : Un botón con elipses se despliega y se ejecuta el evento

“OnEditButtonClick” (mas sobre este evento en próximas secciones). 3. CbsNone : No se despliega ninguna lista de selección.

Page 105: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 90

Definición dinámica del rango de valores a ser seleccionados. Otra alternativa del uso de catálogos en un DBGrid es que en momento de ejecución se asignen los valores a la lista de selección (PickList) para una columna especifica. La opción anterior asignaba los valores en momento de diseño del formulario. El evento “OnCreate” (cuando se crea el formulario) es adecuado para inicializar valores inmediatamente después de crear un formulario en memoria en tiempo real (corrida del programa). La ventana del Inspector de Objetos (para el objeto Formulario y la definición del evento OnCreate se muestran a continuación.

En el Editor de Codigo se puede observar que hay dos líneas que

asignan al objeto DBGrid1 (Celdas del area de detalle, tabla cuerpo), sub-objeto Columns (columnas del DBGrid), sub-objeto primera columna (Items[0]) , a la propiedad PickList el valor “00002” y el valor “00003). Las columnas son enumerados desde cero (0) al numero de columnas menos uno (1). Cada columna es un sub-objeto Items del objeto Columns (todas las columnas de un objeto DBGrid).

Estas dos alternativas de asignacion de valores a una columna de un objeto DBGrid son poco flexibles. Una variante de esta segunda alternativa es leer de la tabla foránea (Maestro en este caso) todos los registros y añadir los valores adecuados en el PickList. En la siguiente ventana se muestra las líneas de código fuente necesarias para incluir el

Page 106: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 91

campo Codigo de la tabla maestro al PickList del DBGrid – Columna Cero (columna “Codigo”),

En el procedimiento anterior la tabla Maestro es secuencialmente

leída y por cada registro se añade el campo código de cada registro. Se pueden aplicar cualquier tipo de criterios para la selección de registros. También es posible añadir mas de un campo en la lista de selección. Por ejemplo, la siguiente línea de código añade el código y descripción a la lista de selección (PickList) separados por un guión. DBGrid1.Columns.Items[0].PickList.Add(Tabla_MaestroCodigo.Value+

' - '+ Tabla_MaestroDescripcion.Value La próxima alternativa es la mas adecuado por su flexibilidad. Utilizaremos otro formulario para seleccionar el valor del campo código.

Page 107: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 92

Uso de formularios como “dialogo” para seleccionar valores. La Ultima alternativa que mencionaremos para manipular catálogos es la mas flexible pero requiere un poco mas de trabajo. El objetivo es crear un formulario que muestre el contenido de la tabla Maestro y usando el ratón se selecciona un código de maestro para ser utilizado como contenido del campo código de maestro en la tabla Cuerpo. El siguiente gráfico muestra el formulario que utilizaremos para mostrar el catalogo del maestro y la ventana del Inspector de Objetos desplegando las propiedades del botón “Ok”.

Un formulario puede ser mostrado en pantalla en un modo normal o en modo “modal” (tipo dialogo). Cuando un formulario es presentado en modo modal, el usuario no puede cambiar de ventana hasta que no termine de procesar la ventana. Por ejemplo, el usuario debe pulsar el botón “Ok” para poder cerrar la ventana. La manera de mostrar un formulario en estas dos alternativas son: Ø Modo Normal : Formulario.Show. Ø Modo Dialogo : Formulario.ShowModal.

Page 108: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 93

En el formulario de transacciones se mostrar el catalogo del maestro en modo Dialogo (Forma_Maestro.ShowModal). En un formulario presentado en forma de dialogo debe por lo menos existir un botón que retorne un valor que determine como se cerro la ventana. Esta caracteristica se denomina “ModalResult”. Delphi define varios tipos de resultado del cierre de un formulario mostrado con el método “ShowModal”. Entre ellas tenemos:

Ø mrNone : Nada Ø mrOk : Correcto. Ø mrCancel : Cancelar. Ø mrAbort : Abortar. Ø mrRetry : Re - intentar Ø mrIgnore : Ignorar. Ø mrYes : Si. Ø mrNo : No. Ø mrAll : Todos.

Dependiendo del tipo de resultado, el formulario que mostró el

formulario tipo dialogo toma una vía de acción determinada. En nuestro caso, y como se muestra en el gráfico anterior, el botón “Ok” tiene definido la propiedad de retorno del ModalResult como “mrOk”. El botón “Cancelar” retorna el ModalResult de “mrCancel”.

A un objeto estándar de Delphi se le pueden crear nuevas propiedades. En el formulario maestro se define una nueva propiedad del objeto Tforma_maestro (el formulario) donde almacenaremos el contenido del campo Código del registro de la tabla Maestro que este siendo mostrado en el momento que se pulse el botón “Ok”. Seguidamente se encuentra todo el código fuente de esta unidad (Unit_Catalogo_Maestro) donde por medio de comentarios se describe como definir la nueva propiedad (Codigo_del_Maestro). Es importante destacar que esta nueva propiedad no esta disponible en el Inspector de Objeto ya que es solo para momento de ejecución.

Page 109: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 94

Page 110: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 95

El formulario de transacciones debe ahora ser modificado para poder manejar la presentación del catalogo de maestro. Los pasos son los siguientes:

Cambiar la propiedad “ButtonStyle”, de la columna “Código” que se encuentra en el DBGrid del formulario, a “cbsElipsis”. Al asignar este valor a la propiedad “ButtonStyle” el DBGrid ejecutara el evento “OnEditButtonClick” cuando se pulse el botón del “PickList” de cualquier columna. El siguiente gráfico muestra el Inspector de Objetos, Editor de Columnas y formulario de transacciones.

El siguiente paso consiste en escribir el código fuente para reaccionar al evento “OnEditButtonClick”. Seleccionando el DBGrid se pulsa F11 para mostrar el Inspector de Objetos y desde la pestaña de eventos se busca el evento “OnEditButtonClick” y se pulsa doble Click para mostrar el Editor de Código. El siguiente gráfico muestra el

Page 111: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 96

Inspector de Objetos y el Editor de Códigos donde se describen las acciones para reaccionar al evento.

La propiedad “SelectedField” del DBGrid posee la descripción del campo que este seleccionado en un momento determinado. Como este evento se puede disparar cuando cualquier columna tenga definida un PickList, se debe preguntar cual columna en especifico esta seleccionada en ese momento. También es relevante comentar la forma en que se muestra el formulario del catalogo de maestro. En este caso se utiliza el método “ShowModal” que retorna el resultado de cerrar la ventana. Si el resultado es “mrOk” significa que la propiedad “Codigo_del:Maestro” del objeto Forma_Maestro posee un valor: Antes de modificar el campo Tabla_CuerpoCodigo se debe validar que la tabla Cuerpo este en modo de edición. La propiedad “State” se utiliza para saber en que estado (inclusión, edición, navegación,...) se encuentra una tabla.

Page 112: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 97

Arquitecturas de Manejo de Base de Datos en Delphi.

Delphi ultiza diferentes estrategias de manipulación de datos dependiendo de donde se encuentren localizadas las tablas que maneja una aplicación. Una aplicación de manejo de base de datos desarrollada bajo Delphi puede ser clasificada en:

• Single – Tiered (un nivel) • Two – Tiered (dos niveles) • Multi – Tiered (tres o más niveles).

Aplicaciones tipo Single – Tiered (un nivel).

La aplicación y la base de datos comparten el mismo computador. El tipo de bases de datos Locales pueden ser Paradox, xBase, MsAccess o archivos planos.

Aplicaciones Tipo Two – Tiered (dos niveles).

La aplicación del cliente provee la interface del usuario para la captura de datos e interactua directamente con una base de datos remota por medio del BDE. Los procesos de manejo de base de datos son compartidos entre el cliente y el servidor de datos. Dependiendo del desequilibrio de responsabilidades el flujo de datos en la red puede crear problemas. El servidor coordina el acceso y actualización de datos requerida por muchos usuarios.

Page 113: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 98

Aplicaciones Multi – Tiered (tres o más niveles).

En este tipo de aplicaciones las funciones de manejo de base de datos son divididas, y distribuidas, en diferentes estratos. Varias computadoras tiene diferentes responsabilidades en cuanto a mantener la integridad de los datos procesados. En la forma más básica pueden existir tres niveles de procesamiento:

1. Aplicación Cliente:

Provee la interface GUI en la maquina local del usuario.

2. Servidor de Aplicaciones: Provee servicios comunes de distribución de datos a todos los clientes (MIDAS - Multi-tier Distributed Application Services Suite (MIDAS).) estando ubicado en la red. Este servidor puede utilizar diferentes protocolos (TCP/IP, DCOM, MTS, o CORBA) para comunicación con los clientes.

3. Servidor Remoto de Base de Datos. Provee el manejador de base de datos relacional (RDBMS).

Delphi puede ser usado para crear tanto la Aplicación Cliente como

también el Servidor de Aplicaciones. Bajo esta arquitectura también se puede crear niveles adicionales para centralizar el control de funciones especificas como lo son los servidores de Internet y servidores de seguridad. Los diferentes elementos que presenta esta arquitectura son:

Page 114: Tecnicas de Programacion Visual Usando Delphi

Manejo Avanzado de Base de Datos. 99

• Modulo de Datos Remoto: Modulo de datos especializado que actúa como un servidor COM o servidor CORBA para darle a la aplicación cliente acceso a los componentes “Provider”

• Objetos (componentes) “Provider”: Un agente o negociador de datos que provee paquetes de datos y resuelve actualizaciones suministradas por el clientes.

• Objetos de Manejo de Datos del Cliente: Componentes que utilizan rutinas de DBCLIENT.DLL en vez del BDE (Borland Database Engine) para manejar datos almacenados en paquetes.

• Objetos (componentes) de Conexión: Grupo de componentes que proveen la comunicación, por medio de diferentes protocolos, entre el cliente y el servidor.

Beneficios de Aplicaciones Multi – Tiered.

• Encapsulamiento de las reglas de negocios. Las normas de manipulación de datos se pueden mantener centralizadas en el nivel intermedio (Servidor de Aplicaciones) dejando el trabajo de integridad de almacenamiento al ultimo nivel (RDBMS).

• Aplicaciones de clientes livianas. La mayor parte del trabajo pesado de manipulación de datos la tienen los niveles intermedio y superior. Esto involucra menores costos de distribución y mantenimiento de aplicaciones finales.

• Procesamiento distribuido de datos. Cada nivel se encarga de una parte especifica de la responsabilidad de procesamiento de datos lo cual incrementa el rendimiento total en la red.

• Incremento en la seguridad. El nivel intermedio es ideal para implementar procedimientos de acceso y restricción de operaciones de manejo de datos.

Page 115: Tecnicas de Programacion Visual Usando Delphi
Page 116: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 100

Una de las características fundamentales de las actuales herramientas de programación visual es el uso de componentes o controles. Dependiendo de la herramienta podemos tener una variedad en el estilo de implementación de componentes. Por ejemplo, Visual Basic y Delphi utilizan componentes estándares como VBX y OCX. También es posible cada lenguaje visual utilice enfoques propietarios para desarrollar componentes. En esta sección se explicara como en Delphi podemos, primero, desarrollar componentes propietarios (de uso exclusivo en el ambiente de Delphi) y luego la creación de componentes “ActiveX” que puede ser incorporados en diferentes herramientas de programación. El desarrollo y uso de componentes es de suma importancia debido a que permite el compartimento de rutinas y objetos entre diferentes aplicación y usuarios. Cuando es evidente que un segmento de código fuente (con su respectiva interfaces GUI) se puede centralizar y encapsular y este código ser compartido entre diferentes niveles de la organización ó mejor vendido a usuarios de otras organizaciones es tiempo de pensar en el desarrollo de componentes. Delphi ofrece mas de 130 componentes que ofrecen una gran variedad aplicaciones. La mayoría de los componentes son propietarios, solo se pueden utilizar bajo el ambiente de programación Delphi. Otros componentes son del tipo ActiveX. Un componentes ActiveX es un conjunto de instrucciones compiladas que herramientas como Visual Basic, Delphi, Visual Fox, PowerBuilder, MS Access, etc., pueden incorporar y utilizar. La creación de componentes en Delphi es muy sencilla aunque el nivel de conocimientos para la creación de este tipo de herramientas en general involucra una gran variedad de experiencias en cuanto a las internalidades de programación en Windows. Creación de Componentes “Delphi.” Cuando el componente a ser creado se utilizara solo bajo Delphi, es recomendable el desarrollo del nuevo componentes usando formatos específicos para Delphi. Si luego surge la necesidad de compartir esa librería con otras herramientas visuales de programación es posible, y sumamente sencillo, convertir el componente Delphi en uno compatible con esas herramientas. Los componentes de Delphi son “clases” y la librería “VCL” es el conjunto de todas las clases (componentes) que posee Delphi. Por ejemplo, el componente Button (Botón) pertenece a la clase TButton y esta definida en la librería VCL del sistema. Cuando se desea crear un nuevo componente estamos definiendo una nueva clase para el sistema y se alojaría en las librerías VCL. Todo nuevo componente se deriva de una clase existente en el sistema. El lugar donde se almacenan los

Page 117: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 101

componentes se le denomina “Paquetes”. Por lo tanto cuando creamos un componente debemos almacenarlo en un paquete. Los componentes suministrados originalmente se encuentran agrupados, en diferentes paquetes, según su funcionalidad. Existe un paquete originalmente predefinido llamado dclusr40.dpk donde el usuario puede colocar nuevos componentes o también es posible crear un nuevo paquete. La mejor forma de entender la creación de componentes es describiendo los pasos involucrados en el proceso. Por ejemplo, si existe la necesidad de utilizar un componente, para ser utilizado en diferentes aplicaciones, donde se muestren todos los nombres de estados de Venezuela y podamos seleccionar uno de ellos. Podemos crear un componente basado en un “ComboBox” que contenga los nombres de los estados, tenerlo en la paleta de componentes y soltarlo en los formularios necesarios. Los pasos serian los siguientes:

Seleccione del menú principal la opción Component -> New Component. Un dialogo se desplegara en pantalla donde pedirá: • El tipo (clase) de ancestro que tendrá el nuevo componente

(TcomboBox para este caso). • El nombre la nueva clase para el componente (Ej., TEstados). • El nombre de la pestaña de la paleta de componentes donde se ubicara el

componente (Samples). • El nombre de la unidad de Pascal que se creara para implementar el

componente (Estados.pas). • La ruta de búsqueda (subdirectorio) donde se ubicara el componente

(C:\Estados). El siguiente gráfico muestra este dialogo: Nota: Según estándares de Delphi el nombre de una clase debe estar precedida por la letra “T”.

Page 118: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 102

Al pulsar “OK” el sistema creara la unidad Estados.pas donde existirá el código fuente necesario para implementar un componente basado en la clase TcomboBox. Por su puesto este código fuente implementa un componente con exactamente las mismas características de un ComboBox. Se necesita el escribir las instrucciones para crear el componente en memoria e inicializar la propiedad “Items” (heredada de la clase TcomboBox) para almacenar los nombres de los estados. El siguiente gráfico muestra la unidad Estados.Pas en su forma original creada automáticamente por el asistente de componentes luego de pulsar “OK”:

El próximo paso consiste en escribir el código fuente para crear el

componente en memoria. Se debe sobre-escribir el método “Create” y “CreateWnd” heredados de la clase “TcomBox” (ver gráfico de la derecha). En la sección de interface se declara el constructor del componente para redefinir el constructor original (Create) de la clase TcomboBox y otro procedimiento original (CreateWnd) de la clase que es invocado inmediatamente después de ser creado el objeto. También se define la propiedad “Style” que pertenece a la clase original para asignarle por

Page 119: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 103

defecto el estilo de presentación del componente. En este caso queremos asignarle el estilo “csDropDownList” que nos permite modificar o incluir nuevos valores en el área de edición del objeto. El usuario solo podrá seleccionar uno de los estados pero no modificar o escribir un nuevo estado. En la sección de implementación se escribe el código necesario para crear el objeto, asignar a la propiedad “Style” e inicializar la propiedad “Items” con los nombres de los estados.

El próximo paso consiste en finalmente compilar e instalar el nuevo componente. Se toma la opción Component -> Install Component del menú principal y el sistema presenta la siguiente ventana:

Al pulsar el botón “Ok” el sistema compila la unidad “Estados.pas” y si no hay problemas de compilación se agrega el componente en el paquete “Borland User Components” (archivo dclusr40.dpk) e instala el mismo en

Page 120: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 104

la pestaña “Samples” de la paleta de componentes. En caso de existir errores de sintaxis en la unidad, el sistema reporta el problema, y se presenta la siguiente ventana para, de nuevo, poder compilar la unidad.

El botón “Compile” se utiliza para compilar la unidad y crear el archivo “dclusr40.dpk” que es el paquete donde se almacenaría el componente. Los botones “Add” y “Remove” son para agregar otras definiciones de

componentes o eliminar un componente. Un paquete puede tener uno o varios componentes declarados. En este caso la sección inferior de la ventana muestra un solo componente (Estados.pas). Eliminación de Componentes de Delphi. Para eliminar un componente ya instalado en Delphi debemos seguir los siguientes pasos: • Cerrar cualquier aplicación que este abierta (File -> Close All). • Abrir el archivo de paquetes adecuado (File -> Open). En nuestro caso

el archivo “dclusr40.dpk”. • La ventana anterior se

despliega en pantalla, se presiona el botón “Remove” y la siguiente ventana es presentada en pantalla: Se debe seleccionar el componente a ser eliminado y presionar el botón “Ok” para ejecutar la eliminación del componente de la paleta y del sistema. El componente “TEstados” es sumamente sencillo, pero ejemplifica

algunos aspectos importantes sobre la creación de componentes de Delphi. El próximo ejemplo muestra el uso de otras técnicas, entre ellas tenemos: Ø La definición de propiedades con sus respectivos métodos “Get” y

“Put”. Ø El uso de otros componentes dentro del nuevo componente. El objetivo del nuevo componente es utilizar la clase TButton para crear

un reloj digital. La propiedad “caption” se utilizara para constantemente mostrar la hora. Un componente Ttimer actualizara la hora en su evento

Page 121: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 105

“OnTimer”. Una nueva propiedad “Activo” se encargara de activar o no el componente Ttimer y por supuesto actualizar o no la hora. Ejecutando la opcion Component -> New Component del menú principal se presentaría la siguiente ventana (mostrada con información ya escrita en el lado derecho de la hoja). El programa fuente se muestra a continuación.

Page 122: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 106

Creación de Componentes “ActiveX”

Un control ActiveX es una pieza de software que se integra a la funcionalidad de una aplicación anfitriona. Esta aplicación puede ser un programa desarrollado en C++Builder, Visual dBase, Visual Basic, InternetExplorer, Netscape Navigator, etc.. Delphi es suministrado con varios controles ActiveX para el manejo de gráficos y manejo de hojas de calculo. Después que un control ActiveX es incluido en el ambiente IDE de Delphi, se puede utilizar en cualquier formulario y modificar sus propiedades y reacción a eventos por medio del Inspector de Objetos. Un control ActiveX también puede ser utilizado en una pagina Web y manipulado por medio de documentos HTML. Delphi suministra dos asistentes para la creación de controles ActiveX. El primer es el “Asistente de Controles ActiveX” que permite la creación de controles a partir de componetes existentes en la librería VCL (componentes normales de Delphi) y también componentes Delphi creados por el usuario. El segundo asistente nos, llamado el “Asistente ActiveForm”, ayuda a crear controles ActiveX desde el principio utilizando un formulario donde se incluyen diferentes componentes para diseñar un control ActiveX basado en el componente TForm. El Asistente de Controles ActiveX genera una unidad de implementación que es un descendiente de dos objetos, el TactiveXControl para el nuevo control y la clase del objeto que es encapsulado. El Asistente ActiveForm genera una unidad de implementación que es un descendiente de TActiveForm.

La creación de un control ActiveX utilizando el primer asistente es un proceso muy simple. Después de crear un componente Delphi, pasos descritos en la sección anterior, se invoca el asistente pulsando la opción de menú “File - New”, la ventana mostrada en el lado derecha de la pagina será desplegada en pantalla. En la pestaña “ActiveX” se selecciona el icono “ActiveXControl” para mostrar la ventana del Asistente de controles ActiveX. La siguiente ventana muestra esta ventana.

Page 123: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 107

En el Asistente de Controles ActiveX, gráfico anterior, se debe dar información sobre el nombre de la clase (componente) que se va a utilizar como el ancestro del control así como también el nombre del nuevo control ActiveX, el nombre de la unidad, etc.. Un aspecto importante es que podemos decidir si el nuevo control tendrá información sobre la licencia, versión y/o formulario “Acerca”. Si por ejemplo queremos crear un componente ActiveX partiendo del componente TEstado que fue desarrollado en la sección anterior solo debemos suministrar la información sobre el nombre de la clase (primer campo de captura de datos en la ventana) y Delphi colocara el resto de la información por defecto. Por su puesto, estos datos pueden ser cambiados por el usuario. Al pulsar el botón “Ok”, un nuevo control ActiveX será creado con la información suministrada. El siguiente gráfico muestra la paleta de componentes, con el componente utilizado como ancestro y el Asistente de Controles ActiveX con los datos por defecto.

Page 124: Tecnicas de Programacion Visual Usando Delphi

Creación de Componentes. 108

Después de crear el control hay que compilarlo y guardarlo en disco. La opción “Proyect - Build” del menú principal nos permite compilar el nuevo control. El nombre por defecto del control será “EstadosXControl1.Ocx. El sigiente grafico muestra la opcion de compilar el control y el Editor de Codigos donde hay dos unidades. La primera unidad, EstadosXControl1, es una librería para inicializar la ejecución del control. Esta librería normalmente no se cambia. La segunda unidad es la implementación de las propiedades, metodos y eventos del nuevo control.

Ya el nuevo control existe en disco y Delphi lo incluyo en el registro de Windows. El ultimo paso consiste en agregar el control como un componente ActiveX de Delphi. La opción“Component – Install ActiveX Control” del menú principal se utiliza para tal fin. El siguiente gráfico muestra la ventana que es utilizada para seleccionar un control ActiveX, de los disponibles y registrados en Windows, e incluirloen la pestaña “ActiveX” de la paleta de componentes. En esta ventana se debe pulsar el boton “Add” para buscar el control OCX (ActiveX) y luego presionar el boton “Install”.

Page 125: Tecnicas de Programacion Visual Usando Delphi
Page 126: Tecnicas de Programacion Visual Usando Delphi

116

Sistema de Inventario

El siguiente capitulo trata de reforzar los conceptos introducidos en los temas anteriores con la explicación del desarrollo un pequeño sistema utilizando Delphi El planteamiento de un problema de procesamiento de datos de una empresa hipotética seria conveniente para ejemplificar los pasos a seguir en el desarrollo del sistema. En este caso tomaremos el típico problema de controlar la entrada y salida de mercancía en un sencillo sistema de inventario. Este sistema es conveniente puesto que presenta la utilización de tablas maestras, de movimientos y catálogos. Este ejemplo no trata de abordar todos los detalles de la elaboración de un sistema completo de control de inventario.

Planteamiento del Problema. “La empresa Sat-Conexiones C.A. tiene como actividad principal la instalación de equipos y accesorios electrónicos para la conexión de sistemas de televisión satelital a clientes locales. Un almacén de piezas y partes debe existir en la oficina principal para garantizar el suministro del servicio de señal de televisión a los clientes. Sat-Conexiones debe controlar no solo las entradas de mercancía, devoluciones, reposiciones, rebajas en existencia por deterioro o robo sino también la salida de equipos y partes para la instalación final a los clientes. El aumento de la cartera de clientes impacta directamente el factor critico de controlar adecuadamente el inventario”. Este sencillo problema de inventario debe tener como mínimo las siguientes entidades de datos:

v Maestro de Productos o partes. v Catalogo de Tipos de Movimiento. v Movimientos de Inventario.

En este sistema existen básicamente dos tipos de movimientos: la entrada de mercancía y por supuesto la salida. La entidad “Catalogo de Tipos de Movimiento” será utilizada para discriminar las diferentes variantes de entradas y salidas en los movimientos de inventario. Por ejemplo, seria conveniente diferenciar la salida de mercancía por deterioro de la misma de la salida de mercancía por robo o instalación a un cliente. El siguiente gráfico muestra el Diagrama Entidad – Relación que describe estáticamente las relaciones existentes entre las entidades.

Sistema de Inventario

Page 127: Tecnicas de Programacion Visual Usando Delphi

117

Sistema de Inventario

Diagrama Físico E – R del Sistema de Inventario.

La entidad lógica “Movimientos de Inventario” se dividió físicamente en dos entidades. La “Cabeza de Movimiento” posee la información centralizada sobre el movimiento (numero, fecha, descripción, tipo, etc.) y el “Cuerpo de Movimiento” mantendrá el detalle de los productos involucrados (código, descripción, cantidad, etc.). Según el diagrama sé esta asumiendo que la empresa agrupa los movimientos por el tipo de movimiento (Una Cabeza de Movimiento ES de un Tipo de Movimiento). Posiblemente la empresa introduzca un tipo de “Movimiento de Inventario” por día si la situación lo amerita. Por ejemplo, todas las entradas de reposición de inventario del día 10/10/1999 estarán agrupadas en un solo movimiento de inventario y todos los deterioros de mercancía detectados el mismo día en otro movimiento lógico de inventario.

1

Producto Cuerpo de Movimiento

1 0/N

Pertenece / Posee

Cabeza de Movimiento

1/N

Esta / Es Tipo de Movimiento

1

Esta / Tiene

0/N

Page 128: Tecnicas de Programacion Visual Usando Delphi

118

Sistema de Inventario

Tablas del Sistema. La estructura física de las tablas que utilizara el sistema de inventario serian: Productos Código Producto * Numero que identifica únicamente el producto Descripción Producto Breve descripción del equipo o parte. Existencia Mínima Cantidad mínima que debe existir como existencia. Existencia Máxima Cantidad máxima que debe existir como existencia. Punto de Reorden Cantidad bajo la cual debe ser repuesta la existencia. Total Entradas Total entradas del producto Total Salidas Total salidas del producto Existencia Actual Campo calculado: Total Entradas - Total Salidas Tipos de Movimiento Tipo Movimiento * Numero que identifica únicamente el tipo de mov. Descripción Descripción del tipo de movimiento Acción Determina como el movimiento afecta la tabla de

productos. Si la acción es: “E” se incrementan las entradas “S” se incrementan las salidas.

Cabeza de Movimiento Numero Movimiento * Numero que identifica únicamente el movimiento Fecha Fecha del Movimiento Descripción Descripción general del movimiento Tipo de Movimiento Tipo del movimiento Cuerpo de Movimientos Numero Movimiento * Numero que identifica únicamente el movimiento Código Producto * Numero que identifica únicamente el producto Descripción Producto Campo leído de la tabla de Productos Cantidad Unidades involucradas en el movimiento Nota: El “*” denota que el campo forma parte de la clave primaria de la tabla.

Recuerde que este ejemplo no representa un sistema completo de inventario.

Page 129: Tecnicas de Programacion Visual Usando Delphi

119

Sistema de Inventario

Creación Física de las Tablas.

El primer paso en el desarrollo de la aplicación consiste en crear las tablas o archivos. Delphi es una herramienta para, normalmente, ser usada en una estación “Cliente” donde podría existir un servidor de datos donde se ubiquen las tablas bajo un manejador de base de datos especifico. En este caso vamos a utilizar a “Paradox” que primero es el manejador más sencillo que podemos utilizar bajo Delphi y segundo las rutinas para definir y manipular los datos se suministran directamente en Delphi por el hecho de que son del mismo fabricante. Claro esta existen una gran variedad de rutinas también suministradas por Delphi para manejar tablas en MSAccess, xBase, Oracle, Informix, SyBase y prácticamente cualquier manejador de base de datos popular.

Delphi provee una herramienta llamada “Escritorio de Base de Datos” (DataBase Desdktop) que nos permite definir y manipular tablas de cualquier tipo de manejedor de base de datos. Esta herramienta se puede ejecutar tanto desde el ambiente integrado de Delphi (opción Tools – DataBase Desktop) como también desde el menú de inicio de Windows. Por medio del Escritorio de Base de Datos se creara la definición física de las tablas de nuestro sencillo sistema de inventario. Al ser invocada el Escritorio de BD se despliega una aplicación tipo MDI donde en el área de trabajo se puede crear y manipular tablas y definir bases de datos. El siguiente gráfico muestra al Escritorio de BD vacío.

NOTA: Es importante destacar que una vía alterna para definir las tablas a ser utilizadas en una aplicación es por medio de las herramientas del manejador de base de datos original. Si existiera Paradox o cualquier otro manejador en el computador, definiríamos las tablas por medio del DDL (Lenguaje de Definición de Datos) original y simplemente desde Delphi manipularíamos los datos.

El Escritorio de BD puede definir básicamente tres tipos de objetos de manipulación de datos: una consulta QBE (búsqueda por ejemplo), una instrucción en SQL o simplemente la descripción física de una tabla. Para definir las tablas se toma la opción “File – New – Table” del menú principal y

Page 130: Tecnicas de Programacion Visual Usando Delphi

120

Sistema de Inventario

luego aparece un dialogo donde se selecciona el tipo de manejador de base de datos original. En este caso tomamos la primera alternativa – Paradox 7. El siguiente gráfico muestra las opciones de menú requeridas y el dialogo respectivamente.

Después de seleccionar el tipo de tabla que se desea crear, el Escritorio de BD muestra una ventana donde podemos definir el diccionario de datos. La siguiente ventana muestra este dialogo donde se introducirán el nombre, tipo y tamaño de cada campo y por ultimo al presionar el botón “Save As...” le daremos el nombre físico a la tabla para ser almacenada en el subdirectorio de su predilección.

Los siguiente gráficos muestran la definición del diccionario de datos de las cuatro tablas que serán utilizadas en nuestro sencillo sistema de inventario.

Page 131: Tecnicas de Programacion Visual Usando Delphi

121

Sistema de Inventario

Tabla: Productos. Nota: Los campos claves se definen marcando un “*” en la ultima columna. El

campo “Existencia Actual” no esta descrito físicamente en la tabla porque es un campo calculado y su definición se realizara desde Delphi y no por medio del Escritorio de BD.

Tabla: Tipos-Movimiento.

Page 132: Tecnicas de Programacion Visual Usando Delphi

122

Sistema de Inventario

Tabla: Cabeza-Movimiento.

Tabla: Cuerpo-Movimiento Nota: El campo “Descripción Producto” es calculado desde Delphi.

Page 133: Tecnicas de Programacion Visual Usando Delphi

123

Sistema de Inventario

Es importante destacar que dependiendo del manejador de base de datos original el Escritorio de BD puede definir varias características adicionales. En la parte izquierda de la ventana del diccionario de datos se puede introducir los valores por defecto, mínimo, máximo y la mascara de edición de los campos. También podemos describir validaciones referenciales y campos de búsqueda automáticos. Estos mecanismos de validación las realizaría el manejador de base de datos y no seria necesario escribir líneas de código en Delphi para ello. El problema fundamental con esta estrategia es que existiría menos independencia de datos. La aplicación dependeria en parte de procesos de validación delegados y particulares al manejador de base de datos. Un futuro cambio de manejador involucraría un proceso más delicado y tedioso. La selección de la alternativa mas adecuada esta fuera del alcance de este documento.

Ambiente General del Sistema.

Antes de comenzar a trabajar con Delphi en la creación del sistema de inventario es conveniente describir brevemente la estructura general de la aplicación. Existen básicamente dos estilos que podemos utilizar para conformar el sistema:

ü Un formulario principal MDI con un sistema de menús donde se manejen formularios hijos que correspondan a cada una de las opciones de actualización de las tablas.

ü Un formulario SDI donde se encuentren las actualizaciones de todas las tablas. Un componente tipo “libro” puede ser utilizado para agrupar la manipulación de cada tabla. El siguiente gráfico muestra esta alternativa.

Page 134: Tecnicas de Programacion Visual Usando Delphi

124

Sistema de Inventario

La primera alternativa posee la principal ventaja que podemos centralizar la manipulación de cada tabla o proceso en formularios diferentes. La segunda alternativa no ofrece esta ventaja ya que todas la definiciones y manipulaciones serán almacenadas en un solo formulario pero tiene el beneficio que podemos fácilmente crear un componente “ActiveForm” y así poder utilizar nuestra aplicación a través de Internet o manejarlo desde otro ambiente visual como por ejemplo Visual Basic o PowerBuilder. En este caso tomaremos la primera alternativa. Crearemos una aplicación MDI para controlar la actualización de las tablas. La estructura del sistema seria de la forma siguiente:

El formulario principal tendrá un menú principal que crearía los

formularios de Productos, Tipos de Movimiento y Movimientos de Inventario. Estos formulario utilizarían un modulo de datos para agrupar y manejar las definiciones lógicas de las tablas respectivas. Como se mencionó en capítulos anteriores el modulo de datos juega un papel importante ya que nos ayuda a centralizar las definiciones y manipulaciones básicas de los datos. En este tipo especial de formulario se almacenan las reglas de uso de datos de la organización y puede ser fácilmente transferible a otros sistemas en el futuro.

Creación del Formulario Principal del Sistema.

El primer paso seria la creación de un formulario tipo MDI. Tomando la opción “File – New Application” del menú principal podemos crear una nueva aplicación con un formulario en blanco. Debemos cambiar varias propiedades de este formulario por medio del Inspector de Objetos. La propiedad “Caption” del formulario se cambiaría a “Sistema de Control de Inventario” y la más

Formulario Principal MDI

Modulo de Datos

Formularios Hijos para cada tabla

Page 135: Tecnicas de Programacion Visual Usando Delphi

125

Sistema de Inventario

importante, la propiedad “FormStyle” se tomaría el valor “fsMDIForm” denotando que este formulario es el formulario “padre” o principal de una aplicación MDI. Cabe resaltar que el Inspector de Objetos mostrara, dependiendo de la propiedad, los posibles valores para dicha propiedad. La ultima propiedad relevante hasta los momentos es el nombre del formulario. La propiedad “Name”, que determina el nombre del formulario, se inicializa, por ejemplo, con el valor de “Forma_Principal”. Después de tener un formulario MDI debemos crear el sistema de menú por medio del cual el usuario controlaría la manipulación de datos. Desde la pestaña “Standard” de la paleta de componentes tomamos el componente “MainMenu” y lo soltamos en el formulario principal. El siguiente gráfico muestra este componente sobre el formulario. En este momento tenemos un componente para definir un menú pero todavía no hay una descripción de los elementos que poseerá este sistema de menú. Al pulsar “dobleClick” sobre el componente MainMenu1 (nombre por defecto del componente) se desplegara el editor de menú donde se definirán las opciones que constituirán el sistema en sí. El siguiente gráfico muestra las diferentes opciones que manejara el sistema.

Hasta este momento tenemos definido las opciones del menú principal.

Todavía no hay asociadas ninguna acción con cada alternativa presentada en el sistema. Después de crear los formularios de manipulación de datos podemos terminar de definir las opciones de menú asociando el evento “Click” de cada opción con su respectivo formulario. Pero antes seria conveniente crear el modulo de datos y definiciones lógicas de las tablas a ser utilizadas en el sistema para luego definir los otros formularios.

Page 136: Tecnicas de Programacion Visual Usando Delphi

126

Sistema de Inventario

Creación del Formulario de Modulo de Datos. Un formulario de datos es creado tomando las opciones “File – New ”

del menú principal de Delphi y seleccionando la opción “Data Module” de la pestaña “New” del libro que se presenta en pantalla. El siguiente gráfico muestra esta ventana tipo “Libro”.

Un formulario en blanco se creara y mostrara en pantalla. En este modulo de datos vacío incluiremos tantos componentes del tipo (clase) “TDataSource” y “TTable” como tablas tengamos que procesar. También debemos definir el evento “OnCreate” de este formulario donde se abrirán dichas tablas. Desde la pestaña “Data Access” seleccionamos los componentes “DataSource” y “Table” y los soltamos en el modulo de datos. El siguiente gráfico muestra esta operación. Después de soltar un par de componentes Datasource y Table procedemos a inicializar las propiedades que nos vinculan a estos componentes con las respectivas tablas físicas. Las propiedades que hay que modificar, por medio del Inspector de Objetos, en ambos componentes para asociar las tablas serian las siguientes:

Page 137: Tecnicas de Programacion Visual Usando Delphi

127

Sistema de Inventario

Componente : Datasource.

Atributo Productos Tipo Mov. Cabeza Mov. Cuerpo Mov. Name: DS_Producto DS_Tipo_Mov DS_Cabeza_Mov DS_Cuerpo_Mov DataSet Producto Tipo_Mov Cabeza_Mov Cuerpo_Mov AutoEdit: False False False False Donde: Name: Nombre del componente. DataSet: Nombre lógico de la tabla. AutoEdit: Si automáticamente se entra en modo de edición. Componente: Table. Atributo Productos Tipo Mov. Cabeza Mov. Cuerpo Mov. Name Producto Tipo_Mov Cabeza_Mov Cuerpo_Mov TableName Producto.db Tipo_Mov Cabeza_Movimiento Cuerpo_Movimiento

DataBaseName C: \Inventario C: \Inventario C: \Inventario C: \Inventario

Donde: Name: Nombre lógico de la tabla/DataSet (nombre del componente). TableName: Nombre físico de la tabla. DataBaseName: Ubicación física de la tabla o nombre de la B.D.

El siguiente gráfico muestra el formulario de modulo de datos después de crear todo los componentes Datasource y Table correspondiente a cada tabla física del sistema y actualizar las propiedades arriba mencionadas.

El próximo paso consiste en definir la relación existente entre un

registro de la tabla Cabeza de Movimiento y uno o muchos registros de la tabla Cuerpo de Movimiento. El establecimiento de esta relación se realiza por medio de dos propiedades. La primera es la propiedad “MasterSource”. En la tabla Cuerpo de Movimiento escribimos el nombre de la fuente de datos que identifica la tabla “maestra”. En este caso la tabla principal o maestra es la tabla Cabeza de Movimiento. Por lo tanto escribimos “DS_Cabeza_Mov”

Page 138: Tecnicas de Programacion Visual Usando Delphi

128

Sistema de Inventario

como el nombre de la fuente de datos maestra. La segunda propiedad es “MasterFields”. Por medio de esta propiedad describimos como se establece la relación de los campos entre las dos tablas. Al seleccionar esta propiedad el siguiente dialogo será desplegado en pantalla:

En la parte superior de la ventana se presentan todos los campos que puede permitir el establecimiento de la relación. Se debe seleccionar un par de campos, uno de cada tabla, y pulsar el botón “Add” para que el sistema añada la relación en la parte inferior de la ventana. Este proceso se realiza tantas veces sea necesario para completamente definir la formo como un registro de la tabla maestra (Cabeza_Mov) se relaciona con uno o muchos registros de la tabla de detalle (Cuerpo_Mov). Cuando creamos un formulario de base de datos por medio del Asistente de “Formularios de BD” estas relaciones se establecen automáticamente. La siguiente ventana muestra la selección necesaria para el sistema de inventario.

Page 139: Tecnicas de Programacion Visual Usando Delphi

129

Sistema de Inventario

Como anteriormente mencionamos se debe definir el evento “OnCreate” del formulario de modulo de datos para abrir las tablas del sistema. El procedimiento consiste en primero seleccionar el formulario, segundo presionar la tecla de función F11 para invocar al Inspector de Objetos y por ultimo seleccionar la pestaña de eventos para buscar al evento “OnCreate” donde se escribirá el código fuente necesario para ejecutar el método “Open” de los componentes de clase TTable usados en el sistema. El siguiente gráfico muestra tanto el Inspector de Objetos como las instrucciones (ejecución de métodos) para abrir las tablas.

Definición de Campos Calculados.

Para ejemplificar el proceso de definición de campos calculados se usaran los campos “Existencia Actual” en la tabla de productos y el campo “Descripción Producto” en la tabla cuerpo o de detalle de movimientos. Para definir el primer campo calculado se selecciona la tabla de productos (componente de clase TTabla) y luego se pulsa “doble-click” con botón izquierdo del ratón mientras el apuntador esta sobre el componente. El Editor de Campos es desplegado en pantalla. En este caso no existen campos “lógicamente” definidos (ver siguiente gráfico) y por lo tanto se encuentra vacío. Para incluir los campos se pulsa el botón derecho sobre el Editor de Campos y un menú

Editor de Campos

Page 140: Tecnicas de Programacion Visual Usando Delphi

130

Sistema de Inventario

emergente será desplegado en pantalla. El gráfico anterior también muestra este menú. Al tomar la opción ”Add All Fields” del menú, Delphi lee todos los campos físicamente definidos de la tabla y los coloca “estáticamente” en el modulo de datos. El siguiente gráfico muestra al Editor de Campos con los campos leídos de la tabla física. Al realizar esta operación el sistema crea una imagen de los campos y los define como subobjetos del formulario de modulo de datos. Estos objetos poseen sus propias propiedades y eventos que pueden ser manejados por medio del Inspector de Objetos. Esta característica nos permitirá mas adelante definir eventos de validación a nivel de los campos.

Después de tener estáticamente definidos los campos podemos incluir un nuevo campo (calculado) a la estructura lógica que se encuentra en el modulo de datos. Volviendo a pulsar el botón derecho del ratón sobre el Editor de Campos se muestra el menú emergente que utilizamos anteriormente y tomamos en este caso la segunda opción “New Field”. La siguiente ventana será desplegada para definir el nuevo campo.

En este dialogo se suministra el nombre del nuevo campo en la parte

superior izquierda y Delphi coloca automáticamente el nombre del objeto o componente que representara el campo lógico (y calculado) que se esta definiendo. El nombre del componente “ProductosExistencia_Actual” esta constituido por un prefijo que es el nombre de la tabla y sufijo el nombre del nuevo campo. Este es el nombre que se utilizara para actualizar (calcular) el

Page 141: Tecnicas de Programacion Visual Usando Delphi

131

Sistema de Inventario

contenido del mismo. Es recomendable destacar que el resto de campos “estáticamente” definidos en el paso anterior también tienen la misma estructura para el nombre del componente, es decir, nombre del archivo mas el nombre físico del campo.

Ya tenemos declarado el nuevo campo calculado pero todavía falta por definir el calculo en sí. En el evento “OnCalcFields“, de la tabla de productos, se debe escribir el código fuente para realizar las operaciones de calculo. Usando el Inspector de Objetos y seleccionado este evento de la tabla de productos podemos escribir el calculo. La siguiente ventana muestra el Editor de Código donde esta la operación necesaria.

Los pasos para definir el segundo campo calculado son muy parecidos

al anterior. Se incluyen “estáticamente” los campos físicos como descripción lógica usando el Editor de Campos. Luego se agrega el nuevo campo, en este caso el campo “Descripcion_Producto” que es de tipo “String” y por ultimo se utiliza el evento “OnCalcFields” para realizar el calculo. Es relevante destacar que este calculo es un poco diferente al anterior. En este caso queremos leer de la tabla de productos, usando el campo “Codigo_Producto” de la tabla Cuerpo_Mov. Un componente de la clase TTable posee el método (entre muchos otros) “FindKey([clave])” que busca, a través del área de índices, un registro en la tabla. Si se encuentra el código de producto se inicializa el campo calculado con la descripción del producto, en caso contrario se coloca una constante que identifique el problema, por ejemplo “Producto No Existe”. Delphi realizara este calculo cada vez que sea necesario para mantener correctamente actualizados todos los campos calculados.

La siguiente ventana del Editor de Código muestra este calculo.

Page 142: Tecnicas de Programacion Visual Usando Delphi

132

Sistema de Inventario

La definición estática de todos los campos físicos de todas las tablas es

recomendable en la mayoría de los casos para fácilmente asignar eventos de validación o cambiar propiedades de los mismos en tiempo de ejecución. Recuerden que un modulo de datos también se definen validaciones y en general reglas de manipulación de datos a ser utilizadas en el sistema. Por lo tanto mas adelante tendremos que regresar a este formulario para definirlas en los respectivos eventos de las tablas y campos lógicos. Por los momentos debemos crear los formularios básicos de captura y edición de información.

Creación del Formulario de Productos.

El formulario de manipulación de datos sobre productos o partes puede ser creado por medio del Asistente para Formularios de Base de Datos (Database Form Wizard) pero en este caso tomaremos otra alternativa menos automatizada. Los pasos serian los siguientes:

Primero creamos un formulario en blanco utilizando el botón rápido (New Form) o tomando las opciones File – New Form del menú principal. El nuevo formulario en blanco se desplegara en pantalla.

En este formulario coloraremos los componentes de manipulación de datos adecuados para actualizar la tabla de productos. Dejemos que Delphi haga parte del trabajo por nosotros. Seleccionemos el modulo de datos por medio del botón rápido View Form

del menú principal y hagamos doble click con el ratón sobre el

Page 143: Tecnicas de Programacion Visual Usando Delphi

133

Sistema de Inventario

componente Ttable que representa la tabla de productos. Una ventana (Editor de Campos) mostrando la lista de campos que contiene la tabla se desplegara en pantalla. Seleccione todos los campos de la tabla Productos y arrástrelos (representado por la flecha roja del siguiente gráfico) al nuevo formulario. Al soltar los campos seleccionados en el Editor de Campos y Soltarlos en el formulario, Delphi detecta que se quiere utilizar el Modulo de Datos desde el nuevo formulario y preguntara si en verdad se desea usar el modulo. Al responder que “si”, Delphi incluirá la cláusula “Uses Unit_Modulo_Datos” en el código fuente del nuevo formulario y por ultimo creara tantos pares de componentes etiquetas (Tlabel) y cajas de edición (TDBEdit) que correspondan con los campos soltados en el formulario. El nuevo formulario, después de arrastrar los campos seleccionados desde el Editor de Campos, se presenta en la siguiente ventana. Nótese que las etiquetas fueron inicializadas con los nombres de los campos, lo cual puede que no sea muy elegante. También los campos fueron organizados verticalmente. Un pequeño arreglo de las etiquetas, por medio del Inspector de Objetos, y moviendo algunos campos en el formulario puede ayudar a que existe una mejor apariencia del mismo. La siguiente ventana muestra el resultado de estas modificaciones elementales sobre el formulario de productos (incluyendo el cambio de la propiedad

Page 144: Tecnicas de Programacion Visual Usando Delphi

134

Sistema de Inventario

Caption del formulario por “Productos). El próximo, y saludable, paso es guardar el formulario. Toma la opción “File – Save” del menú principal y guarde la unidad con el nombre “Unit_Productos” en el subdirectorio deseado.

Ya existen los componentes que nos permitirán manipular cada campo de la tabla productos pero necesitamos un navegador de tablas para poder incluir, modificar, consultar, eliminar o navegar por todos los registros de la tabla. Tómenos la pestaña de “Data Controls” de la lista de objetos disponibles y seleccionemos el objeto “Navegator”. El siguiente gráfico describe esta operación.

Page 145: Tecnicas de Programacion Visual Usando Delphi

135

Sistema de Inventario

El gráfico anterior también muestra el cambio de la propiedad “DataSource” del componente navegador de base de datos que determina sobre cual tabla las operaciones se realizaran. Antes de continuar se deben cambiar algunas propiedades del formulario y del proyecto en sí. Recuerde que estamos creando una aplicación tipo MDI (Interfaces de Múltiples Documentos). Este formulario de productos debe ser un formulario “hijo” del formulario principal. La propiedad “FormStyle” del formulario de productos debe ser cambiada a “fsMDIChild” la cual determina que el formulario es de tipo “hijo” en una aplicación MDI. El próximo paso consiste en definir el formulario de productos como “no auto-creado”. Al ejecutarce una aplicación, Delphi busca cuales formularios se deben crear automáticamente y cuales no. En una aplicación MDI de manejo de base de datos es recomendable que todos los formularios hijos (ej. productos, tipos de movimiento y movimientos de inventario) no se creen al arrancar la aplicación. Al tomar la opción “Proyect – Options” del menú principal, la siguiente ventana se desplegara.

En la parte inferior derecha de este dialogo es usado para determinar cuales son los formularios auto-creados y los que el programador debe crear como reacción de algún evento. En nuestro caso crearemos los formularios hijos como una respuesta de los eventos “OnClick” del menú principal del sistema. Note que el formulario de productos se movió a la sección de formularios disponibles (no auto-creados) en el área inferior derecha seleccionando el formulario que estaba en el lado inferior izquierdo y pulsando el botón que se encuentra en entre las dos áreas inferiores del dialogo. Debemos regresar al formulario principal para definir el evento “OnClick” de la opción “Archivos – Definiciones - Productos” de nuestro sencillo sistema de menús. Seleccione el formulario principal tomando las

Page 146: Tecnicas de Programacion Visual Usando Delphi

136

Sistema de Inventario

opciones “View – Forms – Formulario_Principal” desde el menú principal de Delphi y el formulario principal se desplegara en pantalla. Luego pulse “click” sobre la opción Archivo – Definiciones – Productos”. Un procedimiento en blanco se presentara en el Editor de Código donde se debe escribir el código necesario para crear el formulario y presentarlo en pantalla. Las siguiente ventanas muestran el menú principal del sistema y el Editor de Código.

La instrucción necesaria para crear una instancia de la clase TForma_Productos es el método “Create”. El parámetro Self significa que el formulario donde se ejecutara este método es el dueño del componente a ser creado. Las siguientes ventanas muestran al Editor de Código con esta invocación del método Create y en momento de ejecución la aplicación en sí.

Page 147: Tecnicas de Programacion Visual Usando Delphi

137

Sistema de Inventario

Antes de continuar con la creación de los otros formularios del sistema es conveniente detenernos en el formulario de productos para desarrollar algunas validaciones y configuraciones básicas:

ü Preguntar antes de eliminar un producto. ü Verificar que el producto que se desea eliminar no existe en las tablas de

Movimiento de Inventario. ü Verificar valores numéricos en total entradas, total salidas, existencia y

punto de reorden. ü Evitar la inclusión de códigos de productos duplicados.

Esta no es una lista exhaustiva de las posibles validaciones que debería tener el formulario pero nos ayudan a ejemplificar la manipulación de eventos desde Delphi.

Validación : Preguntar antes de eliminar un producto. 1. Seleccione el navegador de BD que se encuentra en el formulario de

productos. 2. Presione F11 para desplegar el Inspector de Objetos. 3. Cambie la propiedad “ConfirmDelete” de “True” a “False”. Esta

propiedad determina si el navegador preguntara si queremos eliminar un registro. El problema es que el mensaje lo presenta Delphi en ingles y queremos que, por su puesto, sea en español.

4. Muestre el formulario Modulo de Datos por medio de la opción “View – Forms” del menú principal de Delphi.

5. Seleccione el Objeto Ttabla que representa la tabla de Productos. 6. Presione F11 para invocar al Inspector de Objetos. 7. Seleccione el Evento “BeforeDelete” del componente. 8. Incluya el código fuente que se presenta a continuación en el Editor de

Código:

Page 148: Tecnicas de Programacion Visual Usando Delphi

138

Sistema de Inventario

La función MessageDlg presenta una ventana de dialogo, dependiendo sus características de los parámetros suministrados. La sintaxis de esta función es la siguiente:

function MessageDlg(const Msg: String; AType: TMsgDlgType;

AButtons: TMsgDlgButtons; HelpCtx: Longint): Word; Donde: § Msg : Mensaje a ser mostrado en pantalla. En nuestro caso “Desea

Eliminar Producto”. § Atype: Tipo de dialogo: Confirmación, Error, Información, etc. En

nuestro caso es de tipo “mtCOnfirmation” (confirmación). § Abuttons: Lo(s) Botone(s) a ser presentados en la ventana de

dialogo. Pueden existir uno o más botones. En nuestro caso se presentaran los botones Ok (mbOk) y Cancel (mbCancel).

§ HelpCtx: Apuntador al archivo de ayuda, si existe. § La función retorna el tipo de botón presionado por el usuario. El procedimiento “Abort” genera una excepción (error) y cancela la

ejecución del evento y toda la operación que genero el evento. En este caso la operación de tratar de eliminar un producto.

En momento de ejecución y después de pulsar el botón de eliminación del navegador de BD se desplegara el dialogo de confirmación. El siguiente gráfico muestra esta situación.

Page 149: Tecnicas de Programacion Visual Usando Delphi

139

Sistema de Inventario

Validación: Verificar que el producto que se desea eliminar no existe en las tablas de Movimiento de Inventario.

1. Muestre el formulario Modulo de Datos por medio de la opción “View – Forms” del menú principal de Delphi.

2. Seleccione el Objeto Ttabla que representa la tabla de Productos. 3. Presione F11 para invocar al Inspector de Objetos. 4. Seleccione el Evento “BeforeDelete” del componente. 5. Incluya el código fuente que se presenta a continuación en el Editor de

Código:

La primera sección del procedimiento es igual a la definida previamente

para verificar que se desea en verdad eliminar el registro actual de la tabla de productos. El segmento de código fuente que se encuentra enmarcado en el bloque de la sentencia “With” implementa una búsqueda (método Locate del componente Ttable) en la tabla “Cuerpo_Mov” (cuerpo de los movimientos de inventario) para verificar su existencia. Si existe el código de producto en la tabla Cuerpo_Mov la función “Abort” es invocada para cancelar la operación de eliminación.

Importante: Note la inicialización de la propiedad “MasterSource” en la implementación del procedimiento. Cuando, previamente, se crearon los componentes Ttable para las tablas cabeza y cuerpo del movimiento de inventario se establecieron dos propiedades para definir la relacion uno a

Page 150: Tecnicas de Programacion Visual Usando Delphi

140

Sistema de Inventario

muchos (1:N) entre un registro de la tabla cabeza y uno o muchos registros de la tabla cuerpo. La tabla “maestra” de “Cuerpo_Mov” es “Cabeza_Mov” y uno o varios campos comunes entre esas tablas mantienen la relación. La propiedad “MasterSource” de la tabla Cuerpo_Mov” fue inicializada con el nombre de la fuente de datos de la tabla “Cabeza_Mov”.

El establecimiento de esta relación determina, internamente, un filtro por medio del cual existen (lógicamente) solamente los registros de la tabla “Cuerpo_Mov” que están relacionados con el registro actual de la tabla “Cabeza_Mov”. Los otros registro del la tabla “cuerpo” momentáneamente no existen. A este concepto frecuentemente se le denomina “Late Binding” (enlaces dinámicos). El siguiente gráfico trata de mostrar que cuando el registro numero dos de la tabla cabeza esta siendo apuntado solo existen lógicamente dos registros en la tabla cuerpo, los otros registros están ocultos y no accesibles. Delphi realiza este trabajo por nosotros pero en este caso no queremos que esto ocurra. Si por ejemplo, el producto que deseamos eliminar se encuentra solamente en el cuerpo correspondiente al registro 3 de la cabeza (línea de detalle en rojo en el gráfico) y el registro 2 de la tabla cabeza es el que esta siendo apuntado en ese momento, una búsqueda (Locate) en la tabla “cuerpo” no lo encontraría y por lo tanto lo eliminaríamos del maestro de productos. Esto crearía una inconsistencia en los movimientos de inventario. Tendríamos movimientos de productos que no existen.

Esta es la razón por la cual momentáneamente eliminamos la relación entre las dos tablas (MasterSource:= nil) para poder buscar un código de producto en toda la tabla cuerpo y no solo en los registros que estén asociados a un determinado registro de cabeza. Al terminar la búsqueda restauramos la relación (MasterSource := Ds_Cabeza_Mov).

Registro 1 Registro 2 Registro 3

Tabla Cabeza

Detalle 1 de la cabeza 1 Detalle 2 de la cabeza 1 Detalle 3 de la cabeza 1

Detalle 1 de la cabeza 2 Detalle 2 de la cabeza 2

Detalle 1 de la cabeza 3 Detalle 2 de la cabeza 3 Detalle 3 de la cabeza 3

Tabla Cuerpo

Propiedad MasterSource

Page 151: Tecnicas de Programacion Visual Usando Delphi

141

Sistema de Inventario

Validación: Verificar valores numéricos en total entradas, total salidas, existencia y punto de reorden.

1. Muestre el formulario Modulo de Datos por medio de la opción “View – Forms” del menú principal de Delphi.

2. Seleccione el componente Ttable que representa la tabla de Productos. 3. Haga “dobleclick” sobre este componente. El Editor de

Campos se desplegara en pantalla mostrando todos los campos lógicamente definidos para la tabla productos. El siguiente gráfico muestra esta ventana.

4. Haga “click” sobre el campos “Total Entradas”. 5. Presione F11 para

invocar al Inspector de Objetos y seleccione el evento “OnValidate”.

6. Incluya el código fuente que se presenta a continuación en el Editor de

Código:

El parámetro “Sender” cuando se invoque este procedimiento (implementacion del evento de validación) apuntara al objeto que representa al campo “Total_Entradas” de la tabla productos. Seria equivalente a que escribiéramos “If ProductoTotal_Entardas.Value < 0”. Recuerde que el nombre de un componente de un campo de una tabla es inicializado por Delphi y consiste en el nombre lógico de la tabla mas el nombre físico del campo.

Page 152: Tecnicas de Programacion Visual Usando Delphi

142

Sistema de Inventario

Cada campo de la tabla debe tener una implementación de su evento “OnValidate” si deseamos validarlo. Por lo tanto el mismo procedimiento arriba descrito debe también ser realizado para los campos Total_Salidas, Existencia_Minima, Existencia_Maxima y Punto_de_Reorden. Es mas podemos validar que existencia mínima sea menor o igual que existencia máxima, existencia máxima sea menor o igual que existencia mínima o que el punto de reorden este entre los valores de existencia mínima y máxima. Las siguientes tres ventanas muestran la implementacion de estas validaciones.

Validaciones sobre el campo de Existencia Mínima.

Validaciones sobre el campo de Existencia Máxima

Page 153: Tecnicas de Programacion Visual Usando Delphi

143

Sistema de Inventario

Validaciones sobre el campo de Punto de Reorden.

Antes de finalizar con el formulario de productos es conveniente que cambiemos algunas unas propiedades y eventos de este formulario. La propiedad “Position” de un componente “Tform” define como será desplegado el formulario en el área de trabajo de una aplicación MDI o en pantalla en términos generales. En nuestro caso inicializar esta propiedad con el valor “poDesktopCenter” nos presentaría el formulario en el centro del área de trabajo.

La otro propiedad que nos ayuda a control la apariencia del formulario es la de “BorderIcons” que determina los botones de control que deben ser mostrados en la esquina superior derecha del formulario; o sea si podemos maximizar, minimizar, etc. el formulario. En nuestro caso es conveniente que el usuario no pueda maximizar porque no tendría una buena apariencia en general. Delphi no ajusta las posiciones de los componentes que están en un formulario cuando se maximiza. El gráfico a la derecha de la pagina presenta al Inspector de Objetos mostrando esta área de propiedades. El valor de la sub-propiedad biMaximize debería ser cambiada a “False”. La ultima modificacion que tomaremos en cuenta en el formulario de productos es sobre que hacer cuando se cierra el formulario. Siendo el formulario de productos tipo “hijo” de una aplicación MDI, Delphi asume que

Page 154: Tecnicas de Programacion Visual Usando Delphi

144

Sistema de Inventario

la operación de cerrar el formulario es simplemente minimizarlo. Esta asunción no es correcta para una aplicación MDI de manejo de base de datos. En el evento “OnClose” de un componente Tform podemos determinar el tipo de cierre del formulario. Este evento es invocado antes de cerrar un formulario y posee el parámetro “Action”. Este parámetro podemos inicializarlo con los siguientes valores:

caNone: No se permite cerrar el formulario. caHide: El formulario es solo escondido. caFree: El formulario es cerrado, liberando memoria. caMinimize: El formulario es minimizado

En nuestro caso asignaremos la constante “caFree” a parámetro Action. El siguiente gráfico muestra este cambio.

Ya que estamos en este evento deberíamos también decidir que hacer con la tabla productos cuando se intenta cerrar el formulario. Por ejemplo, si el usuario esta editando o insertando un registro, que acción tomar?, actualizar (método Post de un componente Ttable) o cancelar la operación (método Cancel). Lo más recomendable seria cancelar la(s) operación(es) que se estén realizando sobre las tablas del formulario. El siguiente gráfico muestra esta modificación sobre el evento “FormClose”.

Page 155: Tecnicas de Programacion Visual Usando Delphi

145

Sistema de Inventario

Validación: Evitar la inclusión de códigos de productos duplicados.

1. Muestre el formulario Modulo de Datos por medio de la opción “View – Forms” del menú principal de Delphi.

2. Seleccione el componente Ttable que representa la tabla de Productos. 3. Haga “click” sobre este componente para desplegar el Inspector de

Objetos. 4. Seleccione el evento “OnPostError”. 5. Incluya el código fuente que se presenta a continuación en el Editor de

Código:

Cuando ocurre un error (excepción) durante la actualización de un

registro, el evento “OnPostError” es invocado. El procedimiento que implementa la reacción a este evento posee tres parámetros: 1. DataSet : Apuntador a la tabla involucrada en el error. 2. E : El tipo de error o excepción. El código 9729 representa el error de

clave duplicada. 3. Action: La acción que se puede tomar. Las posibles acciones son: § daFail : Aborta la operación y presenta un mensaje de error § daAbort: Aborta la operación y NO presenta un mensaje de error § daRetry: Repetir la operación de actualización. Se asume que este

evento se trato de corregir las causas del error antes de asignar este valor al parámetro Action.

Cuando este evento es invocado por primera vez el parámetro “Action” es inicializado con el valor “daFail”. En nuestra implementación del evento se dejo este valor y se invoco el procedimiento “Abort” para primero mostrar nuestro mensaje de error en español de “clave duplicada” y luego cancelar la operación de actualización.

Page 156: Tecnicas de Programacion Visual Usando Delphi

146

Sistema de Inventario

Para completar los cambios o personalizaciones a los formularios del sistema que se han desarrollado hasta los momentos debemos modificar dos propiedades del formulario de productos que incrementarían la facilidad de manipulación del mismo por parte del usuario. La mayoría de los componentes visuales que posee Delphi tienen la facilidad de mostrar una ayuda o mensaje rápido cuando se coloca el apuntador del ratón sobre los mismos. En el caso del navegador de base de datos seria conveniente que si nos ubicamos sobre uno de sus botones, un mensaje se despliegue informando sobre la acción que puede realizar dicho botón. Estos mensajes son desplegados por dos a cuatro segundos. Por Ejemplo, el siguiente gráfico muestra al nevagador mostrando un mensaje cuando el ratón esta sobre el botón de ir al ultimo registro de la tabla.

Las propiedades que se utilizan para realizar esta acción en el navagador de base de datos son:

§ Hints: Almacena los mensajes correspondientes a cada botón en el orden de izquierda a derecha (ver siguiente gráfico).

§ ShowHints: Si el valor es “true” muestra los mensajes, si es “false” no muestra los mensajes.

Page 157: Tecnicas de Programacion Visual Usando Delphi

147

Sistema de Inventario

Creación del Formulario de Tipos de Movimiento El formulario de tipos de productos posee menos campos que el formulario de productos. Las validaciones son casi iguales que las ya explicadas dado que comparten una misma filosofía: actualizar una sola y sencilla tabla. La siguiente lista resumen los primeros cambios realizados en el formulario de productos aplicados al nuevo formulario de tipos de movimientos: 1. Crear formulario por medio de la opción File – New Form. 2. Guardar (salvar) el formulario a disco con el nombre “Unit_Tipos_Mov”. 3. Cambiar la forma de creación del formulario de Auto-Creado a NO auto-

Creado. (Opción Proyect-Options del menú principal). 4. Cambiar la propiedad Name del formulario a “Forma_Tipos_Mov”. 5. Cambiar la propiedad Caption del formulario a “Tipos de Movimiento”. 6. Cambiar la propiedad FormStyle del formulario a “fsMDIChild”. 7. Cambiar la propiedad BorderIcons – biMaximize del formulario a

“false”. 8. Cambiar la propiedad Position del formulario a “poDesktopCenter”. 9. Seleccionar el componente Ttable que representa la tabla de Tipos de

Movimientos, marcar sus campos y soltarlos en el formulario. 10. Buscar en la pestaña “Data Controls” de la paleta de componentes el

navegador de BD y soltarlo en el formulario. 11. Cambiar la propiedad DataSource del navegador a “DS_Tipo_Mov”. 12. Cambiar la propiedad ConfirmDelete del navegador a “false”.

El formulario debe tener la siguiente apariencia:

Note que para el campo “Acción” Delphi inserto (paso numero 9 en la lista anterior) un componente de la clase TDBEdit. Este campo fue definido

Page 158: Tecnicas de Programacion Visual Usando Delphi

148

Sistema de Inventario

como de tipo carácter y los valores lógicos deben ser “E” para “tipo de movimiento de entrada de productos” y “S” para “Tipo de Movimiento de salida de productos”. Podríamos dejarlo de esta forma y validar que solo se introduzcan los valores “E” o “S” en el evento “OnValidate” de ese campo. También podemos usar un componente de la clase TDBRadioGroup con la finalidad de presentar una interfaz más elegante al usuario.

Vamos a remplazar el componente correspondiente a la acción por uno de la clase TDBRadioGroup. Primero seleccionemos de la pestaña “Data Controls” un componente TDBRadioGroup y soltémoslo en el formulario, cerca del titulo “Accion”. Luego cambiemos las siguientes propiedades del nuevo componente (por medio del Inspector de Objetos):

Propiedad Nuevo Valor Observaciones Caption Acción Titulo del componente Name DbAccion Cualquier nombre para el componente Columns 2 Cantidad de columnas a ser mostradas DataSource DS_Tipo_Mov Fuente de datos DataField Accion Nombre del campo a ser actualizado Items Entrada Titulo del primer elemento Salida Titulo del segundo elemento Values E Valor a retornar del primer elemento S Valor a retornar del segundo elemento

Este componente, luego de ser configurado, presentara dentro de un recuadro las opciones exclusivas “Entrada” y “Salida” con sus correspondientes botones para seleccionar el valor que se depositara en el

Las propiedades Items y Values son actualizadas por medio del “Editor de Strings”.

Page 159: Tecnicas de Programacion Visual Usando Delphi

149

Sistema de Inventario

campo “Accion” de la tabla de tipos de movimiento. De esta forma no es necesario realizar ningún otro tipo de validación sobre la integridad de los datos ya que Delphi se encarga solo de filtrar entradas de tipo “E” o “S” para este campo. El formulario, luego de organizar el resto de componentes, luciría de la siguiente forma:

Ahora debemos conectar el formulario de Tipos de Movimiento con el menú principal del sistema. Al igual que con el formulario de productos, seleccionamos el formulario principal y hacemos “click” sobre las opciones de nuestro menú Archivos – Definiciones – Tipos de Movimiento”. El Editor de Código se desplegara en pantalla con un procedimiento en blanco para definir el evento “OnClick” asociado a la opción “Tipos de Movimiento” de nuestro sistema de menús. La siguiente ventana muestra la instrucción necesaria para realizar la tarea de crear y mostrar el formulario.

Recuerde que en Pascal el uso de unidades debe ser explícitamente definido. La Unidad que define el formulario de Tipos de Movimiento va ser usado por el formulario principal, por lo tanto, tiene que existir una sentencia “Uses Unit_Tipo_Mov” en la unidad del formulario principal. Esta operación puede ser realizada manualmente o tomando la opción “File – Use Unit” del menú principal de Delphi cuando tenemos seleccionado el formulario principal.

Page 160: Tecnicas de Programacion Visual Usando Delphi

150

Sistema de Inventario

Validaciones para la Tabla de Tipos de Movimiento.

Las validaciones básicas que deben existir para la tabla de Tipos de Movimiento y su formulario, al igual que en el modulo de productos, las podemos implementar en el modulo de datos. Estas validaciones son muy parecidas a las desarrolladas para la tabla de productos y seria las siguientes:

ü Preguntar antes de eliminar un tipo de movimiento. ü Verificar que el tipo de movimiento que se desea eliminar no existe en las

tablas de Movimiento de Inventario. ü Evitar la inclusión de tipos de movimiento duplicados.

A continuación se presentan las ventanas del Editor de Código con la implementación de los eventos que realizan las operaciones de validación.

Validaciones: § Preguntar antes de eliminar un tipo de movimiento. § Verificar que el tipo de movimiento que se desea eliminar no existe

en las tablas de Movimiento de Inventario Evento: “BeforeDelete” de la tabla “Tipo-Mov”.

Page 161: Tecnicas de Programacion Visual Usando Delphi

151

Sistema de Inventario

A diferencia de la implementación realizada para la tabla productos, en este evento no es necesario suspender ningún tipo de relación (1:N) porque la búsqueda se esta realizando en la tabla cabeza.

Validaciones: Evitar la inclusión de tipos de movimiento duplicados. Evento: “OnPostError” de la tabla “Tipo-Mov”.

En el formulario de producto se definió el evento “OnClose” para el

formulario. En este evento se determino que el formulario se cerraría completamente y cualquier operación de actualización de la tabla productos se cancelaría. Se debe desarrollar el mismo evento “OnClose” para el formulario de Tipos de Movimiento. El siguiente gráfico muestra la ventana del Editor de Código con la implementación de este evento.

Nota: Recuerde actualizar las propiedades Hints y ShowHint para que se muestren las ayudas rápidas sobre el componente de navegación de BD.

Page 162: Tecnicas de Programacion Visual Usando Delphi

152

Sistema de Inventario

Creación del Formulario de Movimientos de Inventario

El formulario de movimientos de inventario es el más importante del sistema. Este formulario se encargara de actualizar y resumir todas las entradas y salidas de productos de la empresa. Este formulario también nos sirve para ejemplificar el uso de cuatro tablas diferentes: Tipos de Movimiento, Productos, Cabeza de Movimientos y Cuerpo de Movimientos.

Primero debemos crear un nuevo formulario por medio de la opción “File – New Form” del menú principal o utilizando el botón rápido que se encuentra para tal fin. Recuerde que también podríamos utilizar el Asistente de formularios para crear nuestro nuevo formulario, pero vamos a tomar el camino mas largo.

Luego seleccionamos de la pestaña “Standard” dos componente de la clase “Tpanel” y los soltamos en el formulario. Esto es una cuestión de estilos. Los paneles nos ayudaran a que visualmente podamos diferencia las áreas en la superficie del formulario. El primer panel lo usaremos para mostrar los componentes de manipulación de datos. El segundo panel nos servirá para contener los componentes de comandos o acciones. Este estilo lo pudimos también haber usado en los otros formularios. La intención es presentar diferentes alternativas. En una aplicación formal debemos ser consistentes a través de todos los formularios. El siguiente gráfico muestra los dos paneles en el nuevo formulario.

Page 163: Tecnicas de Programacion Visual Usando Delphi

153

Sistema de Inventario

El próximo paso es cambiar varias propiedades del formulario y de los paneles.

1. Guardar (salvar) el formulario a disco con el nombre “Unit_Mov”. 2. Cambiar la forma de creación del formulario de Auto-Creado a NO

auto-Creado. (Opción Proyect-Options del menú principal). 3. Cambiar la propiedad Name del formulario a “Forma_Mov”. 4. Cambiar la propiedad Caption del formulario a “Movimientos”. 5. Cambiar la propiedad FormStyle del formulario a “fsMDIChild”. 6. Cambiar la propiedad BorderIcons – biMaximize del formulario a

“false”. 7. Cambiar la propiedad Position del formulario a “poDesktopCenter”. 8. Cambiar la propiedad Caption de los paneles por “” (valor nulo). No

queremos ningún titulo para los paneles. 9. Cambiar la propiedad Align del primer panel a “alTop” (posicionar el

panel siempre al tope del formulario). 10. Cambiar la propiedad Align del segundo panel a “alBottom”

(posicionar el panel siempre en el fondo del formulario). 11. Ajustar los tamaños de los paneles de tal forma que el primero sea más

ancho que el segundo. El formulario debería tener la siguiente apariencia.

12. Después de tener los dos paneles en el formulario procedemos a colocar

un componente DBNavigator (navegador de BD) en el segundo formulario y los componentes de manipulación de datos de la tabla cabeza en la parte superior del primer panel. En la parte inferior del primer panel ubicaremos un DBGrid (cuadricula de base de datos) para manipular los campos de la tabla cuerpo. El formulario debería tener la siguiente apariencia general.

Page 164: Tecnicas de Programacion Visual Usando Delphi

154

Sistema de Inventario

El componente DBNavigator nos servirá para manejar a la tabla “cabeza

de movimiento” por lo tanto le colocamos en su propiedad “DataSource” el nombre de la fuente de datos de la tabla “Cuerpo_Mov” el cual es “DS_Cuerpo_Mov”. De la misma forma inicializamos la propiedad “DataSource” del DBGrid a la fuente de datos de la tabla “cuerpo” (DS_Cuerpo_Mov) ya con este componente manipularemos esta tabla.

Al tener definida la fuente de datos del DBGrid podemos asignarle estáticamente las columnas que poseerá la cuadricula de base de datos. Al hacer “DobleClick” sobre el componente DBGrid, el “Editor de Columnas” se presentara en pantalla. Volviendo a usar el ratón podemos presionar el botón derecho para que se presente un menú emergente donde seleccionaremos la opción “Add All Fields” para crear los sub-componentes que representarían las columnas para cada campo de la tabla. También por medio del tercer botón rápido que se encuentra en la parte superior del Editor de Columnas es posible realizar esta operación. El gráfico a la derecha muestra al Editor de Columnas con todos los Campos/Campos agregados.

En el modelo relacional de base de datos las conexiones entre tablas se realizan por medio información común. En este caso la relación entre las tablas cabeza y cuerpo de movimientos poseen el campo en común “Numero_Movimiento” (y no necesariamente deben tener el mismo nombre). Recuerde que esta relación la establecimos previamente por medio de la propiedad “MasterFields” de la tabla “Cuerpo_Mov”. Estos comentarios van en relación que Delphi se encarga automáticamente de actualizar el o los campos que establecen la relación entre las tablas maestro – detalle. En este caso cuando incluimos un registro de la tabla “cuerpo”, Delphi

Page 165: Tecnicas de Programacion Visual Usando Delphi

155

Sistema de Inventario

automáticamente inicializa el campo “Numero_Movimiento” de la tabla cuerpo con el valor que tenga el campo “Numero_Movimiento” del registro actual de la tabla “cabeza”. Por esta razón el campo “Numero_Movimiento” de la tabla cuerpo no debe ser actualizado por el usuario y no debe existir como una columna en el DBGrid de nuestro formulario de movimientos de inventario. Debemos seleccionar el campo “Numero_Movimiento” del Editor de Columnas y pulsar el segundo botón rápido que se encuentra en la parte superior del Editor de Columnas. El gráfico a la derecha muestra la ubicación de este botón.

El ultimo paso necesario para probar el nuevo formulario seria conectarlo

con el menú principal del sistema. Seleccionemos el formulario principal y haciendo “click” sobre el menú buscamos la opción “Movimientos” y finalmente hacemos “click” sobre la opción para que el Editor de Código se despliegue en pantalla. En el procedimiento vacío que aparece en el Editor de Código escribimos la siguiente instrucción: TForma_Mov.Create(Self); para crear y mostrar, en momento de ejecución, en pantalla el formulario de movimientos de inventario.

Nota: Recuerde que este formulario también debe ser “No Auto-Creado” (Opción Proyect-Options del menú principal de Delphi).

El siguiente gráfico muestra en momento de ejecución la apariencia del formulario con algunos datos introducidos.

Botón de eliminar la columna seleccionada.

Page 166: Tecnicas de Programacion Visual Usando Delphi

156

Sistema de Inventario

El formulario no esta completamente funcional. Hay varias modificaciones que se requieren para que pueda ser utilizado satisfactoriamente por el usuario. La captura de datos sobre el campo “Tipo de Movimiento” puede ser drásticamente mejorada. Una lista desplegable puede ser utilizada para mejorar la interfaz con el usuario y a la vez garantizar la integridad de los datos. Un componente de la clase “TDBLookupComboBox” puede ser utilizado para tal fin.

Seleccione de la pestaña “Data Controls” de la paleta de componentes un objeto de la clase “DBLookupComboBox” y suéltelo en la parte superior derecha del primer panel del formulario. Luego cambiemos las siguientes propiedades del nuevo componente (por medio del Inspector de Objetos):

Propiedad Nuevo Valor Observaciones DataField Tipo_Movimiento Campo a ser actualizado

DataSource DS_Cabeza_Mov Fuente de datos (tabla) a ser actualizada

DropDownWidth 150 Ancho de la lista a desplegar

KeyField Tipo_Movimiento Campo clave de la tabla foránea

ListField Tipo_Movimiento;Descripcion Campos de la tabla foránea a mostrar

ListFieldIndex 0 Indice del campo foráneo a ser utilizado

ListSource DS_Tipo_Mov Fuente de datos de la tabla foránea

La tabla Tipo_Mov (tabla foránea) se utilizara para que el usuario seleccione de una lista de registros de esa tabla un registro especifico. La lista esta limitada a mostrar el sub-conjunto de campos definidos en la propiedad “ListField”. Cuando se realice la selección, la propiedad “ListFieldIndex” es utilizada para determinar cual campo de los definidos en la propiedad “ListField” va ser utilizado para actualizar el campo definido en la propiedad “DataField”. En momento de ejecución la apariencia de la lista, desplegada, seria la siguiente:

Page 167: Tecnicas de Programacion Visual Usando Delphi

157

Sistema de Inventario

Todavía estamos lejos de tener un formulario que cumpla con los requisitos

mínimos para el mantenimiento de la integridad de los datos. Se deben crear o modificar varios eventos para mejorar esta integridad y a la vez ofrecerle al usuario facilidades en el uso del sistema. Las tareas a ser tomadas en cuenta en el formulario de movimientos son:

ü Evitar la existencia de registros “cuerpo” de movimiento sin que existan sus respectivos registros de “cabeza”.

ü Evitar la existencia de un registro de “cabeza” de movimiento sin sus respectivos registros en “cuerpo”.

ü Verificar que el producto que se desea incluir existe en la tabla de Productos.

ü Verificar el valor numérico del campo “Cantidad”. ü Evitar la inclusión de “Movimientos” duplicados. ü Crear una ventana de dialogo para la actualización del código de producto. ü Búsquedas rápidas de movimientos. ü Actualizar “Cantidad” en el maestro de productos

Vamos a desarrollar cada una de estas tareas/validaciones con el objetivo de ilustrar el uso de eventos en la manipulación de tablas en una base de datos. Recuerde que muchas de estas operaciones pueden ser implementadas a nivel del manejador de base de datos que estemos utilizando pero existiría una dependencia mayor el mismo. Clara esta, la decisión de donde colocar las validaciones, a nivel del cliente o el servidor, depende en gran grado en las circunstancias especificas involucradas.

Evitar la existencia de registros “cuerpo” de movimiento sin que existan sus respectivos registros de “cabeza”.

Esta anomalía puede ocurrir cuando eliminamos un registro de la tabla “Cabeza_Mov” y no eliminamos todos los registros relacionados en la tabla “Cuerpo_Mov”. Seria muy negativo dejar una serie de registros en la tabla de detalle (Cuerpo_Mov) que no posean un registro maestro. En el evento “BeforeDelete” de la tabla “Cabeza_Mov” podemos implementar esta tarea.

La siguiente ventana del Editor de Código muestra como se debe realizar la operación de eliminación de un registro de la tabla “Cabeza_Mov” para garantizar la existencia de la relación “uno a muchos” (1:N) previamente establecida con la tabla “Cuerpo_Mov”.

Page 168: Tecnicas de Programacion Visual Usando Delphi

158

Sistema de Inventario

La implementación del evento esta tomando ventaja de la relación

establecida por medio de la propiedad “MasterFields” de la tabla “Cuerpo_Mov”, previamente descrita cuando creamos el formulario de productos, para eliminar todos los registros de la tabla de detalle. Recuerde que este evento ocurre exactamente “antes de eliminar un registro de la tabla “Cuerpo_Mov”. Inmediatamente después que se ejecute este evento, Delphi procederá a eliminar el registro actual de la tabla “Cabeza_Mov”.

Evitar la existencia de un registro de “cabeza” de movimiento sin sus respectivos registros en “cuerpo”.

Este problema se presenta cuando presionamos el botón de inclusión del

navegador de BD, suministramos los datos sobre la “cabeza” del movimiento e incluimos uno o varios registros del “cuerpo” del movimiento y por ultimo presionamos el botón de “cancelar” del navegador de BD. Cuando presionamos las teclas “flecha arriba” o “fecha abajo” en un DBGrid, el registro actual de la tabla del DBgrid es grabado a disco. Por lo tanto la tabla cabeza esta en modo de inclusión y no se ha grabado el registro a disco mientras el DBGrid puede ya haber grabado permanentemente el registro. La solución a este problema puede ser:

Page 169: Tecnicas de Programacion Visual Usando Delphi

159

Sistema de Inventario

§ No permitir “cancelar” la inclusión de un registro en la tabla “Cabeza_Mov” si existen registro relacionado en la tabla “Cuerpo_Mov”.

§ Eliminar todos los registros relacionados de la tabla “Cuerpo_Mov”, si existen, antes de proceder a “cancelar” la inclusión de un registro de la tabla “Cabeza_Mov”.

Cualquiera de las dos alternativas es aceptable. En nuestro caso tomaremos

la primera. En el evento “BeforeAction” del navegador de BD desarrollaremos el código fuente para esta operación. La siguiente ventana del Editor de Código muestra la implementación del evento.

También existe otra alternativa por medio de la cual podamos tener una

cabeza de movimiento sin lineas de cuerpo de movimiento. Presionando las tecla “CTRL-Supr” simultáneamente estando ubicados sobre un DBGrid es posible eliminar un registro de la tabla que manipula el DBGrid. Es factible que el usuario presione tantos “CTRL-Supr” con registros de “cuerpo” existen para un movimiento lógico de inventario y finalmente quedarnos sin registros “detalle”. Para solucionar este problema se implementa el evento “BeforeDelete” de la tabla “Cuerpo_Mov” para validar que el registro que se desea eliminar no sea el ultimo “registro lógico” del área de detalle. El siguiente diagrama muestra la implementación del evento “BeforeDelete” de la tabla “Cuerpo_Mov” donde se invoca el método “RecordCount” del componente Ttable. Este método retorno el numero de registro que posee la tabla. En nuestro caso, nos es útil porque nos determina si es el ultimo registro que estamos tratando de eliminar. El formulario en momento de ejecución también es mostrado.

Page 170: Tecnicas de Programacion Visual Usando Delphi

160

Sistema de Inventario

Verificar que el producto que se desea incluir existe en la tabla de Productos.

Para la tabla “Cuerpo_Mov” se creo el campo calculado “Descripcion_Producto” que almacena, temporalmente, la descripción de los productos que existan en la tabla de productos. Si por alguna razón no existe el código de producto, el campo calculado es incializado con la constante “Producto No Existe” y el procesamiento continua. Es conveniente no actualizar un registro de la tabla Cuerpo_Mov si el producto es invalido. La siguiente ventana del Editor de Código muestra la validación necesaria en el evento “BeforePost” de la tabla “Cuerpo_Mov” para evitar la actualización del registro en estos casos. El formulario en momento de ejecución también es mostrado.

Page 171: Tecnicas de Programacion Visual Usando Delphi

161

Sistema de Inventario

Verificar el valor numérico del campo “Cantidad”.

La tercera columna del DBGrid almacena el campo “Cantidad” de la tabla “Cuerpo_Mov”. Lógicamente, valores menores que cero (0) no deben ser permitidos en esta columna. La validación del contenido de un campo de una tabla se puede realizar en el evento “OnValidate” del componente que representa el campo en sí. Seleccione el componente Ttable de la tabla “Cuerpo_Mov” y presione “dobleclick” sobre el. El Editor de Campos se desplegara en pantalla mostrando todos los campos de dicha tabla. Seleccione el campo “Cantidad” y presione F11 para invocar al Inspector de Objetos con las propiedades y eventos del componente que representa al campo “Cantidad”. En la pestaña de eventos del Inspector de Objetos se encuentra el evento “OnValidate” que es donde se realizarían las validaciones a los campos de una tabla. La siguiente ventana del Editor de Código muestra la validación necesaria en el evento “OnValidate” del campo “Cantidad” de la tabla “Cuerpo_Mov” para evitar la actualización de dicho campo cuando su valor sea igual o menor que cero (0). El formulario en momento de ejecución también es mostrado.

Page 172: Tecnicas de Programacion Visual Usando Delphi

162

Sistema de Inventario

ü Evitar la inclusión de “Movimientos” duplicados.

Al igual que en las tablas de productos y tipos de movimiento, se debe

definir en el evento “OnPostError” de la tabla de movimiento el procedimiento para detectar e informar al usuario de excepciones (errores) cuando se trata de incluir movimientos duplicados en la tabla “Cabeza_Mov”. La siguiente ventana del Editor de Código muestra la validación necesaria en el evento “OnPostError”.

En la tabla de ”Cuerpo_Mov” también puede ocurrir este tipo de error. Si

se intenta incluir un producto duplicado en el “detalle” o “cuerpo” de movimiento una excepción de registro duplicado es presentado por Delphi. La siguiente ventana del Editor de Código muestra la validación necesaria en el evento “OnPostError” de la tabla “Cuerpo_Mov” para manejar esta situación. El formulario en momento de ejecución también es mostrado a continuación.

Page 173: Tecnicas de Programacion Visual Usando Delphi

163

Sistema de Inventario

Crear una ventana de dialogo para la actualización del código de producto. Hasta los momentos el usuario debe escribir el código del producto a ser

incluido en la tabla de “Cuerpo_Mov”. Seria conveniente que el usuario pudiera seleccionar el código del producto de una lista y automáticamente se incluyera el código en el campo respectivo de la tabla “Cuerpo_Mov”. A este concepto se denomina “Catalogo”. Una ventana desde donde el usuario seleccione información. Esta lista de productos podemos implementarla en un nuevo formulario donde colocaríamos un DBGrid que muestre la tabla de productos. El usuario al presionar “dobleclick” o un botón, el código de producto del registro “actual” de la tabla productos se utilizaría para actualizar el registro “actual” de la tabla “Cuerpo_Mov”.

Tome la opción “File – New” del menú principal de Delphi. Una ventana mostrando los diferentes elementos que se pueden crear se desplegará en pantalla. Tome de la pestaña “Dialogs” la opción “Standard Dialog” para crear

Page 174: Tecnicas de Programacion Visual Usando Delphi

164

Sistema de Inventario

un nuevo formulario con dos botones en la parte inferior. El siguiente gráfico ilustra esta operación.

Deposite un DBGrid, de la pestaña “Data Controls” de la Paleta de

Componentes, en el nuevo formulario. Asigne el valor “DS_Producto” a la propiedad “DataSource” del componente “DBGrid”. Recuerde tomar la opción “File - Use Unit” desde el menú principal que el nuevo formulario “use” el modulo de datos. Luego, pulse “dobleclick” sobre el “DBGrid” para desplegar el Editor de Columnas y configurar los campos que conformaran las columnas. La siguiente ventana muestra el nuevo formulario con el ”DBGrid” configurado.

Page 175: Tecnicas de Programacion Visual Usando Delphi

165

Sistema de Inventario

Este formulario de catalogo será desplegado, desde el formulario de movimientos, en forma “modal”. Recurde que un formulario para ser mostrado en este modo se debe invocar el método “ShowModal” del componente “Tform”. Al cerrar un formulario modal, Delphi retorno un valor determinado. En este caso al presionar el botón “OK” el resultado será la constante “ mrOK”. Este valor de resultado puede ser cambiando actualizando la propiedad “ModalResult” del componente de la clase “TButton“. La propiedad “MododalResult” del botón “Cancelar” de este formulario tiene el valor “mrCancel”.

Ya sabemos como mostrar el formulario (método ShowModal) pero debemos definir donde se realizara la operación. Por supuesto, cuando estemos editando la columna “código de producto” en el DBGrid de “cuerpo” de movimientos es que debemos permitir al usuario poder invocar al catalogo de productos. Seleccionemos la cuadricula de base de datos (DBGrid) del formulario de movimientos y presionemos “dobleclick” para mostrar el Editor de Columnas. Al marcar la columna “Codigo_Producto” y presionar la tecla F11 podemos ver las propiedades de la columna. Ver gráfico a la derecha de la pagina.

Page 176: Tecnicas de Programacion Visual Usando Delphi

166

Sistema de Inventario

La propiedad “ButtonStyle” determina una opción muy impórtente de una columna. Si el valor de esta propiedad es “cbsEllipsis”, un botón en la esquina inferior derecha será mostrado donde si el usuario lo presiona, el evento “OnEditButtonClick” será ejecutado. En este evento (OnEditButtonClick) podemos invocar al método “ShowModal” del formulario de catalogo de productos. El usuario puede editar datos en la columna (Código de Producto) o presionar el botón que aparecerá en el lado derecho de la columna para mostrar el catalogo de productos.

El siguiente paso consiste en definir las operaciones que se realizaran cuando el usuario presione el botón “Ok” del formulario de catálogo de productos. El campo “Codigo_Producto” del registro actual de la tabla de productos debe ser asignado al campo “Codigo_Producto” del registro actual de la tabla “Cuerpo_Mov”. La siguiente ventana muestra la implementación del evento “OnEditButtonClick” del DBGrid que se encuentra en el formulario de movimientos.

El procedimiento muestra el catalogo de forma modal

(Forma_Catalogo_Productos.ShowModal) verifica y a la vez verifica si el botón “OK“ fue presionado para cerrar la ventana. La propiedad “State” de un componente Ttable determina en que estado se encuentra la tabla en un momento determinado: inserción, edición, navegación, calculando, etc.. Si la tabla no esta en modo de inserción o edición el método “Edit” del componente la coloca en modo de edición para despues poder realizar los cambios sobre el campo “Codigo_Producto” de la tabla “Cuerpo_Mov”. Recuerde que luego de ser asignado el nuevo valor al campo y terminar la ejecución de este evento se invocara el evento “OnCalcFields” de la misma tabla. La descripción del nuevo código de producto será mostrada en el “DBGrid” del formulario de movimientos. En la siguiente ventana se encuentra ambos formularios: El

Page 177: Tecnicas de Programacion Visual Usando Delphi

167

Sistema de Inventario

catalogo de productos y el formulario de movimientos en el formulario MDI (formulario principal).

Búsquedas rápidas de movimientos. Es muy conveniente implementar una alternativa de buscar rápidamente

registros en una tabla. El área de índice puede ser utilizada para tal fin. Es importante destacar que esta técnica puede de ser aplicada a cualquier tabla que posea un área de índices. En el panel inferior derecho de nuestro panel colocamos un componente “TMaskEdit” (ver gráfico a la derecha). El evento “OnChange” de este componente utilizara el contenido de su propiedad “Text” (lo que el usuario

Page 178: Tecnicas de Programacion Visual Usando Delphi

168

Sistema de Inventario

escriba sobre él) para buscar en el área de índice de la tabla “Cabeza_Mov”. La siguiente ventana del Editor de Códigos muestra la implementación del evento “OnChange” del nuevo componente.

El método “FindNearest” será utilizado para realizar la búsqueda en la

tabla. Este método realiza búsquedas parciales en la tabla. Por ejemplo si escribimos el texto “34” en el componente TmaskEdit, el resultado de la búsqueda será el primer numero de movimiento que sea igual o mayor a “34” en la tabla “Cabeza_Mov”. Después de ubicar un registro, la relación uno a muchos permite que automáticamente se muestren todos los registros de la tabla “Cuerpo_Mov” en el DBGrid del formulario.

Actualizar “Cantidad” en el maestro de productos. El proceso de actualización en tablas maestras involucra tomar en cuenta

varias alternativas. En nuestro caso acumular en los campos “Total_Entradas” ó “Total_Salidas” dependiendo del tipo de movimiento y de la operación que se este realizando sobre la tabla “Cuerpo_Mov”. Los diferentes casos que podemos encontrarnos son los siguientes: § Cuando se esta incluyendo una línea de movimiento. Sumar “Cantidad”

a “Total_Entradas” ó “Total_Salidas” dependiendo del tipo de movimiento.

§ Cuando se esta modificando “cantidad” en una línea de movimiento. Restar el valor anterior de “Cantidad” a “Total_Entradas” ó “Total_Salidas” dependiendo del tipo de movimiento y sumar el nuevo valor al respectivo campo de entradas o salidas.

§ Cuando se esta eliminado una línea de movimiento. Restar “Cantidad” a “Total_Entradas” ó “Total_Salidas” dependiendo del tipo de movimiento.

Page 179: Tecnicas de Programacion Visual Usando Delphi

169

Sistema de Inventario

Las alternativas, arriba descritas, determinan que debemos tener una variable auxiliar “Cantidad_Anterior” para mantener el valor del campo “Cantidad” antes de cualquier modificación. Esta variable la podemos declarar en el modulo de datos ya que es en esta unidad donde se utilizara. La siguiente ventana muestra la declaración de la variable después de la declaración del formulario de modulo de datos.

Esta variable auxiliar se iniciliza en los eventos “BeforeInsert” y

“BeforeEdit” de la tabla “Cuerpo_Mov” de la siguiente forma:

En el evento “BeforeInsert” debemos incializar la variable ya que en el evento “BeforePost” de la tabla “Cuerpo_Mov” realizaremos una suma algebraica de “Cantidad” con “Total_Entradas” o “Total_Salidas” para correctamente obtener el nuevo valor. En este evento ya se definió la validación de la existencia o no de un producto, por lo tanto al final del procedimiento añadimos la actualización de la tabla productos. La siguiente ventana muestra estas modificaciones al evento.

Page 180: Tecnicas de Programacion Visual Usando Delphi

170

Sistema de Inventario

La ultima implementación necesaria es en el evento “BeforeDelete” de la

tabla “Cuerpo_Mov”. Es este evento simplemente le restamos el contenido del campo “Cantidad” al campo “Total_Entradas” ó “Total_Salidas” dependiendo del tipo de movimiento. La siguiente ventana muestra estas modificaciones al evento.

Page 181: Tecnicas de Programacion Visual Usando Delphi

171

Sistema de Inventario

Creación del Formulario de Consulta de Productos.

El próximo formulario que se desarrollara en el sencillo sistema de inventario es una consulta en SQL sobre los productos. El formulario estará en capacidad de:

1. Mostrar tres tipos diferentes de consultas. § Productos que tengan existencia menor que la existencia mínima. § Productos que tengan existencia mayor que la existencia máxima. § Productos que tengan existencia menor que el punto de reorden.

2. Mostrar el resultado en un “DBGrid”. 3. Seleccionar dinámicamente los campos que aparecerán en el “DBGrid”.

La siguiente ventana muestra lo que será nuestro formulario final de consulta en momento de ejecución. En este caso se esta desplegando una consulta sobre el punto de reorden y solo se muestran cuatro campos en el “DBGrid”.

Primero debemos crear un nuevo formulario por medio de la opción

“File – New Form” del menú principal o utilizando el botón rápido que se encuentra para tal fin. Luego seleccionamos de la pestaña “Standard” un componente de la clase “Panel” y los soltamos en la parte inferior del formulario. En este panel colocamos dos botones TbitBtn para realizar las operaciones de ejecutar la instrucción SQL o salir del formulario.

El próximo paso es cambiar varias propiedades del formulario y de los otros componentes.

Page 182: Tecnicas de Programacion Visual Usando Delphi

172

Sistema de Inventario

1. Guardar (salvar) el formulario a disco con el nombre “Unit_Consulta_Productos”.

2. Cambiar la forma de creación del formulario de Auto-Creado a NO auto-Creado. (Opción Proyect-Options del menú principal).

3. Cambiar la propiedad Name del formulario al nuevo nombre de “Forma_ Consulta_Productos”.

4. Cambiar la propiedad Caption del formulario a “Consulta de Productos”.

5. Cambiar la propiedad FormStyle del formulario a “fsMDIChild”. 6. Cambiar la propiedad BorderIcons – biMaximize del formulario a

“false”. 7. Cambiar la propiedad Position del formulario a “poDesktopCenter”. 8. Cambiar la propiedad Caption del paneles por “” (valor nulo). No

queremos ningún titulo para el panel. 9. Cambiar la propiedad Align del panel a “alTop” (posicionar el panel

siempre al tope del formulario). 10. Cambiar la propiedad Kind del primer botón por “bkOK” y la

propiedad Name y Caption por “Ejecutar”. 11. Cambiar la propiedad Kind del segundo botón por “bkClose” y la

propiedad Name y Caption por “Salir”.

Las consultas se realizaran por medio de un componente “TQuery” que nos permite suministrar una instrucción SQL. El resultado de la consulta se mostrara en un DBGrid. Seleccionemos un componente “TQuery” y otros “TDataSource” de la pestaña de “Data Access” de la Paleta de Componentes y soltémoslo en cualquier parte del formulario. Estos componentes de la clase “TQuery” y “TDataSource” podríamos colocarlos en el modulo de datos pero para ilustrar diferentes alternativas los colocamos en el formulario de manipulación de datos en sí.

Un Componente DBGrid también debe ser soltado en la parte inferior del formulario. Actualicemos la propiedad “DataSource” del DBGrid por “DataSource1” que es el nombre por defecto de la fuente de datos. La propiedad “DataSet” del componente “DataSource1 también debe ser cambiada a “TQuery1” que es el nombre por defecto del nuevo componente “TQuery”. Cambiemos también la propiedad Name del componente “TQuery” a “Query_Productos” y la misma propiedad Name de la fuente de datos por “DS_Consulta”. El formulario debe tener la siguiente apariencia física en momento de diseño:

Page 183: Tecnicas de Programacion Visual Usando Delphi

173

Sistema de Inventario

Para completar los componentes que se necesitan para la consulta,

debemos seleccionar un objeto de la clase “TRadioGroup” y un TGroupBox de la pestaña “Standard” de la Paleta de Componentes. Esta clase de componentes (TRadioGroup) presenta botones de radios definidos por la propiedad Items. El siguiente gráfico muestra esta operación y el cambio de la propiedad Caption por “Tipo de Consulta de Productos”

En el componente GroupBox colocaremos ocho (8) componentes de la clase TCheckBox, uno para cada campo de la tabla productos. Los nombres (propiedad Name) de los componentes también fueron cambiados para que describan la función de cada uno de ellos. “Tipo_de_Consulta” para el

Page 184: Tecnicas de Programacion Visual Usando Delphi

174

Sistema de Inventario

componente “TRadioGroup” y “Campos” para el “TGroupBox”. La propiedad Name de los “CheckBox” también fueron cambiados para auto-documentar el formulario. La siguiente ventana del Editor de Código muestra la implementación del botón “Ejecutar”.

Page 185: Tecnicas de Programacion Visual Usando Delphi

175

Sistema de Inventario

La primera parte de la implementación del evento consiste en formar la cláusula “Select” de la instrucción SQL. Si uno de los “checkbox” esta seleccionado (propiedad “Checked = true”) se añade el nombre del campo respectivo en la variable local “Campos”. El campo “existencia” no existe físicamente en la tabla productos. Es un campo producto del calculo “Total_Entradas – Total_Salidas”. Este calculo se introduce en la cláusula “Select” cuando se cumple la condición “Checkbox_Existencia.Checked = True”. Dependiendo del tipo de consulta seleccionado, la propiedad ItemIndex tendrá el valor cero (0) para la primera consulta, uno (1) para la segunda consulta o tres (3) para la tercera consulta. Las consultas posibles pueden ser:

Ø Select <campos> From Productos Where (Total_Entradas – Total_Salidas) < Existencia_Minima Ø Select <campos> From Productos Where (Total_Entradas – Total_Salidas) > Existencia_Maxima Ø Select <campos> From Productos Where (Total_Entradas – Total_Salidas) <= Punto_de_Reorden

La propiedad SQL del componente TQuery almacena el texto de la

instrucción a ser ejecutada. El método “Add” del componente añade las líneas necesarias para formar la instrucción. Al final de la implementación del evento “OnClick” del botón “Ejecutar” se invoca la ejecución de la instrucción SQL (Query_Productos.Open) y muestra el “DBGrid” que esta “enlazado” con la tabla resultado del componente “TQuery”. El componente TQuery tiene otra propiedad que debe ser inicializada. La propiedad DatBaseName define la base de datos que debe ser abierta para poder ejecutar la instrucción SQL. En este caso, la base de datos no existe, es una tabla local en Paradox. La ruta “C:\Inventario” define la ubicación de las la tablas en el disco duro.