La Ventana de Escritorio
La ventana de Escritorio descrita en este artículo es una combinación de estilos que se tomo de diferentes programas. Es un tributo al poder fácil y entendible flexibilidad que hace de dBASE una plataforma superior de desarrollo. Como es a menudo el caso, una simple vista de diseño puede enmascarar mucho de la complejidad del software. Es difícil hacer que el software se vea fácil.
Desktop.wfm, es de hecho es una versión ligeramente modificada de una forma real que el autor usa en su contabilidad y el sistema de información que diseñó para la industria de la producción. La idea era crear una interfase de fácil uso que incluso un neófito de la computadora podría usar.
Observe el Diagrama. Los botones que corren abajo el lado y por la cima son botones “impactantes” o de una idea fantástica. Es decir, estos cambian de alguna manera cuando usted se mueve encima de ellos. Esto ayuda al usuario a saber que si usted pulsa en esta área, algo pasará. En este caso, los botones en la izquierda y por encima adoptan varias conductas y estados que ayudan a que el usuario entienda lo que está pasando. Cuándo el cursor del ratón se mueve por una de estas áreas, este resalta y va de un color gris a un color vivo como si quisiera decir “yo soy una opción!”. Cuando se aprieta uno de estos botones, asume que fue “pulsado”. Esto ayuda al usuario a recordar qué artículo fue finalmente seleccionado.
Adicionalmente, un pulsado de los botones en la izquierda causa un panel fuera del borde detrás del contenedor de botones, creando un agradable efecto animado. El propósito, en este caso, es proporcionar una opción de dos niveles. Cada botón trae adelante más opciones.
La vista completa de esta forma se fabricó. Nada de esto fue creado automáticamente. Si usted fuera a crear muchas formas grandiosas como esta, pagaría para crear varios controles personalizados y formas con capacidades de clasificar según tamaño y habilidades de despliegue. Esta forma no usa nada de eso. En cambio, toda la funcionalidad se ata a los objetos mismos. Esta forma hace uso extenso de CODEBLOCKS. Un codeblock es un grupo pequeño de órdenes que atan a los eventos de un objeto.
Empieze con un Botón impactante
Como se describió antes, los botones usados en la izquierda y la parte superior de la forma reaccionan a varios eventos del usuario. Antes de ir a los eventos, veamos los objetos que constituyen un botón impactante.
En primer lugar, arrastre un botón de su paleta a la forma. Luego arrastre una imagen y déjelo caer encima del botón. Haga clic derecho en la imagen y apunte a datasource a la imagen gris, en este caso company1.gif.
Cambie la propiedad alignment (alineacion) a «true size» (tamaño real) y cambie la propiedad border (borde) a «ninguno». A estas alturas usted tiene un control de imagen que no tiene ningún borde y llena exactamente el gráfico que está desplegando.
El propósito del botón es proporcionar una apariencia de «resaltado» cuando el ratón se mueve encima de él. En primer lugar, líbrese del texto. Luego, cambie la propiedad del speedbar a verdadera. Esto es para que el botón no mantenga el enfoque. Luego, use las teclas de flechas para posicionarlo de modo que su esquina superior izquierda este alineada con la esquina superior izquierda de la imagen. La idea es posicionar el botón para que si usted presionara la flecha derecha una vez (de este modo moviendo el botón hacia abajo un pixel) el borde superior del botón será escondido por la imagen. Entonces presione la tecla flecha arriba DOS VECES para que el borde del botón sea de nuevo visible. Haga lo mismo con el borde izquierdo. Ahora, mantenga presionadas las teclas shift-flecha abajo para dar tamaño al botón de modo que su borde inferior simplemente sea visible. Finalmente repita el procedimiento para el borde derecho.
A estas alturas, usted puede estar preguntándose por qué es necesario usar el botón, después de todo, que usted podría simplemente cambiar el borde de la misma imagen para parecer un botón. Mientras este acercamiento trabaja y es mucho más simple, causa que la imagen brinque y cambie. En contraste, haciendo un botón subyacente visible crea un efecto muy uniforme.
El evento onMouseMove
Ahora que las partes del botón impactante están en su lugar, es tiempo para trabajar en como traerlo a la vida. Este paso involucra vinculación de código a varios eventos. Los eventos afectan, y se conectan a un objeto. Cuando el usuario mueve el ratón encima de un objeto, los eventos onMouseMove de ese objeto se disparan; lo que significa que ejecutan cualquier código puesto en el evento del onMouseMove.
Deducir qué instrucciones necesitan ser ejecutadas cuando el ratón se mueve encima de la imagen, piense sobre el comportamiento que usted quiere. Primero, el botón debe ponerse visible con el efecto de fabricación «de levantamiento» de la imagen También, debe ser cambio de gris a color. Más allá esto confirma al usuario que esto es de hecho una opción que tendrá un poco de efecto si ellos fueran a pulsar el botón.
En programación orientada
a objetos, es de gran ayuda pensar en términos de objetos y qué
pueden hacer esos objetos. El pseudo código para realizar
esto podría ser como sigue.
Eh pushbutton 1, hágalo visible Eh imagen 1, haz que tu propiedad datasource sea el archivo «company.gif» |
|
El pseudo código no es suficientemente
explícito. Usted podría tener muchas formas ejecutándose
al mismo tiempo. Estas instrucciones se supone que están dirigidas
a los objetos en esta forma, o alguna otra forma. Puesto que es esta forma,
necesitamos decirlo «form.»
form.pushbutton1.visible = true form.image1.datasource = 'filename company.gif' |
|
De modo que estas son las instrucciones, dónde las pondrias?
Puesto que nosotros queremos esto pase cuando el ratón se mueve encima del objeto imagen, sólo tiene sentido que el código se coloque allí. Haga clic derecho en la imagen y llame ventana de Inspector. Pulse la pestaña de eventos en la parte superior. Encuentre el evento llamado «OnMouseMove» y haga clic. Como se mencionó antes, nosotros queremos usar codeblocks en lugar de las funciones. Usted notará que hay dos botones a la derecha de onMouseMove, una herramienta una «T». Para crear un bloque del código o codeblock, usted debe hacer clic en la «T» y despues elegir «codeblock».
Con eso hecho, ahora usted puede
hacer clic en la herramienta y aparece un pequeño editor .
Primero, pulse el botón de radio «commando» y limpie
el código proporcionado «null». En seguida, teclee en:
form.pushbutton1.visible = true form.image1.datasource = 'filename company.gif' |
|
Y entonces pulse el botón «OK»
Ahora si usted ejecuta esta forma,
usted debera ver una imagen en blanco y negro que es lo que nosotros quisimos
ver. ¡Pero el borde o efecto de «relieve» ya está
allí! La conducta predefinida para este objeto necesita estar
como no visible o más bien visible = falso. Remóntese al
diseñador de la forma. Una de las propiedades que están
disponible para cualquier objeto es la propiedad visible. Todos los
objetos siempre son visibles en el diseñador de la forma, pero cualquier
objeto con visible puesto en falso no será visible cuando la forma
realmente está corriendo. Pero aquí hay otro problema,
es difícil seleccionar el pushbutton porque sólo una paqueña
porción es visible porque la imagen casi completamente la tapa.
Usted podría ir a la ventana de inspector y podría usar el
campo de despliege en la parte superior para encontrar el objeto, pero
vamos directamente al código fuente. En dB2K, no hay ninguna
diferencia entre un cambio hecho al código fuente y uno hecho a
través del diseñador de la forma. Haga clic derecho en cualquier
parte de la forma y escoga «Editor de codigo/diseñador.»
Enseguida, encuentre el código que parece similar a lo siguiente:
this.PUSHBUTTON1 = new PUSHBUTTON(this) with (this.PUSHBUTTON1) height = 1.5909 left = 2.4286 top = 0.3636 width = 5.2857 text = "" colorNormal = "BtnText/BtnFace" pageno = 1 value = false endwith |
|
Note que la altura del pushbutton
es 1.5909 y otras propiedades se definen entre el with y endwith.
Inserte una nueva línea en cualquier parte entre el with y endwith
y teclee:
Visible = false |
|
Cierre el Editor. Si usted fuera ahora a inspeccionar el objeto pushbutton1, su propiedad visible ahora estaría como falso. Éste es un ejemplo de las herramientas bidireccionales (two-way tools).
Ahora, si usted ejecuta la forma, usted debe tener una imagen gris, sin bordes alrededor de esta, de hecho. Si usted mueve su ratón encima de la imagen, esta debe levantarse y colorearse. ¡Ahora nosotros tenemos nuestro Botón impactante! Excepto, no que no es todavia impactante. Puede hacer el truco una sola vez y entonces se queda allí atrancado. Esto pasa porque hay ningún código que le diga que se baje y se ponga gris. Veamos como ahora necesitamos un nuevo evento!
Idealmente, debe haber un evento que se dispare cuando el ratón ya no esta sobre la superficie de un objeto; un evento de OnMouseOut. Mientras nos han prometido uno en una liberacion futura de dB2K, mientras nosotros tenemos que hacerlo. Examinemos el problema: nosotros necesitamos un evento que se dispare cuando el ratón se separa de la imagen.
Lógicamente, si el movimiento del ratón esta furea de un objeto, ¿no tiene que moverse hacia otro objeto ? En este caso, la propia forma puede ser el evento. Cuando el ratón se está moviendo encima de la forma, no se debe estar moviendo encima de la imagen. Así que tengamos la forma de decir pushbutton1 (de quien la forma es el padre) apagarse y decir image1 (de quien la forma es el padre) para desplegar la imagen gris de nuevo.
Haga clic derecho sobre la forma
eliga al Inspector. Pulse en la pestaña de eventos en la parte
superior entonces haga clic sobre la linea de OnMouseMove. Pulse
el botón «T» y escoga codeblock. Pulse el botón
del comando de radiobutton entonces teclee (después de quitar «null»):
form.pushbutton1.visible = false form.image1.datasource = 'filename company1.gif' |
|
¡Ahora ejecute la forma y funciona! Cuando usted mueve su ratón sobre la imagen, sube y se colorea, cuando usted aleja, baja la imagen y se pone gris. Si usted ya ha ejecutado esta forma , podrá notar un problema. Cuando usted mueve el ratón alrededor, la imagen parpadea. El evento de OnMouseMove se dispara ciento de veces cuando usted mueve el ratón alrededor porque su trabajo es ejecutarse a cada movimientos del ratón.
Nuestro objetivo es tener una interface del usuario uniforme, asi que necesitamos arreglar este problema. El problema en realidad no es que el evento se dispare un monton de veces, El problema es que piensa que debe reasignar la propiedad datasource de la imagen y hacer el boton visible cientos de veces.
La solución es hacer una
bandera que guarde el registro para saber si el trabajo necesitado ya se
ha realizado. Una vez que la imagen está coloreada y el botón
es visible, no necesitamos cambiar regresar esas propiedades hasta que
el ratón se mueva otra vez hacia la forma. Haga clic derecho sobre
la imagen eliga el Inspector. Haga clic en la pestaña de eventos,
haga clic en onMouseMove y entonces pulse la herramienta. Haga
los cambios siguientes.
if not form.image1.color form.image1.color = true form.image1.datasource = 'filename company.gif' form.pushbutton1.visible = true endif |
|
«Color» es una propiedad personalizable, es decir, es una propiedad que usted puede construir. Se vuelve una propiedad del objeto como la altura (heigth), colorNormal o nombre (name). Nosotros vamos a hacer la propiedad «Color» verdadero si el objeto esta levantado y en color y falso si esta plano y gris. Si usted fuera ejecutar la forma con este cambio, sin embargo usted obtendría un error. Porque «color» es una propiedad personalizada, no existe hasta que nosotros lo creemos. Desde que el evento onMouseMove anterior asume que hay una propiedad «color» de image1, choca cuando lo busca. Es como si el programa dijera «Quién? el Color? Yo no sé de ningun tonto Color!»
De nuevo, necesitamos un nuevo
evento. un evento que asignará la propiedad «color»
en cuanto se abra image1. Eso es lo que el evento de onOpen hace
para existir. Haga clic derecho en la imagen y eliga el panel inspector.
Pulse la pestaña de sucesos y pulse el botón en la línea
«OnOpen». Pulse el botón «T» y escoga «codeblock».
Pulse el botón de la llave y selecione comando. Líbrese
del «null» y tipo:
this.color = false |
|
Note el uso de la palabra «this.». De una manera intuitiva, tiene sentido para decir «esta bandera de 'color' se fija a falso.» «this.» es una manera de referirse específicamente a la imagen, sin nombrarla explícitamente. Porque la palabra «this.» se usa en código atado al objeto image1, sólo podría referirse al objeto image1. Es como si estuvieras viendo a alguien y le dijeras decir «yo estoy mirándolo» contrario a decir «yo estoy mirando a Juan Pérez». La diferencia es que «yo estoy mirándolo» trabajará con cualquiera que te suceda que este en frente en cambio «yo estoy mirando Juan Perez» es sólo útil si usted está hablando de hecho sobre Juan Pérez.
Otra manera de lograr la misma
cosa habría sido teclear:
form.image1.color = false |
|
Piense sobre eso. Éste no es el único botón impactante que nosotros vamos a usar. Nosotros también vamos a tener varios mas de estos. Si somos inteligentes sobre la manera que codificamos esto, nosotros no tendremos que cambiar el código para cada objeto. Considere lo que tenemos que hacer si tenemos cinco imagenes de botones impactantes.
En el primero tenemos que decir:
form.image1.color = false |
|
En el segundo tenemos que decir
form.image2.color = false |
|
Y así sucesivamente.
O, si nosotros simplemente decimos:
this.color = false |
|
Entonces siempre va a fijar su propiedad personalizada «color» a falso. Este tipo de versatilidad es uno de los conceptos más importantes en la programación orientada a objetos.
Los cambios del código descritos resuelven el problema del parpadeo cuando usted mueve el ratón alrededor sobre la imagen. Sólo se pone colorido y levantado una vez gracias a la bandera «color».
Desafortunadamente, el parpadeo
vuelve cuando nos movemos alrededor sobre la forma. Esto es porque
nosotros no le hemos enseñado cómo determinar si el botón
impactante ya esta gris. Necesitamos cambiar el evento onMouseMove
de la forma de la manera siguiente:
if form.image1.color form.image1.color = false form.pushbutton1.visible = false form.image1.datasource = 'filename company1.gif' endif |
|
Grandioso. ¡Ahora nosotros tenemos un botón impactante libre de parpadeo!
Luego necesitamos agregar el efecto de «empuje» cuando se ha seleccionado.
Para esto solo necesitamos cambiar borderstyle de los pushbutton1 de 0 (cero) a 7.
Para esto necesitamos un nuevo
evento para disparar cuando el usuario pulsa en el botón.
Si esto se hiciera en un pushbutton, nosotros usaríamos el evento
de OnClick. Puesto que el evento va a pasar al objeto image1, lo mas cercano
disponible al evento OnClick es el evento OnLeftMouseDown.
Haga clic derecho en el objeto image1 y eliga el panel inspector.
Pulse la pestaña de evento y pulse el evento de OnleftMouseDown.
Pulse «T» y eliga «codeblock» Pulse la llave y
pulse el botón de radio radiobutton «comando». líbrese
de «null» y tipo:
this.parent.pushbutton1.borderstyle = 7 this.on = true |
|
Note el uso de «parent».
Esto es otro aspecto importante de la programacion orientada a objetos.
Usamos «parent» por las mismas razones que usamos «this»
en el ejemplo anterior. Usted puede estar notando que nosotros todavía
estamos usando el nombre explícito «pushbutton1». image1
no esta formalmente relacionanda a pushbutton1. Se apilan unos encima
de otros y nuestra intención es relacionarlos entre ellos, pero
hasta donde la forma sabe, ellos son dos objetos separados, independientes.
Eso significa que el objeto image1 debe llamar el pushbutton por nombre
si consigue dicirle cambiar borderstyles a 7 (la vista de empujado) de
modo que si no hay ninguna relación formal entre pushbutton1 y el
objeto image1, por qué usamos la referencia del padre anteriormente.
¿No haría el trabajo siguiente también?
form.pushbutton1.borderstyle = 7 this.on = true |
|
Sí, también funciona, pero yo estoy pensando adelante. ¿Qué tan bueno es un botón impactante? Normalmente, nosotros los usaremos en combinaciones. Esta organización se presta para usarse en contenedores para sostener grupos de botones impactantes relacionados. Un contenedor o recipiente es similar a una forma o una sub-forma. Si usted mueve un contenedor (container), todos los objetos dentro del contenedor se quedan juntos al parejo del recipiente. Por ejemplo, si usted decidiera que usted quiso todo el tablero de botones impactantes localizado abajo a lado izquierdo de la forma, en cambio, actualmente esté en el lado correcto, simplemente arrastre la forma al lado correcto. Eso es. Ningúna re-codificacion, ningún moviendo de objetos individuales. Asi que ¿cómo se relaciona esto al uso de el «parent» anteriormente?
Es simple y intuitivo trabajar con recipientes (containers), pero usted tiene que entender la relación entre un recipiente y los objetos en el recipiente. Usando la palabra «parent» se refiere al recipiente que sostiene el objeto actual. Puede ser una forma. Asi que si el objeto image1 se refiere a «this.parent» y el padre de image1’s padre es la forma obviamente this.parent es la forma. Pero si usted pone el botón fantástico en un recipiente, «this.parent» se referiría al recipiente. El linea de fondo es que si usted usa «this.parent» en lugar de «form.», el código trabajará en una forma o cualquier recipiente.
Para recapitular, ésto es como creamos el boton fantástico
Obtenga dos archivos de la imagen que se clasifican adecuadamente según tamaño, uno gris, el otro de color. Ponga un botón en la forma, elimine el texto. Ponga una imagen en la forma. Fije el datasource para la imagen a la imagen gris. Cambie la alineación a «top left» (izquierda superior) fije el tamaño del objeto de la imagen para que él exactamente cubra la imagen que está desplegando. Luego, posicione el botón debajo de la imagen para que sólo sus bordes se muestren. Fije la propiedad visible a falso. Cree un codeblock en el evento onOpen de la imagen mismo que crea la propiedad personalizada, llamada «color», y se fija como falso. Agregue un codeblock en el evento onMouseMove que verifica si la propiedad «color» es verdad. Si es verdad, entonces nada se necesita hacer puesto que ya está en color. Si «color» es falso, entonces nosotros necesitamos levantar el botón (hágalo visible), muestre la imagen en color en lugar de la imagen gris, y ponga la propiedad «color» en verdadero puesto que el botón impactante está ahora en color. Luego, necesitamos obtener el recipiente, si es la forma, o un contenedor, para asegurarse que el objeto no está en color y no esta levantado. Si el evento onMouseMove de la forma o el contenedor está disparando, entonces el ratón no está encima del botón impactante. Esta forma o el evento de OnMouseMove del contenedor deben verificar la propiedad «color» del objeto de la imagen del botón impactante. Si esta en color, entonces debe fijar la propiedad visible del pushbutton a falso, y muestra la imagen gris. Finalmente debe fijar la propiedad «color» a falso puesto que el botón impactante ya no se muestra en color. Por último, un codeblock debe atarse al evento onLeftMouseDown del objeto de la imagen del cual se debe cambiar el borderStyle del pushbutton a 7 que le de una apariencia de «presionado» . ¡Guau!
El usuario más avanzado dB2K reconocerá la oportunidad para un control personalizado. No hay ninguna duda que mucho código podría re-usarse si este acercamiento fue seguido. Por otro lado, para el desarrollador intermedio o principiante de dbase pueden beneficiarse de ser un poco menos sofisticado. Teniendo todo el codeblocks atado a los objetos les permite saltar de objeto en objeto para inspeccionar la interacción entre los eventos y propiedades de los objetos usados en la forma. No hay una necesidad de saltar al código fuente para ver algo. El editor del codeblock muestra el snipets de código con el que cada evento cuenta.
Así, ahora que nosotros tenemos un botón fantástico totalmente funcional, es tiempo de hacer juntos algunos trabajos.
Grupos de Botones Fatásticos
Porque al dBASE le falta un evento
del onMouseOut, los objetos tienen que trabajar para decirnos juntos cuando
el ratón esta encima de ellos. El ratón no puede estar disparando
eventos onMouseMove de más de un objeto al mismo tiempo, para que
nosotros podamos asumir de modo seguro si el ratón esta sobre un
objeto, no puede estar encima de otro. Mire el código real que es
asociado con el evento OnMouseMove del recipiente de la primera imagen
en “desktop.wfm.”
form.taskbar.image1.onmiddledblclick() form.taskbar.image2.onmiddledblclick() form.taskbar.image3.onmiddledblclick() form.taskbar.image4.onmiddledblclick() form.taskbar.image5.onmiddledblclick() form.taskbar.image6.onmiddledblclick() |
|
El primero piensa noificar que
hay seis comandos. Cada uno corresponde a las seis imágenes mostradas
en el tablero que corre abajo a un lado (refiérase al diagrama del
escritorio). El contenedor que sostiene estos seis botones fantásticos
se llama “taskBar” (barra de tareas). Cada elemento del botón fantástico
(pushbutton, imagen, texto) esta contenido dentro del recipiente llamado
“taskBar”. para referirse a él, usted tiene que usar notación
de punto. El código anterior se refiere explícitamente a
los objetos de la imagen. Observe la notación del punto:
form.taskbar.image1.onmiddledblclick() |
|
“form” se refiere a la propia forma.
La forma actúa como un recipiente para todos los objetos usados
en esta forma.
“taskbar” se refiere a un recipiente.
Los recipientes sostienen otros objetos
“image1” se refiere al objeto
de la imagen contenido en el contenedor “taskbar”
“onMiddleDblClick()” se refiere
a un evento que es asociado con la imagen “image1”. Note los paréntesis
al final. Esto le indica a dBASE proseguir y ejecutar el código
contenido en ese evento.
¿Qué carajos es el onMiddleDblClick? Hace años, era común para un ratón tener tres botones. El evento onMiddleDblClick es un lugar conveniente para sostener código que usted no quiere que el usuario active directamente. Mientras es ciertamente posible para un usuario tener un ratòn de tres botónes y hacer doble clic mientras esta encima de una imagen, no es probable. Los usuarios experimentados protestarán al instante que esto es confuso y que un método personalizado simplemente debe atarse al objeto. Esto es verdad, pero hay una razón muy buena para no hacerlo en este caso. Más adelante abundaré sobre esto.
Si nosotros miramos el código
atado al evento onMiddleDblClick de image1 se ve como sigue:
if this.color if this.on else this.datasource = 'filename company1.gif' this.parent.pushbutton1.borderstyle = 0 this.parent.pushbutton1.visible = false this.color = false endif endif |
|
El pseudo código en español
sería:
If this image's color flag is set to true, And if this image's "on" flag is true, then do nothing. But if this image's "on" flag is false then Set this image's datasource to the filename company1.gif (gray image) Set this image's parent's pushbutton1's border style to a normal button look Make the pushbutton invisible Because the cool button is gray and not raised up, the "color" flag needs to be set to false |
|
El evento OnMiddleDblClick de la imagen la hace gris y llana lo que indica al usuario que la opción no esta seleccionada actualmente y no es el objeto que es actualmente “selecionado”.
Cuando el contenedor llamado “el taskBar” recibe un movimiento del ratón, simplemente dice a cada botón fantástico que sea llano y gris. Ésta es la conducta correcta porque si el ratón está moviendose sobre el contenedor mismo, no está apuntando a ningun botón fantástico.
Ahora nosotros hemos visto que
una imagen se levanta y se vuelve a color si es que el evento OnMouseMove
se dispara. Se hara llano y gris si es que el evento onMiddleDblClick se
dispara, qué otra conducta se necesita? Si el usuario pulsa en la
imagen para elegirla, el boton fantástico coolbutton tiene que:
a) ponerse colorido, b) empujado,
y c) lanza la acción apropiada. El código siguiente le muestra
hacer eso. Este código se conecta al evento onLeftMouseDown de la
imagen:
form.taskbar.pushbutton1.borderstyle = 7 this.parent.onmiddledblClick() this.on = true this.parent.onmousemove() form.m1.onmiddleDblClick() form.loadwfc("m1.wfc") |
|
El pseudo código en Español
sería:
Set this form's container named taskbar's pushbutton1's border style to look pushed in. Run this image's parent's (the parent is the container named "taskbar") onMiddleDblClick method which makes all the cool buttons flat and gray. Set this image's "on" flag to true. "On" is a flag that we created and is not a normal property of an image. We could have named the property "Sally" or "Edward", instead, the name "on" is meant to tell us whether the object is pushed in and therefore is the cool button that currently is on. Next, run this parent's onMouseMove event which will turn this object to color and turn on the pushbutton behind it (remember that we changed the border to have a "pushed in" look) Next, run the container called "m1"'s onMiddleDblClick event. This needs much more explaining, but briefly it clears out the "m1" container so that it has no objects in it. Finally, the form's "loadwfc" method (or procedure) is run. This procedure populates the "m1" container and then slides it into view. |
|
Mire el diagrama para ver los varios eventos y cómo los eventos actúan recíprocamente.
El Tablero superior
These are one-level cool buttons (no sub-menus)El tablero de la parte superior es un recipiente nombrado “opBar” que trabaja como “taskBar.” La única diferencia importante es que todos estos botones fantásticos instantaneamente lanzan algo cuando se pulsan en lugar de deslizar fuera un menu-subalterno. Puesto que todos los otros codigos trabajan idénticamente al contenedor “taskBar”, los detalles nos los saltamos.
Enmarcando los Botones fantásticos
Agregar un marco alrededor de los dos recipientes (taskbar y opbar) ayuda al usuario a entender que son grupos separados de botones fantásticos que podrían comportarse lógicamente diferentemente. Un método es cambiar el borderStyle de los recipientes. Quise imitar como se ve Microsoft Outlook y así miraba el marco que se use allí. Hay maneras múltiples evidentemente de lograr esto. Yo establecí cuidadosamente en el uso de pushbuttons clasificado según tamaño y los puse para crear el efecto deseado. Pushbuttons son una opción buena porque vuelven (despliegan) muy rápidamente, use recursos eficazmente, y tienen las características visuales necesarias. Note que cada uno de estos pushbuttons tiene su propiedad “speedbar” puesta en verdadero. Mantiene el objeto del enfoque receptor. Esta propiedad “enabled” también se fija a falso de modo que si el usuario pulsa en el marco, no se comportara como un pushbutton.
El problema con usar pushbuttons es que tienen costuras. Aquí las costuras se han rodeado. No se ven del todo mal, pero dan un efecto granular que no es ideal. Es sencillo remendar estas costuras poniendo pequeños objeto paintbox sobre las costuras. Cuando usted crea el objeto paintbox, usted sólo tiene que cambiar dos propiedades. 1) fijar borderStyle a “3” qué significa sin bordes. 2) fijar la propiedad ColorNormal a “btntext/btnface” Este fijara el color al mismo color que los pushbuttons usan. Usted podría estar interesado en saber que estos colores son a su vez obtenidos de Windows. Esto permite a su esquema de color ser cambio para igualar el esquema de color en cualquier máquina.
Para terminar el efecto visual nosotros hemos usado un gráfico y dos objetos de texto. Éstos se agregaron por las razones de estilo y no realizan ninguna función particular. Ellos no tienen ningún evento.
La Bandeja de despliegue lateral
La Bandeja de despliegue lateral introduce un rango competo de nuevos conceptos. Primero, tiene un agradable efecto por el que se “desliza” fuera desde abajo del contenedor “taskBar”. Segundo, usa una concepto “fantástico" de la imagen en lugar de un botón fantástico. En tercer lugar, y mas importante, es polimorfico y usa un sistema de creación de objetos Just-In-Time (creación al momento).
form.m1.visible = false form.m1.width = 9.14 form.m1.visible = true form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left += 1 form.m1.left = 10.86 |
|
"M1"
es el nombre de contenedor que se "despliega" afuera. El Pseudo Código
en español sería:
(Before this is called, M1 is moved to so that its "left" is zero) Make the container called "M1" invisible Make it the proper width Make it visible again Move it to the right one Move it to the right one repeat several times Finally, make its left exactly equal to the screen coordinates where you want it to stop. |
|
Usted podría estar preguntandose donde esta el código anterior. Esa respuesta se obtiene parte de la creación de objetos Just-in-Time y para que la discusión se retarde hasta esa sección. Lo que es importante aquí es que la animación no es difícil o misteriosa.
La Imagen Fantásitica
La Imagen Fantástica trabaja justamente como los botones Fantásticos sólo que no hace el “levantamiento”. Esto se hizo por las razones de estilo. El fondo blanco de la bandeja de despliege externo no parecía bueno con botones blancos. Todos los otros aspectos de este trabajo son los mismo sólo que no hay ningún botón para hacer visible.
Polimorfismo y Just-inTime (Justo-en-Tiempo)
Los aspectos de esta forma de escritorio son polimorficos. “Polimorfico" en este contexto tiene un significado ligeramente diferente que la tradicional POO tradicional (Programaón Orientada a Objetos), pero describe justamente esta forma. Polimorfico quiere decir “muchas formas.”pushbutton puede tener muchas combinaciones de borderStyles y colores, pero todavía es debajo el mismo pushbutton. Sólo sus propiedades cambian. Este polimorfismo se toma para otorgarlo para el programador experimentado. Nosotros constantemente alteramos las apariencias y posiciones y función de todos tipo de objetos.
Polimorfismo en esta forma significa que “shape" (la forma física) puede alterarse bien después que el “.EXE” se ha creado. Esto es logrado creando archivos del texto que contienen las definiciones del objeto. Éstos archivos de texto se abren en runtime (tiempo de ejecucion), (o después en este caso) y los objetos se generan en respuesta a la información contenida en estos archivos de texto.
¿Por qué haría usted esto?
Compilado, esta forma es muy pequeña (sólo más de 100k). Desplegar un nuevo “EXE” sobre Internet no sería ningún problema. Pero las aplicaciones pueden ser mucho mas grandes. La aplicación original para la que esta forma fue diseñada era originalmente más de ocho megabytes. Incluso empacada, todavía es casi de tres megabytes. en 100k, usted puede enviar actualizaciones casualmente. A tres megabytes usted no puede actualizarlo tan casualmente. Porque la aplicación es tan grande y compleja, también tiene más bugs (errores)y más caracteristicas perdidas. Tradicionalmente, cuando usted encuentra un error, usted debe instalar un nuevo “.EXE” para corregir el error o agregar la mejora o herramienta. Si usted usa apropiadamente el poder de dBASE, esto no tiene que ser su única opción.
El archivo “M1.WFC”
Usted recordará que el evento
OnLeftMouseDown de form.taskbar.image1 incluye la línea siguiente:
form.loadwfc("m1.wfc") |
|
Esta linea llama el método
(función, procedimiento, la rutina etc.) LoadWfc que se lista aquí:
Function LoadWFC parameter Mfile ObjInit = new file() ObjInit.open(Mfile,"RW") Mtemp211=0 do while .not. objInit.eof() Mtemp211 ++ Mtemp221 = Objinit.readln() try if substr(Mtemp221,1,1) = '{' Mcodeblock = rtrim(Mtemp221) Mtemp221 = Objinit.readln() Mtemp211 ++ Mevent = rtrim(Mtemp221) Mtemp77 = &Mcodeblock. &Mevent. = Mtemp77 else &Mtemp221. endif catch (exception e) msgbox("Error: "+e.message+chr(13)+"Line:; "+tran(Mtemp211,"99999")+chr(13)+Mtemp221,"Error Message") endtry enddo ObjInit.close() ObjInit = null |
|
El código anterior realmente
es muy sencillo. Un archivo se pasa al parámetro Mfile. Ese archivo
es un archivo del texto que contiene las líneas de código
válido de dBASE. “Mfile” se procesa al momento en una línea.
Busca cualquier línea que empieza con un corchete “{”. Si encuentra
tal línea, el código sabe que está tratándose
de un codeblock. Asigna el codeblock al evento que se lee enseguida. Por
otra parte, simplemente ejecuta cada línea en la forma que la encuentre
usando macro substitución. La cosa completamente es contenida en
un bloque try-catch (prueba-captura) que le permite manejar errores de
una manera elegante. Mire un snippet del código de “M1.WFC”
form.M1.IMAGE1 = new IMAGE(form.M1) form.M1.IMAGE1.height =1.4545 form.M1.IMAGE1.left = 2 form.M1.IMAGE1.top = 0.2727 form.M1.IMAGE1.width = 4.8571 form.M1.IMAGE1.dataSource = "FILENAME salesman1.gif" form.M1.IMAGE1.pageno = 0 form.M1.IMAGE1.borderStyle = 3 {;this.color = false; this.on = false} form.M1.IMAGE1.onOpen {;set proc to openapps.prg additive;} form.M1.IMAGE1.onLeftMouseDown {;if this.color; this.datasource = 'filename salesman1.gif'; this.color = false; endif;} form.M1.IMAGE1.onMiddleDblClick {;if not this.color; this.color = true; this.datasource = 'filename salesman.gif'; endif; this.parent.image2.onmiddledblclick(); this.parent.image3.onmiddledblclick();} form.M1.IMAGE1.onMouseMove {;this.color = false; this.on = false} |
|
Todos lo que “LoadWFC” hace es ejecutar cada línea anteriormente. Cuando toca un codeblock (es decir empieza con un “{”), lo combina con la siguiente línea para ligar el bloque del código con el evento que sigue.
Respaldemonos ahora y veamos la
manera en que “LoadWFC” consigue ejecutarse:
form.taskbar.pushbutton1.borderstyle = 7 this.parent.onmiddledblClick() this.on = true this.parent.onmousemove() form.m1.onmiddleDblClick() form.loadwfc("m1.wfc") |
|
Note el segundo a la última declaración: form.m1.onMiddleDblClick ()
El código que ejecuta sigue:
The code that it executes follows:
do while this.first <> null this.first.release() enddo |
|
Desde que este código se ejecuta de la perspectiva del contenedor llamado “M1”, “this” se refiere a “M1”. Este código procesa todos los objetos contenidos en el recipiente liberando cada uno. Después de que este código ha terminado, el recipiente está completamente vacío. Puesto que el recipiente está vacío, “form.loadwfc ('m1.wfc')” ejecutará las líneas en “m1.wfc” qué multiplicara el contenedor “M1”. Recuerda que el contenedor “M1” está oculto detrás del contenedor “taskBar”, para que el usuario no vea los objetos que se estan desplegando. Sólo después de que los objetos se han creado el recipiente “M1” hace el despliegue externo.
Puede parecer mucho problema para involucrarse, y estaría sin las herramientas apropiadas, pero observa lo que ha sido logrado:
Si el contenido de “M1” necesita cambiar, todos que se requieren es que el archivo de texto “M1.WFC” sea reemplazado. ¡Éste es un archivo de 3.5k! Si usted tuviera una aplicación normal usted podría rolar las diferentes versiones de “M1.wfc” a cada cliente. Aun cuando usted actualizó el archivo “.EXE” el archivo en el futuro, los M1.WFC permanecerían en su estado personalizado.
Esta filosofía del polimorfismo puede extenderse para incluir cada objeto visual. De hecho, el autor extrae todos los elementos visuales para todas las formas y los incluye en éstos “.wfc” los archivos. Antes de que la forma se abra, todos los objetos visuales se crean. El efecto del precio neto es que las formas parecen, el acto y se siente el mismo. Pero cada elemento visual puede cambiarse de forma alguna sin la necesidad de re-distribuir el archivo “.EXE” de la aplicación. Sólo necesitaria enviar el pequeño archivo “.wfc”. De esta manera, una aplicación normal puede estar “personalizada” por cliente mientras retiene la habilidad de actualizar el archivo “.EXE” sin tener que recrear la personalización. Es una forma de como sortear actualizar su navegador de internet: usted puede conseguir nuevas caracteristicas, pero las páginas de HTML viejas todavía trabajan.
Una descripción completa de este proceso va más allá del alcance de este artículo, pero desde que el método es usado en “desktop.wfm”, alguna explicación estaba en puerta.
Conclusión
No todas las aplicaciones garantizan el tiempo y energía que se invirtio en crear el “Escritorio Fantástico”. de hecho toda su funcionalidad pueden reproducirse con mucho menos rodeo. Pero a veces quieres crear una forma que trabaje exactamente cuando te gustaría que lo hiciera. Desktop es tal forma. No era meramente el resultado final de usar objetos de dBASE de una manera tradicional. En cambio, con un concepto de diseño firme en mente, el poder y flexibilidad de dBASE hizo la creación exactamente lo posible deseado.
Esperanzadamente, el lector tomará de esto algunas ideas para cómo mejorar aplicaciones presentes para el usuario. Los mismos conceptos pueden usarse para crear formas que no se parezcan a esta en nada, pero utilizar la misma forma. Este es el poder de dBASE.
Para descargar la aplicación
del Escrotorio Fantástico, haga clic
aqui
(es un archivo ejecutable
empacado de 60Kb)
Traducción
por : Juan Manuel Espinosa, Desarrollador de Software en México,
D.F.
Administrador de
la Comunidad
de dBASE en Español
puede contactarlo
por e-mail en: juan_espinosa_mx@yahoo.com
ó db2kSistemas@netscape.net