Tecnicas de Programacion Visual Usando Delphi
Tecnicas de Programacion Visual Usando Delphi
Tecnicas de Programacion Visual Usando Delphi
TRABAJO DE ASCESO PRESENTADO PARA OBTAR A LA CATEGORIA DE ASOCIADO EN EL ESCALAFN DEL PERSONAL DOCENTE Y DE INVESTIGACIN
UNIVERSIDAD CENTRO OCCIDENTAL LISANDRO ALVARADO Decanato de Ciencias y Tecnologa Barquisimeto, 1999.
Trabajo Aprobado
___________________________ Coordinador
__________________________
__________________________
Agradecimiento
A mis alumnos quienes contribuyeron a ser posible la realizacin de este trabajo, a mis colegas y amigos profesores cuya asesora constituyo un valioso aporte en el desarrollo de este trabajo. Al Prof.Manuel Crespo, por su motivacin 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.
Dedicatoria
A Am miis sh hiijjo os s,, a am mii e es sp po os sa ay ya am miis sc co olle eg ga as sa aq qu uiie en ne es ss su um mo ottiiv va ac cii n nh ha an nh he ec ch ho o p po os siib blle e lla ac cu ullm miin na ac cii n nd de ee es stte e ttrra ab ba ajjo o
Resumen El producto de este trabajo se utilizar como material didctico en la enseanza de Laboratorio II del programa de Ingeniera en Informtica. El objetivo general es presentar una alternativa de apoyo a las ctedras de Base de Datos y Sistemas de Informacin en cuanto a tcnicas modernas de programacin visual. El anlisis y diseo de sistemas informticos debe tener un final en la implementacin materializada en una pieza de software/hardware, usando herramientas de programacin slidas que den una garanta aceptable en cuanto a confiabilidad en la puesta en marcha y productividad deseada. Las tcnicas de manipulacin de bases de datos expuestas en este trabajo, ms el ejemplo de desarrollo de una aplicacin, representan un camino slido en la aplicacin de conceptos actuales de programacin visual. Delphi surge como una herramienta de programacin adecuada para desarrollar aplicaciones informticas a nivel del cliente y servidor. El uso de conceptos sobre programacin orientada a objetos, ms una gran variedad de componentes de manejo de base de datos, determinan que Delphi puede ser fcilmente aprovechado en la Universidad Centro Occidental Lisandro Alvarado en los ltimos semestres del programa de Ingeniera en Informtica. Este trabajo trata de resaltar algunos aspectos de esta herramienta que serian fcilmente aplicables por los alumnos de estos semestres.
Bibliografa
Calver, Charlie. Delphi 4 Unleashed. Sams 1998. Aguilar, Luis Joyanes / Muos Antonio. Borland Delphi, Osborne McGraw Hill 1999 Pacheco, Xavier y Teyseira, Steve. Delphi 4 Develperss 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
Contenido
1
Fundamentos de Delphi
Ambiente de Desarrollo Integrado (IDE) Otros Conceptos Desarrollo de una Aplicacin en Delphi 1 3 6 6 12 12 15 19 21 22 32 32 41 46 46 51 59 63 68 72 72 74 77 86 87 97 100 100 106 109
Componentes Bsicos
Paleta de componentes Estndar Paleta de componentes Adittional
Creacin de Componentes
Creacin de Componentes Delphi Creacin de Componentes Active-X Apendices
Fundamentos de Delphi.
Fundamentos de Delphi.
Delphi es una herramienta de programacin perteneciente a la familia de los actualmente llamados ambientes RAD (Desarrollo Rpido de Aplicaciones). Los ambiente RAD modernos poseen la caracterstica que utilizando el ratn, visualmente, se seleccionan objetos que representan componentes utilizados para la comunicacin entre el computador y los usuarios intermedios (programadores) o usuarios finales. El ciclo de desarrollo de sistemas por prototipos dinmicos 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 tecnologa son:
q q
q q q q q
Participacin directa del usuario en el desarrollo del sistema. Aumento de la motivacin del usuario en la futura implantacin de un nuevo sistema. Disminucin de errores de implementacin de sistemas Simplificacin del ciclo de desarrollo de sistemas. Disminucin de costos de diseo y desarrollo de sistemas. Utilizacin de interfaces GUI. Incremento de la integridad de los datos manipulados.
Las herramientas RAD tambin 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 manipulacin de datos. q Aumento de la posibilidad de dejar un prototipo como el sistema final. Durante la etapa proceso de definicin de requerimientos se puede decidir que el prototipo en desarrollo es suficiente para solucionar los problemas existentes, obviando la terminacin de las etapas de anlisis y diseo adecuado del sistema. El desarrollo de aplicaciones, utilizando Delphi, se simplifica dramticamente. Muchos de los detalles de bajo nivel de la programacin en Windows que deban ser tomados en cuenta estn ocultos en Delphi. Claro esta, esta herramienta no sustituye a un programador, pero minimiza en gran escala la complejidad de la codificacin en ambientes orientados a eventos como lo es Windows.
Fundamentos de Delphi.
Delphi posee tres caractersticas importantes que lo ubican entre las herramientas de desarrollo de software mas eficientes y efectivos existentes en el mercado actual. Estas caractersticas se mencionan a continuacin: 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) estndares por medio de tcnicas de Arrastrar y Soltar facilitan el diseo de interfaces GUI. 3. Programacin en el lenguaje Pascal. Las respuestas del sistema a los eventos se realizan a travs del lenguaje Pascal.
Orientado a Eventos Manejo Visual
Delphi
Programacin en 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 creacin rpida de programas para mantener los datos en medios secundarios de almacenamiento. Delphi tambin puede manipular datos por medio de mecanismos ODBC pero sus manejadores nativos (SQL-Links) son mas eficientes.
Fundamentos de Delphi.
Fundamentos de Delphi. 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 tambin especificas del proyecto (programa) que se este desarrollando en un momento determinado. En el Apndice A se encuentra un breve descripcin de cada uno de los elementos de este men. Botones Rpidos: 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 fcil usuarlos (acceso directo). Este panel de botones puede ser configurado y personalizado por el usuario a su conveniencia (presionando el botn derecho del ratn cuando el cursor esta sobre el panel). El siguiente grfico muestra la funcin de cada botn rpido en Delphi 3. En Delphi 4 se presentan los mismos botones pero organizados de una manera diferente.
Guardar Todo
Ejecutar programa
Suspender ejecucin
Abrir archivo
Guardar archivo
Remover Archivo
Nuevo Formulario
Depurar detalle
Fundamentos de Delphi.
Paleta de Componentes: Todos los componentes que se pueden utilizar en un programa se encuentran en esta paleta. Los componentes estn agrupados en diferentes carpetas. Por ejemplo, al hacer click en la pestaa llamada Data Controls se muestra la carpeta que posee los componentes utilizados para manipulacin 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 pestaa 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 caractersticas (nombre, posicin, 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 caractersticas de un objeto se le denominan propiedades y acciones a las cuales puede responder el objeto se llaman "eventos". En el grfico anteriormente mostrado se despliegan las propiedades del objeto Form1 (formulario). Al presionar la pestaa Events se presentaran todos los posibles eventos a los cuales puede reaccionar el objeto Form1. El Inspector de Objetos se puede invocar rpidamente presionando la tecla de funcin 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 tambin el Editor de Cdigo para cambiar los programas en Pascal que interactuan con el formulario (por ejemplo, definicin de eventos). Utilizando el botn rpido podemos cambiar de un editor a otro (formulario / unidad). El usuario puede abrir varias ventanas del Editor de Cdigo seleccionando del men View la opcin New Edit Window. Esta opcin es til cuando queremos estar viendo (o editando) simultneamente diferentes segmentos de una misma unidad o diferentes unidades.
Fundamentos de Delphi.
Otros Conceptos
El ambiente de desarrollo integrado (IDE) de Delphi permite crear aplicaciones en Windows rpidamente. Antes de desarrollar nuestra primera aplicacin es importante establecer o recordar varios conceptos: En el mundo de las herramientas visuales existe siempre un formulario como el mximo contenedor de objetos. Un formulario es tambin un objeto pero es el mecanismo de mostrar otros objetos al usuario final. La actividad ms comn 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: Caractersticas propias del objeto, por ejemplo; nombre, contenido, posicin en el formulario, color, fuente, etc.. Estas propiedades varan dependiendo del tipo de objeto. El tipo de objeto se le denomina Clase. Eventos: Reaccin de un objeto a un estimulo externo. Estos eventos varan dependiendo de la clase del objeto. Mtodos: Procedimientos o funciones que pueden modificar las propiedades del objeto o permiten la comunicacin con el usuario o sistema operativo. Estos mtodos varan dependiendo de la clase (tipo) del objeto. La programacin en la mayora 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 disear programas cambia dramticamente. Se deben tomar en cuenta un mayor numero de alternativas de respuesta al usuario o al sistema operativo. Ninguna herramienta de programacin 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 aplicacin. Cada formulario tiene su correspondiente unidad (modulo) de programa en Pascal que define sus componentes y eventos.
Fundamentos de Delphi.
Los siguientes grficos 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 estn en color azul. Una unidad en Delphi consiste en dos grandes reas: La seccin de Inteface y la de Implementacin. Los objetos (componentes) que se arrastran a un formulario son automticamente declaradas por Delphi en su respectiva unidad. Al crear un formulario, opcin File - New Form, Delphi crea un archivo de pascal (la unidad con todas las declaraciones bsicas) y un archivo con terminacin .DFM (el formulario) automticamente.
Fundamentos de Delphi.
Fundamentos de Delphi.
2. Un objeto tiene asociado una variedad de propiedades (caractersticas) y eventos a los que puede, opcionalmente, reaccionar. Segn el grfico 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 ratn 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 despus de seleccionar el formulario. El siguiente grfico muestra el resultado de este cambio:
3. El siguiente paso consiste en colocar un botn en el formulario. Seleccione de la Paleta de Componentes la pestaa Standard. En esta hoja de la paleta se encuentran agrupados los componentes mas comunes de una aplicacin en Windows. Usando el ratn, seleccione el componente de botn que se encuentra en esta hoja y arrstrelo 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 grfico muestra el resultado de esta operacin.
Fundamentos de Delphi.
10
Note que el Editor de Cdigo refleja la declaracin del nuevo objeto en la definicin del formulario. 4. Uno de los eventos mas comunes de los componente es OnClick. Este evento define la respuesta de un componente a la accin de pulsar un botn del ratn cuando el cursor se encuentra sobre el mismo. Podemos crear un evento de este tipo al objeto botn siguiendo los siguientes pasos: Seleccione con el ratn el objeto botn. Presione la tecla F11 para mostrar el Inspector de Objetos. Seleccione la pestaa Events del Inspector de Objetos. Todos los posibles eventos relacionados con esta clase de componente se mostraran.
Fundamentos de Delphi.
11
Presione el botn derecho del ratn dos veces (doble click) sobre el evento OnClick. La ventana del Editor de Cdigo se desplegara en pantalla mostrando la estructura vaca de un procedimiento en Pascal (ver siguiente grfico). Entre las lneas de Begin y End se escribe la siguiente lnea de cdigo: ShowMessage(Hola desde el mundo Delphi). Esta lnea de c d i g o m o s t r a ra en pantalla la lnea de texto que recibe como parmetro el procedimiento ShowMessage.
Fundamentos de Delphi.
12
5. El programa esta listo para ser ejecutado. Pulse el botn para compilar y ejecutar el programa. Usando el ratn, presione el botn Buton1 que se encuentra en el formulario y se mostrara el mensaje Hola desde el mundo Delphi. Nota: El titulo de este botn se puede cambiar modificando la propiedad Caption del objeto.
12
En este captulo profundizaremos en el conocimiento de las propiedades y eventos resaltando aquellos que ms comnmente utilizaremos en nuestras aplicaciones, hablaremos de la metodologa de trabajo y veremos en profundidad el componente principal de cualquier aplicacin 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 caracterstica 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 ejecucin de algn mtodo de forma indirecta. Como tambin sabemos, la manipulacin 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 edicin y manipulacin en tiempo de diseo a la vez que nos determinara el mecanismo de acceso y las operaciones posibles a realizar en tiempo de ejecucin. Cabe mencionar que hay propiedades que slo son accesibles en tiempo de diseo o ejecucin, o bien son de slo lectura o slo 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 especficas de un grupo o incluso particulares. En este apartado se presenta un conjunto de propiedades que estn incluidas en la mayora de los componentes y cuyo valor que es generalmente modificado directa o indirectamente para ajustar el control a nuestras necesidades de diseo. Nombre, posicin y tamao. 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 concatenacin del nombre del control y un nmero indica el orden en el que hemos incluido ese control o componente
13
en el formulario en relacin con los componentes de su misma clase; as, en el caso que hayamos insertado dos controles de la clase TLabel (etiqueta), sus propiedades Name tendrn 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 ms intuitivo que el asignado automticamente. Esta operacin slo se puede realizar en tiempo de diseo, asignando el nuevo identificador a travs del inspector de objetos. Otra de las primeras cosas que habitualmente haremos al incluir un nuevo componente en un formulario es definir su posicin y tamao. Estas caractersticas vienen determinadas por las siguientes propiedades. Top y Left nos determinan la posicin 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 tamao. Nota: Los valores de estas cuatro propiedades pueden ser modificados tanto en tiempo de diseo como de ejecucin, en el primer caso podremos cambiar sus valores travs del inspector de objetos o bien seleccionndolos y redimencionando el control por medio del ratn, mientras que en ejecucin basta, con asignar un nuevo valor a estas propiedades. Aspecto Existe un conjunto de propiedades que determinan el aspecto general de la presentacin visual de los componentes dentro de una aplicacin, por lo tanto y como es lgico, estas propiedades slo tienen sentido en componentes visuales. El borde de un componente se establece mediante su propiedad BorderStyle, la cual bsicamente 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 ms 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 codificacin del color en formato RGB mediante seis dgitos hexadecimales, los cuales expresan en grupos de dos dgitos la intensidad en rojo, verde y azul del color,
14
respectivamente. Cuando lo que deseamos es definir las caractersticas 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 informacin 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 tamao, 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 automticamente 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 automticamente 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 operacin, si su valor es dmManual ser necesario realizar una llamada al mtodo BeginDrag para iniciar el arrastre, mientras que si es dmAutomatic la operacin comenzar automticamente al pulsar el botn izquierdo del ratn. La otra propiedad es DragCursor y nos sirve para determinar la forma del puntero del ratn mientras se realiza la operacin de arrastre, siendo sus valores posibles los puntero definidos en el sistema. Desplazamiento entre los componentes de una ventana. Una ventana de nuestra aplicacin 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 introduccin de los componentes en el formulario pero podemos cambiarlo a travs de la propiedad TabOrder que contiene un nmero de 0 a n-1 (siendo n el numero de componentes presente) que indica el orden de activacin del control. Tambin podemos presionar el botn derecho del ratn, un men emergente mostrara varias opciones dnde se encuentra la opcin "Tab Order". Por medio
15
de esta opcin y utilizando el ratn es posible cambiar fcilmente el orden preestablecido, y por ende el contenido de la propiedad TabOrder. Para activar la capacidad de transferir el foco an control y que por lo tanto tenga relevancia el valor de dicho control se tiene una propiedad llamada TabStop. En momento de ejecucin podemos invocar el mtodo "SetFocus". Por ejemplo; si tenemos un componente llamado Boton_Inicio, para transferir el foco a este componente escribiremos la siguiente instruccin: Boton_Inicio.SetFocus. Otras propiedades generales. Es posible crear mens desplegables (emergentes) y asociados a diversos controles en un formulario. Esta caracterstica se activa a travs 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 ratn sobre dicho control. La propiedad Tag, que no tiene ningn significado especfico y estar a nuestra disposicin para poder asignarle un valor numrico que nos puede servir para guardar cierta informacin sobre el control o como seal para realizar una accin determinada.
Eventos.
Un evento es una seal que puede ser interna o externa a nuestra aplicacin y que es detectada por esta ltima, pudiendo aprovechar esta circunstancia para provocar la ejecucin desierto cdigo asociado, al que se le denomina usualmente "Manejador de Eventos". Como ya hemos mencionado anteriormente, la realizacin de aplicaciones en Delphi se basa en asociar fragmentos del cdigo a la ocurrencia de determinados eventos, es decir, crear manejadores de eventos, de forma que cuando se produzca uno de ellos se inicia la ejecucin del cdigo que tenga asociado y no realizando ninguna accin si ocurre un evento para el cual no hemos definido ningn bloque de cdigo. Lo importante que usted tiene que darse cuenta es cuando se realiza una aplicacin en Delphi, el flujo ejecucin del cdigo no es secuencial sino que depender de los segmentos concretos durante cada ejecucin de la aplicacin, no obstante y como es lgico y mientras ms crece el tamao de nuestra aplicacin, tambin ser
16
necesario escribir cierto cdigo que realice determinadas funciones ms complejas y que no entren en conflictos con las ya existentes. Todos los componentes tienen definido un evento por defecto que es el que ms 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 funcin con el resto de los eventos que tenga disponible el componente. El Inspector de Objetos es desplegado presionando la tecla F11. Es importante sealar que los procedimientos asociados a un evento reciben una serie de parmetros, a travs de los cuales obtenemos informacin que nos puede ser til para gestionar satisfactoriamente la respuesta a dicho evento. Eventos generales del ratn. En los entornos visuales como Windows uno de los dispositivos ms usados para interactuar con cualquier aplicacin es el ratn y ser generalmente los eventos asociados con este dispositivo los que ms usemos en nuestras aplicaciones. En Delphi podremos encontrar los siguientes eventos generados por el ratn: OnMouseDown(Sender : TObjet;Button : TMouseButton; Shift : TShiftState; X,Y : Integer). Se genera cuando se pulsar cualquiera de los botones del ratn 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 ratn 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 parmetros que utilizan estos eventos son los siguientes: Sender: Este parmetro lo podremos encontrar en casi todos los procedimientos que gestionan un evento y se corresponde con el objeto que ha
17
detectado la ocurrencia del mismo, en este caso en concreto har referencia al componente que ha detectado la accin del ratn. Button: este parmetro nos indica que botn se ha visto involucrado en la accin y puede tomar los valores mbLeft, mbMiddle o mbRight, indicando que ha sido el botn izquierdo, central o derecho que sea presionado. Shift: este parmetro nos indica el estado de diversas teclas que son de uso habitual con el ratn y los botones del mismo, puede tener los siguientes valores : ssShift: La tecla Shift esta presionada. ssAlt: La tecla Alt esta presionada. ssRight: El botn derecho del ratn esta presionado. ssLeft: El botn izquierdo del ratn esta presionado. ssMiddle: El botn del centro del ratn esta presionado. ssDouble: El botn izquierdo y derecho del ratn estn presionados simultneamente. X y Y: Estos dos parmetros nos suministran la posicin del puntero del ratn en el momento de producirse el evento. Aunque los eventos vistos hasta ahora puedan resultar interesantes en determinadas ocasiones los que tambin normalmente utilizamos en nuestras aplicaciones bajo Windows son los siguientes: OnClick(Sender:TObject): este evento no esta asociado nicamente a la accin del ratn pero sin embargo, es con este dispositivo con el que lo usaremos generalmente, indicando que se ha producido una pulsacin del botn del ratn sobre el componente. Las otras circunstancias que produce este evento son la pulsacin de la barra espaciadora, la tecla <Enter> o la tecla <Escape>. Cabe destacar que adems del parmetro Sender ya conocido, en diversos componentes, el evento OnClick tendr asociado parmetros adicionales para poder realizar una completa gestin del mismo. OnDblClick(Sender:TObject): Este evento es recibido por un componente cuando se realiza una doble pulsacin del botn izquierdo del ratn estando el curso sobre el mismo.
18
19
adicionalmente los parmetros State para obtener informacin acerca del estado de la operacin y Accept con el que indicaremos si el objeto puede o no ser soltado sobre componente que recibe el evento. Los valores posibles del parmetro 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.
20
componentes, o pulsar sobre l para seleccionarlo y posteriormente realizar una segunda pulsacin sobre la posicin del formulario en donde queremos insertarlo. Una vez que el componente se encuentra en el formulario podemos desplazarlo, por medio del ratn, sobre la superficie o rea de trabajo del formulario. Tambin 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 mltiples instancias de un mismo componente, una forma muy cmoda de hacerlo es aadir 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 slo 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 tambin visible en el momento de diseo pero no para el usuario en momento de ejecucin. Un componente no visible, por ejemplo, es la definicin de un archivo o tabla de base de datos. Podemos incluir los componentes no visuales en un mdulo de datos en lugar de hacerlo en el formulario. Ms adelante hablaremos en detalle sobre los mdulos de datos. El siguiente paso es detectar o definir los diversos eventos a los que tendr que responder nuestra aplicacin y asociarles las lneas fuentes de cdigo 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 aplicacin a travs de la insercin de componentes en la ficha o formulario con la oportuna modificacin de sus propiedades y haber escrito el cdigo asociado a los eventos elegidos, estamos en disposicin de pasar a la etapa de prueba y depuracin de nuestra aplicacin. Para ello ejecutaremos el programa sucesivas veces, a travs de las opciones del men "Run" o con los botones rpidos que para ello se encuentran en la barra de acceso rpido, hasta conseguir los resultados deseados. Para la localizacin 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 ejecucin, establecer puntos de ruptura, ejecucin paso a paso, etc. Una vez que hayamos corregido todos los errores, crearemos el archivo ejecutable de la aplicacin con las opciones "Compile" y "Build" del men "Proyect". Para guardar la informacin referente a cualquiera de nuestras aplicaciones podemos distinguir tres archivos distintos. El punto central lo
21
constituye el archivo del proyecto donde se guarda la informacin del resto de archivos usados y desde donde se iniciar la aplicacin; el contenido de este archivo es generado automticamente por Delphi el cual le asigna por defecto la extensin DPR. Cuando compilemos el proyecto para crear el archivo ejecutable o un archivo de enlace dinmico (DLL), el nombre de este ltimo se tomar del archivo de proyecto cambiando la extensin a EXE o DLL respectivamente. Por otro lado, cada formulario de nuestra aplicacin dar lugar a un archivo con extensin .PAS al que denominaremos mdulo de formulario, que contiene la definicin 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 slo tendremos que escribir el cdigo 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 mdulo de formulario pero con extensin .DFM y que a diferencia del resto de archivos vistos hasta ahora, que estn en formato de texto ASCII, contiene informacin 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 aplicacin nos encontramos con este tipo de archivos para guardar su informacin. Adems de estos archivos bsicos podemos incluir en nuestro proyecto mdulos independientes de los formularios que contengan procedimientos funciones, es decir, UNIT, siendo su extensin PAS si no est compilado, DCU en caso contrario. Por ltimo nos encontramos con un archivo recursos donde se guardan los grficos, cursores, iconos, etc. usados por nuestra aplicacin y cuya extensin es RES.
El componente TApplication.
Todas las aplicaciones desarrolladas en Delphi utilizan un componente TApplication el cual ser creado automticamente 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 informacin generalmente sobre la aplicacin, mtodos y eventos que nos permitirn 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 aplicacin est activa o no, ExeName para almacenar el nombre del programa ejecutable, Icon y Title
22
contienen respectivamente el icono y el ttulo que presentar la aplicacin cuando est minimizada. Todos estos parmetros son configurables en tiempo de diseo a travs de las opciones del proyecto. Entre los mtodos ms interesantes podemos mencionar Create, RUN, Terminate y Destroy para crear la variable o componente del tipo TApplication, ejecutar la aplicacin, terminar la aplicacin 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, mtodos 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 pretenda en este apartado es que usted conozca su existencia y no dar una informacin exhaustiva del mismo; si desea ms informacin sobre este objeto puede acudir a la ayuda en lnea de Delphi o consultar con otros manuales que profundiza en ms sobre el tema .
El componente TForm.
El control (componente) TForm, tambin denominado comnmente formulario o ficha, constituye el centro de cualquier aplicacin desarrollada en Delphi y cuenta con una serie de caractersticas especiales que lo distingue del resto de componentes. Este control representa las ventanas de nuestro programa mediante las cuales se permite la interaccin con el usuario y cuenta con mltiples propiedades, eventos y mtodos 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 tambin tienen esta caracterstica. Propiedades generales de uso comn (TForm). A travs de la propiedad Name le asignamos el identificador vlido (nombre) con el que se conocer al componente en nuestra aplicacin, siendo slo modificacable en tiempo de diseo. Con la propiedad Caption podemos indicar el ttulo 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
23
variar el valor de esta propiedad tanto en tiempo de diseo como en tiempo de ejecucin. 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 podrn recibir ningn evento, as mismo si la propiedad Visible tiene el valor False el formulario permanecer oculto. Cuando no es posible la visualizacin completa de todos los controles incluidos en un formulario, debido por ejemplo al tamao de mismo, aparecern por defecto unas barras de desplazamiento que nos permitirn 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 aparicin y desaparicin de las barras de scroll sean gestionadas de forma automtica, deber asignar el valor False a dicha propiedad. Las caractersticas de la barra de desplazamiento horizontal y vertical estn 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
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 posicin y dimensiones del formulario (TForm). Para situar el formulario en una posicin de la pantalla ursaremos las propiedades Top y Left a travs de las cuales indicaremos las coordenadas de la esquina superior izquierda. El valor de estas propiedades en tiempo de diseo pueden modificarse a travs del inspector de objetos o simplemente desplazando el formulario mediante el uso del ratn. 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 aplicacin, el formulario aparecer en la misma posicin y dimensiones que tena en tiempo de diseo 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 tamao que en tiempo de diseo. poDefault: En cada ejecucion se varia la posicion y tamao del formulario. poDefaultPostOnly: La posicion del formulario varia en cada ejecucion pero su tamao permanece fijo. PoDefaultSizeOnly: El tamao del formulario varia en cada ejecucion pero se mantiene su posicion. poScreenCenter: El formulario aparecera en el centro de la pantalla y con el tamao que tenia en tiempo de diseo. 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 automtica si redimencionamos el formulario mediante el uso del ratn. En el caso particular de los formularios, existen dos propiedades adicionales que son ClientWidth y ClientHeight que nos define la dimensin real de espacio disponible para la insercin de componentes o la visualizacin 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
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 tamao 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 diseo, minimizada o maximizada. no obstante recuerde que usted puede variar el tamao y posicin del formulario en tiempo de ejecucin 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 tamao. La escala se indica en la propiedad PixelperInch, representa el nmero 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 ttulo 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 diseo podemos indicar la presencia ausencia de cada uno de estos elementos desplegando la propiedad BorderIcons y asignando los valores True o False segn nos interese, aunque los cambios no sern apreciables hasta que ejecutemos la aplicacin, mientras que en tiempo de ejecucin 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 ejecucin. Los valores posibles de esta propiedad son los siguientes:
26
bsSizeable: Muestra el borde estandar y permite la redimension del formula en tiempo de ejecucin (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 ttulo de la ventana, no permitiendo redimensionamiento ni desplazamiento por la pantalla. bsToolWindow: Idntico al generado por opcin bsSingle pero con una barra de ttulo ms pequea . bsSizeToolWin: Idntico al generado por la opcin bsSizeable pero con una barra del ttulo ms pequea . 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 ratn 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 slo est disponible en tiempo de ejecucin 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 ejecucin podemos usar la propiedad ComponentCount podemos usar la propiedad para determinar el nmero de componentes incluidos en el frmulario, Estando estos ltimos almacenados en la propiedad Components esta propiedad es una matriz de componentes. Mediante las
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 gestin de los controles visuales usaremos el conjunto de cuatro propiedades equivalentes, las cuales se identifican por los nombres ControlCount, Controls, ControlIndex y ControlState. Tambin existe la propiedad PrintScale que determina La escala en que se imprima El formulario usando el mtodo 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 bsicos de formularios. El primero se corresponde a las ventanas comunes de captura o manipulacin de datos, el segundo es un tipo especial de formulario utilizado por Delphi llamado mdulo 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 ejecucin. Uno proyectos puede tener un gran nmero de formularios comunes y formularios de mdulos de datos. En proyectos de mediano tamao cobra una gran importancia el uso de los mdulos de datos. por ejemplo; si vamos a utilizar un componente no visual como la definicin de una tabla de clientes en varios formularios, podemos crear el componente una sola vez en el mdulo de datos y utilizarlo a travs de varios formularios en nuestra aplicacin. La centralizacin de la definicin de componentes en un solo lugar nos permite tener un mejor control del uso de los mismos. Un mdulo de datos se crea tomando la opcin "New" del men "File" y seleccionando "Data Module".El uso de un mdulo de datos desde un formulario se realiza a travs de la inclusin de una directiva en el formulario que necesita dicho mdulo, 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 aplicacin con este estilo. Por otro lado
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 slo formulario padre, en un proyecto MDI, y uno o varios formularios hijo . Mtodos del componente formulario (TForm). El componente TForm dispone de una gran cantidad de mtodos, por lo que vamos a centrarnos en aquellos que son ms importantes o que sabemos que usuaremos ms frecuentemente. Algunos de estos mtodos sern tratados con detalle en captulos siguientes. No obstante, los mtodos presentados en este apartado son suficientes para realizar la mayora de las aplicaciones con un nivel medio de complejidad, y como siempre, recuerde que puede obtener mas informacin detallada de todos los mtodos del componente TForm en la ayuda en linea de Delphi. Cuando iniciamos la ejecucin de una aplicacin, la ventana o formulario principal de la misma se visualiza, sin embargo y como veremos ms adelante, lo normal cuando se realiza una aplicacin de tamao medio es que necesitamos varios formularios y tengamos que ser nosotros, mediante el cdigo los que indicamos la visualizacin o no de las diversas ventanas o formularios que constituyen la aplicacin. Para ello disponemos bsicamente de los mtodos Hide para ocultar un formulario y Show ShowModal para visualizarlos. La diferencia entre los mtodos Show y ShowModal es que el segundo de estos mtodos realiza la visualizacin de una ventana Modal, lo que implica que no podemos continuar con la ejecucin del aplicacin hasta que cerremos dicha ventana, adems, para cerrar una ventana modal no utilizaremos el mtodo Hide, sino que debemos asignar un valor distinto de cero a la propiedad ModalResult del formulario. ms adelante veremos que
29
existen ciertos componentes (botones) que pueden asignar valores para propiedad Modal Result automticamente. Para crear una instancia de un objeto TForm usaremos el mtodo Create, mientras que para destruirlo y liberar los recursos consumidos por un formulario podemos usar los mtodos Free, Destroy y Release . Estos mtodos son invocado directamente y automticamente cuando iniciamos o finalizamos la ejecucin de un programa desarrollado en Delphi. Para cerrar una ventana o formulario usaremos el mtodo Close el cual a su vez hace uso del evento CloseQuery para determinar si el formulario puede ser cerrado. Generalmente usaremos el mtodo Close en la ventana principal de nuestra aplicacin lo que provocara que la ejecucin de la misma termine y se liberen todos los recursos que consuma, es decir, el uso de Close en la ventana principal hace que se cierren todas los formularios existentes y se termine la ejecucin, lo que es equivalente a usar el mtodo Terminate del objeto TApplication. Los mtodos Free, Destroy y Release son automticamente invocados por el mtodo Close. Para redibujar o actualizar un formulario y todos sus componentes, podemos hacer uso de los mtodos Refresh (refrescar), Repaint (redibujar) Update (actualizar), los cuales nos permiten por ejemplo volver a mostrar un formulario cuando se halla daado la parte visual por la superposicin de otra ventana. Mediante los el mtodos BringToFront y SendToBack podemos forzar a que el formulario aparezca encima de cualquier otra ventana o debajo de todas las existentes, respectivamente. Mediante el mtodo Print podemos obtener una copia impresa de la ventana, mientras que si deseamos obtener una imagen de la misma para su posterior manipulacin o almacenamiento en un archivo usaremos el mtodo GetFormImage que nos devuelve una imagen en formato de mapa de bits o BitMap. Eventos del componente formulario (TForm) . El componente TForm dispone tambin de una gran cantidad de eventos asociados entre los que se incluyen los del ratn, teclado y los generales vistos anteriormente. Veamos otros eventos que todava no conocemos y cuya explicacin ser vlida para el resto de componentes que tambin dispongan de los mismos.
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 parmetro 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, producindose 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 visualizacin. 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 tamao 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 mtodos 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 accin a realizar gracias al parmetro 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.
31
OnCloseQuery(Sender : TObject; var CanClose : Boolean): este evento se puede considerar una variante del evento OnClose ya que tambin se produce justo antes de que la ventana se hace rfaga, cuestin que podemos controlar mediante el parmetro 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.
Componentes Bsicos
32
Uno de los elementos o ventanas ms 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 pestaas que agrupan componentes que tienen en comn ciertas caractersticas u objetivos. Dependiendo de la versin de Delphi, pueden existir diferentes pestaas. Es importante destacar que un componente adems de tener simples propiedades, eventos y mtodos tambin puede tener varios subobjetos asociados o de uso interno. Estos subcomponentes a la vez tienen propiedades y mtodos que estn disponibles al usuario. Los subcomponentes se presentan como propiedades del componente mayor y para utilizar sus propiedades y mtodos tenemos que referenciarlos de la siguiente forma: Componente_Principal.SubComponente.Propiedad_o_Mtodo Donde: Componente_Principal : El nombre del componente mayor. SubComponente : El nombre del su-Componente. Propiedad_o_Metodo : El nombre de la propiedad o mtodo del sub-componente. Un tratamiento extenso de todos los componentes con sus propiedades, mtodos 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, mtodos y eventos utilizando la amplia ayuda en lnea con que dispone el sistema. El soporte de la ayuda en lnea ms 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 programacin de tecnologa de punta. A continuacin discutiremos el contenido de alguna de estas pestaas de la paleta de componentes y algunos de los componentes que en ellas se encuentran para poder ser utilizados en nuestros formularios.
Componentes Bsicos
33
Etiqueta (Label): Este componente es nos permite introducir texto en nuestras aplicaciones, es decir, con el componente Label aadimos etiquetas que bien pueden ser explicativas de otros controles (componentes) o bien puede ser mera informacin de la aplicacin al usuario. Posee una propiedad llamada Caption donde se almacena, por medio del inspector de objetos, el texto a ser mostrado. Tambin las propiedades Fuente (Font) y Color para personalizar su apariencia. Caja de Texto (EditBox): Nos permite introducir datos en nuestra aplicacin (formulario). Es la forma ms bsica 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 mltiples. La propiedad Lines (un subobjeto del componente) nos permite almacenar mltiples lneas de texto. Este componente cuenta con varios mtodos 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 mtodo por defecto del componente memo. Add: Aadir una lnea de texto al su objeto Lines. Por ejemplo si tenemos el componente Memo1 en un formulario, y queremos almacenar dos lneas de texto en l, limpiando el contenido del mismo previamente, y luego grabar el texto un archivo, el cdigo necesario sera siguiente: Memo1.Clear; Memo1.Lines.Add('La direccin es incorrecta !'); Memo1.Lines.Add('Intente en otra ocasin'); Memo1. SaveToFile('Respuesta.Text'); Botn (Button): Este componente, aunque ya nos hemos referido a l, es de los ms importantes para el desarrollo aplicaciones. Mediante componente
Componentes Bsicos
34
Button podremos relacionada los eventos con la interaccin del usuario. Es fundamental, por lo tanto, asociar bien el cdigo relativo a los eventos de un botn. Una de las propiedades que ms se suelen modificar es la propiedad Caption, que refleja el ttulo del botn. Con la propiedad Enabled podremos activar o desactivar el botn, para desencadenar o no las acciones definida en su evento OnClick. Por ultimo, la propiedad ModalResult almacena el valor del resultado de presionar el botn cuando est en un formulario mostrado de forma Modal. Por ejemplo si tenemos un botn llamado "Ver", cambiando su propiedad ModalResult a "mrOk", al presionar el botn "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 botn es para cerrar un formulario Modal (dilogo) y que el resultado de cerrar el formulario se encuentra almacenado en la propiedad ModalResult del botn. Casilla de Verificacin (CheckBox): este componente sirve para marcar (activar) una opcin, 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 opcin est marcada o no. El siguiente grfico 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. Botn de Radio (RadioButtom): Los botones de radio o de opcin se usan cuando de una serie de opciones o alternativas podemos seleccionar una y slo una, es decir, la seleccin de una impide que el resto de las otras alternativas. Si se intenta seleccionar otro botn de opcin 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 pestaa (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.
Componentes Bsicos
35
Por ultimo cambiamos la propiedad Caption de cada RadioButtom para describir adecuadamente cada una de las opciones o alternativas. El grfico 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 botn esta marcado o no.
Lista de Texto ( ListBox): Nos permite introducir datos en nuestra aplicacin desde una lista de elementos previamente introducidas por el programador o la aplicacin. Mediante la propiedad Items, representando las lneas de la lista, podemos introducir elementos a la lista, utilizando el inspector de objetos. Tambin podemos en momento de ejecucin limpiar (borrar) y cargar la lista en Items (que tambin 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 cdigo sera necesario para que en momento de ejecucin se cargara la lista:
{Limpiar lista de Items} {Agregar Lista 0 con valor 'A'} {Agregar Lista 1 con valor 'B'} {Agregar Lista 2 con valor 'C'}
Cada elemento de una lista, es decir, cada Item, tiene un nmero de orden. El nmero de orden del elemento seleccionado se obtiene a travs 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 ningn elemento seleccionado el valor de ItemIndex ser igual a 1 (menos uno). Si el nmero de lneas (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 ejecucin, por lo tanto utilizaremos la propiedad ItemIndex para controlar el elemento seleccionado. Por ejemplo, en el caso del componente
Componentes Bsicos
36
Tipo_Cliente, si deseamos saber cual elemento esta seleccionado y mostrarlo en pantalla con la funcin de Delphi ShowMessage que despliega en pantalla una ventana con un mensaje suministrado como parmetro, escribiramos las siguientes lneas de cdigo: If Tipo_Cliente.ItemIndex <> -1 Then ShowMessage(Tipo_Cliente.Items[Tipo_Cliente.ItemIndex]) Else ShowMessage('No hay elementos seleccionados'); Los siguientes grficos 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 aplicacin 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 botn 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 lneas de la lista, podemos introducir elementos a la lista, utilizando el inspector de objetos y la propiedad Text, en momento de ejecucin, tendr el valor seleccionado por el usuario. El grfico 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 automticamente clasifica alfabticamente en forma ascendente la lista de elementos almacenados en el componente. Un ComboBox tambin posee una propiedad muy importante que determina el estilo de presentacin y funcionamiento. La propiedad Style puede tomar los siguientes valores:
Componentes Bsicos
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 presentacin 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 presentacin de la lista. Los elementos de la lista NO tienen que tener la misma altura. El evento OnMeasureItem tambin 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 relacin 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 grfico presenta un formulario con dos GroupBox. El primero se utiliza para delimitar la informacin personal de un empleado y el segundo para informacin relativa al rea de trabajo.
Panel : El componente Panel, al igual que GroupBox, se utiliza para agrupar otros componentes que posean caractersticas lgicas para el usuario en comn. 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
Componentes Bsicos
38
del panel (marco) para diferenciarlos de otros componentes del formulario. Despus 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 combinacin de diferentes valores para estas propiedades.
Nota: Por medio del Inspector de Objetos o en momento de ejecucin del programa, modificando directamente estas propiedades, podemos darle diferentes efectos visuales a la presentacin de nuestros formularios. Otros de los componentes importantes que se encuentran en la pestaa Estndard de la paleta de componentes son los utilizados para la creacin de
Componentes Bsicos
39
sistemas de mens para nuestros formularios. El men es un elemento que permite expresar al usuario lo que desea por medio de mandatos. Podemos diferenciar los mens en dos tipos: Los mens tradicionales, es decir, aquellos que nos encontramos en todas las aplicaciones Windows. Este componente se le denomina MainMenu en Delphi. Los mens Emergentes, tambin llamados mens flotantes que aparecen segn la necesidad presionando el botn derecho del ratn 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 aplicacin. El componente MainMenu debe ser colocado en el formulario donde el men va a ejecutar su trabajo. Es aconsejable disear bien el sistema de mens antes de incluirlo en la aplicacin. Un men bien diseado y estructurado nos permite ver y comprender claramente las funciones comunes de una aplicacin. 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 edicin de mens (Editor de Mens). Haciendo doble click sobre el componente, accederemos sin ms a la ventana del Editor de Mens. Al editar el men por primera vez, estar vaco, a excepcin de un rectngulo punteado indicando la primera entrada a definir (ver siguiente grfico). 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. Despus de escribir el Caption de un subcomponente Items,
Componentes Bsicos
40
Delphi automticamente crea una opcin de men. En el grfico anterior se muestra tanto el formulario principal, donde se encuentra el componente MainMenu, como tambin el Editor de Mens. Despus de actualizar la propiedad Caption de la primera entrada del men podemos, con el uso del ratn o las flechas de direccin del teclado, ir al prximo elemento de opcin, sea en sentido horizontal o vertical en el sistema de men. Presionando simultneamente la tecla Ctrl (control) y flecha a la derecha crearemos un submen de una opcin. El siguiente grfico muestra varias opciones de un men con un submenu para la opcin Facturas, en momento de edicin utilizando el Editor de Men.
Otra alternativa para construir submens es situarnos sobre el mandato del men correspondiente y pulsamos el botn derecho del ratn. De las opciones disponibles debemos seleccionar Create Submen. Entonces aparecer a la derecha un rectngulo punteado donde insertaremos la primera subopcin de este nuevo submen. En la propiedad Caption podemos subrayar y definir la letra que sirve de acelerador de teclado para la opcin de men con el smbolo &. Es fundamental poder usar el men desde el teclado. Para introducir una barra de separacin entre opciones basta crear, en el lugar deseado para la separacin, una nueva entrada que tenga como valor de la propiedad Caption el smbolo 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 combinacin de teclas y que realizara el mandato correspondiente.
Componentes Bsicos
41
Es importante resaltar, en cuanto al aspecto de diseo de mens, que es recomendable no crear un men con demasiados submens. Es preferible un men largo a un men en el que para acceder a una opcin haya que navegar por cientos de etiquetas. Una vez confeccionado el men tendremos que asociarle a cada opcion su funcin. Para editar un mtodo (OnClick) que reaccione a cualquiera de las opciones del men, basta con pulsar con el ratn sobre la opci deseada y escribir el cdigo 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 mtodo Show, precedido del nombre del formulario, es usualmente utilizado para tal funcion. Los mens flotantes es el siguiente tipo de mens 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 botn derecho nos presenta una ventana (men) con una serie de opciones para tomar una medida de accin. El componente PopUpMenu se utiliza en un formulario para tal accin. Cada componente presente en un formulario puede tener asociado un menu flotante o emergente.
Botn con Imagen (BitBtn): Este componente presenta el mismo objetivo que el componente Button de la paleta Estndar pero con la posibilidad de mostrar un grfico BMP dentro del botn. Cuando se instala Delphi 4 una serie de imgenes son grabadas en el disco duro. En el subdirectorio Archivos de Programas \ Archivos Comunes \ Borland Shared \ Images \ Buttons se encuentran archivos BMP con el tamao adecuados para ser utilizados con este componente. El evento OnClick es el mas comnmente usado para relacionar una accin con este componente. El siguiente grfico
Componentes Bsicos
42
muestra al Inspector d Objetos con las propiedades Caption (titulo del botn) y Gliph (imagen). En la parte izquierda tambin se muestra un formulario con este componente utilizando la imagen Abort.BMP que se encuentra en el subdirectorio antes mencionado.
Botn Rpido (SpeedButton): Este componente es tambin utilizado para mostrar botones con grficos. No posee la propiedad Caption como los componente tipo botn anterior. Es frecuentemente agrupado con otros componentes del mismo tipo para presentar barras de opciones rpidas en un formulario. Este componente tambin tiene una serie de propiedades que ayuda a mostrar grficos en diferentes estados (seleccionando, deseleccionado, activo, etc..). La propiedad GroupIndex sirve para agrupar (asociar) botones del mismo tipo y que acten en conjunto. Por ejemplo, los siguientes formularios muestran tres (3) botones rpidos 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 ejecucin del formulario (lado izquierdo) ningn botn a sido pulsado. Cuando se pulsa cualquiera de los botones, se mantiene seleccionado (lado derecho), y si haba otro seleccionado se deselecciona. Los tres botones estn actuando en conjunto.
Componentes Bsicos
43
Caja de Texto de Edicin (MaskEdit): Al igual que el componente EditBox, este componente nos permite introducir datos en nuestra aplicacin (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 telfono con un cdigo de rea con separador basta con inicializar el atributo MaskEdit con la siguiente tira de caracteres: ###-######;1;_ (sin las comillas) escribindola directamente en el Inspector de Objetos o utilizando el Editor de Mascaras (ver siguiente grfico). El Editor de Mascaras se invoca pulsado el botn de elipses que presenta el Inspector de Objetos en la propiedad EditMask de un componente MaskEdit.
Una mascara de edicin esta constituida por tres partes. La primera es la mascara en s. Un smbolo de # representa una entrada tipo numrica, un A solo aceptara valores alfabticos, etc. Para mas informacin ver la ayuda en lnea 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 incluira todos los valores literales como parte de la cadena de caracteres. La ultima parte de una mascara de edicin representa el carcter que se utilizara para espacios en blancos durante el momento de edicin. Este caracteres puede ser inclusive el carcter 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.
Componentes Bsicos
44
Rejilla de Caracteres (StringGrid): Este componente esta diseado especficamente 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 grfico 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 mostrarn).
Numero de columnas
Numero de Filas
La propiedad Cells se utiliza para en momento de ejecucin 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 escribira, en el evento adecuado, la siguiente instruccin: StringGrid1.Cells[3,2] := 5 de abril;
Componentes Bsicos
45
Figura (Shape): Usando este control podemos crear crculos, rectngulos, 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 grfico 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 automticamente este componente cuando no se pueden mostrar todos los componentes de un formulario. El siguiente grfico 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, prcticamente igual, con la salvedad de que los componentes Bevel no actan 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 grfico muestra el efecto de la propiedad Style.
46
Fuente de Datos (Data Source) permite establecer la relacin entre el objeto Tabla (Table) y otros objetos de manipulacin de datos (pestaa Data Controls de la paleta de objetos). Tabla (Table) establece la relacin entre una tabla fsica de un manejador de base de datos y una aplicacin Delphi. Las propiedades DataBaseName y TableName identificaran 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 realizara de la siguiente forma:
Tabla Fsica
Nota: Las relaciones entre los objetos Tabla y Fuente de Datos con otros objetos de manipulacin de datos se establece por medio de las propiedades de los objetos. Mas adelante se explicara la forma de utilizar las propiedades ms importantes para conectar estos objetos.
47
Consulta en SQL (Query). Almacena en una de sus propiedades una instruccin 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. Tambin se pueden utilizar en bases de datos que cumplan con el tipo de conexin ODBC. Una instruccin 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 conexin entre la tabla fsica y los objetos de manipulacin de datos que se encuentran en la pestaa 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 conexin entre la tabla fsica y los objetos de manipulacin de datos que se encuentran en la pestaa Data Controls de la paleta de objetos.
Base de Datos (DataBase). Este objeto se utiliza cuando en una aplicacin se requiere poseer controles discretos sobre una base de datos. Los tipos de controles que provee este objeto son sobre: Conexiones persistentes.
Manejo Bsico de Base de Datos Tipos personalizados de conexin (login). Control de transacciones lgicas.
48
Seleccin de diferentes bases de datos dependiendo de los requerimientos de la aplicacin. El objeto DataBase es de particular importancia cuando se trabaja con bases de datos remotas (Sybase, SQL Server, Oracle, Informix, DB2, InterBase). Delphi automticamente crea un objeto DataBase en momento de ejecucin de la aplicacin si explcitamente no se creo en un formulario.
Sesin (Session). Cuando se estan utilizando varias bases de datos diferentes en una aplicacin, el objeto Session provee un control administrativo global de la conexin de las bases de datos en los formularios de la aplicacin. 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 automticamente crea un objeto Session en momento de ejecucin de la aplicacin si explcitamente 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: Aadir registros de una tabla (fuente) a otra tabla (destino) de una base de datos. Si registros iguales existen NO son remplazados. (Modo Append). Aadir 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).
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. Tambin existen otras alternativas de procesamiento en lote de tablas. Un conjunto variado de mtodos (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 prximos objetos mencionados pueden ser utilizados en aplicaciones avanzadas de manejo de base de datos donde el equilibrio de la comunicacin 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 inclusin (INSERT), actualizacin (UPDATE) o eliminacin (DELETE) de registros por medio de instrucciones de SQL se puede realizar automticamente (in sin intervencin del usuario) sin importar que una Consulta de SQL sea solamente de lectura. Proveedor de Datos (Provider). Engloba mecanismos para proveer datos a una aplicacin multi hilos en una aplicacin 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. Comnmente utilizado en conjunto con el Proveedor de Datos (Provider). Servidor Remoto de Datos (RemoteServer). Describe la conexin remota del servidor con la aplicacin cliente en un proceso multi hilo. Objeto usuado en combinacin con el Proveedor de Datos (Provider) y Cliente de Datos (ClientDataSet).
50
Los objetos disponibles en la pestaa Data Access de la Paleta de Objetos representan la puerta de entrada para una optima manipulacin de datos. En la mayora de las aplicaciones pequeas 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 pestaa Data Controls de la Paleta de Objetos o Componentes posee los objetos disponibles para hacer que una aplicacin tome vida. En esta se encuentran las interfaces que hacen posible la comunicacin entre un usuario y los datos almacenados en una o varias bases de datos. Es conveniente recordar que los objetos brevemente descritos en esta seccin son no visibles y normalmente se depositan en un Modulo de Datos. Los prximos objetos se utilizan exclusivamente en formularios que son visibles a los usuarios finales.
51
Cuadricula de B.D. (DBGrid). Permite la manipulacin de datos de una tabla o consulta SQL en una forma parecida a una hoja de calculo. Una matriz grfica se presenta donde cada fila representa un registro de la tabla y cada columna en un campo de un registro. El siguiente grfico 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 conexin con la tabla fsica (sealado atraves de las flechas punteadas azules). El DBGrid esta mostrando tres registros donde cada registro esta constituido por tres campos (Cdigo, Descripcin y Saldo).
52
Es importante destacar que ya tenemos un formulario de manipulacin de datos completamente funcional. Dependiendo de la configuracin (valores) de las propiedades del objeto DBGrid podemos incluir, modificar o eliminar registros de la tabla en momento de ejecucin. 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 mayora 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 tambin se muestran. Por defecto se presentan todos los botones mostrados en el siguiente grfico pero es posible configurar el objeto (por medio de las propiedades) para que solo presente los botones particulares a una aplicacin.
Primero
Prximo
Incluir
Editar
Cancelar
Anterior
Ultimo
Eliminar
Aceptar
Refrescar
Etiquetas de B.D. (DBLabel). La caracterstica fundamental de una etiqueta es que mantiene (en tiempo de ejecucin) 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. Adems de poseer propiedad DataSource que define la fuente de datos, tambin existe la
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 carcter, numrico o fecha puede ser actualizado por medio de este componente. Tambin existe la propiedad DataField (entre otros) que define que campo de la tabla se manipulara por medio de este objeto o componente. El siguiente grfico muestra tres (3) DBEdit correspondientes a la tabla Maestro. Cada DBEdit corresponde a un campo de dicha tabla: Cdigo, Descripcin 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 lneas 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 imgenes 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 continuacin tiene un campo descripcin que puede tener solo los valores Jamn Tipo A, Jamn de Pierna, Fiambre, etc. Esta lista de valores es comnmente definida en momento de diseo del formulario. El ratn se utiliza para determinar que valor tendr este campo. Delphi se
54
encarga de mostrar que tipo de descripcin corresponde al registro que esta siendo mostrado en el formulario. Por ejemplo, el cdigo 00000 corresponde al Jamn de Pierna y por lo tanto la lista de posibles valores se muestra esta descripcin. Pero cuando se utilice el navegador de base de datos para ir a otro registro de la tabla, el correspondiente valor del cdigo se mostrara en el DBListBox. Cada lnea mostrada en la caja se almacena en la propiedad Items del objeto.
Caja Combo de B.D. (DBComboBox). Este componente posee las mismas caractersticas que el objeto anterior (DBListBox) con la salvedad que es su presentacin es como una caja de texto donde solo se muestra una sola de las opciones. Un pequeo botn 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 lnea mostrada en la lista desplegable se almacena en la propiedad Items del objeto.
Caja de Status o Condicin 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 actualizacin correcta en la base de datos. Como ya se menciono las propiedades DataSource y FieldName deben tener valores apropiados para la correcta actualizacin del campo de datos. El siguiente grfico muestra como la condicin de un cliente puede ser cambiado (y mostrada) usando el objeto DBCheckBox.
Area donde se actualiza el valor del campo. Propiedad que define la etiqueta del objeto DBCheckBox.
55
Grupo de Botones de Radio de B.D. (DBRadioGroup). Algunas aplicaciones de B.D. actualizan campos de una tabla donde ms de dos valores (pero uno solo de ellos en un momento dado) puede ser almacenados. Normalmente un conjunto muy pequeo de valores son los validos para el campo (Ver grfico 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 ratn el usuario seleccionara la condicin adecuada. Los ttulos y valores para cada categora son asignados en las propiedades del objeto. Por ejemplo, la propiedad Values del objeto puede tener los valores A, I y E que corresponderan con cada una de las lneas del tipo de condicin que se desea actualizar. Cada titulo o etiqueta de las condiciones se almacenan en la propiedad Items del objeto. Caja de Lista de Claves Forneas B.D. (DBLookUpListBox). La aplicacin de los conceptos de normalizacin y centralizacin de datos implica el uso de claves forneas. Por ejemplo, el Cdigo del cliente se utiliza en una tabla de facturas para establecer la relacin 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 acta 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 Cdigo.
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 cdigo 00001 tiene una descripcin de Fiambre y pertenece a la transaccin 111111. El campo Descripcin que aparece en el rectngulo blanco representa una nota o aclaratoria de la lnea de transaccin y no la descripcin de la tabla maestro. El siguiente grfico muestra la ventana del inspector de objetos con las propiedades del DBLookUpListBox que se utiliza en el formulario anterior.
Nombre del campo (de la tabla Maestro) que debe concordar con el contenido del campo a ser actualizado (cdigo 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 posicin) del campo de ListField cuyo valor ser retornado al campo definido en DataField (Cdigo de la tabla Transacciones).
La lista parcial de atributos del objeto muestra los elementos ms relevantes para establecer la relacin entre la tabla fuente (DataSource) y la tabla (ListSource) que suministrara la lista de valores para la seleccin. Como la lista de valores puede tener varias columnas (campos) es importante establecer el ListFieldIndex donde se define la posicin de la columna que retornara el valor al DataField. En este caso el ListFieldIndex 0 corresponde al primer campo (Cdigo) que se encuentra en la propiedad ListField. La propiedad KeyField define el nombre que tiene la clave fornea en el ListSource (Tabla Maestro). El nombre del campo en la tabla Maestro y Transacciones no tienen que ser iguales, pero si su contenido.
57
Caja Combo de Claves Forneas B.D. (DBLookUPComboBox). Este componente acta 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 fornea) por medio de una lista desplegable. El siguiente grfico muestra un DBLookUPComboBox
para actualizar el campo Cdigo. Observe que el espacio utilizado es menor que un DBLookUPListBox. Tambin se necesita un componente DBEdit adicional para desplegar la descripcin del cdigo 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, tamaos y colores de fuentes en un mismo prrafo. Este formato es compatible con el Word y WordPad de Windows.
58
Cuadricula de B.D. Libre (DBCtrlGrid). Como se menciono anteriormente, el componente DBGrid despliega una matriz con columnas (campos) y filas (Lneas). El objeto DBCtrlGrid tambin 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 grfico muestra el diseo de un formulario con un DBCtrlGrid y otros componentes.
DBCtrlGrid
DBEdit Label
Un DBCtrlGrid posee un numero determinado de paneles (tres en este caso) que son definidos por una propiedad del objeto. En momento de diseo se colocan los componentes de manipulacin de datos en el primer panel, los otros paneles estn 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 ejecucin. El DBNavigator se utiliza para contralar la navegacin y actualizaciones de la tabla.
59
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 estn seleccionados. 4. Ventana Organizacin de los Campos. Despus de seleccionar los campos que se utilizaran en el formulario hay que definir la posicin donde se ubicaran en pantalla. Existen tres (3) alternativas: Horizontalmente. Verticalmente. En una objeto DBGrid (Matriz tipo hoja de calculo).
5. Ventana Relacin de Campos. Si el tipo de formulario es Maestro Detalle el Asistente debe tener informacin sobre como establecer la relacin entre la tabla Maestro y la tabla Detalle. Esta ventana se muestra en la parte derecha de esta pagina. Por cada registro
61
que es ledo de la fuente de datos Maestro se debe leer uno o ms 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 relacin se establece seleccionando uno o ms campos de la parte izquierda y derecha de la ventana y pulsando en botn 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. Tambin 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 aplicacin. En este caso los componentes serian la definicin de las fuentes de datos (tablas simples o consultas en SQL). Varios formularios podran utilizar la misma fuente de datos y su definicin estara centralizada en un solo Modulo de Datos. Es ms conveniente cambiar cualquier caracterstica de las fuentes de datos cuando estas se encuentran en un solo sitio y no diseminadas en diferentes formularios. Los Mdulos de Datos son invisibles durante la ejecucin del programa. En momento de diseo es cuando se pueden manipular. En estos formularios tambin se pueden definir reglas de integridad y validacin de datos por medio de eventos. Estos conceptos sern posteriormente ejemplificados, pero el aspecto ms relevante es que un Modulo de Datos servira como un contenedor de todas las reglas de manipulacin de datos de las tablas de un sistema. Cuando se necesite la definicin de una tabla tambin se puede suministrar, conjuntamente, todas las validaciones de integridad relacionadas. Despus de generar un formulario de manejo de base de datos se procede a definir las reglas de validacin. Por cada fuente de datos se crean respuestas a eventos que apoyaran el mantenimiento de la integridad de los datos. Por ejemplo, para validar que el campo Saldo de una tabla no sea negativo s definira el evento OnValidate de la fuente de datos. Mas sobre esto en los prximos captulos. El siguiente grfico muestra el
62
63
Ahora, podemos crear una consulta en SQL para obtener la descripcin de todos los registros de la tabla Maestro que tienen monto de transacciones mayores a 1,000. La instruccin en SQL seria la siguiente: Select Descripcin 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 aplicacin con un formulario nuevo. Opcin File New Aplicacin. 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.
64
2. Seleccionar un componente DataSource y un Query de la Paleta de Objetos (pestaa 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 conexin 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 ratn 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 manipulacin de datos sabrn cual es la fuente de datos. El Inspector de Objetos se muestra en la parte derecha de esta pagina. Ahora procederemos a definir la instruccin de SQL adecuada para obtener la consulta deseada. 4. Escribir la instruccin SQL en la propiedad SQL del objeto Query. Seleccionar el objeto Query usando el ratn 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.
Manejo Bsico de Base de Datos Buscar la propiedad SQL, seleccionarla y pulsar el botn que aparece en el lado derecho de la caja de texto (botn con tres puntos suspensivos). La ventana de dialogo String list editor se desplegara en pantalla. Escribir la instruccin en la ventana de dialogo que se muestra en pantalla y luego pulsar OK. Esta ventana de dialogo se muestra a continuacin.
65
5. Hasta este momento esta parcialmente definido el enlace entre la base de dados fsica (C:\Base) y el formulario (Query y DataSource). Ahora debemos buscar una forma de mostrar los datos resultantes de la instruccin SQL. Un DBGrid se puede utilizar para manipular el dataset (datos). Seleccione de la paleta de objetos, la pestaa Data Controls. Seleccione el objeto DBGrid y sultelo en el formulario. Cambie el tamao del DBGrid, usando el ratn, para ajustarlo a la medida que desee. El siguiente grfico muestra de donde obtuvo el objeto DBGrid, el inspector de objetos y la apariencia que posee en el formulario.
66
Seleccionar el objeto DBGrid usando el ratn 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 conexin a un objeto de manipulacin de datos (DBGrid). 6. El siguiente paso seria ejecutar la aplicacin. Ya se defini la instruccin SQL (Objeto Query), su fuente de datos (Objeto DataSource) y como manipular los datos (objeto DBGrid), pero la consulta (instruccin SQL) en si no esta abierta. Hay dos formas de abrir una consulta. La primera es en momento de diseo y la segunda en momento de ejecucin (mtodo Query1.Open). Utilizaremos la primera alternativa para abrir la consulta. Seleccionar el objeto Query usando el ratn 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.
67
Busque la propiedad Activo (Active) y cmbiela por el True. De esta forma Delphi abre y muestra los resultados en los objetos de manipulacin de datos que este relacionados con su DataSource. El siguiente grfico muestra el formulario y el Inspector de Objetos en momento de diseo.
En momento de ejecucin los objetos DataSource y Query no aparecern en pantalla. Estos objetos son visibles solo cuando s esta diseando la aplicacin. Por ejemplo, el siguiente grfico representa como se vera 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 manipulacin de datos que se encuentran en la pestaa 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 Dinmicos (Late Binding) en instrucciones SQL. El concepto de Enlaces Dinmicos ser ampliado posteriormente.
68
En momento de ejecucin del programa se evaluara la instruccin 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.
69
Despus de seleccionar y soltar el botn rpido OK en el formulario hay una propiedad que debe ser modificada. Un botn puede tener diferentes tipos dependiendo de la funcin que realizara. Delphi posee varios tipos de botones predefinidos que podemos utilizar. Tambin podemos definir nuestros propios tipos. En este caso se desea que cumpla con el objetivo de aceptar y ejecutar la instruccin de SQL. Seleccionemos el botn del formulario y presionemos F11 para ver la ventana del Inspector de Objetos (mostrada a continuacin). En la pestaa de propiedades modificamos la propiedad Kind por bkOK. El icono y leyenda del botn cambiaran automticamente. La apariencia del botn cambio pero falta por decirle a Delphi que se debe hacer en el evento de un click del ratn (ejecutar la instruccin SQL). El botn Ok debe realizar varias operaciones. Estas funciones serian: 1. Cerrar cualquier consulta previa del objeto Query1 (Mtodo Close). 2. Limpiar el contenido de la propiedad SQL (Mtodo Clear). 3. Asignar el contenido del objeto Memo1 (propiedad Lines) a la propiedad SQL del objeto Query1. 4. Ejecutar la nueva instruccin en SQL (Mtodo Open). Seleccionamos el objeto botn y presionamos F11. En la pestaa 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 Cdigo se desplegara en pantalla con un procedimiento de Pascal en blanco. En este procedimiento escribimos las instrucciones necesarias para ejecutar las operaciones. El siguiente grfico muestra el cdigo necesario. Cada numero corresponde a las operaciones mencionadas anteriormente.
70
Otra alternativa de ejecucin dinmica de instrucciones SQL es el de formar la instruccin por medio de la programacin. Por ejemplo, un formulario podra pedir un valor del campo descripcin para filtrar sola los registros que cumplan con el criterio. Supongamos que el usuario desea todos los registros cuya descripcin comienzan con la palabra Jamn. En momento de ejecucin se creara la instruccin SQL. La tira de caracteres puede ser leda en un objeto de Caja de Texto (Edit) y al pulsar un objeto de botn se procesa la instruccin. El siguiente grfico muestra el formulario en momento de diseo. El evento OnClick del objeto botn es donde se escribirn las instrucciones para ensamblar y abrir la consulta en SQL. El siguiente grfico muestra las instrucciones necesarias para cumplir con los requerimientos.
71
El botn Ok realiza varias operaciones: 1. Cerrar cualquier consulta previa del objeto Query1 (Mtodo Close). 2. Limpiar el contenido de la propiedad SQL (Mtodo Clear).
3. Asignar, al contenido de la propiedad SQL del objeto Query1, la instruccin en SQL (Mtodo ADD). Desde la lnea numero tres (3) hasta la cinco (5) se realiza esta asignacin. El smbolo $ se utiliza como comodn para denotar que cualquier secuencia de caracteres puede existir despus del contenido de la caja de texto. La instruccin a introducir es la siguiente: Select * From Maestro Where Descripcion Like Contenido de la Caja de Texto%; 4. Ejecutar la nueva instruccin en SQL (Mtodo Open).
72
La propiedad RequestLive del objeto Query debe ser igual a True. Las caractersticas de la instruccin SQL. Para consultas sobre una sola tabla local (Dbase Paradox) deben usar: Clusulas JOIN, UNION, MINUS, GROUP BY, HAVING o DISTINTICT. Funciones Agregadas. Subconsultas.
73
Clusula ORDER BY basada en campos que no son ndices. Tablas que sean solo de lectura. Las caractersticas de la instruccin 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. Ningn ordenamiento de los registros. Las caractersticas de la instruccin SQL. Para consultas sobre una sola tabla remota (Oracle, SysBase, etc.) no deben usar: Clusula 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 estndar de SQL-92.
Si no se cumplen con estas condiciones el BDE (Borland Database Engine) devuelve una condicin de solo lectura para la consulta. Cualquier intento de incluir, modificar o eliminar un registro de la consulta genera un error en tiempo de ejecucin. Es importante resaltar que son pocos los momentos en los cuales se trata de modificar registros que son el resultado de una instruccin que no cumplan con la sintaxis arriba descrita. La mayora de las actualizaciones involucran la utilizacin de tablas donde las validaciones de integridad de los datos determinan un control estricto de manipulacin a nivel de la aplicacin cliente y / o el servidor de datos.
74
Cuerpo DataSource2
Cuando se lea (y muestre) la transaccin numero 00000 tambin deben ser mostrados solo registros de la tabla Cuerpo que posean el numero de transaccin 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
75
Cuerpo. La siguiente tabla tiene las dos instrucciones en SQL para manipular los datos: Query1
Select * From Cabeza;
Query2
Select Numero_Tran, Codigo, Tipo, Descrip_Tran, Saldo From Cuerpo, Cabeza Where Cuerpo.Numero_Tran = Cabeza.Numero_Tran;
Al ejecutar la aplicacin vemos que el resultado es incorrecto. El DBGrid, al final del formulario, contiene todos los registros de la tabla Cuerpo. Solo deba mostrar los registros que posean igual numero de transaccin en la tabla Cabeza y Cuerpo. Las dos ultimas lneas de transacciones (Numero_Tran igual a 11111) del DBGrid no deberan ser mostradas. La solucin para este problema es utilizar el concepto de Late Binding. En momento de ejecucin es cuando se establece correctamente el criterio de seleccin (clusula WHERE) de la instruccin SQL. La lgica deseada, para el primer registro de la tabla Cabeza, seria: SELECT * From Cuerpo, Cabeza Where Cuerpo.Numero_Tran = 00000
76
Claro esta que no podemos tener una instruccin SQL para cada registro de la tabla cabeza. El concepto de Enlaces Dinmicos de registros se establece en Delphi utilizando la propiedad DataSource del objeto Query y una sintaxis especial en la instruccin SQL. El siguiente grfico muestra la ventana del inspector de objetos con las propiedades de Query2 y la instruccin en SQL adecuada. Note los dos puntos (:) que estn antes del campo Numero_Tran. Los dos puntos determinan que el contenido del numero de la transaccin se obtendr de la fuente de datos escrita en la propiedad DataSource del objeto Query2.
Contenido de la propiedad SQL (no mostrada): Fuente de datos para la tabla tipo Maestro. En este caso la tabla Cabeza. SELECT * From Cuerpo Where Numero_Tran = :Numero_Tran;
77
78
La implementacin de rutinas para validar la integridad de datos al nivel de la aplicacin tambin 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 continuacin. Responder Despus, Antes Durante la ocurrencia de un evento (accin) sobre una tabla. Despus de cancelar una operacin. Despus de cerrar una tabla. Despus de eliminar un registro. Despus de entrar en el modo de edicin. Despus de insertar un registro Despus de abrir la tabla Despus de grabar un registro. Despus de cambiar (navegar) de registro. Antes de cancelar una operacin. 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 eliminacin. En momento de un error de editar registro. En momento de filtrar registros. En momento de aadir un registro. En momento de un error de actualizacin. En momento de responder al servidor. En momento de errores de cambios en lote. En momento de cambiar registros en lote.
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) tambin 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 Cdigo. Tabla_MaestroDescripcion: Campo Descripcin. Tabla_MaestroSaldo: Campo Saldo. Al igual que el objeto Tabla_Maestro, los objetos de campos tambin poseen un grupo de propiedades, eventos y mtodos. 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 Cdigo 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 cdigo. BeforeEdit (Objeto tabla Maestro): Antes de modificar un registro de la tabla Maestro se debe guardar temporalmente el valor del cdigo actual (el que va ser cambiado) para usarlo en el evento OnValidate del objeto Tabla_MaestroCodigo (el campo Cdigo de la tabla Maestro). La variable Codigo_Anterior se utilizara para almacenar temporalmente el valor del campo cdigo antes de cualquier edicin. OnValidate (Objeto Tabla_MaestroCodigo del objeto tabla Maestro): En el proceso de validacin de un registro de la tabla Maestro se debe verificar que si cambio el cdigo del maestro, el cdigo anterior no tenga transacciones. Si hubo una modificacin del campo, se debe
80
utilizar el cdigo anterior para validar (que ese cdigo anterior) no tenga transacciones. La implementacion de estos eventos clarificara cualquier duda que se tenga sobre ellos. El siguiente grfico muestra el modulo de datos donde se declararon las tablas y fuentes de datos, el inspector de objetos con informacin sobre el objeto Tabla_Cuerpo y el formulario de manipulacin de transacciones.
El inspector de objetos muestra la asignacin del evento BeforePost. Para seleccionar y utilizar un evento, posiciones el ratn sobre el nombre del evento deseado y pulse doble click. Delphi asignara y creara un procedimiento vaco en Pascal. El nombre del procedimiento es la
81
concatenacin del nombre del objeto (en este caso Tabla_Cuerpo) y el nombre de evento (BeforePost). El nuevo procedimiento (Tabla_CuerpoBeforePost) se muestra a continuacin. Las lneas de programacin necesarias para validar la existencia del cdigo en la tabla maestro cuando se actualiza la tabla cuerpo se encuentra escrito. Secuencias de programacin: 1. Asignacin temporal del nuevo contenido del campo cdigo a la variable Clave. El nombre del objeto Tabla_CuerpoCodigo representa el campo cdigo. La propiedad Value es el contenido actual de ese campo.
2. Utilizar el mtodo Locate (localizar) del objeto Table para buscar en la tabla maestro el nuevo cdigo. El mtodo retorna True si encontr la clave en la tabla. Los parmetros de entrada del mtodo son: Lista de los nombres (separados por ;) de campos a buscar. Lista de contenidos de campos a buscar. Conjunto que define el tipo de bsqueda. Sensitivo a maysculas. [loCaseInsensitive]. Bsquedas parciales. [loPartialKey].
82
3. Si la clave (cdigo) no existe, mostrar un mensaje de error y abortar la actualizacin del registro de la tabla cuerpo. La implementacin del evento BeforePost (antes de grabar o actualizar) garantiza que cualquier accin de incluir o editar un registro de transacciones, exista una validacin de integridad con respecto a la tabla maestro. Tambin hay que implementar la verificacin de integridad en sentido contrario, desde la tabla maestro a la tabla de transacciones (cuerpo). El nuevo procedimiento (Tabla_MaestroBeforeDelete) se muestra a continuacin. Cuando se trata de eliminar un registro del maestro, el evento BeforeDelete se activa. En este evento se verifica que no exista el cdigo del maestro en un registro de transacciones (tabla Cuerpo). Las lneas de programacin necesarias para validar la existencia del cdigo en la tabla cuerpo cuando se actualiza la tabla maestro se muestran a continuacin:
1. Asignacin temporal del contenido del campo cdigo (del maestro) a la variable Clave. El nombre del objeto Tabla_MaestroCodigo representa el campo cdigo del registro de la tabla maestro que se
83
intenta eliminar. La propiedad Value es el contenido actual de ese campo. 2. El mtodo Locate (localizar), del objeto Table, busca en la tabla cuerpo el cdigo, contenido en la variable Clave. El mtodo retorna True si encontr la clave en la tabla cuerpo. 3. Si la clave (cdigo) no existe, mostrar un mensaje de error y abortar la actualizacin del registro de la tabla cuerpo. El prximo paso seria validar que la modificacin de un cdigo del maestro no genere inconsistencias con la tabla maestro. Por ejemplo, no podemos cambiar el cdigo 00000 por 10101 por el hecho de que existen registros de transacciones asociados. La lgica de implementacin puede ser guardar provisionalmente el contenido del campo cdigo 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 Cdigo 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 grfico muestra el segmento de cdigo donde se declara la
84
variable Codigo_Anterior y la ventana donde se define el evento BeforeEdit para la tabla maestro. El proceso de actualizacin (edicin) de un registro de una tabla en Delphi cumple con la invocacin de los siguientes eventos (si estn 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 validacin de cada campo del registro. En este caso la verificacin del campo Cdigo es determinante. En este evento de validacin del campo Cdigo se implementara la consistencia entre las tablas Maestro y Cuerpo. Si existen transacciones para el cdigo que se desea cambiar, se abortara el proceso de actualizacin. Los siguientes segmentos de pantallas muestran
85
como ver y seleccionar el evento Validate para el campo cdigo. 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 cdigo y presionando F11 se puede ver el inspector de objetos para ese objeto seleccionado. En la pestaa 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 continuacin.
En la implementacin del evento se puede observar que la secuencia de instrucciones son muy parecidas a las anteriores. Es importante resaltar que en este evento tambin se puede escribir el cdigo necesario para realizar cualquier otro tipo de validacin que la aplicacin requiera. Por ejemplo, si deseamos validar que el campo cdigo tenga como primer carcter una letra en mayscula 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;
86
87
Definicin esttica 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 diseo del formulario. Por ejemplo, el siguiente grfico muestra el formulario de transacciones donde en el momento de tratar de editar el campo Codigo del DBGrid un botn 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 botn una lista con los valores predefinidos es desplegado. El siguiente grfico muestra esta accin:
88
Valores Predefinidos
Las operaciones que deben realizarce para definir esta caracterstica 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 botn derecho del ratn cuando se este sobre el objeto y seleccionar la opcin 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 botn de aadir campos. Seguidamente se muestra la ventana del Editor de Columnas (Delphi 4).
Nueva Columna Borrar Columnas Aadir Columnas Restaurar Valores
Columna seleccionada
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 Seleccin). En esta propiedad se pueden almacenar valores para ser desplegados en momento de ejecucin. 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 seleccin. La ventana del Inspector de objetos y la ventana del Editor de Strings se muestran a continuacin. 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 botn 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 botn con elipses se despliega y se ejecuta el evento OnEditButtonClick (mas sobre este evento en prximas secciones). 3. CbsNone : No se despliega ninguna lista de seleccin.
90
Definicin dinmica del rango de valores a ser seleccionados. Otra alternativa del uso de catlogos en un DBGrid es que en momento de ejecucin se asignen los valores a la lista de seleccin (PickList) para una columna especifica. La opcin anterior asignaba los valores en momento de diseo del formulario. El evento OnCreate (cuando se crea el formulario) es adecuado para inicializar valores inmediatamente despus de crear un formulario en memoria en tiempo real (corrida del programa). La ventana del Inspector de Objetos (para el objeto Formulario y la definicin del evento OnCreate se muestran a continuacin.
En el Editor de Codigo se puede observar que hay dos lneas que asignan al objeto DBGrid1 (Celdas del area de detalle, tabla cuerpo), subobjeto 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 fornea (Maestro en este caso) todos los registros y aadir los valores adecuados en el PickList. En la siguiente ventana se muestra las lneas de cdigo fuente necesarias para incluir el
91
campo Codigo de la tabla maestro al PickList del DBGrid Columna Cero (columna Codigo),
En el procedimiento anterior la tabla Maestro es secuencialmente leda y por cada registro se aade el campo cdigo de cada registro. Se pueden aplicar cualquier tipo de criterios para la seleccin de registros. Tambin es posible aadir mas de un campo en la lista de seleccin. Por ejemplo, la siguiente lnea de cdigo aade el cdigo y descripcin a la lista de seleccin (PickList) separados por un guin. DBGrid1.Columns.Items[0].PickList.Add(Tabla_MaestroCodigo.Value+ ' - '+ Tabla_MaestroDescripcion.Value La prxima alternativa es la mas adecuado por su flexibilidad. Utilizaremos otro formulario para seleccionar el valor del campo cdigo.
92
Uso de formularios como dialogo para seleccionar valores. La Ultima alternativa que mencionaremos para manipular catlogos 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 ratn se selecciona un cdigo de maestro para ser utilizado como contenido del campo cdigo de maestro en la tabla Cuerpo. El siguiente grfico muestra el formulario que utilizaremos para mostrar el catalogo del maestro y la ventana del Inspector de Objetos desplegando las propiedades del botn 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 botn 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.
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 botn 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 mtodo ShowModal. Entre ellas tenemos: mrNone mrOk mrCancel mrAbort mrRetry mrIgnore mrYes mrNo mrAll : Nada : Correcto. : Cancelar. : Abortar. : Re - intentar : Ignorar. : Si. : No. : Todos.
Dependiendo del tipo de resultado, el formulario que mostr el formulario tipo dialogo toma una va de accin determinada. En nuestro caso, y como se muestra en el grfico anterior, el botn Ok tiene definido la propiedad de retorno del ModalResult como mrOk. El botn Cancelar retorna el ModalResult de mrCancel. A un objeto estndar 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 Cdigo del registro de la tabla Maestro que este siendo mostrado en el momento que se pulse el botn Ok. Seguidamente se encuentra todo el cdigo 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 ejecucin.
94
95
El formulario de transacciones debe ahora ser modificado para poder manejar la presentacin del catalogo de maestro. Los pasos son los siguientes: Cambiar la propiedad ButtonStyle, de la columna Cdigo 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 botn del PickList de cualquier columna. El siguiente grfico muestra el Inspector de Objetos, Editor de Columnas y formulario de transacciones.
El siguiente paso consiste en escribir el cdigo fuente para reaccionar al evento OnEditButtonClick. Seleccionando el DBGrid se pulsa F11 para mostrar el Inspector de Objetos y desde la pestaa de eventos se busca el evento OnEditButtonClick y se pulsa doble Click para mostrar el Editor de Cdigo. El siguiente grfico muestra el
96
Inspector de Objetos y el Editor de Cdigos donde se describen las acciones para reaccionar al evento.
La propiedad SelectedField del DBGrid posee la descripcin 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. Tambin es relevante comentar la forma en que se muestra el formulario del catalogo de maestro. En este caso se utiliza el mtodo 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 edicin. La propiedad State se utiliza para saber en que estado (inclusin, edicin, navegacin,...) se encuentra una tabla.
97
Aplicaciones Tipo Two Tiered (dos niveles). La aplicacin 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 actualizacin de datos requerida por muchos usuarios.
98
Aplicaciones Multi Tiered (tres o ms 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 ms bsica pueden existir tres niveles de procesamiento: 1. Aplicacin Cliente: Provee la interface GUI en la maquina local del usuario. 2. Servidor de Aplicaciones: Provee servicios comunes de distribucin 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 comunicacin 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 Aplicacin Cliente como tambin el Servidor de Aplicaciones. Bajo esta arquitectura tambin 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:
99
Modulo de Datos Remoto: Modulo de datos especializado que acta como un servidor COM o servidor CORBA para darle a la aplicacin 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 Conexin: Grupo de componentes que proveen la comunicacin, por medio de diferentes protocolos, entre el cliente y el servidor.
Creacin de Componentes.
100
Una de las caractersticas fundamentales de las actuales herramientas de programacin visual es el uso de componentes o controles. Dependiendo de la herramienta podemos tener una variedad en el estilo de implementacin de componentes. Por ejemplo, Visual Basic y Delphi utilizan componentes estndares como VBX y OCX. Tambin es posible cada lenguaje visual utilice enfoques propietarios para desarrollar componentes. En esta seccin se explicara como en Delphi podemos, primero, desarrollar componentes propietarios (de uso exclusivo en el ambiente de Delphi) y luego la creacin de componentes ActiveX que puede ser incorporados en diferentes herramientas de programacin. El desarrollo y uso de componentes es de suma importancia debido a que permite el compartimento de rutinas y objetos entre diferentes aplicacin y usuarios. Cuando es evidente que un segmento de cdigo fuente (con su respectiva interfaces GUI) se puede centralizar y encapsular y este cdigo ser compartido entre diferentes niveles de la organizacin 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 mayora de los componentes son propietarios, solo se pueden utilizar bajo el ambiente de programacin 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 creacin de componentes en Delphi es muy sencilla aunque el nivel de conocimientos para la creacin de este tipo de herramientas en general involucra una gran variedad de experiencias en cuanto a las internalidades de programacin en Windows.
Creacin 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, segn su funcionalidad. Existe un paquete originalmente predefinido llamado dclusr40.dpk donde el usuario puede colocar nuevos componentes o tambin es posible crear un nuevo paquete. La mejor forma de entender la creacin 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 opcin Component -> New Component. Un dialogo se desplegara en pantalla donde pedir: tipo (clase) de ancestro que tendr el nuevo componente El (TcomboBox para este caso). El nombre la nueva clase para el componente (Ej., TEstados). El nombre de la pestaa 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 bsqueda (subdirectorio) donde se ubicara el componente (C:\Estados). El siguiente grfico muestra este dialogo:
Nota: Segn estndares de Delphi el nombre de una clase debe estar precedida por la letra T.
Creacin de Componentes.
102
Al pulsar OK el sistema creara la unidad Estados.pas donde existir el cdigo fuente necesario para implementar un componente basado en la clase TcomboBox. Por su puesto este cdigo fuente implementa un componente con exactamente las mismas caractersticas 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 grfico muestra la unidad Estados.Pas en su forma original creada automticamente por el asistente de componentes luego de pulsar OK:
El prximo paso consiste en escribir el cdigo fuente para crear el componente en memoria. Se debe sobre-escribir el mtodo Create y CreateWnd heredados de la clase TcomBox (ver grfico de la derecha). En la seccin 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 despus de ser creado el objeto. Tambin se define la propiedad Style que pertenece a la clase original para asignarle por
Creacin de Componentes.
103
defecto el estilo de presentacin del componente. En este caso queremos asignarle el estilo csDropDownList que nos permite modificar o incluir nuevos valores en el rea de edicin del objeto. El usuario solo podr seleccionar uno de los estados pero no modificar o escribir un nuevo estado. En la seccin de implementacin se escribe el cdigo necesario para crear el objeto, asignar a la propiedad Style e inicializar la propiedad Items con los nombres de los estados.
El prximo paso consiste en finalmente compilar e instalar el nuevo componente. Se toma la opcin Component -> Install Component del men principal y el sistema presenta la siguiente ventana:
Al pulsar el botn Ok el sistema compila la unidad Estados.pas y si no hay problemas de compilacin se agrega el componente en el paquete Borland User Components (archivo dclusr40.dpk) e instala el mismo en
Creacin de Componentes.
104
la pestaa 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 botn Compile se utiliza para compilar la unidad y crear el archivo dclusr40.dpk que es el paquete donde se almacenara 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 seccin inferior de la ventana muestra un solo componente (Estados.pas). Eliminacin de Componentes de Delphi. Para eliminar un componente ya instalado en Delphi debemos seguir los siguientes pasos: Cerrar cualquier aplicacin 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 botn Remove y la siguiente ventana es presentada en pantalla: Se debe seleccionar el componente a ser eliminado y presionar el botn Ok para ejecutar la eliminacin del componente de la paleta y del sistema. El componente TEstados es sumamente sencillo, pero ejemplifica algunos aspectos importantes sobre la creacin de componentes de Delphi. El prximo ejemplo muestra el uso de otras tcnicas, entre ellas tenemos: La definicin de propiedades con sus respectivos mtodos 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
Creacin 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 presentara la siguiente ventana (mostrada con informacin ya escrita en el lado derecho de la hoja). El programa fuente se muestra a continuacin.
106
Un control ActiveX es una pieza de software que se integra a la funcionalidad de una aplicacin anfitriona. Esta aplicacin 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 grficos y manejo de hojas de calculo. Despus que un control ActiveX es incluido en el ambiente IDE de Delphi, se puede utilizar en cualquier formulario y modificar sus propiedades y reaccin a eventos por medio del Inspector de Objetos. Un control ActiveX tambin puede ser utilizado en una pagina Web y manipulado por medio de documentos HTML. Delphi suministra dos asistentes para la creacin de controles ActiveX. El primer es el Asistente de Controles ActiveX que permite la creacin de controles a partir de componetes existentes en la librera VCL (componentes normales de Delphi) y tambin 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 disear un control ActiveX basado en el componente TForm. El Asistente de Controles ActiveX genera una unidad de implementacin 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 implementacin que es un descendiente de TActiveForm. La creacin de un control ActiveX utilizando el primer asistente es un proceso muy simple. Despus de crear un componente Delphi, pasos descritos en la seccin anterior, se invoca el asistente pulsando la opcin de men File - New, la ventana mostrada en el lado derecha de la pagina ser desplegada en pantalla. En la pestaa ActiveX se selecciona el icono ActiveXControl para mostrar la ventana del Asistente de controles ActiveX. La siguiente ventana muestra esta ventana.
Creacin de Componentes.
107
En el Asistente de Controles ActiveX, grfico anterior, se debe dar informacin sobre el nombre de la clase (componente) que se va a utilizar como el ancestro del control as como tambin el nombre del nuevo control ActiveX, el nombre de la unidad, etc.. Un aspecto importante es que podemos decidir si el nuevo control tendr informacin sobre la licencia, versin y/o formulario Acerca. Si por ejemplo queremos crear un componente ActiveX partiendo del componente TEstado que fue desarrollado en la seccin anterior solo debemos suministrar la informacin sobre el nombre de la clase (primer campo de captura de datos en la ventana) y Delphi colocara el resto de la informacin por defecto. Por su puesto, estos datos pueden ser cambiados por el usuario. Al pulsar el botn Ok, un nuevo control ActiveX ser creado con la informacin suministrada. El siguiente grfico muestra la paleta de componentes, con el componente utilizado como ancestro y el Asistente de Controles ActiveX con los datos por defecto.
Creacin de Componentes.
108
Despus de crear el control hay que compilarlo y guardarlo en disco. La opcin 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 librera para inicializar la ejecucin del control. Esta librera normalmente no se cambia. La segunda unidad es la implementacin 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 opcin Component Install ActiveX Control del men principal se utiliza para tal fin. El siguiente grfico muestra la ventana que es utilizada para seleccionar un control ActiveX, de los disponibles y registrados en Windows, e incluirlo en la pestaa 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.
Sistema de Inventario
116
El siguiente capitulo trata de reforzar los conceptos introducidos en los temas anteriores con la explicacin del desarrollo un pequeo sistema utilizando Delphi El planteamiento de un problema de procesamiento de datos de una empresa hipottica seria conveniente para ejemplificar los pasos a seguir en el desarrollo del sistema. En este caso tomaremos el tpico problema de controlar la entrada y salida de mercanca en un sencillo sistema de inventario. Este sistema es conveniente puesto que presenta la utilizacin de tablas maestras, de movimientos y catlogos. Este ejemplo no trata de abordar todos los detalles de la elaboracin de un sistema completo de control de inventario.
En este sistema existen bsicamente dos tipos de movimientos: la entrada de mercanca 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 mercanca por deterioro de la misma de la salida de mercanca por robo o instalacin a un cliente. El siguiente grfico muestra el Diagrama Entidad Relacin que describe estticamente las relaciones existentes entre las entidades.
Sistema de Inventario
117
Producto
Esta / Tiene
0/N
Pertenece / Posee
Tipo de Movimiento
Esta / Es
0/N
1 Cabeza de Movimiento
La entidad lgica Movimientos de Inventario se dividi fsicamente en dos entidades. La Cabeza de Movimiento posee la informacin centralizada sobre el movimiento (numero, fecha, descripcin, tipo, etc.) y el Cuerpo de Movimiento mantendr el detalle de los productos involucrados (cdigo, descripcin, cantidad, etc.). Segn 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 da si la situacin lo amerita. Por ejemplo, todas las entradas de reposicin de inventario del da 10/10/1999 estarn agrupadas en un solo movimiento de inventario y todos los deterioros de mercanca detectados el mismo da en otro movimiento lgico de inventario.
Sistema de Inventario
118
Numero que identifica nicamente el producto Breve descripcin del equipo o parte. Cantidad mnima que debe existir como existencia. Cantidad mxima que debe existir como existencia. Cantidad bajo la cual debe ser repuesta la existencia. Total entradas del producto Total salidas del producto Campo calculado: Total Entradas - Total Salidas
Tipos de Movimiento Tipo Movimiento * Numero que identifica nicamente el tipo de mov. Descripcin Descripcin del tipo de movimiento Accin Determina como el movimiento afecta la tabla de productos. Si la accin 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 Descripcin Descripcin general del movimiento Tipo de Movimiento Tipo del movimiento Cuerpo de Movimientos Numero Movimiento * Numero que identifica nicamente el movimiento Cdigo Producto * Numero que identifica nicamente el producto Descripcin Producto Campo ledo 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.
Sistema de Inventario
119
120
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 grfico muestra las opciones de men requeridas y el dialogo respectivamente.
Despus 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 introducirn el nombre, tipo y tamao de cada campo y por ultimo al presionar el botn Save As... le daremos el nombre fsico a la tabla para ser almacenada en el subdirectorio de su predileccin.
Los siguiente grficos muestran la definicin del diccionario de datos de las cuatro tablas que sern utilizadas en nuestro sencillo sistema de inventario.
Sistema de Inventario
121
Tabla: Productos.
Nota: Los campos claves se definen marcando un * en la ultima columna. El campo Existencia Actual no esta descrito fsicamente en la tabla porque es un campo calculado y su definicin se realizara desde Delphi y no por medio del Escritorio de BD. Tabla: Tipos-Movimiento.
Sistema de Inventario
122
Tabla: Cabeza-Movimiento.
Tabla: Cuerpo-Movimiento
Sistema de Inventario
123
Es importante destacar que dependiendo del manejador de base de datos original el Escritorio de BD puede definir varias caractersticas adicionales. En la parte izquierda de la ventana del diccionario de datos se puede introducir los valores por defecto, mnimo, mximo y la mascara de edicin de los campos. Tambin podemos describir validaciones referenciales y campos de bsqueda automticos. Estos mecanismos de validacin las realizara el manejador de base de datos y no seria necesario escribir lneas de cdigo en Delphi para ello. El problema fundamental con esta estrategia es que existira menos independencia de datos. La aplicacin dependeria en parte de procesos de validacin delegados y particulares al manejador de base de datos. Un futuro cambio de manejador involucrara un proceso ms delicado y tedioso. La seleccin de la alternativa mas adecuada esta fuera del alcance de este documento.
Sistema de Inventario
124
La primera alternativa posee la principal ventaja que podemos centralizar la manipulacin de cada tabla o proceso en formularios diferentes. La segunda alternativa no ofrece esta ventaja ya que todas la definiciones y manipulaciones sern almacenadas en un solo formulario pero tiene el beneficio que podemos fcilmente crear un componente ActiveForm y as poder utilizar nuestra aplicacin a travs de Internet o manejarlo desde otro ambiente visual como por ejemplo Visual Basic o PowerBuilder. En este caso tomaremos la primera alternativa. Crearemos una aplicacin MDI para controlar la actualizacin de las tablas. La estructura del sistema seria de la forma siguiente:
Modulo de Datos
El formulario principal tendr un men principal que creara los formularios de Productos, Tipos de Movimiento y Movimientos de Inventario. Estos formulario utilizaran un modulo de datos para agrupar y manejar las definiciones lgicas de las tablas respectivas. Como se mencion en captulos anteriores el modulo de datos juega un papel importante ya que nos ayuda a centralizar las definiciones y manipulaciones bsicas de los datos. En este tipo especial de formulario se almacenan las reglas de uso de datos de la organizacin y puede ser fcilmente transferible a otros sistemas en el futuro.
Sistema de Inventario
125
importante, la propiedad FormStyle se tomara el valor fsMDIForm denotando que este formulario es el formulario padre o principal de una aplicacin 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. Despus de tener un formulario MDI debemos crear el sistema de men por medio del cual el usuario controlara la manipulacin de datos. Desde la pestaa Standard de la paleta de componentes tomamos el componente MainMenu y lo soltamos en el formulario principal. El siguiente grfico muestra este componente sobre el formulario. En este momento tenemos un componente para definir un men pero todava no hay una descripcin 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 definirn las opciones que constituirn el sistema en s. El siguiente grfico muestra las diferentes opciones que manejara el sistema.
Hasta este momento tenemos definido las opciones del men principal. Todava no hay asociadas ninguna accin con cada alternativa presentada en el sistema. Despus de crear los formularios de manipulacin de datos podemos terminar de definir las opciones de men asociando el evento Click de cada opcin con su respectivo formulario. Pero antes seria conveniente crear el modulo de datos y definiciones lgicas de las tablas a ser utilizadas en el sistema para luego definir los otros formularios.
Sistema de Inventario
126
Un formulario en blanco se creara y mostrara en pantalla. En este modulo de datos vaco incluiremos tantos componentes del tipo (clase) TDataSource y TTable como tablas tengamos que procesar. Tambin debemos definir el evento OnCreate de este formulario donde se abrirn dichas tablas. Desde la pestaa Data Access seleccionamos los componentes DataSource y Table y los soltamos en el modulo de datos. El siguiente grfico muestra esta operacin. Despus de soltar un par de componentes Datasource y Table procedemos a inicializar las propiedades que nos vinculan a estos componentes con las respectivas tablas fsicas. Las propiedades que hay que modificar, por medio del Inspector de Objetos, en ambos componentes para asociar las tablas serian las siguientes:
Sistema de Inventario
127
Componente : Datasource. Atributo Productos Name: DS_Producto DataSet Producto AutoEdit: False
Donde: Name: Nombre del componente. DataSet: Nombre lgico de la tabla. AutoEdit: Si automticamente se entra en modo de edicin. Componente: Table. Atributo Productos Name Producto TableName Producto.db DataBaseName C: \Inventario
Donde: Name: Nombre lgico de la tabla/DataSet (nombre del componente). TableName: Nombre fsico de la tabla. DataBaseName: Ubicacin fsica de la tabla o nombre de la B.D. El siguiente grfico muestra el formulario de modulo de datos despus de crear todo los componentes Datasource y Table correspondiente a cada tabla fsica del sistema y actualizar las propiedades arriba mencionadas.
El prximo paso consiste en definir la relacin 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 relacin 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
Sistema de Inventario
128
como el nombre de la fuente de datos maestra. La segunda propiedad es MasterFields. Por medio de esta propiedad describimos como se establece la relacin 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 relacin. Se debe seleccionar un par de campos, uno de cada tabla, y pulsar el botn Add para que el sistema aada la relacin 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 automticamente. La siguiente ventana muestra la seleccin necesaria para el sistema de inventario.
Sistema de Inventario
129
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 funcin F11 para invocar al Inspector de Objetos y por ultimo seleccionar la pestaa de eventos para buscar al evento OnCreate donde se escribir el cdigo fuente necesario para ejecutar el mtodo Open de los componentes de clase TTable usados en el sistema. El siguiente grfico muestra tanto el Inspector de Objetos como las instrucciones (ejecucin de mtodos) para abrir las tablas.
130
emergente ser desplegado en pantalla. El grfico anterior tambin muestra este men. Al tomar la opcin Add All Fields del men, Delphi lee todos los campos fsicamente definidos de la tabla y los coloca estticamente en el modulo de datos. El siguiente grfico muestra al Editor de Campos con los campos ledos de la tabla fsica. Al realizar esta operacin 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 caracterstica nos permitir mas adelante definir eventos de validacin a nivel de los campos. Despus de tener estticamente definidos los campos podemos incluir un nuevo campo (calculado) a la estructura lgica que se encuentra en el modulo de datos. Volviendo a pulsar el botn derecho del ratn sobre el Editor de Campos se muestra el men emergente que utilizamos anteriormente y tomamos en este caso la segunda opcin 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 automticamente el nombre del objeto o componente que representara el campo lgico (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
Sistema de Inventario
131
contenido del mismo. Es recomendable destacar que el resto de campos estticamente definidos en el paso anterior tambin tienen la misma estructura para el nombre del componente, es decir, nombre del archivo mas el nombre fsico del campo. Ya tenemos declarado el nuevo campo calculado pero todava falta por definir el calculo en s. En el evento OnCalcFields, de la tabla de productos, se debe escribir el cdigo 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 Cdigo donde esta la operacin necesaria.
Los pasos para definir el segundo campo calculado son muy parecidos al anterior. Se incluyen estticamente los campos fsicos como descripcin lgica 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 mtodo (entre muchos otros) FindKey([clave]) que busca, a travs del rea de ndices, un registro en la tabla. Si se encuentra el cdigo de producto se inicializa el campo calculado con la descripcin 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 Cdigo muestra este calculo.
Sistema de Inventario
132
La definicin esttica de todos los campos fsicos de todas las tablas es recomendable en la mayora de los casos para fcilmente asignar eventos de validacin o cambiar propiedades de los mismos en tiempo de ejecucin. Recuerden que un modulo de datos tambin se definen validaciones y en general reglas de manipulacin 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 lgicos. Por los momentos debemos crear los formularios bsicos de captura y edicin de informacin.
133
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 arrstrelos (representado por la flecha roja del siguiente grfico) 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 clusula Uses Unit_Modulo_Datos en el cdigo fuente del nuevo formulario y por ultimo creara tantos pares de componentes etiquetas (Tlabel) y cajas de edicin (TDBEdit) que correspondan con los campos soltados en el formulario.
El nuevo formulario, despus de arrastrar los campos seleccionados desde el Editor de Campos, se presenta en la siguiente ventana. Ntese que las etiquetas fueron inicializadas con los nombres de los campos, lo cual puede que no sea muy elegante. Tambin los campos fueron organizados verticalmente. Un pequeo 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
Sistema de Inventario
134
Caption del formulario por Productos). El prximo, y saludable, paso es guardar el formulario. Toma la opcin File Save del men principal y guarde la unidad con el nombre Unit_Productos en el subdirectorio deseado.
Ya existen los componentes que nos permitirn 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. Tmenos la pestaa de Data Controls de la lista de objetos disponibles y seleccionemos el objeto Navegator. El siguiente grfico describe esta operacin.
Sistema de Inventario
135
El grfico anterior tambin 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 aplicacin tipo MDI (Interfaces de Mltiples 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 aplicacin MDI. El prximo paso consiste en definir el formulario de productos como no auto-creado. Al ejecutarce una aplicacin, Delphi busca cuales formularios se deben crear automticamente y cuales no. En una aplicacin 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 aplicacin. Al tomar la opcin 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 reaccin de algn 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 seccin de formularios disponibles (no auto-creados) en el rea inferior derecha seleccionando el formulario que estaba en el lado inferior izquierdo y pulsando el botn que se encuentra en entre las dos reas inferiores del dialogo. Debemos regresar al formulario principal para definir el evento OnClick de la opcin Archivos Definiciones - Productos de nuestro sencillo sistema de mens. Seleccione el formulario principal tomando las
Sistema de Inventario
136
opciones View Forms Formulario_Principal desde el men principal de Delphi y el formulario principal se desplegara en pantalla. Luego pulse click sobre la opcin Archivo Definiciones Productos. Un procedimiento en blanco se presentara en el Editor de Cdigo donde se debe escribir el cdigo necesario para crear el formulario y presentarlo en pantalla. Las siguiente ventanas muestran el men principal del sistema y el Editor de Cdigo.
La instruccin necesaria para crear una instancia de la clase TForma_Productos es el mtodo Create. El parmetro Self significa que el formulario donde se ejecutara este mtodo es el dueo del componente a ser creado. Las siguientes ventanas muestran al Editor de Cdigo con esta invocacin del mtodo Create y en momento de ejecucin la aplicacin en s.
Sistema de Inventario
137
Antes de continuar con la creacin de los otros formularios del sistema es conveniente detenernos en el formulario de productos para desarrollar algunas validaciones y configuraciones bsicas: 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 numricos en total entradas, total salidas, existencia y punto de reorden. Evitar la inclusin de cdigos de productos duplicados. Esta no es una lista exhaustiva de las posibles validaciones que debera tener el formulario pero nos ayudan a ejemplificar la manipulacin de eventos desde Delphi. Validacin : 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 espaol. 4. Muestre el formulario Modulo de Datos por medio de la opcin 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 cdigo fuente que se presenta a continuacin en el Editor de Cdigo:
Sistema de Inventario
138
La funcin MessageDlg presenta una ventana de dialogo, dependiendo sus caractersticas de los parmetros suministrados. La sintaxis de esta funcin 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: Confirmacin, Error, Informacin, etc. En nuestro caso es de tipo mtCOnfirmation (confirmacin). Abuttons: Lo(s) Botone(s) a ser presentados en la ventana de dialogo. Pueden existir uno o ms botones. En nuestro caso se presentaran los botones Ok (mbOk) y Cancel (mbCancel). HelpCtx: Apuntador al archivo de ayuda, si existe. La funcin retorna el tipo de botn presionado por el usuario. El procedimiento Abort genera una excepcin (error) y cancela la ejecucin del evento y toda la operacin que genero el evento. En este caso la operacin de tratar de eliminar un producto. En momento de ejecucin y despus de pulsar el botn de eliminacin del navegador de BD se desplegara el dialogo de confirmacin. El siguiente grfico muestra esta situacin.
Sistema de Inventario
139
Validacin: 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 opcin 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 cdigo fuente que se presenta a continuacin en el Editor de Cdigo:
La primera seccin 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 cdigo fuente que se encuentra enmarcado en el bloque de la sentencia With implementa una bsqueda (mtodo Locate del componente Ttable) en la tabla Cuerpo_Mov (cuerpo de los movimientos de inventario) para verificar su existencia. Si existe el cdigo de producto en la tabla Cuerpo_Mov la funcin Abort es invocada para cancelar la operacin de eliminacin. Importante: Note la inicializacin de la propiedad MasterSource en la implementacin 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
Sistema de Inventario
140
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 relacin. 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 relacin determina, internamente, un filtro por medio del cual existen (lgicamente) solamente los registros de la tabla Cuerpo_Mov que estn relacionados con el registro actual de la tabla Cabeza_Mov. Los otros registro del la tabla cuerpo momentneamente no existen. A este concepto frecuentemente se le denomina Late Binding (enlaces dinmicos). El siguiente grfico trata de mostrar que cuando el registro numero dos de la tabla cabeza esta siendo apuntado solo existen lgicamente dos registros en la tabla cuerpo, los otros registros estn 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 (lnea de detalle en rojo en el grfico) y el registro 2 de la tabla cabeza es el que esta siendo apuntado en ese momento, una bsqueda (Locate) en la tabla cuerpo no lo encontrara y por lo tanto lo eliminaramos del maestro de productos. Esto creara una inconsistencia en los movimientos de inventario. Tendramos movimientos de productos que no existen. Esta es la razn por la cual momentneamente eliminamos la relacin entre las dos tablas (MasterSource:= nil) para poder buscar un cdigo de producto en toda la tabla cuerpo y no solo en los registros que estn asociados a un determinado registro de cabeza. Al terminar la bsqueda restauramos la relacin (MasterSource := Ds_Cabeza_Mov).
Propiedad MasterSource
Tabla Cuerpo
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
Sistema de Inventario
141
Validacin: Verificar valores numricos en total entradas, total salidas, existencia y punto de reorden. 1. Muestre el formulario Modulo de Datos por medio de la opcin 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 lgicamente definidos para la tabla productos. El siguiente grfico 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.
El parmetro Sender cuando se invoque este procedimiento (implementacion del evento de validacin) apuntara al objeto que representa al campo Total_Entradas de la tabla productos. Seria equivalente a que escribiramos 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 lgico de la tabla mas el nombre fsico del campo.
Sistema de Inventario
142
Cada campo de la tabla debe tener una implementacin de su evento OnValidate si deseamos validarlo. Por lo tanto el mismo procedimiento arriba descrito debe tambin ser realizado para los campos Total_Salidas, Existencia_Minima, Existencia_Maxima y Punto_de_Reorden. Es mas podemos validar que existencia mnima sea menor o igual que existencia mxima, existencia mxima sea menor o igual que existencia mnima o que el punto de reorden este entre los valores de existencia mnima y mxima. Las siguientes tres ventanas muestran la implementacion de estas validaciones. Validaciones sobre el campo de Existencia Mnima.
Sistema de Inventario
143
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 aplicacin MDI o en pantalla en trminos generales. En nuestro caso inicializar esta propiedad con el valor poDesktopCenter nos presentara 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 tendra una buena apariencia en general. Delphi no ajusta las posiciones de los componentes que estn en un formulario cuando se maximiza. El grfico a la derecha de la pagina presenta al Inspector de Objetos mostrando esta rea de propiedades. El valor de la sub-propiedad biMaximize debera 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 aplicacin MDI, Delphi asume que
Sistema de Inventario
144
la operacin de cerrar el formulario es simplemente minimizarlo. Esta asuncin no es correcta para una aplicacin 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 parmetro Action. Este parmetro 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 parmetro Action. El siguiente grfico muestra este cambio.
Ya que estamos en este evento deberamos tambin 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 accin tomar?, actualizar (mtodo Post de un componente Ttable) o cancelar la operacin (mtodo Cancel). Lo ms recomendable seria cancelar la(s) operacin(es) que se estn realizando sobre las tablas del formulario. El siguiente grfico muestra esta modificacin sobre el evento FormClose.
Sistema de Inventario
145
Validacin: Evitar la inclusin de cdigos de productos duplicados. 1. Muestre el formulario Modulo de Datos por medio de la opcin 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 cdigo fuente que se presenta a continuacin en el Editor de Cdigo:
Cuando ocurre un error (excepcin) durante la actualizacin de un registro, el evento OnPostError es invocado. El procedimiento que implementa la reaccin a este evento posee tres parmetros: 1. DataSet : Apuntador a la tabla involucrada en el error. 2. E : El tipo de error o excepcin. El cdigo 9729 representa el error de clave duplicada. 3. Action: La accin que se puede tomar. Las posibles acciones son: daFail : Aborta la operacin y presenta un mensaje de error daAbort: Aborta la operacin y NO presenta un mensaje de error daRetry: Repetir la operacin de actualizacin. Se asume que este evento se trato de corregir las causas del error antes de asignar este valor al parmetro Action. Cuando este evento es invocado por primera vez el parmetro Action es inicializado con el valor daFail. En nuestra implementacin del evento se dejo este valor y se invoco el procedimiento Abort para primero mostrar nuestro mensaje de error en espaol de clave duplicada y luego cancelar la operacin de actualizacin.
Sistema de Inventario
146
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 incrementaran la facilidad de manipulacin del mismo por parte del usuario. La mayora de los componentes visuales que posee Delphi tienen la facilidad de mostrar una ayuda o mensaje rpido cuando se coloca el apuntador del ratn 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 accin que puede realizar dicho botn. Estos mensajes son desplegados por dos a cuatro segundos. Por Ejemplo, el siguiente grfico muestra al nevagador mostrando un mensaje cuando el ratn esta sobre el botn de ir al ultimo registro de la tabla. Las propiedades que se utilizan para realizar esta accin en el navagador de base de datos son: Hints: Almacena los mensajes correspondientes a cada botn en el orden de izquierda a derecha (ver siguiente grfico). ShowHints: Si el valor es true muestra los mensajes, si es false no muestra los mensajes.
Sistema de Inventario
147
Note que para el campo Accin Delphi inserto (paso numero 9 en la lista anterior) un componente de la clase TDBEdit. Este campo fue definido
Sistema de Inventario
148
como de tipo carcter y los valores lgicos deben ser E para tipo de movimiento de entrada de productos y S para Tipo de Movimiento de salida de productos. Podramos dejarlo de esta forma y validar que solo se introduzcan los valores E o S en el evento OnValidate de ese campo. Tambin podemos usar un componente de la clase TDBRadioGroup con la finalidad de presentar una interfaz ms elegante al usuario. Vamos a remplazar el componente correspondiente a la accin por uno de la clase TDBRadioGroup. Primero seleccionemos de la pestaa Data Controls un componente TDBRadioGroup y soltmoslo en el formulario, cerca del titulo Accion. Luego cambiemos las siguientes propiedades del nuevo componente (por medio del Inspector de Objetos):
Propiedad
Caption Name Columns DataSource DataField Items Values
Nuevo Valor
Accin DbAccion 2 DS_Tipo_Mov Accion Entrada Salida E S
Observaciones
Titulo del componente Cualquier nombre para el componente Cantidad de columnas a ser mostradas Fuente de datos Nombre del campo a ser actualizado Titulo del primer elemento Titulo del segundo elemento Valor a retornar del primer elemento Valor a retornar del segundo elemento
Las propiedades Items y Values son actualizadas por medio del Editor de Strings.
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
Sistema de Inventario
149
campo Accion de la tabla de tipos de movimiento. De esta forma no es necesario realizar ningn otro tipo de validacin 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, lucira 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 Cdigo se desplegara en pantalla con un procedimiento en blanco para definir el evento OnClick asociado a la opcin Tipos de Movimiento de nuestro sistema de mens. La siguiente ventana muestra la instruccin necesaria para realizar la tarea de crear y mostrar el formulario.
Recuerde que en Pascal el uso de unidades debe ser explcitamente 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 operacin puede ser realizada manualmente o tomando la opcin File Use Unit del men principal de Delphi cuando tenemos seleccionado el formulario principal.
Sistema de Inventario
150
Sistema de Inventario
151
A diferencia de la implementacin realizada para la tabla productos, en este evento no es necesario suspender ningn tipo de relacin (1:N) porque la bsqueda se esta realizando en la tabla cabeza. Validaciones: Evitar la inclusin 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 cerrara completamente y cualquier operacin de actualizacin de la tabla productos se cancelara. Se debe desarrollar el mismo evento OnClose para el formulario de Tipos de Movimiento. El siguiente grfico muestra la ventana del Editor de Cdigo con la implementacin de este evento.
Nota: Recuerde actualizar las propiedades Hints y ShowHint para que se muestren las ayudas rpidas sobre el componente de navegacin de BD.
Sistema de Inventario
152
Sistema de Inventario
153
El prximo 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 creacin del formulario de Auto-Creado a NO auto-Creado. (Opcin 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 ningn 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 tamaos de los paneles de tal forma que el primero sea ms ancho que el segundo. El formulario debera tener la siguiente apariencia.
12. Despus 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 manipulacin 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 debera tener la siguiente apariencia general.
Sistema de Inventario
154
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 estticamente 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 ratn podemos presionar el botn derecho para que se presente un men emergente donde seleccionaremos la opcin Add All Fields para crear los sub-componentes que representaran las columnas para cada campo de la tabla. Tambin por medio del tercer botn rpido que se encuentra en la parte superior del Editor de Columnas es posible realizar esta operacin. El grfico 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 informacin comn. En este caso la relacin entre las tablas cabeza y cuerpo de movimientos poseen el campo en comn Numero_Movimiento (y no necesariamente deben tener el mismo nombre). Recuerde que esta relacin la establecimos previamente por medio de la propiedad MasterFields de la tabla Cuerpo_Mov. Estos comentarios van en relacin que Delphi se encarga automticamente de actualizar el o los campos que establecen la relacin entre las tablas maestro detalle. En este caso cuando incluimos un registro de la tabla cuerpo, Delphi
Sistema de Inventario
155
automticamente 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 razn 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 Botn de eliminar la columna seleccionada. segundo botn rpido que se encuentra en la parte superior del Editor de Columnas. El grfico a la derecha muestra la ubicacin de este botn. 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 opcin Movimientos y finalmente hacemos click sobre la opcin para que el Editor de Cdigo se despliegue en pantalla. En el procedimiento vaco que aparece en el Editor de Cdigo escribimos la siguiente instruccin: TForma_Mov.Create(Self); para crear y mostrar, en momento de ejecucin, en pantalla el formulario de movimientos de inventario. Nota: Recuerde que este formulario tambin debe ser No Auto-Creado (Opcin Proyect-Options del men principal de Delphi). El siguiente grfico muestra en momento de ejecucin la apariencia del formulario con algunos datos introducidos.
Sistema de Inventario
156
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 drsticamente 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 pestaa Data Controls de la paleta de componentes un objeto de la clase DBLookupComboBox y sultelo 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
DataField DataSource DropDownWidth KeyField ListField ListFieldIndex ListSource
Nuevo Valor
Tipo_Movimiento DS_Cabeza_Mov 150 Tipo_Movimiento Tipo_Movimiento;Descripcion 0 DS_Tipo_Mov
Observaciones
Campo a ser actualizado Fuente de datos (tabla) a ser actualizada Ancho de la lista a desplegar Campo clave de la tabla fornea Campos de la tabla fornea a mostrar Indice del campo forneo a ser utilizado Fuente de datos de la tabla fornea
La tabla Tipo_Mov (tabla fornea) 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 seleccin, 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 ejecucin la apariencia de la lista, desplegada, seria la siguiente:
Sistema de Inventario
157
Todava estamos lejos de tener un formulario que cumpla con los requisitos mnimos 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 numrico del campo Cantidad. Evitar la inclusin de Movimientos duplicados. Crear una ventana de dialogo para la actualizacin del cdigo de producto. Bsquedas rpidas 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 manipulacin 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 existira una dependencia mayor el mismo. Clara esta, la decisin 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 anomala 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 Cdigo muestra como se debe realizar la operacin de eliminacin de un registro de la tabla Cabeza_Mov para garantizar la existencia de la relacin uno a muchos (1:N) previamente establecida con la tabla Cuerpo_Mov.
Sistema de Inventario
158
La implementacin del evento esta tomando ventaja de la relacin 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 despus 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 botn de inclusin 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 botn 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 inclusin y no se ha grabado el registro a disco mientras el DBGrid puede ya haber grabado permanentemente el registro. La solucin a este problema puede ser:
Sistema de Inventario
159
No permitir cancelar la inclusin 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 inclusin 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 cdigo fuente para esta operacin. La siguiente ventana del Editor de Cdigo muestra la implementacin del evento.
Tambin 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 simultneamente 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 lgico 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 lgico del rea de detalle. El siguiente diagrama muestra la implementacin del evento BeforeDelete de la tabla Cuerpo_Mov donde se invoca el mtodo RecordCount del componente Ttable. Este mtodo 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 ejecucin tambin es mostrado.
Sistema de Inventario
160
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 descripcin de los productos que existan en la tabla de productos. Si por alguna razn no existe el cdigo 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 Cdigo muestra la validacin necesaria en el evento BeforePost de la tabla Cuerpo_Mov para evitar la actualizacin del registro en estos casos. El formulario en momento de ejecucin tambin es mostrado.
Sistema de Inventario
161
Verificar el valor numrico del campo Cantidad. La tercera columna del DBGrid almacena el campo Cantidad de la tabla Cuerpo_Mov. Lgicamente, valores menores que cero (0) no deben ser permitidos en esta columna. La validacin 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 pestaa de eventos del Inspector de Objetos se encuentra el evento OnValidate que es donde se realizaran las validaciones a los campos de una tabla. La siguiente ventana del Editor de Cdigo muestra la validacin necesaria en el evento OnValidate del campo Cantidad de la tabla Cuerpo_Mov para evitar la actualizacin de dicho campo cuando su valor sea igual o menor que cero (0). El formulario en momento de ejecucin tambin es mostrado.
Sistema de Inventario
162
Evitar la inclusin 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 Cdigo muestra la validacin necesaria en el evento OnPostError.
En la tabla de Cuerpo_Mov tambin puede ocurrir este tipo de error. Si se intenta incluir un producto duplicado en el detalle o cuerpo de movimiento una excepcin de registro duplicado es presentado por Delphi. La siguiente ventana del Editor de Cdigo muestra la validacin necesaria en el evento OnPostError de la tabla Cuerpo_Mov para manejar esta situacin. El formulario en momento de ejecucin tambin es mostrado a continuacin.
Sistema de Inventario
163
Crear una ventana de dialogo para la actualizacin del cdigo de producto. Hasta los momentos el usuario debe escribir el cdigo del producto a ser incluido en la tabla de Cuerpo_Mov. Seria conveniente que el usuario pudiera seleccionar el cdigo del producto de una lista y automticamente se incluyera el cdigo en el campo respectivo de la tabla Cuerpo_Mov. A este concepto se denomina Catalogo. Una ventana desde donde el usuario seleccione informacin. Esta lista de productos podemos implementarla en un nuevo formulario donde colocaramos un DBGrid que muestre la tabla de productos. El usuario al presionar dobleclick o un botn, el cdigo de producto del registro actual de la tabla productos se utilizara para actualizar el registro actual de la tabla Cuerpo_Mov. Tome la opcin File New del men principal de Delphi. Una ventana mostrando los diferentes elementos que se pueden crear se desplegar en pantalla. Tome de la pestaa Dialogs la opcin Standard Dialog para crear
Sistema de Inventario
164
un nuevo formulario con dos botones en la parte inferior. El siguiente grfico ilustra esta operacin.
Deposite un DBGrid, de la pestaa 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 opcin 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.
Sistema de Inventario
165
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 mtodo ShowModal del componente Tform. Al cerrar un formulario modal, Delphi retorno un valor determinado. En este caso al presionar el botn 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 botn Cancelar de este formulario tiene el valor mrCancel. Ya sabemos como mostrar el formulario (mtodo ShowModal) pero debemos definir donde se realizara la operacin. Por supuesto, cuando estemos editando la columna cdigo 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 grfico a la derecha de la pagina.
Sistema de Inventario
166
La propiedad ButtonStyle determina una opcin muy imprtente de una columna. Si el valor de esta propiedad es cbsEllipsis, un botn 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 mtodo ShowModal del formulario de catalogo de productos. El usuario puede editar datos en la columna (Cdigo de Producto) o presionar el botn 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 botn Ok del formulario de catlogo 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 implementacin 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 botn 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: insercin, edicin, navegacin, calculando, etc.. Si la tabla no esta en modo de insercin o edicin el mtodo Edit del componente la coloca en modo de edicin 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 ejecucin de este evento se invocara el evento OnCalcFields de la misma tabla. La descripcin del nuevo cdigo de producto ser mostrada en el DBGrid del formulario de movimientos. En la siguiente ventana se encuentra ambos formularios: El
Sistema de Inventario
167
Bsquedas rpidas de movimientos. Es muy conveniente implementar una alternativa de buscar rpidamente registros en una tabla. El rea de ndice puede ser utilizada para tal fin. Es importante destacar que esta tcnica 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 grfico a la derecha). El evento OnChange de este componente utilizara el contenido de su propiedad Text (lo que el usuario
Sistema de Inventario
168
escriba sobre l) para buscar en el rea de ndice de la tabla Cabeza_Mov. La siguiente ventana del Editor de Cdigos muestra la implementacin del evento OnChange del nuevo componente.
El mtodo FindNearest ser utilizado para realizar la bsqueda en la tabla. Este mtodo realiza bsquedas parciales en la tabla. Por ejemplo si escribimos el texto 34 en el componente TmaskEdit, el resultado de la bsqueda ser el primer numero de movimiento que sea igual o mayor a 34 en la tabla Cabeza_Mov. Despus de ubicar un registro, la relacin uno a muchos permite que automticamente 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 actualizacin 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 operacin que se este realizando sobre la tabla Cuerpo_Mov. Los diferentes casos que podemos encontrarnos son los siguientes: Cuando se esta incluyendo una lnea de movimiento. Sumar Cantidad a Total_Entradas Total_Salidas dependiendo del tipo de movimiento. Cuando se esta modificando cantidad en una lnea 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 lnea de movimiento. Restar Cantidad a Total_Entradas Total_Salidas dependiendo del tipo de movimiento.
Sistema de Inventario
169
Las alternativas, arriba descritas, determinan que debemos tener una variable auxiliar Cantidad_Anterior para mantener el valor del campo Cantidad antes de cualquier modificacin. Esta variable la podemos declarar en el modulo de datos ya que es en esta unidad donde se utilizara. La siguiente ventana muestra la declaracin de la variable despus de la declaracin 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 validacin de la existencia o no de un producto, por lo tanto al final del procedimiento aadimos la actualizacin de la tabla productos. La siguiente ventana muestra estas modificaciones al evento.
Sistema de Inventario
170
La ultima implementacin 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.
Sistema de Inventario
171
Primero debemos crear un nuevo formulario por medio de la opcin File New Form del men principal o utilizando el botn rpido que se encuentra para tal fin. Luego seleccionamos de la pestaa 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 instruccin SQL o salir del formulario. El prximo paso es cambiar varias propiedades del formulario y de los otros componentes.
Sistema de Inventario
172
1. Guardar (salvar) el formulario a disco con el nombre Unit_Consulta_Productos. 2. Cambiar la forma de creacin del formulario de Auto-Creado a NO auto-Creado. (Opcin 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 ningn 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 botn por bkOK y la propiedad Name y Caption por Ejecutar. 11. Cambiar la propiedad Kind del segundo botn 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 instruccin SQL. El resultado de la consulta se mostrara en un DBGrid. Seleccionemos un componente TQuery y otros TDataSource de la pestaa de Data Access de la Paleta de Componentes y soltmoslo en cualquier parte del formulario. Estos componentes de la clase TQuery y TDataSource podramos colocarlos en el modulo de datos pero para ilustrar diferentes alternativas los colocamos en el formulario de manipulacin de datos en s. Un Componente DBGrid tambin 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 tambin debe ser cambiada a TQuery1 que es el nombre por defecto del nuevo componente TQuery. Cambiemos tambin 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 fsica en momento de diseo:
Sistema de Inventario
173
Para completar los componentes que se necesitan para la consulta, debemos seleccionar un objeto de la clase TRadioGroup y un TGroupBox de la pestaa Standard de la Paleta de Componentes. Esta clase de componentes (TRadioGroup) presenta botones de radios definidos por la propiedad Items. El siguiente grfico muestra esta operacin 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 tambin fueron cambiados para que describan la funcin de cada uno de ellos. Tipo_de_Consulta para el
Sistema de Inventario
174
componente TRadioGroup y Campos para el TGroupBox. La propiedad Name de los CheckBox tambin fueron cambiados para auto-documentar el formulario. La siguiente ventana del Editor de Cdigo muestra la implementacin del botn Ejecutar.
Sistema de Inventario
175
La primera parte de la implementacin del evento consiste en formar la clusula Select de la instruccin SQL. Si uno de los checkbox esta seleccionado (propiedad Checked = true) se aade el nombre del campo respectivo en la variable local Campos. El campo existencia no existe fsicamente en la tabla productos. Es un campo producto del calculo Total_Entradas Total_Salidas. Este calculo se introduce en la clusula Select cuando se cumple la condicin 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 instruccin a ser ejecutada. El mtodo Add del componente aade las lneas necesarias para formar la instruccin. Al final de la implementacin del evento OnClick del botn Ejecutar se invoca la ejecucin de la instruccin 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 instruccin SQL. En este caso, la base de datos no existe, es una tabla local en Paradox. La ruta C:\Inventario define la ubicacin de las la tablas en el disco duro.
Sistema de Inventario