IZTAPALAPA

Anuncio
Casa abierta al tiempo
UNIVERSIDAD AUTONOMA METROPOLITANA
- IZTAPALAPA
CPJI
-
2,'
1
'
"
DESARROLLADO : CRUZ GOMEZ HUMBERTO
NAVARRO GUTIERREZ MARCO A.
RAMOS PENAGOS ALEJANDRO
Y
México, D.F. Abril de 1995
""-.A
Reporte del Proyecto de InvestigaciónII
INDICE
INTRODUCCION A LA PROGRAMACION EN WINDOWS . . . . . . . . . . . . . . . . . . . . . . . . .
1
PROGRAMANDO CON EVENTOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
COMPARTIENDO RECURSOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
WINDOWS. OBJETOS Y C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
PROGRAMACION EN WINDOWS CON OBJETOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
OBJETIVODELSISTEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
MENUPRINCIPAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
DESCRIPCION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
CARACTERISTICAS TECNICAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
BITMAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
MENU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
DIALOG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
ACCELERATORS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
ARCHIVOSDBF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
LA ESTRUCTURA DE ARCHIVOS DBASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
LOS DATOS EN DBASE I1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
EL ENCABEZADO (HEADER) EN DBASE I1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
ESTRUCTURAS DE INDICES EN DBASE I1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
LOS DATOS EN DBASE I11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
EL ENCABEZADO (HEADER) EN DBASE I11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
DIFERENCIAS ENTRE ARCHIVOS DE DBASE I1 & DBASE I11 . . . . . . . . . . . . . . . . . . . 13
ANALISIS DE ARCHIVOS DBASE CREADOR POR LA UTILERIA CLIPPER DBU . . . . 13
MODULO DE IMPRESION
INTRODUCCION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
CARACTERISTICAS TECNICAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
Reporte del Provecto de Investigación II
ANALISIS DEL PROGRAMA PRINCIPAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
DONDE COMIENZA LA APLICACION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
USANDO EVENTOS Y MENSAJES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
DISPOSITIVOS DE SALIDAS Y VENTANAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
EL DEVICE CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
ATRIBUTOS DEL DEVICE CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
ACCESANDO AL DEVICE CONTEXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
DESPLEGANDO L A S CAPACIDADES DEL DEVICE . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
MODULOSDEGRAFICACION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
GRAFICA DE BARRAS EN 2 DIMENSIONES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
CREANDO UNA GRAFICA DE BARRAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28
DESPLEGANDO LA GRAFICA DE BARRAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
ESCRIBIENDO EL TITULO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
DESPLEGANDO ETIQUETAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
DIBUJANDOUNABARRA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
ESTRUCTURA PRINCIPAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
GRAFICA DE BARRAS EN 3 DIMENSIONES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
LA TERCERA DIMENSION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
EL FONDO (BACKDROP) EN TRES DIMENSIONES . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
LOS TOQUES FINALES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
GRAFICADEPIE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
DIBUJANDOUNSLICE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
DESPLEGANDO UNA LEYENDA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
AÑADIENDO
BIBLIOGRAFIA . . . . . . . . . . .
.................................................
39
Rem&
del Provecto
.
. I
INTRODUCCION A LA PROGRAMACI~NEN
WINDOWS
La programación en Windows representa un cambio substancial para la mayoría
de los programadores gráficos de PC. Windows es la extensión del DOS, así que los
programadores pueden tener una consistensia con menÚs, ventanas, interfaz gráficas,
acciones con el mouse y cajas de diálogos. Windows hace posible ejecutar múltiples
procesos simultáneos y tomar ventaja de toda la memoria disponible en la PC. Windows
demanda un nuevo estilo de programación, que a primera instancia puede parecer
bastante complicado, pero que entendiendo la filosofia de la programación orientada a
objetos, y el entorno de Windows, hacen de esta algo agradable de programar.
Windows ofrece mas de 600 funciones a través del API (Application Programmers
Interface). Esta extensa libreria nos brinda un entorno inmenso de programación. Este
estilo, difiere un poco de lo que estamos acostumbrados a programar.
La programación en Windows es diferente por tres básicas razones:
1.- Los programas estan organizados en eventos.
2.- Los recursos de la computadora están compartidas entre aplicaciones.
3.- Los programas no manipulan directamente los dispositivos (como la pantalla).
0
PROGRAMANDO CON EVENTOS
En DOS, los programas son usualmente escritos como una secuencia de pasos
agrupados en funciones. La programación en Windows, sin embargo, esta organizada
alrededor de eventos o mensajes. Un evento ocurre cuando algo dentro de Windows
cambia. Mensajes son usados para informar que un evento ha sucedido o esta cerca
de ocurrir. Por ejemplo, Windows manda un mensaje llamado WM-LBUTTONDOWN
cada vez que se presiona el botón izquierdo del mouse. Un programa, entonces
puede ser escrito para responder a un mensaje como WM-LBUTTONDOWN.
Una aplicación Windows divide el código, tal que responda a varios mensajes internos
manejados por Windows. Por ejemplo, el mensaje WM-LBUTTONDOWN es enviado
cuando el botón izquierdo del mouse es presionado, y WM-LBUTTONUP es enviado
cuando el botón es liberado. Internamente, los mensajes son simples valores enteros
(constantes) que corresponden a los eventos. Las constantes de los mensajes de
Windows, son definidos en el encabezado WIND0WS.H
1
Rep-
0
del Po
rv-
. .,
COMPARTIENDO RECURSOS
Porque en Windows, múltiples programas pueden ser ejecutados virtualmente al
mismo tiempo, los programas en Windows deben compartir los recursos de la
computadora, tales como la memoria, el disco, drives, pantallas e impresoras. La
compartición de recursos se da de la siguiente forma: pedir permiso para accesar a un
dispositivo antes de usarlo, y liberarlo tan pronto como se finalice el trabajo con este.
0
WINDOWS, OBJETOS y C++
Por diseño, Windows está orientado a objetos. Todos los elementos de interface, tales
como las ventanas, las barras de scrolls, las cajas de diálogos, etc. estan organizados
como objetos. Por ejemplo, un botón OK en una caja de diálogo puede invocar una
función que verifique la entrada del usuario y la copie a un conjunto de variables.
Como programador de C++, probablemente sea confortable el hecho de que Windows
organiza la interface del usuario en elementos dentro de objetos. Sin embargo,
Windows no está escrito en un lenguaje orientado a objetos. Consecuentemente,
Windows tiene todos los clásicos signos de objetos, sin la sintaxis, tal como C++
PROGRAMACIÓN EN WINDOWS CON OBJETOS EN WINDOWS
Para explorar las características orientadas a objetos de C++ mientras se programa
en Windows, se necesitará interactuar alrededor de las funciones de Windows. Se
pueden desarrollar funciones propias, sin embargo para este proyecto, por comodidad
utilizaremos las funciones Windows (OWL), las cuáles están incluidas con el
compilador.
OWL maneja bastantes puntos de la programación en Windows, y nos da ventaja de
las características de la programación orientada a objetos (OOP) de C++.
2
OBJETIVO DEL SISTEMA
El proyecto tiene como finalidad desarrollar un sistema editor de gráficos, que sea
capaz de graficar archivos DBF e información aleatoria introducida por el usuario.
El Sistema, además de graficar la información, proporcionará datos estadísticos de
las gráficas tales como medias, varianzas, etc. Contará con una interfaz totalmente bajo
Windows para aprovechar las ventajas de las librerias OWL de C++.
A continuación se describirán en forma técnica los módulos principales que
integran al sistema, así como las herramientas adicionales que se utilizaron para su
diseño.
MENU PRINCIPAL
DESCRIPCION
El menú principal del sistema, facilita el acceso a las diferentes opciones de este;
todas las opciones del menú principal son activadas por el mouse, y con el uso de
teclas rápidas. Por ejemplo, para activar la opción de Archivo, este responde a la
acción del mouse y a la combinación de ALT+A.
CARACTERISTICASTÉCNICAS
El Menu Principal, fué desarrollado en el Workshop, que es una utileria de C++ para
diseñar menús, cajas de diálogos, botones, íconos, etc.
El archivo que se generó en el Workshop es RUTINAS.RES; este archivo contiene
todas los gráficos de interfaz como son los íconos, menus, cajas de diálogos, de
herramientas, etc. Se encuentra dividido en cuatro partes, las cuales se detallan a
continuación:
- BITMAP
- MENU
- DIALOG
- ACCELERATORS
3
del
- rP
0
. .,
BITMAP
En el encabezado de BITMAP se tienen todos los iconos para la generación de los
diferentes tipos de gráficas (Barras 2D - 3D,Pie 2D - 3D, etc), así como los íconos de
funciones estadísticas con el objeto de que al hacer un clic en el icono, este mande a
llamar a su respectiva función.
En el código correspondiente al encabezado del bitmap, se tienen números cuyas
constantes se encuentran definidas en el archivo 1DENTIF.H. A continuación se
enlistan las constantes con una breve descripción de su acción.
Como se puede ver en la tabla, los iconos para las diferentes acciones se encuentran
duplicados, esto debido a que se necesita un icono (con su respectivo identificador)
cuando se presenta en la caja de herramientas, y posteriormente cuando el usuario lo
selecciona. Es decir, es el mismo ícono, solamente que en el momento en que es
seleccionado, el icono cambia poniéndole sombra para diferenciarlo de los demás, es
por esto que cada icono tiene su doble con sombra.
4
En el momento que el usuario selecciona un icono, este cambia PRESSED, para
indicar al sistema que ha sido seleccionado (NORMAL ===> PRESSED).
0
M€NU
En el encabezado de MENU se tienen todas las definiciones del menú principal del
sistema, tales como las de Archivo ---> Abrir, Guardar, Imprimir <---, etc.
Estas opciones son las encargadas de :
1. Abrir el archivo .DBF y mandarlo a procesar.
2. Guardar los datos estadísticos generados en la graficación.
3. Capturar datos aleatorios para posteriormente graficarlos.
4. Imprimir las gráficas resultantes.
5. Salir del sistema y regresar al administrador de programas.
6. Mostrar la barra de herramientas que contiene todos los iconos explicados en la
sección anterior.
7. Mostrar el menú de ayuda.
En la siguiente tabla, se muestran los identificadores con sus respectivas acciones.
0
DIALOG
En el módulo DIALOG, se encuentran las cajas de diálogos de Capturar, de
AcercaDe, y la caja de Herramientas.
En la sección anterior (MENU), se definió como mandar a llamar a estas cajas, en
esta se encuentran el diseño de estas. Estas herramientas fueron diseñadas en el
Resource Workshop, para ser llamadas posteriormente por el módulo de MENU.
5
-
del Provecto
. ..
La caja de CAPTURAR, accede a cualquier dispositivo físico y lógico de la PC para
ser leido; así como a los directorios del dispositivo y muestra los diferentes archivos
localizados en el directorio. Permite seleccionar el archivo por medio de un botón, así
como su cancelación.
La caja de DIALOG-ACERCA, muestra el logo de la UAM, así como la versión del
sistema.
El DIALOG-TOOLS, es la encargada de contener los iconos (bitmaps) definidos en la
seccion BITMAP. Esta caja contiene los espacios para colocar los iconos que acceden
a las diferentes acciones.
0
RCCEMRRTORS
Esta sección, contiene los FILECOMMANDS, que son las activaciones de teclas
rápidas, así como la activación de la tecla Tab. Las teclas rápidas permiten ejecutar
una acción sin el mouse. Por ejemplo, para activar el menú Archivo, se puede realizar
con el mouse o con las teclas de A/t+A. La tecla Tab permite pasarse de opción a
opción; por ejemplo, si se encuentra marcado el botón OK, y se requiere pasar al
botón CANCELAR, presione la tecla Tab hasta que el botón requerido se encuentre
marcado.
Las 4 etapas anteriores, como se menciono anteriormente fueron diseñadas en el
Resource Workshop. El archivo que los contiene es el RUTINAS.RES. La extensión
RES generada por el Resource, ya se encuentra compilada, por lo que para ligarla
con el código fuente de C++, únicamente hay que incluir el archivo RUTINAS.RES en
el project UAMIGRAP.PRJ que contiene todos los archivos necesarios para la
compilación del sistema. C++ liga el código que se tiene, con el archivo del Resource
para generar un Único archivo ejecutable.
6
-del P
. .,
ARCHIVOS DBF
El módulo de lectura de archivos DBF, se encarga de abrir cualquier archivo DBF,
leerlo, procesarlo y generar un archivo de salida en modo texto con los registros
seleccionados en un formato de 2 columnas (x,y) que posteriormente seran mandados a
graficar. El módulo le despliega al usuario todos los campos del archivo, y le solicita que
seleccione 2 campos; una vez seleccionados, genera el archivo de salida con todos los
registros que incluyen a estos campos.
A continuación se describe la estructuras de los archivos DBF, para un fácil
entendimiento del módulo.
l a estructura de archivos dBase
Los datos en dBasell o dBaselll son desplegados en arreglos de columnas y
renglones, como en una hoja de calculo. Un ejemplo de este es el que se muestra en
la figura 1.
Los datos en un campo (o columna) son del mismo tipo (ASCII, numéricos, lógicos,
etc.). Cada nombre del campo es Único y cada registro tiene un Único número.
los datos en dBase II
Los registros de datos comienzan en dBase donde finaliza el encabezado (header).
Un byte precede cada registro. El valor de este byte es un espacio en ASCII (20h)
siempre y cuando el registro no haya sido borrado, en caso contrario un asterisco
(2Ah) representa este byte. No hay separadores, delimitadores o terminadores
usados en los registros de datos (data records).
0
El encabezado en dBase II (Header)
Los archivos en dBase I I consisten de un encabezado (file header) y un conjunto de
registros de datos. Los encabezados proveen información acerca de la estructura de
los registros de datos (data records).
A continuación se describen cada uno de los bytes que conforman al archivo.
7
R e o w l Provecto
. .
8
del Provecto
. .,
ESTRUCTURA DE INDICES EN JBAS€ II
La estructura de indices usadas por dBase II permiten búsquedas secuenciales y
por índices. Cada nodo de la estructura de árbol es completado a 512 bytes. El primer
nodo es llamado el ancho del nodo. Este contiene información de la llave de la expresión,
del nodo raiz, del siguiente nodo disponible y del número máximo de llaves por nodo.
Otros nodos son utilizados como valores de las llaves y como apuntadores de nodos
inferiores.
Los archivos de índices son organizados de la siguiente manera.
9
0
Todos los otros nodos están organizados en la siguiente manera:
Byte O
Numérico de 8-bits
Este es el número de llaves en este nodo.
Byte 1-51 1
Arreglo de entradas de llaves.
10
Reo-
0
del Prove-
. .,
Una entrada de llave esta organizada de la siguiente manera:
Byte 0-1
Apuntador al nivel mas bajo.
Byte 2-3
Número del registro
Byte 4-n
Expresión de la llave en ASCII.
dBASE 111
0
los datos en dBase 111
Los registros de datos comienzan en dBase donde finaliza el encabezado
(header). Un byte precede cada registro. El valor de este byte es un espacio en ASCII
(20h) siempre y cuando el registro no haya sido borrado, en caso contrario un asterisco
(2Ah) representa este byte. No hay separadores, delimitadores o terminadores usados en
los registros de datos (data records).
El encabezado en d6ase 111 (Header)
Los archivos en dBase II consisten de un encabezado (file header) y un conjunto
de registros de datos. Los encabezados proveen información acerca de la estructura de
los registros de datos (data records).
11
R e o m del Prove-
. .
12
R e o m del Porv-
. ..
DIFERENCIAS ENTRE ARCHIVOS DE dBASE II & dBASE 111
ANALISIS DE ARCHIVOS JBASE CREAROS POR LA UTlLERlA DE CLIPPER
5.0 (RBU)
A continuación se muestran los resultados obtenidos al analizar los archivos .DBF
utilizando la utileria DBVIEW del Norton Comander V. 4.0.
Como anteriormente se muestra en el análisis de archivos con formatos de dBase,
las principales partes de estos archivos son :
1.-Header Size (Tamaño del Encabezado)
2.- Record Size (Tamaño del Registro)
3.- Data
(Datos del Archivo)
13
del-orP
. ..
En la siguiente tabla se muestran los resultados obtenidos de 4 diferentes
archivos.
Archivo 1
Header Size
: 66 bytes
Record Size
: 38 bytes
Número de Campos : 1
Archivo 2
Header Size
: 98 bytes
Record Size
: 21 bytes
Número de Campos : 2
Archivo 3
Header Size
: 130 bytes
Record Size
: 21 bytes
Número de Campos : 3
Archivo 4
Header Size
: 162 bytes
Record Size
: 40 bytes
Número de Campos : 4
Como se puede observar de los análisis mostrados anteriormente, el Header Size
es directamente proporcional al número de campos con que cuente el archivo, es decir, si
el archivo (.DBF) contiene en su estructura 4 campos, independientemente del número de
bytes que ocupen los nombres de estos, y del tipo de información que representen (char,
entero, fecha, memo, etc.), el Header Size será siempre de 162 bytes.
Con lo que respecta al Record Size, este representa la sumatoria del tipo de
campos mas 1 byte. Es decir, si contamos con 4 campos en un archivo .DBF de la
siguiente forma:
14
del Prov-
Re-
P
I NOMBRE
I Chad351
. .. U
1
El Record Size será de 35 + 8 + 40 + 8 = 91 + 1 = 92 bytes.
En lo que concierne a la información (data) de los archivos .DBF, esta se
almacena en forma secuencial inmediatamente después de donde termina el Header Size
mas un byte.
Si seguimos con el ejemplo anterior, se tienen 4 Campos (NOMBRE,
MATRICULA, DIRECCION, FECHA-INGRESO), lo que implica un Header Size de 162
bytes, por lo cual la información comenzará en la posición 164 (el byte 164). Como se
indicó, la información se almacena en forma secuencial y en formato ASCII, lo cual facilita
el acceso a esta. En caso de que el dato de un campo no cubra el ancho del campo, se
completa con caracteres NULOS como se indicó en la descripción de archivos de dBase.
Otro punto interesante a comentar, es que como se indicó en el análisis de las
estructuras de archivos dBase, la separación entre campo y campo es de 32 bytes.
Comenzando el primer campo en la posición número 33 (byte 33). Si continuamos con el
ejemplo que se ha estado analizando, el campo NOMBRE, aparecería en la posición
número 33, es decir la 'NI de NOMBRE se encontraría en el byte 33; el campo
MATRICULA comenzaría en la posición 65, el campo DlRECClON en la 97, y el campo
FECHA-INGRESO en la posición 129.
Cabe recalcar que cuando se hace referencia a posiciones, es el equivalente a
bytes. Es decir, si se indica que el campo DlRECClON comienza en la posición número
97 es equivalente a afirmar que el campo DlRECClON comienza en el byte 97.
En nuestro caso, lo que mas nos interesa es poder tomar la información de los
archivos .DBF, que como ya se mencionó se encuentran secuencialmente después del
HEADER SIZE. Por lo que si se conoce la longitud de cada campo (RECORD) , el
RECORD SIZE y el HEADER SIZE, la lectura e interpretación de los datos se vuelve
relativamente sencilla.
15
MODULO DE IMPRESION
0
INTRODUCCION
Se podría decir que imprimir dentro de Windows es simple. El driver de la impresora
soportada por Windows, o inmersa con el hardware de la impresora, le dan al
programador una gran variedad independiente de acciones sobre la impresora.
En Windows se aplican ciertas reglas especiales para el uso de la impresora. La razón
es debido a que son varias las aplicaciones que comparten entre sí la impresora, al
igual que otros recursos del sistema. Para manejar las impresoras se utilizan los
controladores de impresora DDL y que, por lo general, se entregan junto con
Windows. A los usuarios no se les proporciona el código objeto de los controladores
de la impresora; sin embargo, en la mayoría de los casos no se necesitarán. La forma
más sencilla de manejar una impresora es considerándola como un objeto,
posiblemente como flujo de datos, en donde se acepten expresiones como la
siguiente:
printecobject << “imprimiendo ... << end?;
If
No es complicado construir una clase de impresora que soporte lo anterior, sin
embargo su desventaja es el desempeño no es tan bueno cuando se trata de trabajar
con gráficas, como es el caso del Sistema a desarrollar.
CARACTERISTICASTECNICAS
En diversas aplicaciones de Windows se utilizan las bibliotecas de enlace dinámico
(DLL). Sus beneficios resultan especialmente Útiles cuando se trata de soportar
características ventajosas para aplicaciones a la vez. En vez de poner el código de
soporte en cada programa, Windows permite vincular el código a una aplicación dada
durante la ejecución misma.
Imprimir dentro de Windows es complejo. Se necesita soportar la inicialización de la
impresora (orientación, calidad de DPI, alimentación, etc.), manejar multiples salidas a
la impresora, informar al usuario el porcentaje de la impresión, y permitir al usuario
interrumpir la impresión. La clase que se describe a continuación, soporta todo lo
anterior a excepción del porcentaje de impresión.
16
R e m del Porv-
. .,
La clase Printer requiere un constructor a la ventana del objeto Printer. Este
apuntador es almacenado en una variable private. El constructor Printer usa la
función miembro De/eteA//() para la inicialización de la impresora; esta función se
encarga también de inicializar la variable hDC a O. En Windows, todas las salidas a
cualquier dispositivo (pantalla, impresora, plotter, etc.) se realizan a través de un
dispositivo de contexto, el cual apunta al dispositivo deseado. Por lo cual, para
imprimir un gráfico a la impresora, se necesita que el hDC sea un apuntador a la
impresora para lograr la salida deseada. Por ejemplo, para mandar una ellipse a la
impresora, la línea que manda la salida a esta sería:
Elipse (hDC,x 7, y 7, x2, y2)
Si hDC esta apuntando a la impresora, la línea anterior manda la ellipse a la
impresora; para lograr la salida de la ellipse a pantalla, hay que hacer que hDC apunte
a la pantalla. Lo anterior parece simple, sin embargo para acceder al apuntador a la
impresora, se necesitan realizar varias rutinas que accedan al driver de esta, para
regresar el apuntador.
La idea general de la impresión del Sistema, es crear un objeto del tipo Printer al
principio de la aplicación (usando el comando new), usar este objeto cuando se
necesite, y entonces eliminarlo (usando el comando delete) cuando la ventana
principal se cierre. La ventaja del Sistema, es que actua sobre la impresora que se
tenga predeterminada, es decir si se necesita cambiar de impresora, lo Único que hay
que hacer es ir al administrador de impresión de Windows, y seleccionar una nueva
impresora, en caso de que esta no se encuentre, basta con darla de alta y
seleccionarla como impresora predeterminada, y automáticamente el Sistema
(UAMIGFWPH) lo reconocerá.
A continuación se detallan las principales funciones miembro de la clase Printer.
0
El Constructor de Printer
El constructor de la clase Printer, requiere un apuntador a la ventana que esta siendo
creada. Este apuntador es almacenado en una variable private. El constructor manda
a llamar a la función De/eteA//(),la cual se encarga de inicializar a la impresora.
17
P
0
R e m del Porv-
. ..
La función miembro DeleteAllO
De/eteA// comienza checando si el objeto de la impresora esta imprimiendo un
documento (InDocument == TRUE) y detiene el proceso usando la función
€núDocurnent() si es necesario. Si el device context de la impresora es valido (hDC >
O), este libera el device context actual usando De/eteDC().
De/eteA//() entonces usa la función API de Windows GetProfileString()para leer el
profile del archivo WIN.INI, GetProfileString() se encaraa de leer la sección de
WIN.INI y reoresar todo que siaue a = (siano igual) en la primera línea en la que
comienzan los device=. Esta línea contiene el nombre de la impresora, el nombre de el
archivo donde el driver de la impresora se encuentra (sin la extensión .DRV), y el nombre del
dispositivo de salida (por eiemplo LPTl:). Para obtener por separado las 3 características
anteriores, se utiliza la función strtok() utilizando el delimitador de coma (,) para
obtener los parámetros anteriores.
Finalmente el Device Context para la impresora es creado usando CreateDCO,
GetDeviceCapsO es utilizado para determinar si la impresora puede soportar el
manejo de bitmaps. La estructura RECT almacenada en rSize es inicializada con las
coordenadas lógicas de la impresora.
0
La función miembro SetupPrinterO
Setupprinter es llamada cuando el usuario quiere configurar el driver de la impresora
predeterminada por Windows. AI llamar al driver, se pueden seleccionar parámetros
como la orientación, los fonts instalados, la memoria disponible, etc. Setupprinter()
llama a una función externa (la cual incluye una caja de diálogo externa). El driver de
la impresora es requerido para manipular las características de esta. Para accesar a
este driver, se comienza utilizando la función LoadLibraryO para cargar el driver de la
impresora. Este es el nombre del archivo del driver, obtenido usando la función
GetProfileString(), con la extensión .DRV. Entonces se
utiliza la función
GetProcAddressO para encontrar la función DEVICEMODE dentro de este archivo, y
llamar a la función a la dirección obtenida. Esta llamada resulta en la caja de diálogo
que esta siendo desplegada, y la información que el usuario introduce en esta, es
automáticamente almacenada por el driver de la impresora. Setupprinter() concluye
liberando la libreria.
18
ReDQde del Porv-
0
. .,
La función miembro StartDocument()
StartDocument() utiliza la función Escape() para enviar un SETABORTPROC a la
impresora. La función Escape() es utilizada para enviar un STARTDOC a la
impresora, el cual manda a la impresora lo que tiene almacenado en el buffer.
0
La función miembro Newpage()
La función Newpage() es utilizada para liberar la hoja actual y comenzar con otra.
Esta utiliza la función Escape() con el código NEWFRAME, tal y como se indica a
continuación.
0
La función miembro EndDocumentO
EndDocumentO utiliza el comando de escape ENDDOC para terminar la impresión, tal
y como se indica en el siguiente código:
19
-
del Prove-
. .,
A continuación se listan los principales códigos de escape que soporta la función
Escape().
SELECCIONANDO LA IMPRESORA DENTRO DE LA APLICACION
Recuerde que la clase Print utiliza la impresora predeterminada por Windows en
el archivo W h l n i . Para permitirle al usuario que seleccione a que impresora desea la
salida, hay que leer la lista de impresoras instaladas en el archivo Win.lni. Para regresar
una lista de impresoras instaladas, use NULL como segundo parámetro en la función
GetProfileString().
20
del Po
rv-
. .,
ANALISIS DEL PROGRAMA PRINCIPAL
El codigo principal de UAMIGRAPH, se encuentra en el archivo CONTROLXPP,
el cual es el encargado de mandar a llamar a todas las demás rutinas tanto internas como
externas. A continuación se describen las partes mas relevantes de este módulo.
AI final de CONTROL.CPP podemos encontrar la llamada principal al sistema, la
cual consta de las siguientes líneas:
La clase principal la conforma TUserApplication, la cual es una clase derivada de
TApplication. Tambien se utiliza la clase Window. La mayoría de las aplicaciones
en Windows, utilizan estas dos clases; a continuación se detallan brevemente cada
una de estas.
TApplication provee los detalles de la aplicación que Windows necesita; y Window
especifica que el programa desplegará y la interacción del usuario.
También se pueden observar tipos nuevos de variables, estas nuevas definiciones de
variables, son macros o tipos definidos en el encabezado WIND0WS.H. La siguiente
tabla muestra algunos de estos tipos y explica brevemente que significan.
21
DONDE COMIENZA LA APLICACION
El origen de la aplicación se da en la función WinMain. WinMain instruye a Windows a
crear el objeto TUserApplication, el cual ejecuta la función miembro Run, y regresa
un status del objeto al sistema operativo.
La función RUN esconde el secreto del comportamiento de la aplicación. Esta
contiene un bucle While que continuamente pregunta a Windows por el siguiente
mensaje a procesar y enviarlo al manejador (handle). El bucle termina cuando el
mensaje WM-QUIT ocurre.
En muchas formas, WinMain es similar a la función main de C. Como main,
WinMain acepta varios argumentos, tales como los primeros dos parámetros, los
cuales son usados por Windows múltiples ocurrencias de un programa. El parámetro
IpCmdLine apunta a un comando de línea, y nCmdShow indica a Windows como
inicialmente debe aparecer la ventana.
En realidad, no hay que preocuparse por estos parámetros, ellos son solamente
pasados a traves del objeto constructor TUserApplication. Estos son utilizados para
que el objeto de la aplicación pueda manejar el estado actual de Windows. OWL
maneja todos estos detalles por nosotros.
22
-
del Po
rv-
. ..
USANDO €V€NTOSY M€NSAJES
Una importante parte del aprendimiento sobre escribir programas en Windows,
involucra el concepto de event-driven. Windows responde a eventos que nosotros
realizamos. Por ejemplo, cuando presionamos el botón izquierdo del mouse, Windows
responde al mensaje WM-LBUTTONDOWN. Por lo tanto, para manipular la acción a
este mensaje, lo Único que hay se necesita hacer es sobrecargar las funciones
miembros. WML-ButtonDown (accesible a través de la clase Window), la cual
corresponde a este evento.
DISPOSITIVOS DE SALIDA Y VENTANAS
Uno de los principales objetivos del GDI es un dispositivo independiente gráfico
programable. El hit es hacer que el código funcione en un display VGA, sin embargo,
lo ideal es que funcione también en un display EGA, e incluso en una impresora.
Windows se encarga de esto, diseñando las funciones gráficas para trabajar con tipos
devices en lugar que sobre un tipo específico de hardware. Windows soporta cuatro
tipos de devices: pantalla. impresoras y plotters. bitmaps y archivos especiales
conocidos como metafiles,
Sin embargo, no todas las salidas tienen las mismas capacidades. Por ejemplo, un
plotter no soporta operaciones gráficas para plotting pixels o despliegado de bitmaps.
Y algunas impresoras no soportan todos los tipos de gráficas.
E l DEVICE CONTEXC
Si analizamos el código de UAMIGFWPH, encontraremos un tipo de variable que
se repite constantemente, este es del tipo device context, el cual tiene como función
primaria lo descrito en los párrafos anteriores.
Windows mantiene información acerca de un tipo en particular de device, el cual llama
device context, el cual es la liga a la salida a un dispositivo. Actualmente, un device
context tiene varios propósitos:
Para el manejo de gráficos utilizadas por la aplicación, tales como estilos de fonts,
rellenos, bordes, etc.
Acceso a rutinas de dibujo y capacidades para un tipo específico de dispositivo.
0
Como mediador entre múltiples aplicaciones que quieren accesar al mismo
dispositivo. En una pantalla, el device context se asegura de que la aplicación no
23
dibuje en una zona prohibida. En una impresora, el device context mantiene la
operación de impresión separada en el administrador de impresión.
RTRIBUTOS DE1 DEVICE CONTEXT
Un device context contiene todo lo concerniente a lo que se encuentra dibujando,
tales como las funciones que utiliza, el estilo de la línea, el relleno del dibujo y el font
que utiliza. La siguiente tabla lista los atributos incluidos en el device context y sus
valoreres por default.
24
P
ReDQde del Prove-
. .,
ACC€SANDO A l DEVICE CONT€XT
Un device context se encuentra definido en WIND0WS.H de tipo HDC. La
siguiente instrucción declara un manejador de tipo device context llamado hDC, tal y
como se utiliza en el sistema.
HDC hDC;
Para obtener acceso a un device en particular, hay dos formas o técnicas
manejadas por C++. Una es en respuesta al mensaje WM-PAINT,
la cual es
generada cuando una ventana es actualizada. En este caso, las funciones
Beginpaint y EndPaint son utilizadas para obtener y liberar un manejador al video
del device context. Por ejemplo, el siguiente código muestra como estas dos
funciones dibujan un rectángulo en la pantalla:
La segunda forma de obtener el device context es es utilizando la función GetDC:
HDC GetDC (HWND HWindow);
Una vez que se ha obtenido el manejador, se pueden mandar todos los gráficos que
deseemos. El módulo de impresión de UAMIGRAPH descrito anteriormente, utiliza
esta técnica para mandar la salida de los gráficos a la impresora.
Como se puede observar, todas las rutinas de dibujo en GDI, requeren de un
manejador para ser pasado como primer argumento, e ahí la importancia de lo
descrito hasta ahora. Esta es la manera en que Windows se asegura de que se tiene
el permiso para acceder a los dispositivos de salida, y saber que dispositivo utilizar.
Después de utilizar el dispositivo, es necesario liberarlo. Esto se puede lograr
liberando el manejador por medio de la función ReleaseDC.
RealeaseDC (HWindow, hDC);
25
Provecto
.
. I
El siguiente código, muestra el uso de las funciones GetDC y ReleaseDC para
manejar un rectángulo en respuesta al click izquierdo del mouse.
DESPLEGANDO LAS CAPACIDADES DE1 DEVICE
Se pueden obtener las capacidades o propiedades del device, y las características
que soporta por medio de la función GDI GetDeviceCaps.
int GetDeviceCaps (HDC hDC, int Devicecode);
También se puede utilizar GetDeviceCaps para determinar cuando un device soporta
un tipo particular de operación, tales como una operación de bitmap o el dibujo de una
curva.
26
MODULOS DE GRAFICACION
0
GRAFICA DE BARRAS EN 2 DIMENSIONES
A continuación se describe el módulo de graficación en dos dimensiones, con sus
respectivas clases.
TBarGraph se encarga de los detalles de la impresión de la barra en una ventana.
La definición para la clase TBarGraph y su código se encuentra en los archivos
BARGRAPH.H y BARGRAPH.CPP.
Las gráficas de barras creadas, contienen cuatro componentes primarios: un área
rectangular, un título, etiquetas en el eje de las X y las Y, y las barras. La clase
TBarGraph implementa todo lo que se necesita para inicializar los valores de la
gráfica y dibujarla en la ventana. A continuación se muestra la definición de la clase
incluida en BARGRAPH.H
27
La clase
TBarGraph incluye seis variables privadas que almacenan la
información acerca que la gráfica de barras, tales como los valores de los ejes, el
título de la gráfica, etc. Algunos de estas variables tienen valores por default que son
inicializados en su constructor, sin embargo, todos estos valores pueden ser
modificados. La variable BarValues, es un arreglo de entreros, el cual contiene un
valor por cada barra.
La siguiente tabla, lista cada función en TBarGraph y muestra una pequeña
descripción de su comportamiento.
CREANDO UN GRAFICA DE BARRAS
AI utilizar la clase TBarGraph para dibujar una gráfica, se involucran tres pasos a
seguir:
1. Crear e inicializar el objeto TBarGraph. Se puede pasar como parámetro el título de
la gráfica al constructor.
2. Colocar las barras en la gráfica llamando a la función TBarGraph::AddBar
3. Llamar a la función TBarGraph::Display para dibujar la gráfica de barras.
Primero se debe de crear el objeto TBarGraph de la siguiente forma:
TBarGraph *BarGraph = new TBarGraph('%ráficade Prueba")
28
del Po
rv-
. .
La sentencia anterior aloja e inicializa un objeto TBarGraph que es apuntado por
BarGraph. El constructor le da el título a la gráfica.
Las barras son añadidas de izquierda a derecha, utilizando la función miembro
AddBar; por ejemplo para añadir 3 barras a la gráfica se llamaria a la función de la
siguiente manera:
Elprimer parámetro a AddBar es el valor de la barra, y el segundo es la etiqueta.
Losvalores son almacenados en el arreglo Barvalues y las etiquetas son
almacenadas en el arreglo de caracteres BarLabels. Por lo cual, cada llamada a
AddBar incrementa NumBars, el cual tiene a su cargo el número de barras en la
gráfica.
NOTA : El constructor a TBarGraph actualmente acepta dos parametros. El primero
es el título, el cual es siempre requerido. El segundo parámetro es opcional.
Este especifica cuantas líneas horizontales son dibujadas en el fondo. Este
valor es almacenado en NumRules; por default el valor es 4, el cual es el
número de líneas a dibujar en caso de que ningún otro valor sea especificado:
D€SPl€GANDOLA GRAFICA D€ BARRAS
Para desplegar la gráfica, se llama a la función de Display en TBarGraph.
Normalmente, se debe de llamar a Display en la función Paint.
29
Actualmente la función Display toma tres acciones:
1. Despliega el titulo de la gráfica.
2. Determina el máximo valor de la barra.
3. Llama a Drawchart, el cual dibuja el fondo, las barras y las etiquetas.
€SCRIBI€NDO€1TITULO
Una gráfica puede tener varios tamaños. Para compensar esto, el título de esta, se
ajusta en escala para que se encuentre dentro de las regiones ocupadas por la
gráfica.
El fonts es seleccionado llamando a la función GDI CreateFont. Una petición es
hecha por el tipo de font Roman junto con el alto y el ancho.
Un problema puede ocurrir si el título es demasiado largo, sin embargo. Para no tener
problemas con textos largos, se llama a la función GDI GetTextExtent, para ver que
tan largo es el texto actualmente, tal y como se muestra a continuación:
if (LOWORD(GetText€xtent(hDC, Title, strlen(Tit1e))) > (Right-Left*W3)
Si el texto es mas largo que dos tercios del ancho de la gráfica, un nuevo tipo de font
es seleccionado llamando a la función CreateFont una vez mas. En este caso, el
ancho del texto es seleccionado.
Después que el titulo ha sido creado, la alineación es modificada para centrar el
string, para posteriormente desplegar el título.
SetTextAlign (hDC, TA-CENTER I TA-BOTTOM);
TextOut (hDC, (Left+Right)/2. Top-2, Title, strlen(Tit1e));
30
R e D w del Prove-
. .,
La siguiente sentencia en Display determina el máximo valor a ser desplegado en la
gráfica, y guarda este valor en MaxBarValue. Todas las barras son ajustadas al
máximo valor. Entonces, la ejecución procede a la función miembro Drawchart, la
cual finaliza el dibujo de la gráfica.
DESPLEGRNDO ETIQUETAS
Las etiquetas a través del eje de las Y y las líneas horizontales son pintadas en
DrawChart después de que el fondo es pintado. Recuerde, que el número de
etiquetas y las líneas horizontales depende del parámetro NumRules pasados al
constructor TBarGraph.
Como en el título de la gráfica, las etiquetas para el eje de las Y son ajustadas de
acuerdo al tamaño de la gráfica. En este caso, el ancho y la algura del font
seleccionado es puesto a un sexto de separación entre las líneas horizontales y los
pixeles verticales. Esta separación es calculada en Drawchart y almacenado en la
variable Offset. Note que cada etiqueda es justificada hacia la derecha.
int Offset = (Bottom-Top) / NumRules;
Los strings que aparecen debajo de las barras en el eje de las X, son escritas con el
mismo tipo de font. Las etiquetas para las barras, las cuales son especificadas en las
llamadas a AddBar, son almacenadas dentro el arreglo BarLabels. Si una etiqueta no
se desea para una barra en particulas, su correspondiente valor en BarLabels es
puesto en NULL.
El loop For localizado al final de Drawchart despliega una barra por cada valor en
BarValues, una etiqueta.
31
Dl6UJRNDO UNA BARRA
Dentro del loop for, se hace la llamada a la función DrawBar, que es la encargada
de desplegar cada barra. Sin embargo, si se examina DrawBar se verá una simple
llamada a la función Rectangle. Esto es para hacer posible que otras aplicaciones
utilicen TBarGraph para diferentes tipos de gráficas. Introduciendo el código que
actualmente dibuja cada barra en la función virtual DrawBar, se puede sobrecargar
esta en clases derivadas de TBarGraph para dibujar otros tipos de barras. De hecho,
esto es lo que se hace para realizar las gráficas de pie.
La altura de cada barra depende del factor en la escala. Este valor se basa en el valor
máximo de la barra a dibujar que se encuentra almacenado en MaxBarValue:
-
Scale = double(i3ottom Top) / MaxBarValue;
Para determinar el ancho y el espacio de las barras,.ia idea básica es dividir los ejes
horizontales entre las barras a dibujar. La siguiente fórmula determina el espacio de
separación y almacena el resultado en Offset:
Offset = (Right - LeR) / (NumBars + 7);
32
ESTRUCTURA PRlNClPBl
A continuación se detallan el manejo de clases utilizadas en este módulo:
La clase TBarGraphWindow derivada de Window, contiene el código que utiliza
TBarGraph. Esta clase incluye la variable BarGraph, la cual es un apuntador al
objeto TBarGraph. El constructor de TBarGraphWindow dinamicamente aloja e
inicializa el objeto BarGraph.
La función TBarGraphWindows de Paint llama a la función TBarGraph::Display
para dibujar la gráfica:
33
R e D W del Prove-
. .
GRAFICA DE BARRAS EN 3 DIMENSIONES
La gráfica que se desarrolló anteriormente en 2 dimensiones es bastante
aceptable, sin embargo, con un poco de creatividad se puede realizar una mejor. Esta
es una gráfica de barras en 3 dimensiones que es la que a continuación se detalla.
Como Windows no tiene una función que dibuje gráficas en 3 dimensiones.
Desarrollaremos la clase TThreeDBar incluida en los códigos de los archivos
3DBAR.H y 3DBAR.CPP. Como la clase TBarChart, esta nueva clase contiene todas
las funcionalidad que se necesita para realizar gráficas de 3 dimensiones.
Como es de esperarse, realizar una gráfica en 3 dimensiones es un poco mas
complicado que una de 2 dimensiones. Para realizar el efecto de 3 dimensiones, se
tienen que dibujar cada barra dimensional, crear un fondo en 3 dimensiones, y escribir
el código necesario para las etiquetas de la gráfica. A continuación se muestra la
definición de la clase TThreeDBar, la cual posee la mayoria de las funciones a utilizar.
34
riÑriDlEND0 lfi T€RC€RA DIMENSION
Para barras en dos dimensiones, solamente se necesita especificar la locación,
altura y ancho de la barra. Para una barra de tres dimensiones, añadiremos un
parámetro de profundidad y color. Como se verá a continuación, para enfatizar la
profundidad de las barras, se añadirá sombra a los lados de las barras con un color
mas obscuro que el usado en el frente.
Parte de la ilusión de la profundidad es creado añadiendo polígonos a los lados y
alto de un rectángulo. Estos polígonos son ajustados en un desplazamiento del 25 por
ciento del ancho del frente de la barra.
int Depth = (Right - Left) / 4;
La primera llamada a Polygon en ThreeDBar dibuja una cara de la barra en tres
dimensiones. El color de relleno de la barra es pasado a ThreeDBar.
El color de los lados, sin embargo es mas obscuro dividiendo los componentes
del color RGB de la barra in una mitad, y recombinando estos colores en una brocha:
El alto y los lados derechos de la barra de tres dimensiones son desplegados por
llamadas a Polygon.
E l FONDO (BACKDROP) EN TRES DIMENSIONES
Parte de la complejidad de TThreeeDBar es la de realizar el fondo en tres
dimensiones. La geometria del fondo es similar a la utilizada para dibujar las barras
dimencionales. Los panels verticales son pintados coun una brocha gris clara
(LTGRAY-BRUSH) y el piso del fondo con una brocha obscura (GRAY-BRUSH).
35
Los lados de la parte de atras del fondo es dibujado utilizando la función
Rectangle y los páneles izquierdo y el de abajo son dibujados con la función
Polygon. Debido a que estas dos funciones alinean los pixeles en diferente forma,
debemos ajustar para la parte de abajo y la derecha del panel dibujando con
Rectangle.
Rectangle (hDC, Left + DOffset, Top - Doffset, Right + DOffset + 7,
Bottom - DOffset + 7);
LOS TOQU€S FINALES
Aún se necesita añadir el título y las etiquetas de la gráfica. Para esto, usaremos
los fonts por default en lugar de crear fonts dinámicos. En adición, se escribió el
código de tal forma que varios renglones de las barras puedan ser desplegados.
Como resultado, el arreglo Barvalues esta ahora como un arreglo de dos
dimensiones. También, la función GetMax esta provista para buscar en el arreglo
Barvalues por el mayor valor de Y .
El código de 3DTEST.CPP, contiene las funciones que realizan los gráficos de
barras en tres dimensiones.
36
R
e
. ..
C
GRAFICA DE PIE
Las gráficas de pie, proveen otra tecnica para la graficación de información. A
continuación se muestra la clase TPieChart, la cual contiene todos los detalles para
dibujar una gráfica de Pie y una leyenda. El código fuente para TPieChart se
encuentra en los archivos P1E.H y PIE.CPP.
Dl6UJANDO UN SLICE
Para dibujar los slice (rebanadas) de la gráfica, se utilizó la función Pie de OWL.
Típicamente cada slice representa la proporción, o porcentaje, de una pieza de
información en relación a la gráfica entera.
Para nuestra aplicación, se asume que se tiene una serie de valores de
porcentajes. Cada valor del porcentaje corresponde con un slice en la gráfica, y el
total de los slice, representa el 100 por ciento.
Claramente, se quiere que la gráfica de pie ha ser desplegada sea circular. Sin
embargo, si se utiliza el mapping mode MM-TEXT, no se garantiza esto. Sin
embargo, uno de los primeros pasos de la clase, es cambiar al mapping mode
MM-ISOTROPIC.
SetMapMode (hDC, MM- IS0 TROPIC);
SetWndowExt (hDC, rect.right, rect.bottom);
SetViewPortt5xt (hDC, rect.righf, recf.bottom);
Entonces, el origen es temporalmente cambiado a la posición que se convertirá el
centro de la gráfica de pie.
SetViewPort (hDC, rect.righü4+ 1O, rect.bottom/2);
El radio de la gráfica de pie, es calculado para ser un cuarto del ancho de la
ventana. Despues, la función miembro PieceOfPie es llamada para cada slice en la
gráfica. Esta función tiene dos responsabilidades: desplegar el slice con el color de
fondo apropiado y desplegar un valor de porcentaje a lo largo del slice.
37
RepQdkdel-orP
. .,
Sin embargo, desplegar el slice se logra con una simple llamada a Pie, se debe de
calcular las posiciones iniciales y finales del slice. Estas coordenadas son calculadas
como sigue:
StartLocX = Radius * cos(;! * PI * Startpercentage / 100.O);
SfartLocY = Radius * sin(2 * PI * Startpercentage / 100.0);
EndLocX = Radius * cos(2 * PI * (StartPercenfage + SlicePercentage) / 100.O);
EndLocY = Radius * sin(2 * PI * (Sfattfercenfage + SlicePercentage) / 100.0);
El cálculo dentro de las funciones Seno y Coseno conviertes los valores en
porcentajes del slice en radianes basados en su radio:
La variable Startpercentage especifica la suma de los porcentajes de los slice. El
valor de SlicePercentage es el porcentaje del slice. El resultado de la operación es
pasado a la función miembro Pie para dibujar el slice:
Pie (hDC, -Radius, -Radius, Radius, Radius, StartLocX, StarfLocY, EndLocX,
EndLocy);
El color de cada Slice, es almacenado en el arreglo Colors de TPieChart.
Determinando donde desplegar los valores de los porcentajes requiere un cálculo
similar. Sin embargo, aqui el radio es extendido a un factor de 1.2. De modo, que para
compensar por las varias posiciones del texto alrededor de la gráfica de pie, el
atributo de justificación del texto, se basa en el ángulo en cual el texto es alojado.
D€SPL€GANROUNA LEWNDA
AI final de la clase TPieChart, se encuentra la función Display, la rutina ShowKey
es llamada para desplegar cada slice. La leganda muestra un rectángulo y una
etiqueta por cada pie slice, en el lado derecho de la pantalla. La función Rectangle es
utilizada para dibujar cuadros rellenos, los cuales son de 16 pixeles en tamaño. Cabe
resaltar, que el mapping mode es puesto a MM-TEXT en la función miembro Display
en el momento de realizar los cálculos.
38
U
J
w
n
u)
w
u)
a
o
w
n
a
3oa
P
I
+
o
ReD-
Porv-
. ..
BIBLIOGRAFIA
Windows Graphics Programming with Borland C++
Loren Heiny
John Wiley & Sons, Inc.
Programming Windows with Borland C++
William Roetzheim
PC Magazine
Aplique Turbo C++
Herbert Schildt
McGraw -Hill
Borland C++ 3.1 Programación Orientada a Objetos
Faison
Prentice Hall
Programación Avanzada de Gráficos e n C para Windows
Adams
Mc Graw Hill
Advanced Graphics on VGA and XGA Card Using Borland C++
Ian O. Angel1 & Dimitrios Tsoubelis
Halsted Press
39
Descargar