Sei sulla pagina 1di 137

1////137

En memoria de Barry Horne..

Barry Horne fue un activista britnico, vegano de base, firme en la lucha por la defensa de los animales. Horne, nacido en Northhampton, fue condenado en 1997 a lo que se considera la sentencia ms larga contra un activista por la Liberacin Animal -18 aos de prisin- una condena que ni siquiera reciben muchos violadores, narcotraficantes o criminales en serie. Se le acus de daos por 5,8 millones de libras esterlinas en incendios provocados en protesta contra los abusos de animales en experimentos cientficos (cabe destacar que dichos incendios se provocaban nicamente cuando no haba personas que pudieran perecer en el atentado). ..El objetivo de sus huelgas de hambre no era conseguir su propia libertad, sino forzar al Gobierno britnico a poner en marcha una comisin oficial para valorar los abusos cometidos con los animales viviseccionadosEl 60% de los experimentos en el Reino Unido se hace sin ningn tipo de anestesia. Todos los animales mueren como consecuencia de los experimentos o son aniquilados al acabar los experimentos.

2////137

Estimado estudioso o interesado en aprender a programar: la relacin que vamos a tener va a ser muy directa, ms que como profesor y alumn o, como dos amigos interesados en ayudarse, por lo que voy a tutearte, para hacer ms entretenida estas clases o sesiones de aprendizaje. Para empezar la sesin lo primero es lanzar la aplicacin RealBasic. Tanto si se tiene la versin classic o la X el resultado es similar: se abren una serie de ventanas, con distintos nombres. Estas en el IDE (integrated development environment) que es un ambiente de programacin. En este ambiente diseas tu programa, pruebas lo que haces, ves resultados, etc., siempre dentro de la aplicacin RealBasic (RB). Cuando lo que programas has comprobado que funciona y est finalizado, es cuando compilas lo programado, creando una aplicacin independiente que funciona de forma autnoma. Esta aplicacin llevar tu nombre, tu diseo de icono, la versin que hagas, etc. Uno de los mens del RB permite hacer correr lo programado: Debug-Run. Cuando haces un "run", tu programa "corre" dentro del RB, y cuando sales de tu programa ests de nuevo en el RB, en el ambiente de la programacin. Entonces, dentro del RB tienes la zona de programacin, que es el llamado editor, y la posibilidad de verlo correr cuando haces RUN. Cuando abres RB, creas un PROYECTO. Cuando grabas, das nombre al proyecto. Siempre puedes ir a la ventana del proyecto con comando 0. El proyecto siempre incorpora de entrada una ventana llamada "window1" y un men llamado "menubar1". Eso es porque toda aplicacin tiene al menos una ventana, y la mayora tienen mens. En versiones modernas de RB adems de estas dos ventanas aparece otro componente que aparece con el nombre "app". Si haces dobleclick sobre "window1" se abre esta ventana window1, que aparece en primer plano. Detrs est la ventana proyecto. Si cierras esta ventana, y haces luego dobleclick en el elemento window1 del proyecto, se vuelve a abrir. La ventana es un ELEMENTO, con PROPIEDADES (caractersticas que la definen). Las propiedades de la ventana aparecen en una ventana situada a la derecha, encabezada como 'properties'. En esta ventana, que aparece y desaparece con comando-opcin 2, se muestran las propiedades de la ventana, en el caso de que esta ventana est seleccionada. Pero tambin se muestran las propiedades de cualquier otro elemento que luego usemos y est seleccionado. Ya lo veremos ms adelante. Propiedades de la ventana: no hace falta aprenderlas, lo importante es ir conocindolas poco a poco (algunas no las usaras nunca).

3////137

Primera propiedad: 'name' (nombre) es window1. Puedes cambiarlo: toca con el cursor donde pone window1 de la ventana properties, y teclea ventana1 (sin espacios). Si saltas a otro sitio, vers que la ventana tiene ya otro nombre que se refleja en el proyecto. NOTA: los nombres de elementos no permiten espacios ni otros signos. Si quieres escribir como nombre 'Ventana verde, debers usar el guin inferior 'Ventana_verde' Otras propiedades de la ventana son 'width' (anchura) y 'eight ' (altura). Si estiras la ventana con el ratn vers que estos valores cambian. Y si primero cambias estos valores, veras que la ventana se acomoda a los nmeros que escribas. Estos nmeros de width y eight son pixeles de pantalla. Propiedad 'title': untitled. Cambiala escribiendo en la ventana properties lo que quieras, por ejemplo 'Mi Ventana' (como esto no es nombre de elemento, puede tener espacios y smbolos). Bueno, no toques nada ms. Puedes grabar el proyecto y darle nombre. Por ejemplo, 'Proyecto A'. Empecemos por aadir elementos a la 'Ventana1'. Veras que a la izquierda est siempre presente una ventana con un conjunto de elementos que aparecen con iconos relativos a lo que son. La ventana aparece y desaparece con las teclas comando-opcin 1 Estos elementos se aaden a las ventanas, no al proyecto. Comencemos arrastrando un botn a nuestra ventana. El botn (pushbutton) aparece con las letras OK. Arrstralo sobre la ventana1. Aparece un botn seleccionado, con las letras 'untitled' Veras que la ventana properties ha cambiado, pues ahora muestra las propiedades del botn aadido. Si tocas en la ventana y se deselecciona el botn, las propiedades vuelven a ser las de la ventana1. Bueno, este botn vemos que se llama pushbutton1. Cambiemos su nombre por algo ms lgico para nosotros: 'BotonRun' Una propiedad es el 'caption' (encabezado) del botn, que ahora es untitled. Lo vamos a cambiar por 'OK' Resumen, tenemos una ventana con un botn. Y hemos cambiado caractersticas de ambos elementos. Vamos a aadir otro elemento a 'ventanal'. Es este caso, un elemento de texto, denominado 'StaticText'.

4////137

De la ventana de elementos, hay uno que muestra como icono 'Aa'. Arrstralo sobre 'Ventana1' a la posicin que desees. Si est seleccionado, vers en propiedades que se denomina 'StaticText1'. Cambiemos su nombre en 'Name' por otro ms fcil de recordar: 'MiTexto'. En propiedades, aparece bajo el epgrafe 'Appearance' la propiedad 'Text' que es precisamente el texto que muestra este elemento. Por defecto, 'text' es 'Label' pero podemos cambiarlo de dos formas: si el elemento est seleccionado, basta con que tecleemos cualquier texto. La otra forma es ir a la ventana 'properties' y cambiar donde pone 'label' y escribir lo que queramos. Vamos a poner 'HOLA'. Entonces, este elemento muestra como propiedad 'texto' la palabra 'HOLA'. Con el ratn, vamos a desplazar este elemento por la ventana hasta una posicin 20, 30, es decir, left=20 y top=30 En una ventana, la esquina superior izquierda es el punto 0, 0., luego el punto left = 20 equivale a desplazar 20 pixels a la derecha del 0 y el punto top=30 equivale a desplazar hacia abajo 30 pixels. Podemos ver donde estamos desplazando el elemento y examinando la ventana 'properties' mientras desplazamos. Tambin podemos asignar, en la ventana properties, el valor 20 a la propiedad 'left' y el valor 30 a la propiedad 'top'. Pasemos a ver ahora como funciona un programa. Lo primero es saber que los elementos de la ventana no hacen nada por s mismos, es preciso que les demos instrucciones para efectuar algo. Vamos a ello: Hacemos dobleclick sobre el botn de nombre 'BotonRun'. Se nos abre una nueva ventana, que se denomina 'Code Editor' y que corresponde a elementos de la ventana (o a la propia ventana) en la cual hemos hecho dobleclick. Este Editor muestra dos partes: a al izquierda, los elementos de 'Ventana1' y las acciones que pueden realizar esos elementos (Action, Close, GotFocus..) y a la derecha una zona de escritura donde escribir el cdigo que queramos. Bueno, de las diferentes opciones asociadas a 'BotonRun' aparece seleccionada la denominada 'Action' (acccin o actividad) que es justamente el tipo de accin o actividad que har el botn cuando se pulse por el usuario. En el editor, aparece los comandos o trminos del lenguaje Basic 'Sub', que significa inicio de una Subrutina, y 'End Sub', que es el

5////137

final de la Subrutina. As pues, la subrutina 'Action' del BotonRun est vaca de programacin. Pues vamos a escribir algo en esta subrutina. Por ejemplo, nos gustara que al pulsar el 'BotonRun' el texto 'HOLA' que aparece en la ventana de nuestro programa se cambie de posicin, y de estilo. Pues vamos a teclear un cdigo muy simple: Para decirle al elemento 'MiTexto' que se desplace al punto 100, 150, simplemente le asignamos esos valores a sus propiedades, escribiendo debajo de Sub: Ventana1.Mitexto.left=100 Ventana1.Mitexto.top=150 Bueno, pues lo que estamos haciendo es programar lo siguiente: Cuando el usuario pulse el botn 'BotonRun' que aparece con el caption 'OK', el BotonRun realizar la Subrutina 'Action' la cual lleva el cdigo que acabamos de escribir. El cdigo que hemos escrito es fcil de entender: primero, es jerrquico, de mayor a menor. Lo primero que se cita es el nombre de la ventana ('Ventana1'), luego el nombre del elemento al que hacemos referencia ('Mitexto') y por ultimo la propiedad de este ltimo que queremos modificar ('left'). En este cdigo jerrquico, siempre se separan los diferentes elementos (ventana, texto, propiedad, etc.) con un punto. La tercera lnea de programa que escribiremos en la subrutina 'action' es el siguiente: Ventana1.MiTexto.TextSize=18 que quiere decir que el TextSize (tamao texto) del elemento 'MiTexto' de 'Ventana1' pase a ser 18. La subrutina debe quedar as: SUB Action() Ventana1.Mitexto.left=100 Ventana1.Mitexto.top=150 Ventana1.MiTexto.TextSize=18 END SUB Ya est escrito nuestro primer programa. Grabemos para que no se pierda.

6////137

Y ahora vamos a ver si no nos hemos equivocado en la sintaxis, etc,. y ver cmo funciona. Cerremos la ventana editor, y en el Men 'Debug' elegimos Run. Se compila lo programado y vemos el RESULTADO: Se nos abre una ventana en la que aparecen un botn que pone OK y un texto que dice 'HOLA'. Si pulsamos el botn veremos que el texto cambia de posicin y tamao. Es todo. Para finalizar, elegimos en el men REALBASIC el tem Quit. Con eso finaliza nuestro programa y volvemos a entrar en el IDE, en el ambiente de programacin. Bueno, nuestro primer proyecto o programa ha sido muy simple. Vamos a hacer algo nuevo a partir de l. Lo primero, vamos a grabarlo con otro nombre para no perder el 'Proyecto A' original. Vamos a grabarlo como 'Proyecto B' usando el men Save As. Ahora vamos a ir un poco ms rpido, (1) Abrimos 'Ventana1'. Aadimos otro elemento del tipo Botn, y lo colocamos donde nos parezca. Le damos nombre : 'BotonQuit'. En el caption de este botn, escribimos 'FIN', y al hacer doble click sobre l, se nos abre el editor, apareciendo seleccionado el evento 'action' con la Subrutina correspondiente vaca. En esta subrutina escribimos 'quit' quedando as: SUB Action() quit End Sub Quit es un comando de basic y cuya accin es esa, quit, finalizar el programa. (2) Nos vamos al editor, y seleccionamos del evento 'action' y vemos las lneas que ya habamos escrito. Aadimos otra lnea: Ventana1.MiTexto.text = ADIOS Qu significa? No es difcil darse cuenta, que este cdigo le dice a MiTexto de Ventana1 que el texto que debe mostrar es 'ADIOS' OJO: El texto, en programacin, SIEMPRE va entre comillas, es una manera de informar que se trata de texto y no de nmeros o variables. elemento BotonRun el

7////137

(3) Cerramos el editor, seleccionamos con un click el 'BotonRun' y en propiedades marcamos la casilla 'Default'. Ahora este botn estar seleccionado por defecto, es el botn que responder si el usuario pulsa retorno. Grabamos. Vamos a debug y seleccionamos el tem Run. Ahora en la ventana que se abre tenemos 2 botones, uno que dice OK, y aparece seleccionado, otro que dice FIN. Si pulsamos OK o retorno vemos el resultado de lo que programamos. Si pulsamos Fin el programa finaliza y volvemos al IDE. Finalizamos as la primera sesin.

8////137

SESION 2 En esta sesin 2 damos por supuesto que se han entendido y se recuerdan las nociones bsicas realizadas en la Sesin 1. Si este no es el caso, se recomienda volver a leer y practicar de forma lenta y reposada, las actividades realizadas previamente. Es necesario que poco a poco se vayan asimilando cuestiones generales, para poder avanzar en la programacin. As, las cuestiones relativas a dar nombre a los elementos, a cambiar sus propiedades, a entender la sintaxis, a hacer correr el programa, etc. deben estar ya asimiladas. Tambin es recomendable ir guardando una lista de los comando basic que van apareciendo, y desde luego, practicar un ingls elemental o tener a mano un diccionario (el Ultralingua que se encuentra en internet, por ejemplo). Resumiendo: las sesiones cada vez sern menos detalladas en cuanto a cmo dar nombre a una ventana, o cambiar sus dimensiones, etc. De forma que muchos detalles explicados en las primeras sesiones irn desapareciendo ya que se supone que el lector las domina y sabe cmo realizarlas. Lanzamos RealBasic. Comenzamos por darle nombre a la ventana inicial que aparece en el proyecto, cambiando el nombre que aparece por defecto: 'Window1' , por 'Ventana1'. Le damos un tamao a la ventana de 400 de ancho (width) por 200 de alto (height). Aadimos un Pushbutton (botn) a esta ventana. Lo colocamos donde nos plazca y lo denominamos 'BotonQuit'. Como ttulo, ponemos en su propiedad caption 'FIN' Hacemos doble-click sobre el botn y se nos abre el editor, en la SUBRUTINA action. Tecleamos 'quit' que es un comando de basic que debemos recordar, ya que es el cierre de nuestro programa-aplicacin en basic. Aadimos un segundo botn a nuestra 'Ventana1' y le damos como nombre 'Boton1' y como caption escribimos 'Cambio de ventana'. ! A RECORDAR: Las ventanas, los elementos de una ventana, y las variables que veremos ms adelante, no pueden tener en su NOMBRE espacios, smbolos de suma, resta, etc. Pero las CAPTION son texto, y s pueden llevar cualquier tipo de smbolo. Una caption puede ser 'Mi Ventana' pero si queremos llamar as a una ventana o dar ese nombre a

9////137

un elemento debemos usar el guin bajo uniendo las palabras: 'Mi_Ventana'." Nos vamos ahora al Menu File del RealBasic y elegimos 'New window'. Aparece una nueva ventana, cuyo nombre por defecto cambiaremos a 'Ventana2'. Le daremos el mismo tamao 400 x 200 que le dimos a 'Ventana1'. Aadimos a 'Ventana2' un botn al que daremos por nombre 'Boton1', y en cuyo caption pondremos 'Cambio de ventana'. Adems, en la ventana propiedades correspondiente a este botn, ponemos en OFF la propiedad 'enabled' lo que significa que este botn estar inactivo. Para ponerla en OFF punteamos (deseleccionamos) el cuadradito que aparece seleccionado. Si esta propiedad est OFF podemos decir que desde el punto de vista del cdigo basic es equivalente a escribir: Boton1.enabled = false Si est en ON, es equivalente a decir : Boton1.enabled=true (enabled puede traducirse como habilitado)

Tenemos as, dos ventanas, y es la primera la que se usa por defecto, es decir, si el programa 'corre' (Run) , la primera ventana que se abre, la ventana inicial o principal es la que estaba por defecto en el proyecto (aunque esto se puede cambiar si se desea). Una cosa importante: CADA VENTANA ES UN ENTORNO PRIVADO, de forma que los controles (botones, textos, dibujos, etc.) de la 'Ventana1' son propios e independientes de los correspondientes de la 'Ventana2'. De esta forma podemos tener un botn con el mismo nombre en cada ventana sin que se interfieran entre ellos: Ventana1.boton1 Ventana2.boton1 cdigos que hacen referencia a elementos distintos de ventanas distintas. Es importante recordar que los elementos o controles son especficos de ventana.

En la 'Ventana1' hacemos dobleclick sobre el 'Boton1' y se nos abre el editor, en la SUB action. La sub 'action' es un evento, uno de los

10////137

posibles eventos que puede recibir el botn por actividad del ususario. Los posibles eventos se muestran en el editor. Bueno, pues en este evento action tecleamos: SUB action() Ventana2.show END SUB El trmino 'show ' no corresponde a un evento, pues no es una respuesta a la actividad del usuario. Show es un 'mtodo' , es un tipo de accin predeterminada por el RB para el elemento ventana, que fuerza a que la ventana a hacerse visible. Al realizarse este mtodo, la 'Ventana2' se activar y pasa a ser la ventana frontal, la ventana disponible al usuario. Ahora hacemos algo equivalente en el 'Boton1' de la 'Ventana2'. Hacemos dobleclick en el 'Boton1' de la 'Ventana2' y en el editor aparece la SUB action, en la que escribimos: SUB action() Ventana1.show END SUB Lo que estamos 'programando', es que haya un botn en la ventana1 que al pulsarlo se abra y se muestre la ventana2, y en la ventana2 un botn que muestre la ventana1 . As el usuario, al pulsar los botones, cambia la ventana activa. Nos falta hacer algo : recordemos que el 'Ventana2.Boton1' estaba inactivado de inicio (enabled=false) por lo tanto debemos activarlo para que el usuario pueda pulsarlo. Hay varias formas de hacerlo, y entre ellas vamos a usar un evento de la propia ventana a la que pertenece este botn. Este evento es la apertura de la ventana, el evento denominado 'Open', que es el proceso de mostrarse la ventana (este evento puede ocurrir por actividad del usuario o mediante cdigo). Si hacemos dobleclick sobre alguna parte de 'Ventana2' se abre el editor, y aparece justamente la SUB open. Escribimos SUB OPEN() Ventana2.boton1.enabled=true END SUB y cerramos el editor. Con este cdigo estamos modificando la propiedad 'enabled' del 'Boton1' de la 'Ventana2' y haciendo que el botn est disponible por el usuario. Como puede notarse, el evento se dispara cuando la propia ventana2 se abre.

11////137

Bueno, pues parece que est todo dispuesto para hacer 'correr' al programa que hemos escrito. Primero lo grabamos con el nombre que nos parezca, para que si hay algn error gordo, no perdamos el trabajo realizado. Ahora vamos al Menu 'Debug y seleccionamos 'Run'. Se nos aparece la ventana inicial, y si pulsamos el botn 'Cambiar de ventana' se nos aparece de la nada la segunda ventana, que queda en primer plano, etc. Bueno, pues ya empezamos a ver como funcionan las ventanas y sus elementos, y vemos que preparar este tipo de interaccin del usuario con botones y acciones, es relativamente fcil, y bastante intuitivo. Finalizamos nuestro programa con comando+q, o pulsando el boton 'Fin' de 'Ventana1' Un problema que observamos en nuestro programa es que las dos ventanas se superponen en pantalla, lo que es bastante molesto, pues no podemos ver lo que contiene cada una de forma simultnea. Vamos a solucionarlo, modificando ligeramente el cdigo: En la SUB open de 'Ventana2' vamos a aadir una lnea de cdigo debajo de la previamente escrita: (recordemos: cada instruccin o cdigo debe ir en una lnea diferente). SUB Open() Ventana2.top=300 END Sub Que es decirle a 'Ventana2' que su propiedad 'top' (posicin en altura) sea 300 pxeles contando desde la lnea de pantalla superior. Si ahora hacemos un run, vemos que las dos ventanas ocupan espacios distintos y no solapan. Finalizamos pulsando el botn 'Fin' de 'Ventana1'. Por ltimo, vamos a examinar otro 'evento' que es tpico de ventanas y otros elementos. Hacemos doble click sobre el 'BotonQuit' (Fin) de 'Ventana1'. Se abre el editor en la SUB action. Pero nosotros seleccionamos la SUB MouseEnter que corresponde a la actividad del usuario en la cual el cursor del ratn entra o pasa por encima del propio botn. Escribimos: SUB MouseEnter() Beep End Sub

12////137

Beep es otro comando basic que conviene recordar, y que simplemente hace sonar, por una sola vez, el sonido que est activo en nuestro ordenador. Cerramos el editor. Hacemos run. Cuando movemos el ratn y pasamos por encima del botn FIN se oye el sonido una sola vez. Este evento es muy simple, y puede aplicarse a otros elementos. Finalmente, y como otro tipo de evento que muestra la relacin usuario-programa, vamos a aadir un nuevo elemento a 'Ventana1'. Con comando + opcin + 1, abrimos la ventana de controles de RealBasic. Arrastramos sobre 'Ventana1' un elemento que aparece con forma de ovalo. En la ventana propiedades, vemos que se denomina 'Oval1'. Cambiemos su nombre, llamndolo 'Ovalo'. Entre las propiedades de este elemento hay una llamada 'FillColor'. Tocamos sobre esta propiedad y se nos abre una ventana para elegir un color. Elegimos el que nos parezca. Nos vamos a nuestra 'Ventana2' al 'Boton1', y hacemos dobleclick sobre l. En el editor que se nos abre, buscamos la SUB 'MouseEnter, y aadimos una lnea de cdigo: Sub MouseEnter() Ventana1.Ovalo.visible=false End sub Que simplemente dice que el ovalo se hace invisible cuando el ratn dirigido por el usuario entra en la zona que ocupa el botn. Sin cerrar el editor, buscamos el evento o SUB con el nombre 'MouseExit' que como su nombre indica, es el evento relacionado con el momento en que el cursor del ratn abandona la posicin o rea ocupada por el ratn. Este evento est prximo a MouseEnter. En esta SUB MouseExit tecleamos el cdigo: Sub MouseExit() Ventana1.Ovalo.visible=true End sub Ya podemos grabar y hacer Run para ver si todo funciona bien y como esperamos. Observamos como la actividad del usuario dispara acciones en una u otra ventana.

13////137

Hasta ahora hemos visto las propiedades de algunos elementos (botones, ventanas) mediante la ventana propiedades que se muestra/oculta con la combinacin de teclas comando +opcin+2 Pero hay otras propiedades que no se muestran ah, pero que pueden consultarse invocando la Ayuda de RealBasic, mediante la combinacin comando+1 Cuando se abre la ayuda, aparecen un listado de elementos a la izquierda que puede ser por temas o alfabticamente. Si en la parte superior tecleamos 'windowclass' y pulsamos el botn 'search' aparecen un listado de propiedades asociadas a cualquier ventana ( backcolor, backdrop .height. title.zoomicon), de mtodos (AcceptFileDropshowupdateNow) y de eventos (Activate.MouseEnter.resized) . No es preciso conocer como funcionan estas Mtodos y Eventos, ni para que sirven todas las Propiedades de una ventana. Lo importante es saber que cada elemento tiene sus Propiedades, Mtodos y Eventos, y que cuando precisamos alguna caracterstica, podemos CONSULTAR esta ayuda y examinar para que vale y qu hace cada Mtodo y Evento. Algunos Eventos ya los conocemos (MouseEnter) y tambin hemos visto algn mtodo (show). Poco a poco se van aprendiendo segn las necesidades de programacin. En resumen: NO ES NECESARIO aprender primero y luego programar, ya que somos aficionados y no profesionales, y lo que queremos es divertirnos y no estar sufriendo a base de aprender pginas y pginas de comandos, etc. Otro detalle que hemos visto: cuando escribimos cdigo, al teclear el nombre de un elemento existente o de una propiedad del mismo, el RealBasic nos ofrece la posibilidad de aceptar la palabra correcta, mostrando en gris el texto correcto que nos falta por teclear. As, si tenemos una ventana llamada 'MiVentana' y empezamos a teclear 'MiV' el RealBasic nos presenta la opcin de escribir el nombre completo. Para ello, cuando intenta adivinar pulsamos la tecla Tabulador para ver las opciones que interesan. (Lo que pretendo decir, es ms fcil de examinar que de explicar). Es una ayuda bastante til.

Otra caracterstica que hemos visto, o podemos encontrar: Si cometemos un error al teclear el cdigo, cuando hacemos Run el RealBasic detecta el error, se detiene en el punto errneo y muestra algn tipo de mensaje relativo al error cometido.

14////137

Por ejemplo, si en lugar de ventana.Show se teclea por errror Ventana.sohw, el RealBasic se detiene cuando hacemos run y nos muestra un mensaje diciendo que hay una variable desconocida. Se dice que el editor ha entrado en fase de depuracin (Debug) de errores.

15////137

Esta sesin es bastante terica, por lo que conviene leerla con atencin, y si no queda clara, leerla ms de una, y ms de dos veces. Y si incluso as quedan dudas, lo mejor es releerla, ...................... y en ultimo caso comprarse un libro de RealBasic. El autor ha aprendido a programar de forma autnoma, sin direccin ni gua, simplemente batallando a lo de muchos aos con distintas formas de basic y pascal, y quizs no sepa transmitir de forma clara lo que es un programa, cmo se estructura y cules son los elementos ms importantes para el que se inicia. Pero hay que pensar que lo que se explica a continuacin, est muy condensado, y equivale a varios captulos de un libro escrito por un experto en Basic y en Realbasic. BASIC El Basic es un lenguaje de programacin muy antiguo, que utiliza sintaxis simple y fcil de recordar del idioma ingls. Es un lenguaje de alto nivel, en el sentido de que cada instruccin encierra un conjunto de instrucciones ms simples de un lenguaje de nivel inferior, ms bsico, ms cercano a las instrucciones de mquina. El RealBasic es sin embargo un lenguaje moderno, orientado a objetos (ventanas, botones, ratn, teclado, imgenes, etc.), pero que sigue utilizando comandos o sintaxis del basic clsico. Es importante que el usuario nuevo en RealBasic, aprenda el basic clsico, o al menos, que tenga un libro bsico en el que se expliquen los diferentes comandos del basic. La ayuda online del RealBasic (comando+1) explica el uso del Basic y muestra ejemplos de su utilizacin, por lo que conviene acudir a la misma cada vez que se precise. Sugiero que cada comando del basic que aparezca en estas sesiones se apunte en una hoja para recordarlo. Por ejemplo, Quit, Beep SUBRUTINAS Hemos hablado en sesiones anteriores de SUBRUTINAS. Una subrutina, o simplemente una Sub, es un grupo de instrucciones que pueden realizar una o muchas acciones. Una SUB es como una isla, esta aislada del resto de SUBs , realiza una accin pero no tiene por qu afectar a otra Sub. Las Subrutinas son tambin llamadas Mtodos. O a la inversa, un Mtodo es una Sub. Un programa en RealBasic es en esencia un conjunto de Mtodos o subrutinas que ocurren una tras otra completando un circuito. Siempre hay como una carretera que marca el orden en que ocurren los mtodos: primero se abre una ventana, esta

16////137

ventana muestra unos botones, un botn nos lleva a otra ventana a ejecutar una subrutina que cuando finalice nos devuelve al punto de partida, etc., etc. Una caracterstica muy til de las Subs. es que sus variables son privadas, son especficas de la SUB en cuestin. De esta forma, el programador no tiene que estar obsesionado con los nombres que asigna a variables de una SUB, porque no salen de ah. Podemos tener una variable llamada Total en 3 o mas SUBs sin problema alguno, sin que se interfieran las Subrutinas entre s. Igual que ocurre con los elementos de una ventana, que como ya hemos dicho, son especficos de ventana. De esta forma una ventana es un entorno cerrado, al igual que una SUB. Tipos de Datos o Variables Hasta ahora hemos visto algunas Propiedades de ventanas, de pusbuttons, etc. Es muy importante saber que estas propiedades son y se denominan VARIABLES, y que existen diferentes tipos de Variables o Datos. Las variables ms importantes para iniciarse en la programacin son: Las de tipo texto que se denominan STRING Las de tipo numrico que pueden ser

o Nmeros enteros, y se denominan INTEGER o Nmeros reales (con decimales) y se denominan DOUBLE (o SINGLE) Las de tipo verdadero o falso, que se denominan BOOLEAN

EJEMPLOS: (a) Si escribimos Ventana.Left= 200 La propiedad o variable Left es un nmero entero, un INTEGER Por lgica, si la pantalla consta de pxeles y Left indica el nmero de pxeles hacia la izquierda en donde se coloca la ventana, el valor de Left no puede ser 200,35 ya que no existen 0.35 pxeles. As pues, es lgico que Left sea un entero (integer). Las variables numricas (Integer , Single y Double) admiten manipulaciones propias de nmeros: suma, resta, divisin, etc. Tambin es lgico darse cuenta que si necesitamos el resultado de una divisin entre dos nmeros, este resultado debiera asignarse a una variable numrica tipo DOUBLE ya que nos gustar ver los decimales resultantes de la divisin, los cuales no podremos ver si asignamos tipo integer al resultado de la divisin. Por la misma razn, el valor de pi (3.14169) debe estar en una variable DOUBLE (significa doble precisin). 17////137

(b) Si queremos que el Titulo de una ventana sea Mi Ventana y sabemos que este ttulo se debe teclear en la propiedad caption de la ventana, el valor de caption es precisamente el conjunto de letras que configuran la frase Mi Ventana Pero Mi Ventana es un texto , es un STRING, no es un nmero evidentemente. Y los strings tienen caractersticas y admiten manipulaciones distintas a los nmeros. IMPORTANTE: Los textos o strings SIEMPRE se delimitan con comillas dobles: Ventana.caption= Mi Ventana es la forma correcta de asignar el valor Mi Ventana a la variable tipo string Caption. (c) Cuando escribimos Boton.Visible=false , Ventana.enabled=true Estamos usando un tipo de dato BOOLEAN (booleano, del lgebra de Boole) cuyas alternativas ms simples son True (verdadero) y False (falso). Variables de usuario En la programacin no solo se precisan las variables propias de un elemento (propiedades) sino que se necesitan variables definidas por el programador para realizar determinadas acciones que son la finalidad de su programa. Las variables propias de elementos del RealBasic se denominan propiedades, luego una propiedad es en realidad una variable. Cuando se precisa una variable propia o de usuario (que no pertenezca a las ventanas o a sus elementos) es preciso definirla o dimensionarla (es lo mismo). Esto se logra con la palabra de basic DIM (de dimensionar) [RECORDAR] Definir una variable es simplemente decir que existe, dndole nombre y un tipo determinado (integer, boolean, etc,). En una SUB, las definiciones SIEMPRE van AL PRINCIPIO, en las primeras lneas. Esto debe ser as, porque las instrucciones de una SUB se leen o ejecutan desde arriba hasta abajo, de una en una, y naturalmente, antes de usar una variable es preciso decir que existe, que se llama Zutano, y es de tipo Fulano. IMPORTANTE: Las variables, al dimensionarlas, tiene por defecto determinados valores: si es numrica , por defecto vale cero 0

18////137

si es string es un texto vaco, sin ningn carcter, ni siquiera espacios, es decir si es booleana, por defecto es false Como una SUB es un mtodo aislado, privado, se deduce que si se ejecuta una SUB y a una variable numrica se le asigna el valor 47, cuando salimos de esta SUB la variable se pone a cero, y si volvemos a entrar en la misma SUB el valor inicial de esta variable es 0. Es decir, los valores de las variables de una SUB empiezan con los valores de defecto y terminan con esos mismos valores. La informacin no se guarda. Que ocurre si necesitamos una variable (informacin a fin de cuentas) para que sea usada simultneamente por la ventana y por varios de sus elementos? O empleada por varias SUBs a la vez? En este caso, definimos la variable de usuario como una propiedad GENERAL de la ventana (o incluso de todo el proyecto). Supongamos que necesitamos una variable comn para todos los elementos y SUBs de una ventana: entonces la definimos usando, del men Edit del RealBasic, el item New Property. Al invocarlo, se abre una ventana en la que ponemos el nombre de la variable y el tipo que le asignamos. Vamos a verlo en el ejemplo que sigue. Lanzamos el RealBasic (RB) En la ventana inicial window1 aadimos un elemento EditField, que aparece en la ventana de elementos como un rectngulo blanco con una barra vertical negra. Como al aadir un elemento en una ventana podemos ver su nombre inicial en la ventana properties, si no es lo que deseamos (un EditField) simplemente lo seleccionamos y borramos usando la tecla borrar del teclado.. Bueno, pues ahora aadimos un segundo editfield y lo colocamos debajo del primero. Tenemos as, el EditField1 y el EditField2. Aadimos un StaticText y le damos una anchura de 300 y una altura de 46. Finalmente, aadimos dos PushButtons, a los que ponemos, en su propiedad text, los valores o textos Concatenar y Finalizar Nos vamos al editor del botn Finalizar y en la SUB action escribimos: quit para poder finalizar el programa. Vamos ahora a la SUB action del botn Concatenar y escribimos el cdigo: 19////137

SUB Action() Dim palabra1 as string

20////137

Dim palabra2 as string Dim frase as string palabra1 = window1.editField1.text palabra2 = window1.editField2.text frase = frase + palabra1 + palabra2 window1.statictext1.text = frase END Sub Vamos a analizar el significado de estas expresiones o sintaxis de basic. Dim es un comando Basic para inicializar, definir o dimensionar una variable. En nuestro caso, la1 variable la definimos con el nombre palabra1 y tipo string (texto), e igual para la variable palabra2 y la variable frase. El smbolo igual = permite asignar un valor a la variable que aparece a la izquierda, de forma que si se escribe ab = 23, estamos dando el valor 23 a la variable ab. Si la variable ab vale 23, la asignacin ab = ab + 3 hace que el NUEVO valor de ab sea el que tena + 3 , es decir, ahora vale 26. Este es un tipo de sintaxis que a los principiantes les cuesta aprender, parece poco lgica, pero es totalmente usual en basic. Repetimos de nuevo: la variable a la izquierda del smbolo de igualdad = toma el valor correspondiente a lo que se expresa a la derecha del smbolo de igualdad. Si decimos ab = ab /2 estamos diciendo que el nuevo valor de ab es el que tena dividido por 2. Si decimos frase = frase + palabra1 estamos diciendo que la variable tipo string frase es desde ese momento igual a lo que originalmente era frase + lo que contiene palabra1. Las variables, al iniciarse, valen 0, si son numricas, y estn vacas si son de texto. Bueno, pues nuestra 4 lnea de cdigo ASIGNA a la variable palabra1 que es tipo string, el contenido de tipo string que tiene el elemento EditField1 en su propiedad text Si el usuario ha tecleado algo, un texto, en el EditField1, este texto estar en la propiedad text del editfield. Entonces, la asignacin hace que este texto tecleado lo tome la variable palabra1 La lnea 5 hace que la variable palabra2 tome el mismo texto que tiene el editfield2, sea un texto vaco, sea un texto tecleado por el usuario.

21////137

NOTA: Los valores de Window1.EditField1.Text y Window1.EditField2.text no se pierden por el hecho de que hagamos una asignacin de su contenido a otras variables. La lnea 6 de nuestro cdigo hace que frase sea igual a lo que contena frase + lo que contiene palabra1 + lo que contiene palabra2. Pero la variable frase es privada, y eso quiere decir que inicialmente su contenido por defecto es un texto vaco, es decir, nada. Por lo tanto, y a efectos prcticos, frase ser igual a la adicin de lo que contengan palabra1 y palabra2. La ultima lnea de cdigo lo que hace es asignar a la propiedad text del elemento window1.statictext1 lo que se indica a la derecha del smbolo igual, es decir, el contenido o texto de frase. [La adicin de varios textos se denomina concatenacin.] Entonces en Statictext1.text tendremos unidos los textos originalmente tecleados por el usuario en los dos EditFied. Probemos si funciona: del men Debug elegimos Run. Aparece la window1 con dos editfields vacos y un statictext que reza label. Tecleamos tengo en el primer editfield y hambre en el segundo. Pulsamos el botn concatenar y el resultado de nuestro cdigo se muestra en el statictext. Aparece el texto tengohambre. Podemos cambiar los textos de los editfields y ver el resultado de la concatenacin cuantas veces queramos. RECORDEMOS: cada vez que pulsamos el botn concatenar iniciamos la SUB action de este botn, por lo que sus 3 variables privadas (palabra1, palabra2, frase) estn vacas. Finalizamos pulsando el botn Finalizar que sabemos que equivale a quit. Vamos a modificar ligeramente el cdigo anterior: Cambiemos la ultima lnea de la SUB action del botn Concatenar as: window1.statictext1.text = palabra1 + + palabra2 Ahora se concatenan 3 elementos, el texto de palabra1, un texto fijo escrito por nosotros (por lo tanto entrecomillado) que es simplemente un espacio, y el texto de palabra2. Al hacer Run y escribir lo mismo que antes, el resultado que aparece es Tengo hambre.

22////137

Finalizamos el programa. Una cosa que podemos observar es que cada vez que pulsamos el botn Concatenar, se nos muestra la unin de los textos ACTUALES del los dos editfields. El contenido previo de las variables palabra1 y palabra2 se pierde. Esto es lo normal, ya que como se dijo, al pasar por una Sub las variables empiezan vacas por defecto, no guardan informacin previa. Y cada vez que pulsamos Concatenar le decimos al RealBasic que se dirija a la Sub action de este pushbutton. Pero quizs nos interese no perder esta informacin previa. Si este es el caso, necesitamos una variable general de ventana, que no dependa de una Sub determinada, que sea accesible a cualquier sub de la ventana y a cualquier elemento. Vamos a definir una variable GENERAL de ventana, Abrimos el editor de Window1 y nos dirigimos al men Edit del RB, eligiendo el tem New Property. (este tem esta inactivo a menos que se abra el editor). En la ventana que aparece tecleamos frase as string (eliminamos la opcin 'private' suponiendo que est seleccionada) y confirmamos con el botn OK . Hemos creado o dimensionado una propiedad GENERAL DE VENTANA, propiedad que aparece en el apartado propiedades (properties) del editor y que podemos examinar, y editar, haciendo dobleclick sobre ella. (Esta modalidad de dimensionar una variable global de ventana no precisa aadir DIM delante del nombre). Como la variable frase est ahora definida como general, tenemos que eliminar la definicin de frase que est en la SUB action del botn concatenar Cambiemos el cdigo de la Sub action de Concatenar eliminando la lnea 3 que deca Dim frase as string NOTA : si una variable definida como general tiene el mismo nombre que una variable definida en el interior de una Sub (privada, por tanto) , en la Sub se usa la privada, en el resto de Subrutinas de la ventana se usa la general. Bueno, vamos a ver el efecto que tiene declarar frase como variable general

23////137

Ahora, el cdigo frase= frase + palabra1 + palabra2 concatena (une) lo que originalmente tena en su contenido la variable frase + el nuevo texto tecleado por el usuario en los dos editfield. La primera vez que pulsemos concatenar la variable frase est vaca, pero en la segunda ocasin, como su valor no es nulo, al texto anterior se une el texto nuevo de los editField. Y cada vez que pulsemos el botn Concatenar la longitud de frase ser mayor, e ir creciendo hasta que finalicemos el programa. Hagamos run y probemos con distintas palabras o letras. Finalicemos el programa. _________________________________________________ Un pequeo problema: el texto, al crecer, desborda el tamao asignado al elemento window1.Statictext y no lo podemos leer entero. Para solucionarlo: seleccionamos el elemento StaticText y entre sus propiedades vemos una que dice multiline. La seleccionamos. Esta propiedad permite que un texto aparezca en varias lneas.

24////137

En esta sesin vamos a practicar procedimientos utilizados en las sesiones previas, amn de algunas variantes interesantes propias del basic. Hagamos un pequeo programa. Queremos que unas cuantas personas (de 3 a 8 por ejemplo) introduzcan a travs del programa su nombre de pila y su edad. Y que el programa registre y guarde los nombres a la vez que hace un promedio de la edad de las personas que han accedido al programa. Lo primero, es pensar qu es lo que deseamos, y tener las ideas claras de como llevarlo a cabo. Para esto ltimo hay muchas formas, ya que el Basic admite llegar a lo mismo por caminos muy diferentes. Como nosotros todava sabemos muy poco, vamos a usar un mtodo simple. ================================================ Necesitamos: -

un campo donde el usuario teclee su nombre un campo donde teclee su edad un mtodo para tomar la informacin introducida en los campos, y almacenarla. un mtodo que haga el calculo de la edad promedio de las entradas, lo que implica ! sumar todas las edades que se introducen (suma de edades) ! saber cuantas edades se han introducido (numero de entradas) un botn asociado a la recogida de datos y realizacin de los mtodos un botn de salida o finalizacin del programa

Este sera el esquema inicial de trabajo. Y hacer este esquema es necesario cuando se pretende programar, de hecho, es una parte importante de la programacin, en ocasiones la ms importante. Parece evidente que necesitamos hacer un ciclo, el cual podr repetirse un nmero determinado o indeterminado de veces. Este ciclo bsico comprender la entrada de datos por el usuario, entrada que implica teclear nombre y edad, y entonces confirmar que ha finalizado. En este ciclo hay una rutina que se repetir varias veces: una vez un usuario teclee nombre y edad, y confirme la entrada, un mtodo tomar el nombre, y edad introducidos. Las variables para hacer esto no necesitan ser muy generales, pueden ponerse a cero en cada ciclo o entrada de datos, es decir, sern variables privadas de la SUB. Otra rutina del ciclo, que tambin se repetir, deber sumar las edades, guardar esta informacin para hacer el promedio, y guardar los nombre propios, por lo que deber mantener su informacin de un ciclo a otro, de una entrada a otra. Las variables no deben ponerse a cero, ya que se perdera las entradas de los usuarios, es decir, sern variables generales del ciclo o ventana. Veamos qu tipo de variables necesitamos: 25////137

El texto que se teclea es SIEMPRE un tipo de dato STRING Bueno, pues queremos que: el nombre de la persona que aparece en el EditField se guarde en una variable tipo String a la que queremos llamar 'nombre'. la edad se guarde en una variable numrica a la que llamaremos 'edad' . Como la edad es un nmero sin decimales, un entero, la asignaremos a una variable tipo INTEGER. el total de entradas lo guardaremos en una variable llamada 'total_entradas' que ser tipo INTEGER y de tipo general o compartido (no privado) la suma de las edades que se introducen lo guardaremos en 'Suma_Edades', que ser tipo INTEGER y de tipo general. el promedio de edades ser numrico pero llevar decimales, por lo que lo asociaremos a una variable DOUBLE a la que llamaremos 'promedio'. los nombres propios de cada usuario se guardarn en una variable general, de tipo STRING a la que llamaremos 'lista'. Necesitamos por lo tanto 6 variables definidas por el usuario. Las variables privadas de una SUB se definen o dimensionan en la misma SUB , y la sintaxis es: Dim nombre as string Dim edad as integer Las variables generales de ventana o globales de todo el proyecto se definen como se vio en la sesin anterior, con el tem New Property del men Edit del RB.

Bueno, pues vamos a empezar el programa. Lanzamos RealBasic. Se abre un proyecto con una ventana inicial window1. Empezaremos por crear las variables globales de ventana. Para ello, primero hacemos dobleclick sobre la ventana inicial Window1 y se abre el editor. Del men Edit del RealBasic elegimos New Property, y en la ventana que aparece tecleamos total_entradas as integer (eliminamos la opcin private suponiendo que est seleccionada) y confirmamos con el botn OK . Hemos creado o dimensionado una propiedad GLOBAL DE VENTANA que aparece en el apartado propiedades (properties) del editor y que podemos examinar, y editar, haciendo dobleclick sobre ella. (Esta modalidad de dimensionar una variable global de ventana no precisa aadir DIM delante del nombre).

26////137

Repetimos creando una New Property que ser: suma_edades as integer (eliminamos la opcin private) y confirmamos con OK. y otra que ser lista as string y confirmamos con OK Si examinamos la ventana editor, aparecen en properties las tres variables que hemos creado. Cerramos el editor. Sobre la ventana inicial Window1 aadimos, desde la ventana de controles, dos EditField (el icono de editfield aparece como un rectngulo en blanco con una lnea vertical negra). A uno le damos de nombre 'NombreEd' y al otro 'EdadEd'. A 'NombreEd' le damos en la ventana propiedades los valores 150 para left y 20 para top, y a EdadEd 150 para left y 50 para top. A la izquierda de 'NombreEd' aadimos un elemento StaticText al que ponemos por text 'Nombre propio ='. A la izquierda de EdadEd aadimos otro StaticText al que ponemos por text 'Aos ='. Aadimos otros 2 elementos statictext que colocamos en la parte inferior de la ventana. A uno le llamamos 'UsuariosSt' y le damos una anchura de 300 y una altura de 60. El 'text' puede ser varios guiones seguidos. Activamos la propiedad 'multiline'. Al segundo le llamamos 'PromedioEdadSt' y de 'text' ponemos un cero. A la izquierda de 'UsuariosSt' aadimos un nuevo StaticText cuyo text sea 'Nombres de usuarios ='. Y a la izquierda del PromedioEdadSt aadimos otro StaticText cuyo text diga 'Promedio de edades ='. Aadimos un pushbutton al que no hace falta cambiar de nombre pero al que pondremos como caption 'Aceptar' y otro pushbutton al que ponemos de caption 'Finalizar'. Hacemos doble click sobre el botn con texto 'Finalizar' y en el editor, en action escribimos Quit. 27////137

Hacemos ahora dobleclick sobre el botn con texto 'Aceptar' y aparece la SUB action asociada a este botn. Aqu es donde vamos a poner un cdigo nuevo. Escribimos SUB action() Dim nombre as string Dim edad as integer Dim promedio as double nombre = nombreEd.text rem el texto del editfield lo asignamos a la rem variable nombre edad = val(Window1.EdadEd.text) rem texto del editfield se asigna a rem variable edad suma_edades= suma_edades + edad rem sumamos la nueva edad a la rem suma de anteriores edades total_entradas=total_entradas + 1 rem total de entradas aumenta una unidad promedio=suma_edades/total_entradas rem se calcula el promedio lista = lista + nombre rem se unen los nombres propios introduci-rem por cada usuario window1.usuariosSt.text = lista rem ponemos la lista de nombres en rem el elemento StaticText window1. promedioEdadSt.text = str(promedio) END SUB (NOTA: puedes copiar el cdigo anterior y pegarlo en la sub correspondiente, pero no copies ni la primera ni la ultima lnea) Vamos a estudiar en detalle aspectos nuevos que aparecen en estas ltimas lneas. REM es una palabra BASIC que permite aadir comentarios del programador. El texto a la derecha de REM y en la misma lnea, no se lee por el Basic, no significa nada, no se interpreta. Es una buena costumbre aadir comentarios al programar, para recordar lo que se pretende, y para entenderlo si ms adelante volvemos al mismo cdigo. El smbolo igual = permite asignar a la variable que aparece a su izquierda, el valor resultante de la expresin que aparece a su derecha. Es por tanto un comando basic. Las variables, al iniciarse, valen 0, si son numricas, y estn vacas si son de texto. Entonces el valor inicial de TODAS nuestras variables es cero o vacas. Si en un momento queremos poner a cero una variable numrica (ab) , nuestro cdigo debe asignar : ab = 0

28////137

Y si es una variable de texto (palabra) ponerla a cero o vaciarla de texto se escribe como palabra = "" Bueno, seguimos con la SUB: La linea 4 asigna a la variable nombre el texto introducido por el usuario en el EditField correspondiente a la entrada de su nombre propio. La linea 5 asigna a la variable edad el VALOR NUMRICO del texto introducido por el usuario. Como la variable edad es numrica, no podemos asignarle un texto. Necesitamos convertir el texto (string) a nmero (Integer). Para ello se usa un comando basic, VAL, cuya sintaxis es: numero = val (string) ejemplo: El val(16) es un nmero que vale 16 Hay un comando basic llamado STR que hace lo contrario: transforma un texto en nmero: string = str (nmero) ejemplo : si una variable string llamada 'sumatorio' lleva el texto "342" entonces el STR(sumatorio) es un texto con los caracteres 346 Este comando se usa en la ltima linea de cdigo, para colocar el valor numrico promedio en la propiedad text de un staticText.

Hacemos RUN y exploramos el programa. Por ejemplo, tecleamos Pedro y 24 y pulsamos el botn 'Aceptar' Etc., etc.

Un problema poco importante: cuando se unen los nombre de dos usuarios, en la lista ambos nombre aparecen sin espacio separador. ! Tarea 1 Modifique Vd. mismo el programa para que cada nombre quede separado del anterior por un guin. 29////137

! Tarea 2 Aada Vd un staticText en la parte superior de window1 que indique al usuario lo que debe hacer: teclear nombre, teclear edad, pulsar botn 'aceptar' (es decir, instrucciones para el usuario). ! Tarea 3 Para saber el nmero de usuarios que han introducido datos, aada Vd uno o dos StaticText que reflejen el numero de usuarios que ya han introducido datos.

Soluciones Si no ha sido capaz de realizar las 3 tareas anteriores, lea las posibles soluciones que se le ofrecen a continuacin: (1) Una solucin es modificar la sentencialista = lista + nombre

y cambiarla por esta: lista = lista + nombre + "-" que aade un carcter guin (como es texto, siempre entrecomillado) al final del nombre aadido a la variable 'lista' (2) Se trata simplemente de desplazar todos los elementos de la ventana inicial hacia abajo, dejando sitio para aadir un StaticText al cual le pondremos en la propiedad 'text' las instrucciones que nos parezcan oportunas. Por ejemplo: Introduzca nombre propio y edad en los campos apropiados y confirme pulsando el botn que dice "Aceptar". (3) Dos StaticText nuevos uno junto a otro en la misma horizontal. El de la izqda. en su 'text' que diga "N usuarios introducidos=" . El de la derecha ser ms estrecho y llevar como 'text' inicial un cero, y por nombre "NumeroUsuariosSt'. Nos falta aadir una linea de cdigo que refleje en este statictext el valor de la variable general 'total_entradas' que es donde guardamos el nmero de usuarios que han pulsado el botn 'aceptar' NumeroUsuariosSt.text = str(total_entradas) Esta lnea la aadimos a la SUB action del botn 'Aceptar' . Es importante la posicin en la que se aade: tiene que ir posterior a la lnea de cdigo total_entradas=total_entradas + 1

30////137

para que la variable refleje el nmero correcto de usuarios que han introducido datos.

Finalizamos con un resumen de comandos Basic examinados hasta esta sesin: Quit Beep Rem = Dim + Val Str

NOTA: RealBasic no acepta comillas tipogrficas, de forma que si se escribe en un procesador de texto debe tenerse cuidado de no usarlas al hacer 'copy' y 'paste'.

31////137

Cuando se hace referencia a elementos de una ventana desde esa misma ventana o desde elementos que pertenecen a la misma, no es necesario incluir el nombre de la ventana. Por ejemplo, en 'window1' tenemos un 'editfield1' y un 'pushbutton1' Si queremos aadir un texto ("Hola") a este editfield desde la SUB action de 'pushbutton1' usualmente escribimos: window1.editfield1.text = "Hola" Pero como ambos elementos, editfield1 y pushbutton1 pertenecen a la MISMA ventana, podemos escribir igualmente: editfield1.text = "Hola" es decir, una ventana es un entorno cerrado, con sus elementos, propiedades, mtodos, etc., y si no se hace referencia al nombre de la ventana se entiende que la llamada es a un elemento de ella. Otra cuestin diferente es que se llame a un elemento de una ventana diferente; en este caso s sera necesario incluir el nombre completo del elemento: window2.editfield1.text ....etc.

Otra cuestin que ahorra un poco de trabajo a la hora de escribir cdigo: al dimensionar variables de usuario, si hay variables del mismo tipo, podemos agruparlas en una misma lnea de cdigo: Dim a, valor, numero, suma, total, calor as integer Dim texto, s, letra as string Esta forma de dimensionar ahorra espacio, pues en una sola lnea estn dimensionadas todas las variables de un mismo tipo. La sintaxis es como se muestra: cada variable se separa de la anterior con una coma. Siempre hay que tener cuidado con la sintaxis, pues escribir algo mal genera un cdigo de error del IDE del RB bajo la forma de un mensaje al lado de la lnea de cdigo errnea. Puede ser que se utilice una variable string para un dato numrico, puede ser que no se haya dimensionado una variable, o puede ser un simple error de sintaxis. Por ejemplo: Dim a, b, c, as integer generar un error, pues la coma despus de la variable c no debiera estar, ya que la coma es un separador de elementos en la definicin de DIM. OJO: Un problema para espaoles, es que la coma NO ES el separador decimal, el separador decimal es el punto. Incluso si en preferencias del sistema se estipula que el punto es el separador decimal, a nivel de los diferentes lenguajes de programacin, incluido el Basic, el punto es el separador decimal. Ojo con posibles errores.

32////137

A veces el mensaje de error no se entiende, uno no sabe a que se refiere, pero la experiencia de aos es que aunque el programador no vea el error y el enfado lleve a proferir todo tipo de insultos contras el maldito programa en basic, y se sospecha de que estar corrompido, endemoniado, o posedo, la realidad es que el error suele estar ante nuestras narices y no lo vemos. Como ancdota, recuerdo un programa que hice para mi uso personal, de estadstica, que despus de una semana de trabajo cometa algn tipo de error que yo era incapaz de descubrir. Pas horas y horas, y das, maldiciendo, repasando paso a paso el cdigo.... sin suerte. Desesperado, pens en un fallo del basic... hasta que le di un listado a un compaero, suplicandole que me buscase el error. A pesar de no haberlo escrito l, mi amigo lo descubri en unos 5 minutos: haba una variable numrica llamada O (letra o mayscula) y en un punto del cdigo, al querer poner a cero una variable, escrib: dato = O. Repasando el cdigo, yo siempre que pasaba por este listado lo que lea era siempre lo mismo: dato = 0 (cero). Claro, yo nunca pona la variable a cero, pues la haca igual al valor de otra variable O. Moraleja: el programa nunca se equivoca, el programador es el que falla. Lo cierto, es que jams volv a usar la letra O como variable ! Las variables que hemos visto hasta ahora son elementos nicos, en el sentido de que 'valor' es una sola variable y no existe otra, en la misma ventana, con ese nombre. Pero hay una definicin diferente que permite crear variables que son vectores, o conjuntos de elementos que llevan el mismo nombre y solo se diferencian en un nmero interno de orden. Un ejemplo vale a veces ms que mil palabras: Dim numero(5) as integer En esta definicin, creamos una variable-vector (array en ingls) llamada 'numero' que tiene 5 elementos, a cada uno de los cuales se le llama por su nmero. Es decir, tenemos 5 variables dimensionadas de una sola vez. Entonces podemos escribir: numero(3) = 23 numero(5) = 13 numero(1) = numero(3) + numero(4) - numero(5) Como puede verse, cada vez que se invoca un elemento de este array o vector, es preciso hacer referencia a su nmero de orden. No podemos escribir numero = 667 porque no existe una variable nica con ese nombre, y el RB nos mostrara un mensaje de error. Tambin podemos dimensionar variables tipo string: Dim letra(1200) as string estamos creando un vector de 1200 elementos de tipo string.

33////137

Estas variables array son muy, pero que muy tiles, y permiten realizar acciones que de otra forma seran prcticamente imposibles. Por ejemplo, si preciso de 1200 variables para almacenar cada palabra de un texto que he recibido de una base de datos, no voy a dimensionar 1200 variables cada una con un nombre distinto. Las dimensiono todas a la vez, con un mismo nombre y un nmero de orden. Cuando se hace referencia a una variable de un array, no es preciso escribir el nmero de orden explcitamente, ya que este nmero puede ser una variable numrica de tipo integer. Por ejemplo: dim a as integer dim letra(1200) as string Como 'a' es una variable integer, es un nmero entero, nos puede servir como referencia de orden de un elemento de 'letra' Si queremos hacer una referencia al elemento 527 de letra podemos escribir letra(527) = "Pepe" pero tambin podemos hacer lo siguiente: a = 527 letra(a) = "Pepe" y el resultado es idntico. Ojo: no podemos usar una variable DOUBLE para llamar un nmero de orden de un array, ya que las referencias de orden son enteros. NOTA: Los array tambin tienen el elemento cero: letra(0), numero(0), etc., por lo que si dimensionamos letra(1200) realmente estamos creando 1201 elementos. Siempre hay un elemento cero que se puede usar sin problemas. Vamos ahora a aprender uno de los comandos ms tpicos del basic. Es un comando que implica realizar un ciclo ms de una vez, esto es, un nmero determinado de veces. Es el ciclo For...Next. La sintaxis aparece en la ayuda del RB. For a = 1 to 5 Next Lo que dice es : desde el valor inicial de la variable 'a' que lo defino como 1, hasta el valor final de 'a' que lo defino como 5, realiza las lneas de cdigo que van hasta el vocablo Next (siguiente). y luego vuelve al inicio del ciclo, a la posicin del vocablo For 34////137

Inicialmente, la variable 'a' vale uno (a = 1) pero cada vez que se llega a Next, el valor de 'a' se incrementa una unidad. Cuando 'a' valga 5 al llegar a Next ya no se vuelve a For, y se realiza la lnea siguiente al ciclo. Es un ciclo que se realizar 5 veces, tomando la variable 'a' los valores 1, 2, 3, 4 y 5. Si escribimos For a = 4 to 14 el ciclo se realizar 11 veces, con los valores de la variable desde 4 hasta 14 inclusive. IMPORTANTE : La variable del ciclo For....Next debe ser integer, o habr error. Vamos a hacer un programa que utilice este ciclo For...Next as como variables vector o array. Queremos, a partir de un conjunto de nmeros, obtener sus valores al cuadrado; y luego, un sistema para visualizar el cuadrado del nmero que introduzcamos. Los nmeros pueden ser desde el 1 hasta el 9. Para hacer este proyecto usaremos una sola ventana. En ella necesitaremos los siguientes elementos: un botn de fin de programa, un botn para crear los nmeros al cuadrado, un editfield para introducir un nmero, un statictext para visualizar el cuadrado de este nmero, y un botn para confirmar la entrada. Lo primero ser crear los nmeros al cuadrado y almacenarlos. Para almacenarlos ser necesario usar una variable tipo general. Y adems ser tipo integer ya que son nmeros enteros, y ser un array o vector. Llamaremos a la variable 'cuadrados' y al dimensionarla le adjudicaremos 9 elementos. Necesitaremos un botn para iniciar el programa y crear y almacenar los nmeros al cuadrado. Este botn le podemos poner por caption 'Calcular'. Una vez creados los cuadrados, no necesitamos ms el botn 'Calcular' de forma que lo haremos invisible. Para ahora introducir un nmero y ver su cuadrado, necesitamos 1. un editfield, en el cual teclear el nmero que queramos entre 1 y 9, 2. un botn que tome esta informacin del editfield y muestre el cuadrado del mismo, botn al que pondremos por caption 'Ver cuadrado' 3. un statictext en donde veamos el cuadrado del nmero introducido. Estos 3 elementos no necesitan estar visibles al inicio, para no confundir al usuario. Pero deben hacerse visibles inmediatamente que creemos los valores al cuadrado. Por ultimo, un botn, siempre visible, con caption 'Fin' que nos permita finalizar el programa.

35////137

Hasta aqu, estamos creando un proyecto, con un lpiz y un papel, pensando lo que se precisa, cmo ser el flujo del programa, qu aspectos son necesarios para que el usuario lo entienda, etc. A partir de entonces, si las ideas estn claras, empezamos a progrmar el cdigo necesario. Empecemos lanzando el RB. En la ventana inicial 'window1' aadimos un pushbutton, le ponemos por nombre 'Boton1' y le ponemos por caption 'Calcular' Aadimos otro y le llamamos 'Boton2 y con caption 'Ver cuadrado' cuya propiedad 'visible' estar deseleccionada (off, false). Y un tercer pushbutton que llamaremos 'BotonFin' con caption 'Fin'. Aadimos un editfield y un statictext, y en ambos la propiedad 'visible' estar off. Empezamos con el cdigo. Hacemos dobleclick sobre el botn 'Fin' y en la SUB action que aparece en el editor escribimos quit Sin cerrar el editor, vamos al men edit y al tem New Property, y en el dialogo que se nos presenta escribimos: cuadrados(9) as integer y confirmamos con OK. Ya tenemos la variable cuadrados dimensionada como array integer de nueve elementos (diez si contamos el elemento cero). Vamos a la Sub action del botn 'Calcular' y escribimos: SUB action () Dim a as integer For a = 1 to 9 cuadrados(a) = a * a Next boton1.visible = false boton2.visible=true editfield1.visible=true statictext1.visible=true END SUB Tenemos un ciclo For...Next. Vamos a interpretar qu es lo que hace. Se utiliza una variable integer 'a' para contar los ciclos. El total de ciclos es 9. En el primer ciclo, el valor de 'a' es 1. Entonces, cuando pasamos por la 3 lnea , al elemento 1 de la variable cuadrados le asignamos el resultado de la expresin a la derecha, esto es, a * a ( el valor de 'a' al cuadrado). La linea 4 es Next, que aumenta el valor de la variable 'a' en una unidad y vuelve el flujo de programa a For comenzando el segundo ciclo.

36////137

Ahora 'a' vale 2 por lo que el elemento 2 de la variable cuadrados, cuadrados(2), se le asigna el valor de a * a que es 2 x 2 = 4 . Etc. Cuando 'a' toma el valor 9 se obtiene en cuadrados(9) el valor 81. Y al llegar a Next, como 'a' tiene el limite 9 indicado en For, se finalizan los ciclos y se pasa a la linea siguiente a Next. Las lneas que siguen, hacen invisible el propio 'Boton1' y hacen visibles los 3 elementos necesarios para la interaccin del usuario con el programa. Ahora necesitamos el cdigo en el botn 'Ver cuadrado'. Hacemos dobleclick sobre el y en la Sub action escribimos Sub action() Dim n as integer n= val (editfield1.text) rem asigna el valor introducido por usuario a la rem variable n statictext1.text = str(cuadrado(n)) rem pone el valor del elemento n del array rem en el statictext End sub Ya tenemos el proyecto finalizado. Hagamos Run y veamos como funciona.

Hay un pequeo problema y es que cuando el usuario introduce un nmero para hallar su cuadrado, el mximo que puede introducir es 9, ya que hemos dimensionado la variable 'cuadrados' hasta 9 elementos. Esto quiere decir, que si un usuario introduce el nmero 23 y pulsa 'Ver cuadrado', el cdigo busca el elemento 'cuadrado(23)' que no existe, ni est dimensionado, lo que origina un parn del programa y la aparicin de un cdigo de error. Una forma de evitar este inconveniente es limitar la entrada de caracteres en el editfield, haciendo que solo admita un carcter. De esta forma evitamos introducir un nmero mayor de 9, o un nmero negativo. Para ello, seleccionemos el editfield y en la ventana de propiedades, bajo el apartado 'behavior' aparece la propiedad 'LimitText' que por defecto es cero. Este valor cero indica que no hay lmite a la longitud del texto que puede teclearse en el editfield. Si ponemos el valor 1 estamos estableciendo un lmite de 1 carcter: slo puede introducirse un nuevo carcter borrando el anterior. Esta propiedad puede tambin cambiarse mediante cdigo, como cualquier otra propiedad, simplemente escribiendo, en la SUB open del editfield, lo siguiente: editfield1.limitText = 1 Probemos que ahora nuestro programa funciona para los numeros 1 a 9 y no admite nmeros mayores que este ltimo. Hay otras alternativas para evitar el error que comentbamos sin necesidad de limitar la longitud de la entrada de texto. Vamos a ver una forma distinta de abordar el mismo problema que nos permitir aprender comandos nuevos del Basic. Para empezar, desharemos la modificacin anterior de la propiedad 'LimitText' , volviendo a 37////137

poner el valor cero que es el valor por defecto de esta propiedad.

38////137

Hay un comando basic que es RETURN y que significa abandonar inmediatamente una SUB y volver al punto de inicio, al punto desde donde fue llamada la SUB. Cuando iniciamos un proyecto, el punto de inicio es la propia ventana inicial. Eso quiere decir, que si en la Sub asociada a un elemento se encuentra un RETURN, se vuelve a la ventana inicial. Otro comando basic es LEN que nos informa de cual es la longitud de un string, y nos lo dice dando valor a una variable integer. La sintaxis es : variable [tipo integer] = len(string) Por ejemplo, tenemos una variable string que contiene el texto "Hola que tal" y una variable tipo integer llamada 'longitud'. La lnea de cdigo longitud = len (texto) hace que longitud valga 12 (sumando letras y espacios). Y por ltimo, uno de los comandos ms bsicos del basic es un condicional, basado en que slo si se cumple una determinada condicin, se realizan las acciones de unas lneas de cdigo: IF condicin = true THEN ---------------------END que se lee: SI una condicin de tipo booleano es cierta, ENTONCES Por ejemplo: Dos variables 'p' y 'q' son integer con valores p=5 y q= 8 Si escribimos: IF p = q then beep End Como la condicin p = q NO ES CIERTA, las lneas de cdigo situadas entre THEN y END no se realizan. Pero si escribimos IF p < q then 39////137

beep End

40////137

ahora la condicin p < q es cierta y la linea con el comando 'beep' es interpretada. Las condiciones ms simples son; A=B A>B A<B A>=B A<=B Las dos ultimas deben escribirse en ese orden, primero el smbolo de mayor o menor y luego el igual. A > = B quiere decir que la condicin es true si A es mayor o igual a B. Al lado derecho de la condicin booleana puede escribirse una expresin mas o menos compleja. Por ejemplo vale decir: If A > B/2 + C *7. La expresin se evala y el resultado se compara con A para decidir si es true o false. Tambin la sintaxis admite variantes. La ms notable es la palabra ELSE que viene a decir que si NO se cumple la condicin lo que se realiza es lo que sigue al termino ELSE hasta alcanzar END. If a < b then 12 ELSE 345 END En este ejemplo, si la condicin es true el flujo de programa pasa por 1, 2 y luego salta a la lnea siguiente al final END. Pero si no se cumple, el flujo salta a 3, 4 y 5 y luego a la linea tras END El trmino ELSE podra traducirse como "en caso contrario"

Volvamos a nuestro programa. Queremos ahora que si el usuario introduce un nmero mayor de 9 no ocurra un error. Como cualquier nmero mayor de 9 tendr dos cifras (dos caracteres) podemos poner como condicin que si la longitud del nmero tecleado por el usuario es de longitud mayor que 1 no se haga nada, pero si el nmero es de longitud uno, se calcule su cuadrado. Vamos a ello: En la Sub action del botn 'Ver cuadrado' debajo de la lnea dim n As integer

41////137

escribimos lo siguiente: dim s as string s=editfield1.text IF len(s) < 2 then el resto se deja como estaba, y al final de la Sub, como ultima linea escribimos End Ahora tenemos una condicin: cuando el usuario pulsa el botn 'Ver cuadrado' lo primero que hace nuestro cdigo es tomar el texto escrito por el usuario en el editfield y asignarlo a la variable tipo string 's'. Luego se pone una condicin en la cual se evala la longitud (Len) de este texto y slo en el caso de que sea menor de 2 (por lo tanto de una sola cifra) se sigue el cdigo que permite obtener el cuadrado del nmero. Si el texto es de 2 o ms cifras el flujo del RB se salta esas lneas hasta despus de End, y como detrs de este End slo queda End Sub, se vuelve entonces a la ventana inicial. Hagamos los cambios en nuestro proyecto, grabemos, y hagamoslo correr con Run. Comprobemos que si en editfield escribimos 3 funciona dndonos el valor 9. Pero si introducimos +3 ya no funciona pues el smbolo + junto con el 3 tienen una longitud de texto de 2 caracteres.

Y ahora probemos la otra alternativa, el comando RETURN. Dijimos que este comando hace que una vez encontrado, el flujo vuelva (return=retorno) al punto del cdigo desde donde se envi el flujo a la SUB. En nuestro caso, llegamos a la sub action del botn cuando lo pulsamos desde la ventana inicial, luego si encontramos return en esta sub, volveremos a la ventana inicial. Bueno, pues cambiamos el cdigo que modificamos antes de una forma simple: cambiamos la lnea: IF len(s) < 2 then por esta otra: IF len(s) > 1 then return end y eliminemos el trmino 'end' del final de la sub. Comprobemos que tambin este cambio funciona bien.

En esta sesin hemos aprendido dos elementos del basic muy importantes: El ciclo ' FOR .... NEXT ' que nos permite realizar tareas repetitivas de forma simple, y nos permite manejar variables de tipo array con cientos de elementos.

42////137

La condicin ' IF ................. THEN ......... ELSE ........ END' que permite dirigir el flujo de actividad de nuestro programa segn nos interese, y segn se cumplan determinadas situaciones de todo tipo. Y tambin hemos usado dos nuevos comandos de basic: LEN RETURN Recordemos que un ciclo FOR ....... siempre lleva un NEXT, o se generar un error. Tambin un ciclo condicional IF ............... lleva asociado un END.

43////137

En esta sesin vamos a seguir con el programa anterior para conocer y usar nuevas opciones y funcionalidades del basic que facilitan la accin del usuario y del programador. En primer lugar, el programa que hicimos en la sesin anterior para obtener los cuadrados de los nmeros 1 a 9 puede simplificarse. Nosotros usamos un array llamado 'cuadrados' de 9 elementos, simplemente para conocer un poco del funcionamiento de los array. Pero ahora vamos a usar rutinas ms simples y directas y que no nos limiten a los nmeros del 1 al 9. Comencemos por lanzar el RB y cargar el programa de la sesin anterior tal como lo dejamos. Eliminemos la variable cuadrados, simplemente abriendo el editor, yendo a properties, haciendo doble click sobre el nombre de la variable y seleccionando 'delete' del men edit. Eliminemos el botn 'calcular', lo cual elimina el elemento y todas las subrutinas asociadas con l. Para ello lo seleccionamos y lo borramos con la tecla borrar. Seleccionamos los 4 elementos de la ventana y hacemos que su propiedad 'visible' est seleccionada (true). Abrimos la sub action del botn 'Ver cuadrado'. Borramos todo lo que estaba escrito y luego escribimos: SUB action() statictext1.text = str(val(editfield1.text)*val(editField1.text)) END Qu estamos diciendo con este extrao y largo cdigo? Estamos asignando mediante el signo = un texto al elemento StaticText1.text Este texto es un string, ya que usamos la palabra del basic STR que convierte nmeros en string. Lo que convertimos a string est entre parntesis, y corresponde a una multiplicacin de dos nmeros iguales; por lo tanto es equivalente a elevarlos al cuadrado. Cada nmero proviene del editfield1.text, es decir, el texto introducido por el usuario. Este texto se convierte a un nmero mediante la funcin VAL. En resumen, estamos hallando el cuadrado del nmero del editfield, convirtiendo este resultado en un string mediante la funcin STR y finalmente asignando este string al statictext1 para que sea visible en la ventana. Como podemos ver, no necesitamos ni variables ni otra lnea de cdigo. Y adems, podemos introducir cualquier nmero de dos o ms cifras sin problema.

La lista de edicin (ListBox) o simplemente Lista, es un nuevo elemento que podemos aadir a nuestra ventana. Permite almacenar informacin, igual que una 44////137

variable array, pero podemos adems visualizarla e incluso editarla. Es por lo tanto de una grandsima utilidad. La lista (ListBox) se organiza como una tabla de filas y columnas. El nmero mnimo de columnas es 1, evidentemente, pero puede aumentarse segn se precise. El nmero de filas inicial es cero, y debemos ir aadiendo filas al ir creando la lista. En base a las filas y columnas podemos decir que la listbox est formada por celdas y que cada celda (cell) est determinada por una fila (row) y una columna (column). Por ejemplo la cell 6,3 sera la celda de la fila 6 columna 3. NOTA: Siempre el orden en que se llama una cell es fila, columna. IMPORTANTE: toda listbox tiene como primera la fila (row) nmero cero, y como primera columna, la columna 0. Entonces, la primera cell es la 0,0. Vamos a utilizar una ListBox para ver nuestros nmeros y sus cuadrados. E incluso vamos a calcular el cubo del nmero introducido. Lo primero es eliminar el elemento StaticText de la ventana. Luego, colocamos el editfield y el botn 'Ver cuadrado' en la parte superior de la ventana. Cambiamos el caption del botn por este otro: 'Ver cuadrado y cubo'. Ponemos el botn 'Fin' en la parte inferior derecha de la ventana. Aadimos ahora un elemento listbox, y lo alargamos todo lo que permita nuestra ventana, es decir, que ocupe desde el tope hasta la parte inferior. De 'width' ponemos al menos 275. Una propiedad del listbox que podemos examinar en la ventana 'properties' es 'columncount' que es el nmero de columnas. Ponemos tres. En la propiedad 'initialValue' tocamos en donde pone 'edit' y se nos abre un dilogo. Escribimos tres palabras: "Numero Cuadrado Cubo" y las separamos una de otra por un tabulador (no escribir las comillas) Vemos que el listbox muestra 3 columnas cada una encabezada por una de las palabras introducidas. La propiedad 'InitialValue' es la que nos permite dar un ttulo a las columnas. Ahora vamos a la SUB action del botn y escribimos: SUB action () dim n as integer n=val(editfield1.text) listbox1.addRow "" listbox1.cell(0,0)=str(n) listbox1.cell(0,1)=str(n*n) listbox1.cell(0,2)=str(n*n*n) End sub La primera linea es simplemente dimensionar una variable integer. La segunda es un mtodo propio de la listbox que aade una fila a las existentes. Inicialmente

45////137

una listbox no tiene filas. Es preciso aadir fila tras fila antes de colocar informacin en un listbox. Si queremos aadir fila e informacin de forma simultnea, escribiremos un texto detrs de 'addrow' (por ejemplo, listBox.addrow = "Luisa") pero si slo queremos aadir la fila, escribimos un texto vaco "". NOTA: si se intenta leer el texto de una celda o llenarla sin antes haberla creado mediante el mtodo 'addrow', se nos genera un error que puede colapsar el programa. Una vez aadida la fila, que ser la nmero cero (0), podemos rellenar las tres cell de esta fila. Como las 3 columnas son la 0, la 1 y la 2, las 3 cell llevan como elementos fila, columna, los valores (0,0), (0,1) y (0,2). Bueno, pues nuestro cdigo toma el valor 'n' introducido por el usuario en el editfield, pone este valor en la cell de la columna 0 (como string), y luego eleva este nmero 'n' al cuadrado y al cubo , poniendo los resultados, como string (usamos str), en las dos cell de las columnas 1 y 2. Si hacemos run, vemos que aparecen el nmero, su cuadrado y su cubo en cada columna. Pero hay un problema, y es que cada valor que metemos borra el resultado anterior. Cual es la razn? Repase el cdigo y piense un momento sobre ello, a ver si encuentra la solucin ................

Tiempo !! Bueno, pues la razn es que el cdigo siempre se dirige a las mismas celdillas, las de la fila cero, por lo que tendremos que usar una variable de tipo general (para que mantenga su valor) que indique a que fila deben dirigirse los datos. Vamos a crear una variable general que llamaremos 'filas' de tipo integer. Y ahora modifiquemos el cdigo de la sub action del botn. SUB action() dim n as integer n=val(editfield1.text) listbox1.addRow "" listbox1.cell(filas,0)=str(n) listbox1.cell(filas,1)=str(n*n) listbox1.cell(filas,2)=str(n*n*n) filas = filas + 1 rem aumenta el valor en una unidad cada ciclo End sub Ahora, la variable filas retiene el valor que se le da, ya que es una variable general. Su primer valor es cero, por lo que rellenamos la cell inicial, pero luego, en la ltima lnea lo aumentamos en una unidad, por lo que en la segunda llamada a la sub el valor de filas es 1; y ser 2 en la siguiente, etc.

46////137

Si hacemos run, cada nmero aparece en la fila correspondiente. Y podemos notar que si se repite la entrada un nmero alto de veces, automticamente aparece una barra de scroll en la listbox. Grabemos nuestro proyecto para futuras cambios. Aunque hay ms cuestiones interesantes en relacin con las ListBox, vamos a finalizar aqu est sesin, pues necesitamos introducir unas cuestiones muy bsicas pero absolutamente necesarias para entender la forma de trabajar del Real Basic: Mtodos, SubRutinas y Funciones.

47////137

SUBRUTINAS, MTODOS y FUNCIONES A lo largo de las sesiones previas hemos visto que existen algunas subrutinas asociadas a una ventana o a sus elementos. Si hacemos dobleclick sobre nuestra ventana, se abre el editor y podemos ver una serie de 'events' (eventos) que estn asociados a la ventana. Los eventos reflejan las acciones que el usuario puede realizar con el ratn y el teclado. Unos eventos llevan asociadas SUBRUTINAS, como 'activate' o como 'mouseEnter', pero otros eventos llevan asociadas FUNCTIONS como es 'keydown', 'mousedown' o 'cancelclose'. Subrutinas y funciones pueden considerarse Mtodos, conjunto de instrucciones de cdigo que realizan actividades programadas. Las Subrutinas empiezan con SUB y acaban con END SUB, mientras que las funciones empiezan con FUNCTION y acaban en END FUNCTION Cuando se llama a un mtodo, el flujo del programa se transfiere a ste, se realizan las lneas de cdigo del mtodo, y luego se vuelve (return) al punto desde dnde se hizo la llamada. Un mtodo puede a su vez llamar a otro mtodo. En este caso, se llega al segundo mtodo, se realiza, y se vuelve al mtodo que lo llam, justo a la lnea de cdigo inmediatamente posterior a la llamada. MUY IMPORTANTE: Subrutinas y funciones pueden recibir informacin procedente de la sub o function que los invoca, que los llama. Esta informacin son simplemente variables de tipo numrico, o texto, etc. Por ejemplo, si un mtodo precisa calcular el cuadrado de un nmero, en lugar de hacerlo por s mismo puede llamar a otro mtodo que lo haga, y este segundo mtodo, slo necesita que se le enve, como informacin, la variable en cuestin. Esta informacin la recibe el mtodo en la (o las) variable que aparece entre parntesis inmediatamente despus del nombre de la SUB (o de la function). Si examinamos los eventos de una ventana, vemos que 'close' es una SUB y que aparece un parntesis inmediatamente detrs del nombre 'close' pero est vaco. Evidentemente, si cerramos una ventana usando el ratn, la SUB asociada no precisa variables. Pero si miramos la sub 'dropObject' que es el evento asociado a que el usuario arrastre y deje caer un objeto dentro de la ventana, veremos que entre parntesis aparece la variable 'obj' (objeto) como tipo 'dragitem'. En este caso tiene sentido que la informacin (el objeto arrastrado) llegue a la SUB para poder "trabajar" con este objeto. La diferencia ms notable entre un Mtodo-SubRutina y un Mtodo-Funcin es que las Function SIEMPRE devuelven un valor al mtodo que las llama, mientras que una Subrutina puede no devolver nada, o devolver uno o ms valores pero de una forma diferente. Vamos a empezar a emplear Mtodos, para lo cual, en esta sesin 7, examinaremos cmo es una Function. Vamos a crear un proyecto muy simpln. Por ejemplo, queremos calcular el cuadrado de un nmero cualquiera. Lancemos el RB y en la ventana inicial 'window1' aadamos un EditField, un StaticText, y dos botones. Un botn ser 48////137

'FIN' con el comando 'quit' en su action, y el otro botn llevar como caption 'Elevar al cuadrado'. En la SUB action de este botn ponemos el cdigo necesario para tomar el valor introducido por el usuario en el EDITFIELD, elevarlo al cuadrado y pasarlo, como string, al STATICTEXT, tal como sigue: SUB action() dim n as integer n = VAL(EditField1.text) REM obtiene el valor numrico del texto n= n * n REM la variable 'n' almacena ahora el cuadrado StaticText1.text = str (n) REM ponemos el string de 'n' en el StaticText End Sub Podemos probar que este proyecto funciona. Pero podemos hacer que el cuadrado del nmero lo realice un Mtodo-Function independiente. Vamos a crear esta Function, a la que llamaremos 'Obtener_Cuadrado' y que simplemente calcular el cuadrado de un nmero que le enviaremos y nos devolver este nuevo valor. En el men edit del RealBasic seleccionamos el tem New Method, el cual es el mismo para crear un mtodo o una funcin. Se nos abre un cuadro de dilogo. En la primera casilla escribimos el nombre elegido por nosotros, en este caso 'Obtener_cuadrado'. En la segunda celda del dilogo, que se titula 'parameters', es donde escribimos las variables que "MANDAN" informacin al mtodo, y las que queremos que "DEVUELVAN" informacin. Como queremos calcular el cuadrado de un nmero entero slo necesitamos una variable, que ser integer. Podemos llamarla 'dato' escribiendo en esta celda: dato as integer Por ltimo, la tercera celda, elegimos simplemente el TIPO de variable de retorno. Como el cuadrado de un nmero entero es otro entero, seleccionamos o escribimos 'integer'. Pulsamos OK y aparece una function de esta forma: Function Obtener_cuadrado(dato as integer) as integer End Function Este mtodo es una function, ya que hemos rellenado la tercera celdilla del dialogo donde deca 'Return type' (si la dejamos en blanco, crearamos una Sub). El ttulo de esta Function est claro. Luego, entre parntesis, aparece la variable que NECESITA para trabajar, que se llamar 'dato' y es de tipo integer. OJO: Ya no hace falta dimensionarla dentro de la function, ya est dimensionada al crear la function. Por ltimo, despus del parntesis aparece 'as integer', que es la variable que se retorna o devuelve.

49////137

Ahora nos falta rellenar las lneas de cdigo de esta nueva Function. Escribimos lo siguiente: Function Obtener_cuadrado(dato as integer) as integer dim alcuadrado as integer REM usaremos una variable propia de la Function, y REM por eso la dimensionamos en la propia Function alcuadrado = dato * dato REM ya tenemos el cuadrado en esta variable Return alcuadrado End Function El valor de la variable 'alcuadrado' es el valor que se devuelve mediante 'return' Bueno, pues vamos a ver cmo se invoca, como se llama a esta function. Vayamos al botn que lleva por caption 'Elevar al cuadrado' y en su SUB Action escribimos: SUB Action () dim n, cuadrado as INTEGER n = val (EditField1.text) REM toma el string introducido en el editField y REM lo transforma en un valor numrico integer como REM es el caso de la variable n cuadrado = Obtener_cuadrado(n) StaticText1.text = str(cuadrado) End Sub Bueno: pues la lnea cuadrado = Obtener_cuadrado(n) es una llamada a una function existente, a la cual se le enva el VALOR que tiene la variable que se indica entre parntesis, es decir, 'n'. Este valor es recibido por la Function en la variable 'dato', es decir, si 'n' vale 8, la variable 'dato' valdr tambin 8. Entonces la Function ejecuta sus lneas de cdigo, es decir, obtiene el cuadrado de 'dato'; y por ltimo mediante el comando 'Return' devuelve el valor de su variable 'alcuadrado' que es recibido de vuelta por la variable 'cuadrado'. Llamemos 'variable origen' a la variable que se usa para enviar un valor a la Function. Y llamemos 'variable destino' a la que recibe ese valor en la Function. Toda esta explicacin parece liosa pero no lo es tanto. Vamos a poner un esquema grfico que nos ayude a entenderlo:

50////137

SUB de llamada Sub Action ( ) dim n, cuadrado as integer n= val(editfield1.text) cuadrado = Obtener_cuadrado (n) StaticText.text = str(cuadrado) End Sub

Function que recibe la llamada Function Obtener_cuadrado (dato as Dim alcuadrado as integer alcuadrado = dato * dato , return alcuadrado END function Cuando se hace la 'llamada', el valor de 'n' pasa a 'dato', el cual se utiliza para obtener 'alcuadrado'. El valor de 'alcuadrado' es el que se 'devuelve' a la variable 'cuadrado' mediante Return. Bueno, pues slo falta probar nuestro proyecto, y comprobar que la function cumple bien su misin. Damos por hecho que todo funciona como se espera, y en tal caso seguimos adelante en la sesin.

La utilidad de una Function es que se puede reutilizar con cualquier programa que precise obtener el cuadrado de un nmero. No hace falta escribir el cdigo de nuevo. La Function trabaja autnomamente, slo precisa un valor inicial que se le enva desde la Sub de llamada. Adems no tenemos que preocuparnos de los nombres de las variables origen y destino, sabemos que se llamen como se llamen, la function va a devolver un dato correcto.

IMPORTANTE: la function recibe un 'valor', no recibe una variable. Es decir, el valor que tiene la variable origen cuando se hace la llamada es lo que realmente se enva. Eso quiere decir que la Function no puede cambiar el valor de la variable origen, puede usarlo para los clculos, pero no modificarlo. Realmente lo que se recibe es una constante, un valor fijo. Y la variable destino que lo recibe en la Function, no es realmente una variable, es como un alias del valor recibido, ya que no puede modificarse.

51////137

En nuestro ejemplo, la variable 'dato' de la Function no es una variable verdadera, es un alias del valor que tiene la variable origen, en nuestro ejemplo, el valor de 'n' en el momento de la llamada. IMPORTANTE: Si en la FUNCTION se omite el comando RETURN, lo que se devuelve es cero, para variables numricas, y vaco "" para las variables string. IMPORTANTE: Una vez se alcanza un comando return, el flujo del programa abandona la FUNCTION y vuelve al punto de llamada, aunque no se hayan realizado todas las lneas de cdigo de la Function. El comando return es por lo tanto, una salida incondicional. Y por cierto, en una function puede hacer mas de un comando return. Tal sera el caso de una situacin condicional, de un comando If... then....else....end. Si una condicin es correcta se puede devolver un valor mediante return, pero si la condicin no se cumple se puede devolver, mediante otro return, un valor diferente.

En el ejemplo que hemos puesto antes, slo se enva un dato correspondiente al valor de una variable. Pero pueden enviarse todos los valores que la Function necesite para trabajar. Por ejemplo, cuando se hace una llamada de este tipo: resultado = calcular (valor_1, valor_2, divisor) a una Function que se llame 'calcular' y que est definida as: Function Calcular(a as integer, b as integer, c as integer) as double dim solucin as double solucin = (a + 2 * b) / c return solucin End function se envan 3 datos, los valores de las variables valor_1, valor_2 y divisor, valores que se reciben en EL MISMO ORDEN, por las variables a, b y c de la FUNCTION. Y es importante recordar este orden, porque si se cambia en origen, la function devolver un valor que no es el que pretendemos.

A la vista de todo lo expuesto hasta aqu, debe estar claro que la Function no puede modificar la variable que enva su valor, pues de hecho la variable no se enva . Pero hay una forma de obviar este problema, de permitir que la function pueda modificar a la variable origen. Y es enviar realmente la variable en cuestin, en lugar de enviar su valor actual. Se dice que en este caso la variable se enva 'como referencia'. Y la modificacin sintctica consiste en escribir la palabra 'byref' antes de dimensional la variable de la Function. Por ejemplo, vamos a definir una function que calcule el valor en euros y en libras de una variable que es el precio en pesetas que cuesta un artculo, y a la vez nos devuelva la propiedad 'verdadero' si los euros superan un total de 500 y por tanto es un producto caro, y 'falso' si los euros no llegan a 500 y

52////137

por tanto es barato . Vamos a crear un mtodo seleccionando el tem New Method, y demos el nombre 'cambio' al mtodo. En la segunda celda, en parameters, escribimos: pesetas as double, byref euros as double, byref libras as double. En la tercera celda, en return type, elegimos boolean, que recordemos es un tipo de variable que devuelve verdadero o falso. Cerramos el dilogo. Nos aparece una Function que tiene 3 variables de tipo double. La primera, que es pesetas recibir un valor, pero la segunda y tercera, que llevan la palabra byref antes del nombre, recibirn una referencia a la variable origen, es decir, la propia variable, que entonces puede modificarse. Podemos probarlo con un ejemplo rpido. Abrimos el RB y aadimos tres statictext, un editfield, y un pushbutton en la ventana inicial. El editfield es para que el usuario introduzca el total en pesetas. Dos de los tres statictext son para representar el valor correspondiente en euros y en libras, y el tercer statictext es donde el programa escribir si el precio es caro o barato, segn supere o no el total de 500 euros. El pushbutton es para lanzar la actividad del programa. As pues, en la action de este botn escribimos: Sub action() dim pelas, euromonedas, librasinglesas as double dim esmuycaro as boolean pelas = val(editfield1.text) esmuycaro = cambio(pelas,euromonedas,librasinglesas) staticText2.text=str(euromonedas) staticText3.text=str(librasinglesas) if esmuycaro = true then statictext1.text = "Muy caro" else statictext1.text = "Es barato" end End Sub En la Function que hemos creado aadimos las lineas de cdigo siguientes: Function cambio(pesetas as double, byref euros as double, byref libras as double) as boolean euros = pesetas / 166.386 libras = pesetas / 251 if euros > 500 then return true else return false end END FUNCTION Notemos que en el cdigo se modifican las variables euros y libras que hacen referencia a las variables origen euromonedas y librasinglesas.

53////137

Vemos tambin que hay una condicin del tipo IF ....THEN....ELSE que permite devolver a la variable boolean de origen los valores true o false. Probemos si funciona correctamente. Hacemos correr el programa, y en el campo de edicin introducimos 30000 como valor en pesetas, y luego pulsamos el botn. En el statictext aparecer el resultado. Introduzcamos otro valor diferente, y pulsemos de nuevo el botn, etc. El programa no es muy amigable, pues la interface, lo que el usuario tiene delante, no nos dice ni tan siquiera cual editfield son euros y cual pesetas. Bueno, pues modifique Vd. mismo el programa para que todo quede claro y amigable. Con este ejemplo acabamos esta sesin.

54////137

Mtodos - Subrutinas En la sesin anterior hemos estudiado como funciona el Mtodo Function. Si se ha entendido bien la filosofa y la forma de trabajar de una Function, entender las subrutinas es muy fcil. La diferencia bsica estriba en que una Function siempre devuelve un valor, mediante return, mientras que una Subrutina es un Mtodo que NO DEVUELVE ningn dato. La Subrutina puede recibir informacin desde la Sub de llamada, o puede no necesitarla, igual que ocurre con una function. Tambien la SUB puede recibir el valor de una variable o puede recibir la variable en cuestin y modificar su valor; para ello se utiliza el vocablo 'byref' en la definicin de la SUB. Vamos a hacer un programilla para ver como funciona una Sub. Supongamos que queremos calcular el volumen, en pintas, de un envase tipo tetrabrick. Para ello disponemos de tres mediciones en cemtmetros: su altura, su ancho de base y su fondo. El volumen se calcula multiplicando los tres valores, y luego convirtiendo el resultado de centmetros cbicos a pintas, para lo cual hay que multiplicar los centmetros cbicos por 2.1133 y dividir por 1000. La Sub que hace la llamada necesita enviar 3 valores, alto,ancho y fondo. La Sub que recibe la llamada y hace los clculos tiene que devolver 2 valores, el volumen en cc y el volumen en pintas. Para crear la Sub que recibe la llamada vamos al editor, y en el men Edit seleccionamos New Method. Se nos abre un dilogo con 3 celdas. En la primera escribimos el nombre del nuevo Mtodo, que vamos a llamar 'Calcula_Volumen. En la segunda celda escribimos los nombres y tipos de las 3 variables que envan sus valores, y los nombres, precedidos por el vocable byref, de las dos variables que son modificadas por la Sub al recibir los nuevos valores: alto as double, ancho as double, fondo as double, byref cc as double, byref pintas as double) En la tercera celda no escribimos nada. Como esta celda es la correspondiente al valor que se retorna, y no hemos escrito nada, estamos realmente indicando que no es una Function, por lo tanto es una Sub. Podemos verlo al cerrar el dilogo y ver que aparece una Sub vaca con slo el ttulo y las variables. En ella escribimos: Sub Calcula_Volumen(alto as double, ancho as double, fondo as double,byref cc as double, byref pintas as double) cc = alto * ancho * fondo pintas = cc * 2.1133 / 1000 End Sub Vamos ahora a aadir objetos a la ventana inicial. Pondremos tres editfield, para que el usuario pueda introducir los valores de alto, ancho y fondo en centmetros. Aadamos un statictext a la izquierda de cada EditField que indique el dato que debemos introducir en cada uno de ellos. Adelante. Aadimos otros dos StaticText, en donde mostraremos los resultados, es decir, el volumen en centmetros cbico y en pintas. Al primero le damos por nombre 'ccSt' y al segundo 'pintasSt'.

55////137

Una vez tengamos los diferentes statictext y los tres editfield, demos nombre a estos ltimos: uno, ser 'altoEd', otro 'anchoEd' y el tercero 'fondoEd'. Aadimos un botn con caption 'quit' y cuya sub action lleve una sola lnea de cdigo con el comando 'quit'. Aadimos otro botn con caption 'Calcular' y el la Sub Action de este botn escribimos: Sub Action() dim alto, ancho, fondo, VolCC, volPintas as double ancho = val(anchoEd.text) alto = val(altoEd.text) fondo = val(fondoEd.text) calcula_Volumen(ancho, alto, fondo, VolCC, VolPintas) ccSt.text = str(VolCC) + " centmetros cbicos" PintasSt.text = str(volPintas) + " pintas" End Sub Esta Sub hace la llamada a la Sub que calcula el volumen. Las dos variables que la Sub Calcula_Volumen recibe por referencia, son modificadas, recibiendo el valor correspondiente. Finalmente, una vez el flujo del programa vuelve a la Sub principal, el valor del volumen en cc que est guardado en la variable 'VolCC' lo mostramos en un statictext al cual aadimos como texto y mediante el comando suma (+) un corto string que dice 'centmetros cbicos' y lleva un espacio en cabecera. Lo mismo para el volumen obtenido en pintas. Hacemos correr el programa y examinamos con detenimiento como funciona.

Los Mtodos, Sub y Functions, pertenece a una ventana. Si hay variables generales de ventana, pueden ser usadas por los mtodos de dicha ventana. Pero cuidado con las variables generales y el vocablo byref: una variable local a un mtodo puede ser pasada por referencia, pero una variable general de ventana no puede ser pasada de esta forma, pues como su nombre indica, es general y vlida para todos los elementos de la ventana. Hay Functions y Subrutinas que estn ya implementadas en la interface del RealBasic, y nosotros no necesitamos programarlas. Por ejemplo, cuando tecleamos, hay una function llamada 'KeyDown' que recibe la tecla pulsada. Vamos a examinar est Function. Lancemos el RealBasic. Abrimos la ventana inicial 'window1' y hacemos dobleclick en cualquier punto de la misma, con lo que se abre el editor. Aparece seleccionada una SUB llamada 'Open' y que corresponde u uno de los posibles eventos o acciones que puede recibir la ventana por la actividad del usuario. Si nosotros aadimos cdigo sobre esta SUB, este cdigo se ejecutar cada vez que abramos la ventana. Seleccionemos ahora el evento de ventana llamada 'close'. En la Sub que se abre aadimos 'quit' como nico cdigo. Probemos si funciona. Hacemos Run y se nos abre una ventana que est vaca de

56////137

contenidos. Si tocamos con el ratn el cuadrado de cierre de la ventana, esta se cierra y a la vez se finaliza el programa. Si antes de 'quit' aadimos 'beep' el programa emitir un sonido cuando se cierre la ventana. Que ocurre si antes del comando 'quit' aadimos el comando 'return' ? Pues es fcil de adivinar: la ventana se cierra, pero la SUB devuelve el flujo del programa sin pasar por los comandos 'beep' y 'quit', con lo cual el programa no finaliza y deberemos hacerlo de forma manual, pulsando comando y Q. Vamos a hacer algo ms til. Primero, eliminemos el comando return. Segundo, aadamos un statictext a la ventana inicial (statictext1). Ahora hacemos dobleclick en un punto de la ventana para abrir el editor y vamos al evento de la ventana denominado 'keydown'. Ahora no tenemos una Sub, tenemos una Function. Y sabemos que las functions devuelven un valor. Bueno, pues esta Function devuelve una variable boolean (verdadero,falso) como podemos ver en la definicin. Y vemos tambin que la Function recibe una variable de tipo string que se llama 'key'. Pues esta variable lleva precisamente el string correspondiente a la tecla pulsada por el usuario. Si se pulsa una hache minscula, el valor de key es "h", si se pulsa un siete, el valor de key es un string "7", etc. Vamos a aadir a esta Function una sola lnea de cdigo, que diga: statictext1.text = key con lo cual ponemos el string de la tecla pulsada en el statictext de la ventana. En esta function implementada en el RealBasic no necesitamos aadir el comando 'return' ni el valor de la variable booleana. Bueno, pues si hacemos correr el programa, notaremos que cada tecla pulsada aparece en el statictext. Otro evento en relacin a la ventana es el movimiento del ratn. Cada vez que el ratn se desplaza, hay un evento que es recogido por el RBasic, el cual enva las coordenadas del ratn a una SUB llamada 'MouseMove'. Esta sub recibe del RealBasic las variables X e Y de tipo integer, las cuales llevan, en este orden, el valor en pixels de anchura (X) y altura (Y) correspondientes a la posicin del ratn. Bueno, pues vamos a aadir otro statictext a nuestra ventana (statictext2), a la vez que borramos (no olvidarse) el cdigo que escribimos en la Function 'KeyDown'. Ahoran en la SUB MouseMove aadimos: statictext1.text = str(X) statictext2.text = str(Y) Si hacemos correr el programa, veremos las coordenadas del ratn en pixels dentro de la ventana, coordenadas que irn cambiando segn lo desplazamos. Podemos notar que estas coordenadas se corresponden con la posicin del ratn dentro de "su" ventana, es decir, si desplazamos el ratn fuera de esta, no se detecta su posicin. Notemos tambin que las posiciones dentro de la

57////137

ventana empiezan en el valor 0, 0 que corresponde a la esquina superior izquierda, que la anchura aumenta hacia la derecha, y la altura o valor vertical aumenta hacia abajo. Otro evento es hacer click con el ratn, esto es, pulsar el botn del ratn. La Function 'MouseDown' recibe informacin de las coordenadas del punto exacto donde estaba el cursor en el momento de hacer click. Usted mismo aada cdigo a esta Function para poder ver las coordenadas de un click del ratn. Tambin algunos elementos u objetos que se aaden a las ventanas reciben eventos o acciones por parte del usuario. Uno de los ms tpicos es el elemento 'EditField' o campo de edicin, lugar donde el usuario puede escribir texto. El editfield recibe, como evento ms importante, la informacin derivada del teclado, de forma que si hay un editfield en una ventana y est activo (enabled), es este elemento el que recibe la tecla pulsada por el usuario, y no es la propia ventana. Pero si un editfield est presente en una ventana pero no esta activado (enabled=false) entonces la informacin de la tecla pulsada la recibe la ventana en su subrutina 'KeyDown'. Que ocurre si en una ventana hay ms de un editfield? Cul recibe la informacin de la tecla pulsada? Pues la recibe el que est 'resaltado', el que tenga lo que se denomina el 'focus'. Si hay varios editfield, y el usuario toca con el ratn en uno de ellos, el RealBasic se encarga de que este editfield sea el que tenga el focus. Si se toca en otro editfield, el focus cambia al editfield seleccionado. El focus es un resaltado, una especie de recuadro de color suave que rodea el elemento que recibe informacin del usuario. Se puede cambiar el focus mediante cdigo, con los mtodos asociados a eventos de determinados elementos. As, un editfield tiene un mtodo denominado 'GotFocus' que una vez ejecutado hace que este editfield sea el que recibe acciones del usuario, y otro denominado 'LostFocus' que hace que el editfield pierda este focus. Para probar lo anterior, hagamos un pequeo programa en RB. En la ventana inicial de un nuevo proyecto, aadamos dos editfield. Haciendo dobleclick en uno de ellos, busquemos, en la ventana editor, el mtodo 'GotFocus', y en la SUB correspondiente aadamos como cdigo la siguiente lnea: me.text = "Tengo focus" y para el mismo editfield, en la SUB del mtodo 'LostFocus' escribamos: me.text = "Ya no tengo focus" Aprovechamos para decir, que el vocablo 'me' hace referencia al elemento que tenemos seleccionado, en este caso el 'editfield1'. Es decir, 'editfield1.text' es sinnimo de 'me.text' siempre que est escrito "dentro" de algn mtodo de dicho elemento. Pero si fuera un pushbutton, el vocablo 'me' hara referencia a este elemento. Es por lo tanto un vocablo genrico, vlido para cada elemento del RB, que tiene su importancia y utilidad, pues

58////137

aunque cambiemos el nombre del elemento, no precisamos cambiar el cdigo correspondiente dentro del mismo. Bueno, pues hagamos correr el programa. Segn toquemos con el ratn en uno u otro editfield, vemos que uno queda resaltado y el otro no, y el texto que aparece en el editfield1 es el que nosotros hemos puesto en cdigo. Los mtodos, subrutinas y functions, no son exclusivos de ventanas o de sus elementos. Pueden ser escritos por el programador para realizar una actividad simple o muy compleja, y ser invocados de forma simple. Por ejemplo, podemos crear un mtodo llamado 'atencion' que simplemente reproduzca un total de 4 veces el sonido de alerta del ordenador. Y que cada uno de estos sonidos est separado del anterior por un segundo, para que no se oigan como un pitido continuo. Lancemos el RB y en el editor de la ventana inicial vayamos al menu edit y seleccionemos el item New Method. Le damos por nombre 'atencion' y cerramos el cuadro de dilogo. En esta Sub escribimos: dim antes, ahora, i as integer for i = 1 to 4 antes = ticks/60 do ahora=ticks/60 loop until ahora - antes > 1 beep next Ticks es una funcion que devuelve el nmero de partes de un segundo transcurridas desde que el ordenador se encendi. Si ticks se divide por 60, obtenemos los segundos transcurridos. Si se divide por 3600 (60 y nuevamente 60) se obtienen minutos. Naturalmente, ticks cambia constantemente, de forma que cuando es invocado devuelve un valor, pero si se invoca unos dcimas de segundo despues devuelve otro valor distinto y mayor. Tenemos un ciclo For....Next de cuatro vueltas, y en cada vuelta hay un comando 'beep'. En cada vuelta, la variable antes toma el valor de ticks y lo divide por 60 para obtener segundos. Se entra entonces en un ciclo Do....Loop del cual slo se sale cuando la diferencia entre ahora y antes sea mayor que 1, es decir, transcurrido un segundo. En ese momento, se ejecuta 'beep'. Bueno, pues si tenemos esta Sub, para llamarla desde cualquier lugar basta con escribir: atention y ser ejecutada. Y esto es vlido para cualquier otro mtodo que escribamos. En la siguiente sesin examinaremos en detalle el ciclo Do ------------------ LOOP. Fin de la sesin.

59////137

60////137

En esta sesin empezaremos por examinar el funcionamiento del ciclo Do...Loop. El significado podra traducirse como "Hacer....Bucle". Este es un ciclo o bucle que se repite indefinidamente a menos que se cumpla una condicin, la cual se incorpora en el inicio o en el final del ciclo: do until (condicion es cierta) ......................... loop o alternativamente: do ....... loop until (condicion es cierta) Until se traduce como "Hasta que" de forma que el ciclo es indefinido hasta que la condicin sea verdadera. Por ejemplo: dim n as integer n=0 Do until n = 5 n=n+1 beep loop este bucle se realizar un total de 5 veces hasta que se cumpla la condicin de que n tome el valor 5. Pero este otro dim n as integer n=0 Do n=n+2 beep loop until n = 5 no finalizar nunca pues nunca cumplir la condicin de que 'n' sea 5, y esto bloquear el programa y provocar que la aplicacin falle cuando 'n' alcance una valor fuera de los lmites de una variable integer. Se puede usar el trmino 'exit' para abandonar el ciclo de forma inmediata. Es preciso tener mucho cuidado con este ciclo o bucle Do....loop, pues si la condicin no se cumple, no se sale nunca del bucle, y el programa queda congelado, siendo necesario reiniciar el ordenador (o forzar salida). Para evitar situaciones de este tipo, se puede incluir en el bucle una palabra reservada del Real Basic: usercancelled. Esta palabra corresponde a una variable de tipo universal, booleana, que slo es cierta (true) cuando el usuario teclea comando + punto, e inmediatamente vuelve a su valor por defecto que es false. 61////137

Lo usual es incluir esta variable booleana en un condicional:

62////137

If usercancelled then rem ...lo que quiera el programador end En lo "que se quiera" se puede escribir 'quit' para finalizar, o 'exit' para abandonar el bucle, etc. Volviendo al bucle DO .... Loop, es importante notar que si la condicin 'until' est al principio del bucle, y se cumple, el ciclo no se realiza ni una vez, pero si la condicin est al final y se cumple, el ciclo se realiza una sola vez. Se puede notar examinando las dos alternativas siguientes: n = 22 Do until n > = 22 n=n+1 beep loop rem no se pasa por el bucle n = 22 Do n=n+1 beep loop until n > = 22 rem se pasa una vez por el bucle Una utilidad simple del ciclo es la que usamos en la sesin anterior: detener la ejecucin del programa un tiempo determinado, usando la funcin ticks. Pero hay utilidades muy diferentes que cada uno puede probar. Por ejemplo, se puede usar el ciclo Do...Loop en lugar del ciclo For...Next empleando una variable que cambia su valor en cada ciclo hasta que se cumple una condicin. Y esta variable no precisa ser un nmero entero, como precisa el ciclo For...Next; podemos usar una variable de tipo string o booleana o de otro tipo. Por ejemplo: dim s as string Do s = s + "a" loop until len(s)>20 En cada vuelta, la variable s aumenta en un carcter, y despus de un nmero alto de vueltas su longitud (len) superar el valor 20 lo que finalizar el ciclo.

Un elemento importante del RB es la lista de edicin, el denominado 'ListBox' que vimos en una sesin anterior. En esta sesin vamos a retomarlo dada su importancia y utilidad, y para examinar algunas cuestiones de su actividad. Un listbox es como una hoja de cuadrculas, cada una de las cuales viene determinada por una fila y una columna. Cada cuadrcula es una celda o 'cell', que est identificada, en este orden, por la posicin de fila y columna. Las filas, inicialmente, no existen, es preciso 63////137

crearlas durante la ejecucin del

64////137

programa. La primera fila es siempre cero, y la primera columna tambin. Entonces, la primera celda de un listbox, a la izquierda y arriba, es la 0,0. Vamos a usar una Listbox para ver y guardar un conjunto de datos y para ver el potencial que tiene para el programador. Lancemos el RealBasic. Alarguemos la ventana inicial del proyecto, y arrastremos sobre ella el icono del listbox. Segn la versin del RB puede haber uno o dos iconos para este elemento, pero da lo mismo cual incorporemos. Lo primero, cambiemos el nombre por defecto, listbox1, por 'lista'. Segundo, demos en propiedades la dimensin de 370 pixels tanto al width como al height del listbox. Tercero, en la propiedad 'ColumnCount' que indica el nmero de columnas, pongamos 5. Ahora vamos a dar nombre a las columnas; para ello, al tocar en la propiedad 'InitialValue' se abre un cuadro de dilogo, en el cual escribimos: Nmero Cuadrado Cubo Ptas. Pies cada palabra separada de la siguiente por un tabulador. Al pulsar el botn OK se cierra el dilogo y vemos las 5 columnas cada una con su encabezado. La propiedad 'HasHeading' debe ser true (estar seleccionada) para que haya un encabezado visible. Bueno, pues ahora pongamos un pushbutton en la misma ventana, con caption 'Rellenar', y otro con caption 'FIN'. En la sub action de este ltimo ponemos el comando 'quit'. Creemos ahora un mtodo para rellenar la lista de datos. En el men Edit elegimos New Method, y le damos por nombre 'Rellenar_Lista'. Ahora vamos a aadir cdigo para rellenar un total de 15 filas, lo que har un total de 15 por 5 = 75 celdas. Uno de los mtodos asociados a un listbox es 'addrow'. Este mtodo no es un evento, y no aparece en el editor correspondiente al listbox. Los mtodos que no son eventos, aparecen en la ayuda del RealBasic, y conviene leerlos para ir conociendo las potencialidades del RB, y tambin para aprender nuevas posibilidades. Como toda la ayuda est en ingls, conviene practicar un poco este idioma. El mtodo 'addrow' realiza dos funciones: como indica su nombre, aade una fila al listbox, que por defecto no tiene ninguna; pero adems, se aade un texto en la columna 0 de la fila recin creada. Si el listbox tiene varias columnas, el texto se aade a la celda recien creada de la columna 0. La sintaxis general sera la siguiente: listbox.addrow string El string que se aade es texto, que o bien puede teclearse entrecomillado, o puede estar almacenado en una variable string.

65////137

Nosotros no vamos a aadir nada, por lo que pondremos un texto vaco abriendo y cerrando comillas. Vamos con el cdigo de la Sub. Lo que pretendemos es rellenar la tabla o listbox de 15 por 5 con un nmero, su cuadrado, su cubo, su valor en euros y su valor en pies (suponiendo que el nmero original es en euros y metros). Los nmeros de partida sern el 5, el 10, el 15, etc., hasta el 75. Necesitamos hacer un ciclo o bucle que nos proporciones estos nmeros. Puede ser un ciclo For...next con una pequea modificacin que veremos luego. Una vez obtenido uno de estos nmeros, el 5, lo aadiremos a la primera columna del listbox, la celda 0,0. Luego necesitamos obtener su cuadrado, su cubo, etc. los cuales deben incorporarse en la misma fila 0 pero en las columnas 1,2,3 y 4, es decir, en las celdas 0,1 y 0,2 y 0,3 y 0.4. Con esto se cierra un ciclo, y se empieza el siguiente con el nmero 10, etc., etc. Veamos como: SUB Rellenar_Lista () dim i,fila as INTEGER For i = 5 to 75 step 5 lista.addrow "" lista.cell(fila,0) = str(i) lista.cell(fila,1) = str(i*i) lista.cell(fila,2) = str(i*i*i) lista.cell(fila,3) = str(i*166.386) lista.cell(fila,4) = str(i/3.28) fila = fila + 1 next End Sub El ciclo For...Next usa la variable control i. Esta variable toma su valor inicial como 5. Pero en cada ciclo, en lugar de incrementar su valor una unidad, el incremento es de 5 unidades de forma que su segundo valor es 10 en lugar de 6. Esta opcin de modificar el incremento viene especificada por el vocablo 'STEP' que podemos traducir como 'etapa'. Es decir, la variable i aumenta desde 5 hasta 75 en etapas de 5 unidades. El mtodo addrow ya lo hemos definido: aade una fila de celdas a la ListBox. Una vez aadida la fila, la tarea que nos queda es rellenar cada celda con el valor que deseemos, y eso lo realizamos con el mtodo 'cell', un mtodo de la listbox que simplemente aade un texto a la celda referenciada. Tal como se lee en el cdigo anterior, el mtodo 'cell' lleva unido un parntesis con la referencia fila y columna de la celda. Usamos una variable entera llamada 'fila' para aumentar de uno en uno el valor de las filas. El primer valor de la variable, por defecto, es cero, para rellenar la primera fila que recordemos es siempre la fila cero. En el segundo ciclo, la variable vale 1 como corresponde a la segunda fila del listbox. Por ltimo, en el botn con caption 'rellenar' escribimos, en la sub action:

66////137

SUB action() rellenar_lista me.visible = false End sub la primera lnea es para invocar el Mtodo anterior, y la segunda es para que el botn se haga invisible y no pueda ser pulsado ms de una vez. Al hacer correr el programa podemos ver como se rellenan de forma instantnea las celdas de la listbox. Grabemos el proyecto para reusarlo ms adelante. Como tarea sencilla, intenta reescribir la SUB Rellenar_Lista usando un ciclo DO...LOOP en lugar del ciclo FOR...NEXT. Una posible solucin se muestra a continuacin. SUB Rellenar_Lista () dim i,j,fila as INTEGER i=5 DO lista.addrow "" lista.cell(fila,0) = str(i) lista.cell(fila,1) = str(i*i) lista.cell(fila,2) = str(i*i*i) lista.cell(fila,3) = str(i*166.386) lista.cell(fila,4) = str(i/3.28) fila = fila + 1 i=i+5 LOOP UNTIL i = 75 END SUB El lenguaje basic es rico en comandos de forma que se puede llegar a un mismo resultado utilizando cdigo diverso. Vemos que tanto el ciclo FOR..NEXT como el DO..LOOP nos permiten realizar la misma finalidad.

67////137

Una de las acciones que interesa conocer a cualquier programador es por una parte poder incorporar datos procedentes de otras aplicaciones, y por otra poder exportar datos creados en nuestro proyecto. En definitiva, importar y exportar. Para manejar ficheros, discos, carpetas, etc, se precisa de otro tipo de variable, el denominado tipo 'FolderItem'. Tambin se considera que un 'FolderItem' es un objeto, pero nosotros lo trataremos como un tipo ms de dato. Un 'folderitem' tiene propiedades que pueden examinarse en la ayuda del RealBasic, y tambin tiene mtodos o subrutinas propias. Conviene que se lea cuidadosamente la ayuda del RealBasic y se hagan pruebas para saber cmo funcionan las distintas opciones. Un folderitem es como un objeto, ya que hace referencia a un volumen, a una carpeta o a un fichero, y en ese sentido podemos referirnos a propiedades tpicas de esos elementos del programa. Por ejemplo, el 'path' o camino jerrquico de un fichero, que es una descripcin del lugar exacto donde se encuentra, y que siempre debe informar de mayor a menor importancia: el volumen, el disco, la carpeta, la subcarpeta, etc. El folderitem ms bsico de trabajo es el fichero. Podemos crear un fichero o abrir un fichero existente. Si lo creamos es para meter datos en el, es decir, lo abrimos como entrada o 'input'. Tambin podemos abrir un fichero existente para aadirle datos, con lo cual lo abrimos tambin como input; pero si lo que pretendemos es leer a partir de l un conjunto de datos, es decir, para sacar datos del mismo, lo abrimos como output. Input hace referencia a escribir (write) datos en un fichero; output a leer (read) datos de un fichero. Si creamos un fichero, tenemos que especificar el tipo de documento que queremos que sea. Si pretendemos que slo lleve texto, ser tipo text; si llevar imgenes ser tipo jpeg, o pict, pero puede ser un movie, un sonido, etc. Vamos a poner un ejemplo simple, que nos permita grabar en un fichero los datos que tenemos en un listbox, como es el caso del proyecto de la sesin anterior. Los datos los grabaremos en el formato texto, que es el estndar usado para grabar datos tabulados y poder importarlos y exportarlos entre distintos programas, como excel, word, programas estadsticos, bases de datos, etc. Lo primero que necesitamos es elegir el formato y la extensin que llevar nuestro fichero. En el RealBasic, en el men Edit hay un tem llamado File Types (tipos de fichero). Al elegirlo se abre un dilogo en el cual aparece un botn que pone Add (aadir). Al pulsarlo, se abre un segundo dilogo en el que nos pide nombre, etc. A la derecha del editfield que dice nombre, aparecen dos flechas y al pulsar en ellas se nos muestra un largo listado de tipos de fichero preestablecidos. Seleccionamos uno que dice Text/Plain, es decir, texto plano o texto sin formato. Entonces aparece como Mac Creator un conjunto de 4 letras que corresponde a la aplicacin que crea el fichero. Si estas 4 letras fuesen 4 interrogantes, sera una forma de indicar que cualquier aplicacin puede intentar abrir nuestro fichero. El Mac Type (tipo de fichero) es TEXT, y las extensiones tpicas de un fichero solo texto son varias: txt, text, asc, etc. Cambiemos, por comodidad, el nombre Text/Plain por Text. Este ser el tipo de documento 68////137

que vamos a crear.

69////137

Abramos el proyecto anterior y aadamos un pushbutton al que daremos por caption 'Grabar' y por nombre 'GrabarBt'. En propiedades seleccionamos 'invisible', para que no pueda usarse al principio. En la Sub action de este pushbutton escribiremos el siguiente cdigo: SUB action() dim f as folderitem dim i,j as integer dim linea as string dim fichero as TextOutputStream f = GetSaveFolderItem("text","") if f < > nil then MiFichero = f.CreateTextFile rem text es el tipo antes definido. Se abre rem un dilogo para grabar nombre y lugar. rem si f no es nulo, por haber pulsado cancel.

for i = 0 to 14 'son 15 filas del listbox Linea = Lista.Cell (i,0) 'coge contenido celda primera columna for j = 1 to 4 ' para las otras 4 columnas Linea = Linea + Chr(9) + Lista.Cell (i,j) rem chr(9) es el carcter tabulador next Fichero.WriteLine Linea 'escribe el contenido de linea al fichero Linea = "" 'vaca el contenido variable linea Next Fichero.Close ' cierra fichero: importante para evitar error end if End Sub Vamos a comentar por partes. Primero, la variable f es el folderitem, y se dimensiona como otra variable. GetSaveFolderItem es una funcin que nos abre un dilogo para elegir un nombre y lugar para grabar. Esta funcin tiene dos variables, una es el 'tipo' de fichero, que ya definimos antes (text), y la segunda, es el nombre por defecto que queremos dar al fichero. Si no tenemos nombre por defecto, ponemos un string vaco, es decir, abrir y cerrar comillas. Si en el dilogo el usuario pulsa cancel, f es nulo, por eso siempre se pone la condicin de que f no sea nulo (nil) antes de intentar hacer algo con l. Una vez tenemos f con un valor (que si queremos podemos examinar), definimos una variable TextOutputStream, es decir, un fichero de salida. Y para crearlo usamos la funcion createTextFile propia de un objeto folderItem: MiFichero = f.createTextFile. Una vez creado el fichero, al que hemos dado por nombre MiFichero, podemos grabar datos en el con los mtodo Write o writeLine del TextOutputStream (ver siempre la ayuda del RB). Hemos usado el segundo, writeline, porque al escribir el dato en el fichero aade un retorno de lnea, un fin de linea, al string o texto que grabamos.

70////137

Para generar los strings que queremos grabar, hemos usado dos ciclos For...Next anidados. Esta tcnica no la habamos usado hasta ahora, pero es muy simple: El primer ciclo For ... Next se inicia con la variable control i que toma su primer valor, en este caso cero. Entonces se inicia el segundo ciclo con la variable control j que tambin vale cero. Este segundo ciclo se completar tomando j los valores 1,2,3 y 4. Eso quiere decir, que cuando llamamos a una celda del listbox para tomar su contenido, la primera celda es 0,0, la segunda 0,1 etc, hasta 0,4 que es la ltima de la fila 0. Durante la ejecucin del segundo ciclo, la variable string 'linea' que inicialmente est vaca, va concatenando (uniendo) su valor ms el valor de una celda, ms un tabulador; es decir, en cada vuelta crece con el valor de cada celda y un tabulador. Para insertar el tabulador, ya que este no tiene representacin de teclado, se usa el comando basic CRH (character) que devuelve el string correspondiente al cdigo ascii introducido. Para tabulador, el cdigo es 9. Ahora salimos del segundo ciclo, grabamos 'linea' en el fichero, vaciamos la variable 'linea' y llegamos al next del primer ciclo, con lo que iniciamos todo el proceso de nuevo pero ahora con la variable i tomando el valor 1, etc., etc. Bueno, pues slo nos queda un detalle. En la Sub Action del botn con caption "Rellenar" aadimos como ltima lnea: GrabarBt.visible = true para que una vez rellena la ListBox de datos, podamos grabarlos, pero no antes; evidentemente, por eso este botn inicialmente era invisible. Ahora podemos probar si nuestro programa funciona. Si todo va bien, se crear un fichero tipo texto con el nombre que le demos y en el lugar elegido. Este fichero se podr abrir con simpleText, con TextEdit, con Word, Bbedit, etc. y lleva los datos de nuestra listbox tabulados por lo que pueden abrirse en excel, por ejemplo, y ver los datos clasificados por celdas.

Soy consciente que la sintaxis necesaria para grabar y leer ficheros es un poco difcil de recordar. Pero para eso estn los mtodos propios. Uno puede preparar un mtodo para abrir y leer un fichero, y este mtodo puede usarse en distintos proyectos. Lo mismo para el caso de grabar datos, tabulados o no. Vamos ahora a ir a la inversa. Vamos a abrir el fichero texto que hemos creado y leer su contenido en el RealBasic. Hagamos un nuevo proyecto y en la ventana inicial, como siempre, dos botones, uno para finalizar el programa con el cdigo asociado 'quit' y otro al que pondremos por caption 'Importar'. Aadimos tambin un statictext al que pondremos por nombre 'Listado', y en sus propiedades seleccionamos como true la propiedad 'multiline'. Las dimensiones de 71////137

este elemento sern 380 x 380 para que pueda mostrarnos todo el contenido del fichero. En la sub action del botn 'Importar' escribimos este cdigo: SUB action() dim f as folderitem dim contenido as string dim Mifichero as TextInputStream f = GetOpenFolderItem("text") if f < > nil then mifichero = f.OpenAsTextFile contenido = Mifichero.readline ' luego lo cambiamos por Mifichero.readAll Listado.text = contenido Mifichero.close end if END Sub Al correr el programa, cuando invocamos la funcin GetOpenFolderItem se nos abre un cuadro de dilogo que nos permite abrir aquellos ficheros que correspondan con el 'tipo' fijado entre parntesis. Como queremos abrir un fichero tipo texto, hacemos como en el proyecto anterior, en el men edit en file Types elegimos text/plain y luego modificamos este nombre a nuestro gusto, dejndolo en text. Como el folderItem se abre como input, el fichero asociado debe ser del tipo TextInputStream. Ponemos la condicin de que f no sea nulo, y abrimos el folderitem como texto con el mtodo 'OpenAsTextFile'. Una vez abierto Mifichero, podemos leer una lnea (read) de su contenido, una lnea con la marca de final de linea (readline), o todo el fichero (readall). Utilizaremos inicialmente 'ReadLine' para leer la primera linea del fichero, que recoje texto y tabuladores; y ms adelante cambiamos el cdigo a 'ReadAll' para cargar todo el fichero de una sola vez. Esta funcin, readline o readall, la pasamos a la variable contenido, y por ltimo, pasamos el valor de la variable 'contenido' al texto del statictext mediante la asignacin listado.text = contenido. Cerramos el fichero y podemos hacer correr el programa para ver el resultado. Probamos luego con el mtodo 'readall'. Tambin podemos importar los datos en un listbox, y verlos en un sistema de filas y columnas. A estas alturas del cursillo, ya debes de saber cmo programar esta alternativa. En cualquier caso, si abrimos el fichero que exportamos anteriormente, podremos examinar los datos que creamos en la sesin anterior.

72////137

NOTA : Cuando se copia cdigo de un procesador de texto, (por ejemplo, de este fichero .doc) y se pega en algn lugar del RealBasic, hay que poner cuidado, ya que hay caracteres del procesador de textos que no son admitidos por el RB y nos generan errores sin que sepamos porqu ocurren. Por ejemplo, las comillas de un procesador como el Word o AppleWorks, son especiales, tipogrficas ( a no ser que se especifique en preferencias del procesador), y no son las mismas que aparecen en el RealBasic cuando se pulsa la misma tecla. De la misma forma, hay errores "tontos" que no somos capaces de apreciar y solo dan dolores de cabeza. Por ejemplo, el signo de desigualdad se escribe como <> en este orden, no en el contrario, y SIN espacio entre ambos caracteres. Para expresar, como una condicin, que A es mayor o igual que B, no puede escribirse A = > B ya que la notacin correcta es A > = B. Si lo escribimos incorrectamente se genera un error que a veces cuesta encontrar. Fin de la sesin.

73////137

Con las sesiones que ya hemos visto hasta aqu, creo que estamos preparados para asumir desafos ms importantes que los proyectos que hemos realizado. Vamos a emprender un proyecto de ms envergadura que adems de hacernos trabajar con lo ya aprendido, nos permita utilizar nuevos mtodos del RealBasic, y finalmente nos sea de utilidad. Vamos a hacer un juego real, simple, pero que podemos pasar a nuestros conocidos, y puede divertir a nuestros hijos. El juego lo vamos a llamar "Colores". Se trata de un juego clsico, en el que aparecen colores en distintas zonas de la pantalla y debemos memorizarlos para hacer parejas del mismo color. Bueno, empecemos por el diseo del proyecto. Este paso es de los ms importantes, pues es la base del trabajo sobre el cual centrarnos. Si el diseo est mal hecho, el programa ser confuso, y funcionar mal. Es importante tomar papel y lpiz y empezar a pensar en lo que pretendemos hacer y en cmo conseguirlo. Planteemos de entrada cuntos objetos con color va a tener el juego. Pongamos que 20. Es decir, el usuario deber hacer 10 parejas que coincidan en color, y habr ganado. Entonces necesitamos 20 objetos y 10 colores. Los objetos pueden ser todos iguales, rectngulos, por ejemplo, que es un objeto del RB. Bueno, pues debe de haber, para cada color, 2 rectngulos iguales. Adems necesitamos otro color para cuando el rectngulo no muestre color, y este podra ser el blanco. Los rectngulos debern mostrarse en pantalla, pero ocultando su color real. El usuario podr tocar con el ratn y seleccionar dos rectngulos de los 20 posibles. Estos dos rectngulos debern mostrar el color real que tienen. Si ambos tienen el mismo color, la pareja debe desaparecer. Si no coinciden en color, deben ocultarlo, hacerse blancos de nuevo, y permanecer en pantalla. Con este esquema de trabajo, la accin (evento) que realiza el usuario ser tocar con el ratn alguno de los rectngulos. En este evento deberemos poner el cdigo para que todo funcione. Lo primero es lanzar el RB y crear el proyecto. Lo llamaremos "Colores". En la ventana inicial window1 aadiremos un rectngulo desde la ventana de objetos. Le cambiaremos el nombre, que por defecto ser 'rectangle1', y pondremos 'cuadro' . Lo dimensionaremos con 60 de width y 60 de height. En la ventana propiedades, debajo del nombre (name) aparece la palabra 'index'. Si ah ponemos un nmero, estaremos creando un 'array' (conjunto, matriz, vector) de elementos rectangle. Bueno, pues pongamos un cero. Nuestro rectngulo llevar como referencia 'cuadro(0)'. Si en la ventana window1 seleccionamos el rectngulo y lo duplicamos (mediante el men, o pulsando comando + D) tendremos un segundo rectngulo referenciado como 'cuadro(1)'. Seguimos pulsando comando + D hasta llegar al rectngulo con index 20.

74////137

Podemos eliminar el primer rectngulo que hicimos (index=0) y nos quedarn en pantalla 20 rectngulos, denominados desde cuadro(1) hasta cuadro(20). Es decir, un array de elementos 'rectangle'. Ahora podemos hacer referencia o llamada a cada elemento simplemente cambiando el valor de index. Coloquemos estos 20 rectngulos en la ventana, en 5 filas de 4 elementos, ordenadamente, dejando un espacio fijo por cada lado. Aadamos en la ventana dos botones, uno que ponga FIN y otro que llamaremos jugarBt y que lleve por titulo JUGAR. En la sub action del primer botn aadamos el comando quit. Necesitamos los 10 diferentes colores para nuestro juego. Vamos a definirlos, intentando que sean suficientemente diferentes para que el usuario los identifique sin dificultad. Un color es un nuevo tipo de variable, la variable 'color'. Un color se puede definir mediante la unin de rojo (red), verde (green) y azul (blue). Es la definicin RGB. Para cada luz, los valores van desde 0 a 255. Para blanco, cada luz lleva el mismo valor. Blanco intenso ser definido por los 3 valores que siguen: rgb(255,255,255) cada valor separado por una coma del anterior. Para negro pondremos todo a cero : rgb(0,0,0) mientras que gris ser un valor intermedio pero igual para cada luz: rgb(127,127,127) Una forma de saber los 3 valores de rgb que toma un determinado color, es usar el propio RealBasic. Si en window1 seleccionamos un rectngulo, en la ventana propiedades aparece fillcolor, que se refiere el relleno de color del elemento. Si tocamos ah, se nos abre una ventana en la que aparecen varias opciones de seleccionar un color. La segunda opcin empezando por la izquierda son unos 'sliders' (cursores), que seleccionamos y elegimos despus la opcin 'rgb sliders'. Moviendo los 'sliders' vemos colores distintos y los valores RGB correspondientes. Por ejemplo, un tono rojo intenso tiene rgb(255,0,0). Antes de definir los colores, necesitamos una variable para almacenarlos. Usaremos una variable global de ventana, por lo tanto elegimos del men del editor 'New property'. Creamos una variable: tono(20) as color

75////137

y otra ms blanco as color Como los colores los tenemos que definir, podemos hacerlo en la SUB Open de la ventana window1. Hacemos doble click en la ventana, y en editor, en la sub open escribimos: tono(1)=rgb(0,0,0) 'negro tono(2)=rgb(255,0,0) 'rojo tono(3)=rgb(0,255,0) 'verde tono(4)=rgb(0,0,255) 'azul tono(5)=rgb(255,255,0) 'amarillo tono(6)=rgb(255,128,0) 'naranja tono(7)=rgb(0,255,255) 'azul claro tono(8)=rgb(172,117,0) 'ocre tono(9)=rgb(150,150,150) 'gris tono(10)=rgb(255,0,255) 'rosa Como hay 20 rectngulos necesitamos 20 elementos de color , es decir, hasta 'tono(20)', Pero ya que hay un mismo color por cada pareja de rectngulos, los tonos del 11 al 20 son los mismos colores del 1 al 10 ya definidos. Entonces podemos aadir ms cdigo y la sub quedar as: Sub Open() dim i as integer tono(1)=rgb(0,0,0) 'negro tono(2)=rgb(255,0,0) 'rojo tono(3)=rgb(0,255,0) 'verde tono(4)=rgb(0,0,255) 'azul tono(5)=rgb(255,255,0) 'amarillo tono(6)=rgb(255,128,0) 'naranja tono(7)=rgb(0,255,255) 'azul claro tono(8)=rgb(172,117,0) 'ocre tono(9)=rgb(150,150,150) 'gris tono(10)=rgb(255,0,255) 'rosa for i=1 to 10 tono(10+i)=tono(i) next blanco=rgB(255,255,255) End Sub Ya tenemos los colores definidos, los 10 colores por adivinar, y el blanco como fondo cuando no hay color. Ahora necesitamos asignar los colores a los rectngulos de una forma aleatoria, es decir, que no se sepa el color de cada uno, y que cada vez que se juegue el orden sea diferente.

76////137

Para crear elementos numricos al azar se usa la variable random (o la function rnd). Esta variable 'random' nos permite obtener nmeros al azar entre los lmites que designemos. Por ejemplo, sacar un elemento de la variable 'tono' que sabemos empieza en 1 y acaba en 20 (ms correcto, empieza en cero). Vamos a examinar una function y un mtodo asociados con los array. Uno es 'ubound' que nos devuelve el valor ms alto que tiene una variable tipo array. Por ejemplo, si definimos limite como variable integer y escribimos: limite = ubound(tono) el valor de limite ser 20, pues es lo que hemos dimensionado para esta variable. Un mtodo de arrays muy interesante es 'remove' , que permite eliminar un elemento cualquiera del array, a la vez que disminuye la dimensin (y el ubound) del array: tono.remove posicion siendo posicion una variable integer que indica el elemento del array que queremos eliminar. Por ejemplo, si escribimos tono.remove 5 estamos eliminando el elemento 5 (color amarillo) del array tono. Bueno, pues vamos a crear un mtodo para asignar al azar colores a los rectngulos. Para ello seleccionamos "New method" y le damos por nombre 'pintar', sin aadir parmetros. Lo que pretendemos es que para el array de rectngulos que va de 1 a 20, exista otro array de colores que vaya de 1 a 20, y cuando llamemos a un rectangulo por su nmero del array, por ejemplo el 14, encontremos su color asociado en el array de colores en posicin 14. Vamos a ver el cdigo asociado a la Sub pintar: Sub Pintar() dim azar as random dim numero,i,ultimo as integer for i=1 to 20 cuadro(i).visible=true next azar=new random for i=1 to 20 ultimo=ubound(tono) tono.remove numero numero=azar.inRange(1,ultimo) cuadro(i).fillColor=tono(numero)

77////137

next redim tono(20) for i=1 to 20 tono(i)=cuadro(i).fillColor cuadro(i).fillColor=blanco next End Sub El primer ciclo For...Next hace que los rectngulos (array cuadro) sean visibles. Luego se define una variable random, utilizando el operador 'New' que es necesario para crear un nuevo objeto. El siguiente ciclo conviene examinarlo en detalle. La variable ultimo corresponde al ltimo elemento del array 'tono' (que recordemos que almacena los colores). Inicialmente, ultimo valdr 20. Numero es un integer obtenido al azar entre 1 y ultimo, es decir, entre 1 y 20. Entonces al cuadro(1) se le asigna este color utilizando la propiedad 'fillColor' que proporciona un color de relleno al rectngulo (u otro elemento de tipo Rect). La sentencia "tono.remove numero" elimina un elemento de 'tono', aquel que est en posicin 'numero', que es precisamente el color que acabamos de usar. Es por tanto lgico quitarlo del array de colores, ya que ha sido asignado a un rectngulo. Como eliminar un elemento de 'tono' reduce en una unidad su dimensin, en el segundo ciclo de For...Next, ultimo valdr 19, y el nmero al azar ser ahora entre 1 y 19. En cada ciclo, se reduce la dimensin del array, de forma que en el ciclo 20 el array 'tono' solo llevar un elemento que se asignar al cuadro(20). El mtodo 'redim' lo que hace es redimensionar el array 'tono' y devolverle el tamao 20 que haba perdido con los consecutivos mtodos 'remove'. Finalmente, el ltimo ciclo For...Next recoge en el recin dimensionado array 'tono' los colores asignados a los rectngulos para su uso posterior, a la vez que pone de color blanco los 20 rectngulos de window1 para que el usuario no vea los colores que guardan (en tono) cada uno de ellos. Este mtodo 'pintar' lo que hace, en definitiva, es asignar colores al azar a los rectngulos, y lo podemos incluir en la sub action del botn JugarBt : Sub action() pintar End sub Tambin lo vamos a incluir en la Sub Open de la ventana inicial, para que incluso sin pulsar el boton 'Jugar' el usuario pueda de forma inmediata tocar los rectngulos y empezar el juego: Sub Open()

78////137

dim i as integer tono(1)=rgb(0,0,0) 'negro tono(2)=rgb(255,0,0) 'rojo tono(3)=rgb(0,255,0) 'verde tono(4)=rgb(0,0,255) 'azul tono(5)=rgb(255,255,0) 'amarillo tono(6)=rgb(255,128,0) 'naranja tono(7)=rgb(0,255,255) 'azul claro tono(8)=rgb(172,117,0) 'ocre tono(9)=rgb(150,150,150) 'gris tono(10)=rgb(255,0,255) 'rosa for i=1 to 10 tono(10+i)=tono(i) next blanco=rgB(255,255,255) pintar End Sub El siguiente paso es preparar la interaccin del usuario con el programa. La forma ms lgica es, como planeamos, que cuando el usuario toque un rectngulo con el puntero del ratn se muestre el color que lleva asociado. Pero solo puede tocar dos rectngulos. Si el color es el mismo, ambos rectngulos deben eliminarse y un contador deber aumentar en una unidad. Si son de diferente color, deben permanecer en pantalla pero volverse blancos de nuevo. Necesitamos una variable global de ventana para saber si el usuario ha seleccionado un solo rectngulo o dos. Vamos a crear esta variable global de tipo integer con el nombre 'seleccionados'. Tambin necesitamos saber cual ha sido el primer rectngulo seleccionado por el usuario para compararlo con el segundo rectngulo. Debemos tambin tomar la precaucin de que el usuario no toque dos veces el mismo rectngulo, pues entonces los colores coincidirn, evidentemente, y ser un error. Creamos entonces una variable global integer que llamaremos 'primero' en la que guardaremos el nmero del rectngulo seleccionado en primer lugar. El evento correspondiente a tocar el rectngulo con el ratn es 'MouseDown'. Seleccionamos este evento de cualquier rectngulo, y en la function escribimos: Function MouseDown(index as integer, X as integer, Y as integer) as boolean if seleccionados = 1 and index = primero then return true end cuadro(index).fillColor=tono(index) self.refresh seleccionados=seleccionados+1

79////137

if seleccionados=2 then seleccionados=0 if tono(index)=tono(primero) then cuadro(index).visible=false cuadro(primero).visible=false beep else cuadro(index).fillColor=blanco cuadro(primero).fillColor=blanco end return true end primero=index End function Esta function recibe en 'index' el nmero del elemento array seleccionado, es decir, el nmero del rectngulo seleccionado por el usuario. En la variable primero, guardaremos el nmero del rectngulo previamente seleccionado. El primer paso es examinar si index es igual a primero, es decir, si el usuario selecciona el mismo rectngulo dos veces. Si tal es el caso, se sale de la function sin hacer nada (return true). Si el rectngulo seleccionado es diferente del previamente seleccionado, se sigue al paso siguiente, que consiste en hacer visible el color del rectngulo seleccionado. Para hacerlo visible, usamos 'fillColor' y el color correspondiente obtenido del array 'tono'. La siguiente lnea de cdigo es necesaria para ver de forma inmediata este color. La sintaxis es window.refresh. En nuestro caso usamos el termino genrico 'self', que hace referencia a la ventana en la que trabajamos (window1). Este mtodo 'refresh' es una forma de refresco o repintado de la ventana de forma inmediata. Aumentamos en una unidad la variable 'seleccionados', que si vala 0 o 1 pasar a valer 1 o 2, y de esta forma sabremos si hay que comparar o no los colores de los rectngulos. Si seleccionados vale 2 , se comparan los colores de los dos rectngulos mediante if tono(index)=tono(primero) then y si son iguales se hacen invisibles los rectngulos correspondientes, y se sale de la Function con return , y si no son iguales simplemente se les deja de color blanco e igualmente se abandona la function usando return. La ltima lnea de cdigo slo se realizar cuando seleccionados valga 1, y en este caso se guarda en la variable 'primero' el nmero del rectngulo seleccionado para la posterior comparacin.

80////137

Podemos ya probar si nuestro programa funciona. Enseguida notamos que al hacer la seleccin del segundo rectngulo no podemos apenas ver el color pues el programa corre muy deprisa y enseguida los vuelve blancos. Necesitamos una pausa para poder ver el color del segundo rectngulo. Vamos a aadir un ciclo DO...LOOP con la instruccin ticks, que corresponde a un integer que mide el nmero de sesentavos de segundo transcurridos desde que se arranc el ordenador. Si dividimos por 60 tendremos segundos. La Sub quedara as: Function MouseDown(index as integer, X as integer, Y as integer) as boolean dim t1,t2 as integer if seleccionados = 1 and index = primero then return true end cuadro(index).fillColor=tono(index) self.refresh seleccionados=seleccionados+1 if seleccionados=2 then seleccionados=0 t1=ticks/60 do t2=ticks/60 loop until t2-t1>2 if tono(index)=tono(primero) then cuadro(index).visible=false cuadro(primero).visible=false beep parejas=parejas+1 else cuadro(index).fillColor=blanco cuadro(primero).fillColor=blanco end return true end primero=index END Sub Ahora quedarn visibles los dos rectngulos mostrando su color durante dos segundos. Probemos que funciona. Necesitamos un contador del nmero de parejas de rectngulos adivinados para saber cuando se ha finalizado. Y tambin podemos aadir un contador del nmero

81////137

de intentos que hace el usuario para saber si su eficacia memorstica es buena o mala. En la ventana window1 vamos a aadir dos statictext. En uno pondremos como 'text' lo siguiente: "N de intentos" y en tamao de texto 20 por ejemplo. El segundo lo llamaremos 'IntentoSt' y como texto, de tamao 24, podemos poner un cero. Creamos una variable global tipo integer que llamaremos 'intentos'. Modificamos la Sub action del botn 'Jugar' para poner las variables a cero: Sub Action() parejas=0 intentosSt.text="0" intentos=0 pintar me.visible=false End Sub Modificamos tamben la Sub MouseDown como sigue: Function MouseDown(index as integer, X as integer, Y as integer) as boolean dim t1,t2 as integer if index=primero then return true end cuadro(index).fillColor=tono(index) self.refresh seleccionados=seleccionados+1 if seleccionados=2 then seleccionados=0 intentos=intentos+1 intentosSt.text=str(intentos) t1=ticks/60 do t2=ticks/60 loop until t2-t1>2 if tono(index)=tono(primero) then parejas=parejas+1 else cuadro(index).fillColor=blanco cuadro(index).visible=false cuadro(primero).visible=false beep

82////137

cuadro(primero).fillColor=blanco end return true end primero=index END Sub Ahora necesitamos una forma de finalizar el juego, y una opcin para empezarlo de nuevo. Podemos usar la Sub MouseMove de la ventana window1. Esta Sub corresponde al evento de mover el ratn por parte del usuario, y devuelve las coordenadas del mismo como variables X e Y. Como el ratn se mueve continuamente, esta Sub es llamada por el RB de forma continua. Podemos aadir una lnea de cdigo que slo realice una accin cuando acabe el juego: Sub MouseMove(X as integer, Y as integer) if parejas=10 then pushButton2.visible=true End Sub Ahora, cuando el usuario termine el juego, el botn 'Jugar' se har visible y podr jugar de nuevo. Finalmente, podemos aadir una instrucciones. Creamos una ventana nueva, window2 y la renombramos como 'InstruccionesWd'. Sobre ella aadimos un statictext al que damos un tamao que ocupe prcticamente toda la ventana, y seleccionamos como 'true' la propiedad 'multiline'. Aadimos un botn que lleve por texto 'OK' y seleccionamos como true la propiedad 'default' del botn. En la Sub action de este botn escribimos: SUB action() self.close End Sub que hace que la ventana se cierre. En la ventana inicial 'window1' aadimos un tercer botn al que ponemos por texto 'Instrucciones' y en la sub action de este nuevo botn escribimos: Sub Action() InstruccionesWd.showmodal End Sub El mtodo de ventana 'showmodal' indica que la ventana aparece y el programa se detiene hasta que la ventana se cierra (si slo se pone 'show' la ventana permanece abierta y el usuario puede cambiar de una a otra ventana, lo que no nos interesa).

83////137

Bueno, ya est acabado el proyecto. Ahora solo falta compilarlo como aplicacin independiente. Compilarlo significa crear una aplicacin que "corra" sin necesidad del Real Basic, autnoma. Si vamos al men File del RB, encontramos un tem denominado 'Build Settings...' que si lo seleccionamos nos permite elegir si compilar para el sistema classic, para el sistema X o para Windows. Podemos elegir nombre y poner un icono a nuestro gusto. Conviene poner el nmero de versin que se ha realizado, e incluso cuatro caracteres que correspondan al creador de la aplicacin. Una vez se han establecido estas 'settings', elegimos el tem 'Build Application' y se nos crea una aplicacin independiente. Ya podemos jugar tranquilamente a los "Colores", nuestra primera aplicacin seria. En cualquier caso, nuestro proyecto tiene todava inconsistencias, y puede mejorarse bastante. Por ejemplo, aadir una msiquilla cuando se finalice, o un mensaje de felicitacin. Pero esos detalles quedan para el alumno.

84////137

El juego "Colores" realizado en la sesin anterior ha sido un buen inicio para darse cuenta de las dificultades que encierra hacer un proyecto: planificar, hacer mdulos de trabajo, probar rutinas, aadir elementos de interface, etc. Pues vamos a continuacin a abordar un proyecto de veras complejo, que plantea dificultades que en ocasiones no se detectan al hacer el diseo, y que nos va a permitir seguir aprendiendo la versatilidad del RealBasic como herramienta para llevar a buen trmino nuestras intenciones. El proyecto que propongo realizar es la construccin de una calculadora. Es algo que nunca he realizado, por lo que me siento obligado a pensar en cmo organizarlo, qu elementos se precisan, etc. Comencemos a pensar en ello. Lo primero, es que la calculadora ser una ventana con una serie de botones y un visor o pantalla. La pantalla, lugar donde presentaremos la entrada de datos numricos y la salida de resultados, podra ser un statictext. Un problema es que necesitamos que el texto aparezca a la derecha de la pantalla, es decir, justificado a la derecha. Si miramos en la ayuda del RealBasic, vemos que hay una propiedad llamada 'textalign' que permite justificar el texto. Bueno, pues inicialmente, la pantalla ser un editfield. Necesitamos tambin una serie de botones. Para empezar, 10 botones para representar los nmeros del 0 al 9. La funcin de estos botones es simple: cuando se pulsen, debe aparecer el dgito correspondiente en la pantalla, y debe recordarse en memoria para posibles operaciones. Se precisa tambin un botn para introducir nmeros negativos, y el punto para decimales (ya van 12). Luego estn las operaciones bsicas de matemticas: suma, resta, multiplicacin y divisin. Y un botn para obtener el resultado de la operacin. Y necesitamos al menos dos botones ms, uno para borrar todo lo realizado, y otro para borrar los ltimos dgitos introducidos, es decir, borrado parcial ( y son 19). Y tambin el abrir y cerrar parntesis (21). Estos seran los botones bsicos, un total de 21. Podemos tambin introducir los botones de acmulo en memoria, introduccin y borrado en memoria, recuperacin de memoria y borrado de memoria. Total 25 botones. Si ms adelante queremos aadir otros botones con funciones especiales, no tiene porqu haber problemas. Pero la interface no es lo ms importante de un programa como ste. El primer planteamiento al hacer una aplicacin debe ser el esquema de lo que se precisa para su funcionamiento. La interface, lo que se muestra al usuario tambin es importante, pero es algo que se puede ir mejorando poco a poco. Entonces empecemos por pensar qu es una calculadora, y qu es lo que debe 'hacer'. Ya hemos dicho que se necesitan un conjunto de botones que proporcionan la entrada de nmeros y los operadores matemticos, y adems una pantalla de salida en la que se muestra el resultado. Y ahora la cuestin principal: cmo hacemos para realizar los clculos usando instrucciones en lenguaje basic. A priori, parece relativamente fcil: si tengo dos variables 85////137

numricas a y b y las quiero multiplicar, utilizo una tercera variable y escribo:

86////137

resultado = a * b Es una asignacin del lenguaje basic del resultado de una operacin simple. Pero no siempre ser tan fcil. Por ejemplo, sabemos que en matemticas los operadores de multiplicacin (*) y divisin (/) se efectan antes o tienen prioridad sobre los operadores suma (+) y resta (-). Entonces una vez que el usuario teclea un signo de suma, debemos esperar para saber qu teclea a continuacin. Por ejemplo, en esta secuencia de tecleo: 4+7 antes de efectuar el clculo (11), debemos esperar por si acaso el usuario teclea 4+7*2 ya que entonces el resultado correcto ser 4 + 14 = 18 En resumen, no se trata slo de ir realizando clculos segn el usuario teclea cualquier cosa. Es preciso seguir un procedimiento para interpretar correctamente las reglas matemticas y hacer los clculos correctos. Adems est el tema de los parntesis: siempre se debe evaluar el contenido de un parntesis antes de cualquier otra operacin. Por ejemplo: 8 - 2 * (8 + 7) + (23 - 4) es necesario evaluar el primer parntesis con lo cual nos quedara 8 - 2 * 15 + (23 - 4) y luego se efectuara el cmputo del segundo parntesis quedando: 8 - 2 * 15 + 19 En resumen, antes de empezar a programar debemos enfrentarnos con los pasos necesarios para afrontar este problema. Hay dos alternativas generales de entrada y proceso de datos en una calculadora. La clsica es ir efectuando clculos segn se teclea, dejando algunos clculos pospuestos hasta evaluar un parntesis, etc. La otra alternativa, ms moderna, consiste en teclear un conjunto mas o menos largo de nmeros y operadores y luego evaluar la expresin de una sola vez. La ventaja de este mtodo es que el usuario puede ver todo el conjunto de instrucciones que teclea antes de ejecutar la orden de evaluar. E incluso puede editar lo que ha escrito, y si es incorrecto, corregirlo. En el presente proyecto, vamos a optar por esta segunda alternativa. Lo mejor es ponerse a examinar los problemas que pueden surgir y elaborar una estrategia de solucin que sea asequible a los comandos basic.

87////137

Lo primero es darse cuenta de las alternativas que puede teclear el usuario. Al ir pulsando teclas y operadores, en pantalla deben aparecen todas sus acciones como un string mas o menos largo: 45 - 8 / 3 + 0.048 * 4 - (66 - 44) / 7 Supongamos este string. Consta de 24 caracteres. Encontramos varios operadores y un parntesis. Pero los comandos del lenguaje Basic no realizan estas operacin compleja, por lo que tenemos que ingeniarnoslas para extraer informacin de este string, evaluarla y obtener una respuesta numrica correcta. Entre varias alternativas, una opcin es buscar signos mas (+) y menos (-) contiguos, y extraer los caracteres que estn entre ellos, pero sin romper los parntesis. Partiendo del string anterior, antes del primer nmero no hay un signo visible, pero sabemos que existe un signo mas aunque no se escriba. Si lo aadimos nos queda as: + 45 - 8 / 3 + 0.048 * 4 - (66 - 44) / 7 Al descomponer este string en base a estos signos (+ -) obtenemos estos 8 fragmentos: + 45 8/3 + 0.048 * 4 (66 - 44) / 7 Es decir, los operadores mas y menos seran los lmites entre fragmentos. Si exceptuamos el parntesis, cada fragmento solo lleva operadores para multiplicar y dividir, por lo que podemos crear un mtodo con el cdigo necesario para evaluar la expresin del fragmento numricamente. El parntesis es diferente, pues puede llevar en su interior signos mas y menos, de forma que debemos tratarlo como otro string original, extraer sus fragmentos, evaluar cada uno y finalmente calcular el valor numrico. Vamos a expresar los pasos anteriores en un esquema de flujo. Los pasos son: (1) obtener el string tecleado por el usuario (2) examinar si el string lleva parntesis (3) si hay parntesis, se extrae el string del primer parntesis, y este string se enva al paso 5, y una vez procesado y valorado numricamente, el flujo del programa vuelve al punto 2 para redisear el string. (4) si no hay parntesis se pasa al paso 5. 88////137

(5) Se examina si el string lleva fragmentos limitados por ms y menos

89////137

Si el string lleva fragmentos, se extrae el contenido del primer fragmento y se enva al punto 8, y una vez procesado, el flujo del programa vuelve al punto 5 para redisear el string. (7) Si no lleva fragmentos, el string completo se enva al paso 8. (8) el string se descompone en fragmentos limitados por signos de multiplicacin (9) Si hay varios fragmentos, cada uno se enva a al punto 11, y una vez procesado, se valora el resultado y el flujo del programa vuelve a este punto 9 para valorar numricamente el string.
(6) (10)

12

Si solo hay un fragmento, el string se enva a 11, se recibe el resultado y se pasa a

Se realizan las divisiones que estn indicadas en el string. Se devuelve un valor numrico. (12)Se finaliza el proceso, devolviendo el valor final numrico del string
(11)

Este flujo de informacin del programa se puede representar grficamente con mayor o menor acierto, pero es siempre una buena idea trabajar sobre un esquema de este tipo para darse cuenta de las diferentes alternativas y problemas que pueden surgir. Se muestra a continuacin un esquema grfico realizado con AppleWorks, y que ocupa una pgina entera: string inicial (frmula) I buscar parntesis .(A) I sacar contenido parntesis como un string Extraer string del fragmento 1 Busca ados agmento y s - B Multiplicar/Dividir I RESULTADO

SI volver a nuevo Unir con resto fragmen, -SOLUCION Problemas que surgen: En una frmula de clculo, se puede empezar con un signo menos. Por ejemplo: 90////137

- 45 - 8 / 3 + 0.048 * 4 - (66 - 44) / 7 pero entonces, los fragmentos cambian un poco, pues el primer fragmento ya no sera 45, sera el signo menos (-) y 45 sera el segundo fragmento.

91////137

Para evitar este problema, cuando se inicie la frmula con un nmero positivo, aadiremos un signo '+' para que nuestro cdigo de extraccin de fragmentos funcione uniformemente. Es decir, modificaremos el string inicial as: + 45 - 8 / 3 + 0.048 * 4 - (66 - 44) / 7 Otro problema es el uso de nmeros negativos. Al introducir una frmula el usuario puede escribir: 4+6*-2 cuyo resultado sera igual a 4 - 12 , y por tanto -8. El problema es que el signo menos, en este caso, no delimita fragmentos, es parte de un fragmento de multiplicacin. Igual ocurrira si el usuario teclea 33 + 8 / + 2 - 6 cuyo resultado es 33 + 4 - 6 = 31 pero ahora el signo '+' del nmero 2 no es un delimitador. Esto quiere decir que si inmediatamente despus de un signo * o un smbolo / aparece un mas (+) o un menos (-) no debemos considerar a estos ltimos como delimitadores de fragmentos. Bueno, pues estas cuestiones deben ser consideradas en nuestro cdigo. Y adems debemos de tener activa una rutina de errores en nuestro cdigo, de tal manera que si una frmula (el string inicial) se escribe errneamente, el programa lo detecte antes de empezar a hacer clculos, pues en tal caso se volvera 'loco' y podra entrar en ciclos sin fin, o cometer errores de bulto. Por ejemplo, si el usuario teclea: 18 * / 3 ha cometido un error, lo mismo si teclea 5 + - 3, o si el nmero de parntesis que abre no se corresponde con el de parntesis que cierra. En resumen, modificamos el flujo de nuestro programa y tendremos ahora que inmediatamente que se recoge el string tecleado, se enva a una Function que examina si hay errores de bulto y si los encuentra, simplemente se enva un mensaje a la pantalla que informa de un error, y no se avanza en el procesado del string. En la siguiente sesin comenzaremos a construir los mdulos del programa. Para finalizar, se muestra a continuacin la forma escrita del flujo del programa que en forma de pseudocdigo ha sido preparado amablemenete por Alberto Molinos:

Principio del pseudocdigo:

Obtener la cadena tecleada por el usuario proceso de errores Mientras la cadena tenga parntesis Extraer datos del parntesis Llamar al proceso general traspasndole los datos del parntesis Sustituir el parntesis por el valor numrico devuelto por el proceso general Fin de mientras Llamar al proceso general Mostrar el resultado obtenido en el proceso general Fin del programa Proceso de errores Si hay dos signos contiguos errneos entonces mostrar mensaje de error y parar el programa Si la cantidad de abrir parntesis no es la misma que la de cerrar parntesis entonces mostrar mensaje de error y parar el programa Fin del proceso de errores Proceso general Si el primer caracter de la cadena es un nmero aadir un signo ms al principio de la cadena Mientras el string tenga signos ms o menos Extraer contenido entre esos signos Mientras haya signos de multiplicar o dividir Realizar la operacin correspondiente Sustituir la operacin por su resultado Fin de mientras haya signos de multiplicar y dividir Realizar la operacin correspondiente Sustituir la operacin por su resultado Fin de mientras haya signos ms o menos Fin del proceso general devolviendo el resultado Fin del pseudocdigo.

Para iniciar un programa complejo es conveniente construir un miniprogram en el cual ir examinando poco a poco los elementos que se introducen nuevos, ver si funcionan adecuadamente, y una vez comprobado, ir aadiendo otras funciones y subrutinas. Se trata de comprobar si lo que estamos programando funciona como esperamos y si es as, ir aadiendo nuevas funcionalidades. Este miniprograma puede tener elementos que sean tiles para nuestra programacin y que luego, una vez comprobado que todo funciona como es debido, sean desechados. Por ejemplo, nosotros vamos a trabajar con variables tipo string, buscando parntesis, extrayendo partes del string inicial, etc. Entonces el tener un elemento listbox en el cual colocar y examinar si los strings extrados son correctos o si estn equivocados, es una ayuda que podemos usar desde el principio. Lo mismo podemos decir para un statictext, o un editfield. Hay algunas herramientas que a estas alturas del cursillo ya deben de conocerse. Por ejemplo, el comando 'msgbox' que nos permite examinar el valor de una variable durante un 'run' . Este comando nos muestra un string, por lo que podemos conocer sobre la marcha el contenido de una variable string o de una variable numrica, en este ltimo caso utilizando el comando 'str'. Otro comando interesante es el 'usercancelled' que es de tipo booleano y se corresponde con la accin tpica del usuario de parar una accin usando la combinacin de teclas comando y punto. Este comando es til cuando se entra en bucles del tipo DO...LOOP de los cuales a veces no se sale por un fallo en nuestra programacin. Entonces, y dentro del ciclo, es muy til escribir: If usercancelled then quit (o exit) end con lo cual si nuestro programa se queda congelado en el bucle, basta pulsar comando y espacio para escapar, en lugar de tener que salir por las bravas del RealBasic. Tambin es til y conveniente conocer las opciones de depuracin de errores (Debugger) del RealBasic. En cualquier lugar del cdigo puede aadirse un Breakpoint desde el Men Debug. Al hacer correr el programa el flujo del mismo se detendr al encontrar este Breakpoint, y en ese momento podemos examinar, en una ventana que se abre automticamente, los valores que presentan las variables de la funcin o subprograma detenido, as como las variables globales. Esto es totalmente necesario al programar, para saber si estamos consiguiendo lo que se pretende e ir corrigiendo errores. Una vez parados en un punto, el programa se puede seguir paso a paso, o de mtodo en mtodo, o interrumpir el run, etc. Conviene leerse los manuales del RealBasic en relacin a este apartado de la depuracin de errores.

Nuestro primer miniprograma puede contener, en una nica ventana, un editfield en el cual

teclear una entrada de nmeros y operadores matemticos, un botn

para iniciar el proceso de cmputo (calcular) , un statictext que nos muestre la solucin y un botn de fin de programa cuya sub action lleve el comando quit. Una de las funciones ms simples que debemos implementar es la de dividir, es decir, obtener el resultado correspondiente a un string en el que slo existe el operador de divisin. Esta funcin recibir un string y devolver el resultado numrico correspondiente como una variable numrica double: FUNCTION dividir(s as string) as double dim i, numero As integer dim numerador, denominador, resultado as double if countFields(s,"/")= 1 then rem si hay un solo campo, es que NO hay signo de dividir resultado = val (s) return resultado rem se devuelve el valor del string inicial s recibido rem por la funciction end numero = countFields (s,"/") rem obtiene numero de signos de dividir, mas 1 numerador = val (nthField (s,"/",1)) rem numerador es lo anterior al signo / denominador = val (nthField(s,"/",2)) rem denominador es lo posterior a / resultado = numerador / denominador if numero > 2 then rem si hay ms de un signo de dividir, se sigue el proceso, rem diviendo el resultado anterior por el valor del rem siguiente campo (denominador) rem necesitamos sacar el campo 3 y luego los siguientes for i = 3 to numero denominador = val (nthfield(s,"/",i)) resultado = resultado / denominador next end return resultado rem se devuelve el resultado END FUNCTION Utilizamos un comando (function) del basic: nthfield que nos dice, para un string determinado, en cuantos campos distintos se divide por la presencia de un determinado carcter (o caracteres). Al escribir nthfield(s,"/") nos devuelve el nmero de fragmentos (campos) que quedan separados por el carcter "/". Si el resultado es uno, es que no existe ningn carcter de divisin, con lo cual se devuelve simplemente el valor del string.

El resto del cdigo es simple y fcil de entender. Podemos probar en un miniprograma si este cdigo funciona bien para distintos strings que introduzcamos en un editfield. Una vez validado, pasa a formar parte de nuestro programa general. (Nota: se puede hacer copia y pegado del texto previo en el RealBasic, es decir, crear el mtodo y luego pegar el contenido anterior.) Una vez escrita la function dividir, la siguiente en la jerarqua del flujo del programa es la de multiplicar, que corresponde aplicar a un string que lleva signos de multiplicar y dividir. Como veamos en el esquema general de flujo del programa, la multiplicacin llama a la divisin. La Function multiplicar sera la siguiente: FUNCTION multiplicar(s as string) as double dim multiplicadores As integer dim i as integer dim fragmento As string dim resultado(10), final as double final = 1 multiplicadores = countFields(s,"*") rem para saber nmero de signos de multiplicar rem (para ninguno, se obtiene un 1) rem si no hay ningun multiplicador el ciclo for...next que rem empieza ahora no se realiza ya que rem multiplicadores valdra 1 for i = 1 to multiplicadores fragmento = nthField (s,"*",i) rem sacamos un fragmento limitado por * resultado(i) = dividir(fragmento) rem se envia el fragmento a la Function dividir final = final * resultado(i) next return final END FUNCTION Hemos dimensionado resultado(10) a 10 elementos pues creemos que no habr nunca un nmero tan alto de multiplicadores en el string inicial. Gracias a las dos Function multiplicar y dividir, un string con slo estos operadores es evaluado y el valor final devuelto en una variable de tipo double. Conviene probar en un miniprograma si esta Function trabaja correctamente. Para ello se prepara un miniprograma que tenga un editfield en el cual teclear un string con nmeros y signos de dividir y multiplicar y examinar si las dos function caminan bien.

Una vez resuelto el tema de los signos de multiplicar y dividir, pasamos al tema de los signos ms y menos. Necesitamos crear un mtodo que extraiga, del srtring inicial, fragmentos limitados por signos ms y menos. Cada fragmento extrado puede ser enviado a la function multiplicar, quien a su vez lo enva a la function dividir, y el resultado devolverlo para ser unido convenientemente a los restantes fragmentos. Crearemos una function que llamaremos sacarfragmentos: FUNCTION SACARFRAGMENTOS(s as string) as string dim i,n,w,posicion(10) as integer dim a, fragmento(10),simbolo(10) As string dim valorfinal ,parcial(10) As double n=1 posicion(1)=1 w=len(s) for i=2 to w rem sacamos cada caracter del string y examinamos rem mediante un IF si es un signo mas o menos rem y NO va precedido de un signo de multiplicacin rem o division a = mid(s,i,1) if (a="+" or a="-") and mid(s,i-1,1)<>"*" and mid(s,i-1,1)<>"/" then n = n + 1 rem para saber cuantos signos hay en el string posicion(n) = i rem guardamos en la variable, las posiciones rem de los signos + y -end next for i=1 to n rem para cada posicin ya registrada, obtenemos en la rem variable simbolo si el signo es un mas (+) o menos (-) simbolo(i)= mid(s,posicion(i),1) next rem conocidos los signos + y - y sus posiciones, extraemos rem fragmentos del string original for i=1 to n-1 fragmento(i)=mid(s,posicion(i)+1,posicion(i+1)-posicion(i)-1) fragmento(n)=mid(s,posicion(n)+1,w-posicion(n)) rem ahora cada fragmento se envia a la Function multiplicar, y el rem resultado lo recoge la variable parcial for i=1 to n parcial(i)=multiplicar(fragmento(i)) next rem Ahora a los diferentes resultados de cada fragmento, que rem estn en la variable 'parcial', se les pone el signo

next

rem correspondiente y se acumulan todos ellos en la variable rem valorfinal for i=1 to n if simbolo(i)="-" then parcial(i)=parcial(i)*-1 end valorfinal=valorfinal+parcial(i) next rem por ultimo se devuelve a la SUB action del boton el valorfinal return str(valorfinal) END FUNCTION Hemos adelantado mucho. Mediante esta ltima function, valoramos todo un string, que puede ser corto o largo, examinando los operadores mas (+) y menos (-) . Slo nos falta el tema de los parntesis. Necesitamos un mtodo que extraiga el contenido de los parntesis. Los strings correspondientes pueden entonces enviarse a la function sacarfragmentos para ser valorados. La function que vamos a crear tomar el string inicial y lo modificar: esto obliga a que la variable string que recibe la function tiene que llegar con la palabra 'byref' para que nos permita modificarla a lo largo de la function. Una vez modificado el string, esto es, eliminados los parntesis, nuestra function devolver mediante return la misma variable string. FUNCTION BUSCAR_PARENTESIS(byref s as string) as string dim a, b, numeroparentesis as integer dim entreparentesis, pre, post, nuevo As string DO numeroparentesis = countFields(s,")") - 1 rem se resta 1 porque como mnimo siempre hay 1 campo if numeroparentesis = 0 then rem volvemos al principio, abandonamos esta function return s rem devolvemos el string end rem buscamos 1 el parentesis cierre y luego el de apertura for a = b downto 1 rem buscamos en el string s, hacia atrs, el "(" ms prximo if mid(s,a,1) = "(" then rem lo encontramos en posicion 'a' exit end next entreparentesis = mid(s, a + 1,b - a-1) rem extraemos string entre posiciones a y b , es rem decir, el texto entre un par de parentesis pre=left(s,a-1) rem fragmento anterior al string extraido antes post=right(s,len(s)-b) rem fragmento posterior

if left(entreparentesis,1) < > "-" and left(entreparentesis,1)< > " + " then rem si fragmento no empieza por un signo menos o mas entreparentesis = "+" + entreparentesis rem entonces le aadimos un signo mas end nuevo = sacarfragmentos(entreparentesis) rem enviamos fragmento a la Function rem sacarfragmentos que ya tenemos y funciona rem bien, por lo que nos devolver el valor rem correspondiente al parentesis como un string s = pre + nuevo + post rem La Function nos devuelve el valor nuevo como string rem Unimos los fragmentos previo y posterior con el nuevo valor. rem Tenemos ahora un string 's' modificado, parcialmente rem valorado rem Al unir fragmentos cabe la posibilidad de que aparezcan rem juntos dos signos de suma y/ o resta. Usaremos la Funtion rem sustituir, que definiremos luego, para eliminar esta rem posibilidad sustituir(s) rem Ya se han eliminado signos dobles.

Loop rem se vuelve al inicio del bucle, a la busqueda de rem otro parntesis para repetir todo el proceso. END FUNCTION Hemos usado en la function anterior una llamada a una SUB llamada sustituir. Esta SUB no estaba prevista en el esquema general, y ha sido necesario crearla sobre la marcha para corregir un problema menor generado durante la eliminacin de parntesis: SUB SUSTITUIR(byref s as string) rem Para eliminar posibles signos dobles, siguiendo las reglas matemticas rem tal que dos signos menos son un signo ms, etc. s = replaceall(s,"--","+") s = replaceall(s,"++","+") s = replaceall(s,"+-","-") s = replaceall(s,"+","-") END SUB Si en nuestro miniprograma hemos ido creando los diferentes Mtodos detallados ms arriba y el cdigo de cada uno, podremos probar si introduciendo una secuencia de nmeros y operadores y parntesis, el resultado es correcto, la evaluacin matemtica funciona correctamente. Con el Mtodo Buscar_parentesis conseguimos eliminar los parntesis adems de evaluar su contenido. Lo que nos queda es un string nuevo que rene los contenidos de los diferentes parntesis, y que es preciso evaluar para tener un valor final o resultado

matemtico. Este string lo podemos simplemente enviar a la Function sacarfragmentos que nos devolver un ltimo nmero, con lo que habremos terminado los clculos. Entonces necesitamos otro Mtodo para esto ltimo. Podemos usar la SUB Action del botn inicial que llambamos 'Calcular'. Vamos a implementar el cdigo: SUB ACTION dim a, s, resultado as string dim i, h as integer s = editField1.text rem recogida del string de la potencial pantalla s = buscar_parentesis(s) rem se envia el string s al mtodo indicado rem El string ya viene modificado, sin parentesis, y examinamos rem si lleva un signo ms o rem menos en cabecera, en caso contrario lo aadimos if left(s,1) < > "-" and left(s,1) < > "+" then rem aadir signo al inicio del string s = "+" + s end resultado = sacarfragmentos(s) rem Se envia el string s al mtodo sub sacarfragmentos staticText1.text = resultado rem El string se ha convertido en un resultado final que rem se muestra en un statictext END SUB Con este ltimo mtodo, nuestro miniprograma ya es capaz de recoger una frmula matemtica compleja, y devolvernos un resultado final. Pero nos faltan todava algunos detalles importantes. Por ejemplo, si se introduce una frmula errnea, el resultado ser errneo o impredecible. Necesitamos un mtodo que examine el string inicial y si encuentra errores nos avise y detenga el proceso de cmputo. FUNCTION BUSCAERRORES(s as string) as boolean if countfields(s,")") < > countfields(s,"(") then rem'ver si hay igual numero de rem parentesis que abren y que cierran return true rem devuelve el valor true a la variable boolean end rem Se busca que no haya dos signos seguidos rem incompatibles: ** ++ etc. if instr(s,"**") > 0 then return true end if instr(s,"*/") > 0 then return true end if instr(s,"/*") > 0 then return true

end if instr(s,"//") > 0 then return true end if instr(s,"++") > 0 then return true end if instr(s,"--") > 0 then return true end if instr(s,"+-") > 0 then return true end if instr(s,"-+") > 0 then return true end if instr(s,"+*") > 0 then return true end if instr(s,"-*") > 0 then return true end if instr(s,"+/") > 0 then return true end if instr(s,"-/") > 0 then return true end if instr(s,"..") > 0 then return true end rem +++++++++++++++++++++++++++++++++++++++ if instr(s,".+") > 0 then return true end if instr(s,".-") > 0 then return true end if instr(s,".*") > 0 then return true end if instr(s,"./") > 0 then return true end rem ++++++++++++++++++++++++++++++++++++++ if instr(s,"(*") > 0 then return true end if instr(s,"(/") > 0 then return true end

if instr(s,"+)") > 0 then return true end if instr(s,"-)") > 0 then return true end if instr(s,"*)") > 0 then return true end if instr(s,"/)") > 0 then return true end rem ++++++++++++++++++++++++++++++++++++++ if instr(s,".(") > 0 then return true end if instr(s,".)") > 0 then return true end rem ++++++++++++++++++++++++++++++++++++++ If left(s,1)="*" then return true end If left(s,1)="/" then return true end If left(s,1)=")" then return true end rem ++++++++++++++++++++++++++++++++++++++ If right(s,1)="+" then return true end If right(s,1)="-" then return true end If right(s,1)="*" then return true end If right(s,1)="/" then return true end If right(s,1)="." then return true end If right(s,1)="(" then return true end END FUNCTION

Para activar esta Function, aadimos un poco de cdigo en la SUB Action anteriormente examinada del boton 'Calcular' , con una nueva variable de tipo boolean, quedando as: SUB ACTION dim a, s , resultado as string dim i, h as integer dim hayerror as boolean s=editField1.text rem recogida del string de pantalla hayerror=buscaerrores(s) rem primer paso es buscar errores en string rem enviamos el string s a la Function buscaerrores if hayerror=true then beep editfield1.text= "error" rem Aviso al usuario return rem Si hay error no se hace nada, se retorna al principio end s=buscar_parentesis(s) rem se envia el string s al mtodo indicado rem El string ya viene modificado, sin parentesis, y rem examinamos si lleva un signo ms o menos en cabecera, rem en caso contrario lo aadimos if left(s,1) < > "-" and left(s,1) < > "+" then rem aadir signo al inicio del string s = "+" + s end resultado = sacarfragmentos(s) rem Se envia el string s al staticText1.text=resultado rem El string se ha convertido en un resultado final rem que se muestra en un statictext END SUB Slo hemos aadido 7 lneas de cdigo. Bueno, pues ya tenemos la arquitectura bsica de nuestro programa. Grabemos toda la informacin con un nombre apropiado, y podemos tambin usar la opcin "Grabar como..." para darle un nuevo nombre, por ejemplo, 'calculadora beta' y comenzar a aadir elementos para construir la interface. Aqu finalizamos la sesin, que ya es bastante larga. Conviene repasar todo el cdigo anteriormente expuesto y si hay algn paso que no queda claro, persistir en el mismo, hasta dar con la solucin, es decir, hasta tener claro porqu se realiza cada uno de los pasos indicados. Y recordar que el basic es un lenguaje muy rico, y que se puede llegar a la misma solucin por caminos diferentes. Es decir, la solucin que se muestra en mtodo sub sacarfragmentos

cada Function o Sub puede enfocarse de otra forma, siendo cada uno libre de hacerlo como le parezca ms eficaz o ms intuitivo.

Iniciamos la sesin abriendo el programa previo, la minicalculadora o miniprograma al que posiblemente pusimos por nombre 'calculadora beta'. Segn vayamos aadiendo cdigo sobre este proyecto, conviene grabar cada cierto tiempo con un nuevo nombre para no perder lo realizado con anterioridad. Como ya tenemos el cdigo bsico de funcionamiento de la calculadora, ahora nos toca empezar el diseo de la misma, lo que ver el usuario, la funcionalidad mejor o peor conseguida. Para comenzar el diseo de la calculadora, pensemos en una ventana a la cual le aadimos botones y una pantalla. Los botones, inicialmente, pueden ser pushbuttons y la pantalla puede ser un editfield. El diseo ser de un rectngulo apaisado, ms ancho que alto. Ampliemos convenientemente nuestra nica ventana y coloquemos un primer botn al que llamaremos 'botn' con index 0. La caption ser un cero. Le podemos dar de width 40 y de high 37 pixels. El texto puede ser system y el size del texto 32. Si ahora seleccionamos este botn y lo duplicamos, tendremos otro elemento con el mismo nombre pero con index 1. Le ponemos por caption 1. Si seguimos haciendo lo mismo, es decir duplicando, y cambiando el caption, tendremos finalmente un array o vector de elementos pushbutton, todos llamados igual y cada uno con un nmero de index diferente. Inicialmente tendremos hasta index 9 con caption 9, pero podemos seguir duplicando este elemento para conseguir botones con los captions correspondientes a los smbolos de los operadores ms, menos, multiplicacin y divisin, otros dos con los dos parntesis y un ltimo que llevar el punto como separador decimal. Hasta aqu tenemos un array de botones con el mismo nombre (botn) y con indices de 0 a 16. Necesitamos adems un botn para borrado parcial al que pondremos por nombre 'borrarBt' y por caption una C mayscula, y servir para borrar un solo carcter; otro que llamaremos 'BorrartodoBt' con caption CE y otro ms que llamaremos 'CalcularBt' para iniciar el clculo y obtener el resultado. Este ltimo puede ser de mayor anchura y llevar como caption 'Calcular'. Ms adelante aadiremos otros botones. Aadamos un editfield al que pondremos por nombre 'pantalla', y que servir de pantalla de la calculadora, y por lo tanto, para mostrar la entrada de datos as como el resultado de la operacin. Ahora vamos a colocar los diferentes botones de forma ordenada. Para simular el teclado de una calculadora, pondremos en fila los tres botones que llevan los nmeros 7, 8 y 9 , en este orden de izquierda a derecha, debajo los 4, 5 y 6, debajo de estos los 1, 2 y 3 y debajo de estos el 0, el decimal y el botn calcular. Realmente, el diseo es libre y cada uno puede colocar los botones a su gusto. Reproduzco a continuacin el primer diseo que hice en mi programa 'calculadora beta' :

Puede verse un editfield con fondo amarillo y nmeros rojos, que correspondera a la pantalla de entrada y salida. Este editfield muestra text usando la fuente o tipo courier que es el ms apropiado para nmeros. Bueno, dejando aparte detalles dependientes del gusto de cada uno, vamos con el cdigo. Lo primero puede ser eliminar el botn 'fin'. Como este botn lleva asociada la terminacin del programa, necesitamos otra forma de hacerlo. Podemos usar el evento de ventana 'close' que es la accin de pulsar con el ratn el botn de cierre de ventana, y escribir, en la sub: SUB CLOSE( ) quit END SUB El botn 'calcular' sera el que lleva la SUB action detallada en la sesin anterior. Esta sub toma el texto que aparece en el editfield y efecta el cmputo del valor correspondiente, que aparecer en este mismo editfield. Al editfield podemos darle por nombre 'pantalla' para comodidad de programacin, por lo que debemos cambiar el cdigo correspondiente. En las propiedades de este editfied podemos quitar la opcin 'UseFocusRing' y activar la opcin 'ReadOnly' con lo cual el usuario no puede, de momento, teclear directamente en la pantalla. Como el editfield pantalla debe mostrar por una parte la 'entrada' de usuario y por otra parte el 'resultado' de la operacin, segn el momento de la actividad del usuario, el texto

de pantalla debe borrar la entrada y mostrar el resultado, o a la inversa, borrar el resultado y comenzar a mostrar la entrada. Para poder

trabajar con estas dos opciones desde diferentes elementos de la ventana, crearemos dos variables generales tipo string, que denominaremos 'entrada' y 'respuesta'. La variable 'respuesta' la utilizaremos para guardar el resultado de la ltima operacin realizada en la calculadora, pues a veces es muy til poder utilizar este valor en una operacin ulterior. En la SUB action del botn calcular, aadiremos una ltima lnea de cdigo que diga: respuesta = resultado Aprovechemos para cambiar, en esta misma SUB, todas las entradas donde diga editfield1 por pantalla. Una vez hecho, el texto ir directamente al editfield que llamamos pantalla. A continuacin tenemos que asociar una accin a la pulsacin de cada botn. Hacemos dobleclick sobre el botn 0 y en la sub action escribimos dos lneas de cdigo: SUB ACTION(index as integer) entrada = entrada + botn(index).caption pantalla.text = entrada END SUB Como hay 17 botones con el mismo nombre y diferente index, aqu index hace referencia justamente al botn pulsado, y el cdigo agrega el texto (caption) del botn pulsado, a la variable 'entrada' que a su vez se muestra en 'pantalla'. Podemos ahora apreciar la utilidad de usar arrays, pues el cdigo escrito para uno de los elementos del array nos vale para todos ellos, y no necesitamos escribir este cdigo 17 veces para 17 botones distintos. Para el botn de borrado parcial 'borrarBt' la sub action queda as: SUB ACTION(index as integer) entrada = left(entrada,len(entrada)-1) pantalla.text = entrada END SUB de forma que cada pulsacin de este botn acorta la longitud del string 'entrada' en una unidad, y por ltimo, la sub action del botn 'borrartodoBt' ser: SUB ACTION(index as integer) entrada = "" pantalla.text = entrada END SUB OJO : Un problema que es preciso comentar: en basic, la coma no es el separador decimal, de hecho la coma es un separador de variables, o de elementos, o de partes, etc. Por esta razn, si queremos usar la coma como separador, tendremos errores de bulto. Podemos hacer dos cosas:

Seguir usando la coma en la interface del usuario, pero convirtiendo cada coma tecleada en un punto a efectos de cmputo. (b) Usar para todo el punto.
(a)

Creo que esta segunda alternativa es mejor, y de hecho las calculadoras que se compran en cualquier tienda llevan el punto como separador decimal. Bueno, pues cambiar coma por punto es muy fcil, basta cambiar la caption del botn correspondiente. Tambin necesitamos aadir una lnea de cdigo en la sub action del botn 'calcular': entrada = "" que es necesario para que una vez obtenida la respuesta podamos teclear una nueva entrada desde cero. Probemos que nuestra calculadora funciona, y si tal es el caso, grabemos el proyecto con un nuevo nombre: 'calculadora alfa'. Otra cuestin que puede y debe mejorarse: el resultado aparece a la izquierda de la pantalla, lo cual no es lo usual. Para solventar este problema, debemos saber cual es el nmero de caracteres que caben en 'pantalla' . Lo podemos averiguar si en el IDE seleccionamos este editfield y en propiedades, en text, vamos aadiendo nmeros hasta que se llene completamente, y entonces contamos cuantos caracteres caben. Supongamos que son 24. Bueno pues si nuestro string 'respuesta' ocupa por ejemplo 4 caracteres, los 20 restantes los podemos rellenar con espacios, con lo cual la respuesta ser un string de longitud 24 que aparece rellenando toda la pantalla. Suponiendo estos 24 caracteres (puede ser otro valor) debemos modificar la sub action del botn 'calcular, aadiendo estas lneas h = 24 - len(resultado) for i = 1 to h resultado = " " + resultado next antes de presentar 'resultado' en 'pantalla'. Al aadir espacios antes del nmero hemos solucionado un problema pero hemos creado otro, y es que la asignacin que antes comentamos: respuesta = resultado ahora lleva en cabecera un montn de caracteres 'espacio', es decir, huecos vacos. Para eliminar estos espacios existe un comando del Basic que se denomina LTRIM y que elimina todos los espacios que existen a la izquierda de un string. Entonces aadimos esta lnea de cdigo: respuesta = ltrim (respuesta) Por si acaso el cdigo de la sub action del pushbutton 'calcularBt' ha quedado algo confuso con las sucesivas adiciones y modificaciones, lo reproduzco a continuacin: (nota: el smbolo ' equivale a un REM)

SUB ACTION dim a, s, resultado as string dim hayerror as boolean dim i, h as integer s = pantalla.text ' recogida del string de pantalla hayerror = buscaerrores(s) rem primer paso es buscar errores en string rem Se enva el string a la Function buscaerrores if hayerror = true then editfield3.text = "error" ' Aviso al usuario return rem Si hay error no se hace nada, se retorna al principio end s = buscar_parentesis(s) if left(s,1) < > "-" and left(s,1) < > "+" then rem aadir signo al inicio del string s = "+" + s end resultado = sacarfragmentos(s) rem Se enva el string al mtodo SUB sacarfragmentos h = 24 - len(resultado) for i = 1 to h resultado = " " + resultado next pantalla.text = resultado respuesta = resultado respuesta = ltrim(respuesta) entrada = "" END SUB Aprovecho para recordar que hay palabras reservadas que no pueden usarse como variables. Una de ellas es 'error' , razn por la cual en el cdigo anterior se le ha aadido el vocablo 'hay'. Una tecla de la que aun no hemos hecho comentarios es la aparece con el caption 'Respuesta' en el esquema de la calculadora. Esta tecla es til para utilizar la respuesta obtenida en nuevos clculos. Bueno, pues simplemente, en la sub action de este botn escribimos: Sub Action entrada = entrada + respuesta pantalla.text = entrada End sub Finalmente, hay un elemento en nuestra calculadora del que no hemos hecho mencin todava. Bajo los botones de borrado y a la derecha del boton RM aparece un recuadro. Podemos usarlo para saber el contenido de la memoria de nuestra calculadora, y tambin para mostrar un mensaje de error si es que ocurre alguno. En este hueco aadiremos un elemento llamado 'rectangle' que no es otra

cosa que un rectngulo. Primero, y cuando est seleccionado, vayamos al menu Format y seleccionemos 'Move to Back' para enviarlo al fondo de la ventana. Luego, le daremos las dimensiones apropiadas para que encaje en el hueco que dejan los botones, y su borde negro sea ntido. En la ventana propiedades de este rectangulo, hay una propiedad denominada 'FillColor' que nos permite darle un color especial de relleno de fondo al rectangulo. Ahora vamos a aadir un statictext sobre la ventana, y a colocarlo justo encima del rectangulo, con las dimensiones practicamente iguales (uno o dos pixeles menos) que las del rectangulo. Cambiemos el nombre de este statictext1 por 'informacion'. En las propiedades de 'informacion' seleccionemos 'TextColor' para elegir un color de texto, seleccionemos TextFont y pongamos Arial (u otra a elegir) y seleccionemos TextSize y pongamos 13. Sigamos con otras teclas o botones de nuestra calculadora. Muchas calculadoras incluyen una funcin bastante til: una memoria intermedia en la cual almacenar resultados previos que puedan ser recuperados y utilizados ms adelante. Usualmente esta memoria lleva asociadas 4 teclas diferentes, una para introducir un resultado en memoria, borrando cualquier registro previo, otra para introducir un resultado sumndolo al previamente introducido, otra para recuperar el contenido de la memoria y una ltima para borrar la memoria. Este ltimo no lo vamos a utilizar, de forma que vamos a aadir 3 botones a nuestra calculadora, que lleven como caption las letras : M, M+, RM . Una vez aadidos estos 3 botones, nuestra calculadora puede tener este aspecto:

Primero definimos una variable global que llamaremos 'memoria' de tipo double.

El botn con caption M, al que llamaremos 'MemoriaBt' , llevar, en su correspondiente Sub action, el siguiente cdigo:

SUB ACTION memoria = respuesta informacion.text = memoria END SUB Al botn con caption M+ le pondremos por nombre 'MemoriaMasBt' y el cdigo: SUB ACTION memoria = str(val(memoria) + val(respuesta)) informacion.text = memoria END SUB y por ltimo llamaremos 'RecuperarBt' al botn 'RM' y por cdigo escribiremos : SUB ACTION entrada = entrada + memoria pantalla.text = entrada END SUB Pero necesitamos algunos ajustes para que al llamar al valor en memoria, no se nos generen errores. Por ejemplo, si la memoria es un nmero negativo (-6 por ejemplo,) y tecleamos en nuestra calculadora: 23 - RM en pantalla aparecer 23 - - 6 y al detectarse dos signos menos seguidos, se nos genera un error. Para evitar este pequeo problema, podemos meter entre parntesis el contenido de memoria. De esta forma, al teclear lo mismo que lo apuntado antes, en pantalla aparecer: 23 - (-6) que no producir error y ser evaluado correctamente. Corregimos entonces el cdigo de la sub action anterior que quedar as: SUB ACTION entrada = entrada + "(" + memoria + ")" pantalla.text = entrada END SUB Por la misma razn, la sub action del botn 'RespuestaBt' deber modificarse as: Sub Action entrada = entrada + "(" + respuesta + ")" pantalla.text = entrada End sub Siempre hay detalles que deben pulirse al realizar un programa, bien porque no se hayan considerado, bien porque deriven de incompatibilidades generadas por nuestro cdigo. Una cuestin que debemos arreglar: cuando estamos tecleando la entrada en pantalla, no tiene sentido que los botones M y M+ estn activos, pues si se

pulsan pueden introducir, como dato en memoria, parte de un string sin ningn sentido numrico. Entonces lo que necesitamos es que estos botones estn inactivos cuando se est introduciendo un string en pantalla, y activos una vez que se ha realizado el clculo y la respuesta aparece en pantalla. Vamos a introducir dos lneas de cdigo en la sub action del array de botones con captions 0, 1, 2, etc., la cual quedar as: SUB action(index as integer) memoriabt.enabled = false memoriamasBt.enabled = false entrada = entrada + botn(index).caption pantalla.text = entrada END SUB Ahora tenemos que activar estos dos botones una vez que se obtenga el resultado. El lugar es, evidentemente, la sub action del botn 'Calcular' , de forma que al final de la misma aadimos las dos siguientes lneas de cdigo: memoriabt.enabled = true memoriamasBt.enabled = true Ahora, cuando se inicia el programa los botones estn activos, pero nada ms tocar uno de los botones de entrada de datos se desactivan, volvindose activos al realizar el clculo. Otro pequeo ajuste necesario es poner la variable 'memoria' a cero al iniciar el programa, pues si no se hace e inmediatamente de iniciar el programa pulsamos la tecla 'Respuesta' nos aparecer en pantallados parntesis ( ) lo cual es errneamente evaluado como una unidad. Para inicializar algunas variables o para ajustes iniciales de este programa podemos usar un mtodo de la ventana (window) : la SUB OPEN. Como uno de los eventos iniciales es la apertura de la nica ventana del proyecto, todo lo que escribamos en esta Sub se ejecutar al principio del programa. Entonces, abrimos este mtodo y escribimos: SUB OPEN() respuesta = "0" me.left = 200 me.top = 100 END SUB Hemos aadido dos lneas para que la ventana (nuestra calculadora) quede mas o menos centrada en la pantalla del monitor, a 200 pixels a la izquierda y 100 hacia abajo. Modificando estos datos podemos conseguir que aparezca en donde queramos. Finalizamos esta larga y compleja sesin en este momento. Podemos decir que tenemos terminado nuestro proyecto, que tenemos un producto funcional, atractivo, y sobre todo, nuestro. Es cierto que podemos hacer muchas mejoras, y que todava tiene algunos puntos flojos que se descubren al funcionar con ella. Por ejemplo, si se genera un error y aparece la palabra "error" en la ventana de

informacin, sera aconsejable que esta palabra desapareciera y se mostrase de nuevo el contenido de la memoria intermedia. Esta es una tarea relativamente sencilla, que dejo en manos del lector. Pero lo importante es que nuestra calculadora es capaz de hacer de forma correcta lo esencial, e incluso hace de una sola 'tacada' pasos complejos que otras calculadoras no hacen. Alguna mejora la haremos en la siguiente sesin.

Ya tenemos nuestro proyecto de calculadora finalizado en su parte "dura" de software. Lo ms complejo, la solucin matemtica del string inicial, lo realiza perfectamente. Evidentemente, nuestra calculadora no es una obra maestra, pues no realiza operaciones que la mayora de las calculadoras s son capaces de realizar, como por ejemplo, raz cuadrada, inversos, logaritmos, etc. Pero tenemos construida una slida estructura base, de tal forma que podemos aadir funcionalidades extras sin excesivas complejidades. A partir de aqu, ser tarea de cada programador el aadir nuevos botones, cambiar la interface, etc. Vamos a hacer todava dos cosas que sin ser imprescindibles, tienen inters para nosotros ya que nos permitirn trabajar con elementos nuevos del basic. La primera es conseguir introducir datos desde el teclado, sin usar el ratn, sin necesidad de pulsar los botones de la calculadora. En la ventana de propiedades del editfield 'pantalla', eliminemos la opcin 'ReadOnly' para que el usuario pueda introducir datos desde el teclado. Ahora, como la pantalla es un editfield, si tecleamos cualquier carcter, este aparecer en la 'pantalla' de nuestra calculadora, ya que por defecto, un editfield recibe la entrada de teclado y la muestra de forma inmediata. Pero no nos interesa que aparezcan letras como la hache o la jota. Slo nos interesan los nmeros y los operadores que hemos utilizado hasta ahora. Tenemos por lo tanto que evitar que el editfield 'pantalla' muestre todos los caracteres del teclado, es decir, que queremos que solo acepte aquellos que son necesarios en nuestras frmulas de entrada. El editfield pantalla tiene una Function llamada KeyDown que recoge la tecla presionada por el usuario. Tenemos que poner una condicin para que algunos de los caracteres tecleados sean aceptados por el editfield y aparezcan en l, pero otros sean rechazados. Lo primero que debemos saber, es que hay caracteres que tienen una representacin grfica directa, como la letra eme, tanto mayscula como minscula, pero hay caracteres sin representacin, como el tabulador, la tecla borrar, flecha de desplazamiento a derechas, el espacio, etc. Sin embargo, cada carcter, sea del alfabeto o de otro tipo, tiene un valor en una tabla llamada ASCII , al cual podemos hacer referencia mediante el comando del basic ASC. Por ejemplo, la letra minscula 'k' tiene el valor ascii 107, un integer. Si conocemos este valor ascii, podemos recuperar el carcter con el comando basic CHR que devuelve un carcter tipo string. Entonces n = asc("k") rem devuelve 107 en la variable integer n s = chr(107) rem devuelve k en la variable string s

de forma que si queremos escribir una letra k en un statictext podemos lograrlo con cualquiera de las dos formas siguientes: statictext.text = "k" statictext.text = chr(107) (Si no se conocen los valores ascii del teclado, podemos hacernos un pequeo programa en basic, que nos muestre el valor ascii de la tecla presionada usando el comando 'asc'.) Para saber si la tecla presionada es de nuestro inters, vamos a utilizar un nuevo comando basic : INSTR Este comando busca la primera posicin que ocupa un string dentro de otro string. Por ejemplo, 3 = instr("efp92ewpcb", "p") el string 'p' aparece por primera vez en posicin 3 dentro del string 'efp92ewpcb'. Si el string buscado no se encuentra, la posicin que se devuelve es 0. Entonces podemos crear un string que rena los caracteres que queremos que aparezcan en nuestra 'pantalla' de calculadora. Estos seran: 0123456789+-.(*/) Entonces, en la Function KeyDown del editfield 'pantalla' escribimos: Function KeyDown(key as string) as boolean dim s as string s = "0123456789+-.(*/)" if instr(s,key) = 0 then return true end End function cuando nuestro editfield recibe un evento del tipo keydown (tecla pulsada) , la tecla en cuestin (key) se busca dentro del string y caso de que no se encuentre (el comando instr devuelve cero) se sale de la function devolviendo el valor booleano true. Cuando se devuelve 'true' se evita la accin por defecto del editfield, esto es, no hay respuesta del editfield a la accin del usuario. Suponiendo que la pulsacin corresponda a uno de los caracteres que deseamos sea admitido, el comando instr devolver un valor distinto de cero y entonces aadiremos el carcter a la variable 'entrada' como sigue: me.text=entrada entrada = entrada + key me.selstart=len(entrada)

la ltima lnea consigue que el cursor aparezca en el edit field a la derecha del ltimo carcter escrito. Tambin es necesario admitir la pulsacin del carcter 'retorno de carro' que corresponde a pulsar OK o confirmar una accin. Este carcter no tiene representacin grfica, y su ascii es 13 por lo cual lo aadimos al string anterior el cdigo chr(13), quedando as: s = "0123456789+-.(*/)" + chr(13) Por otra parte, la tecla 'borrar' del teclado lleva el valor ascii 8. Podemos escribir, al inicio de la function keydown: if asc(key) = 8 then entrada = left(entrada,len(entrada)-1) return false end Al devolver mediante return la variable booleana false, la accin de la tecla pulsada se realiza automticamente por el editfield. En resumen, la Function del editfield queda as: Function KeyDown(key as string) as boolean dim s as string if asc(key)=8 then entrada=left(entrada,len(entrada)-1) return false end s=chr(13)+"0123456789.+-*/()" if instr(s,key) =0 then return true end me.text=entrada entrada = entrada + key me.selstart=len(entrada) END FUNCTION Pero nos falta desactivar los botones de entrada a memoria: memoriabt.enabled = false memoriamasBt.enabled = false y una vez aadidas estas dos lneas tenemos finalizada nuestra opcin de entrada por teclado. Finalmente, vamos a preparar dos nuevas teclas para nuestra calculadora, ambas relacionadas con la memoria que almacena un valor determinado. Hemos implementado hasta ahora las teclas M, para introducir un resultado en memoria, M+ para sumar un resultado sobre el previamente acumulado, y RM

para recuperar el valor de memoria a la pantalla. Pero hay dos teclas que debieran tambin aparecer en nuestra calculadora: M- para restar (en lugar de sumar) el resultado sobre la memoria previa, y CM para borrar el contenido en memoria. Bien, podemos modificar nuestro diseo actual de la calculadora para dejar espacio a estas dos nuevas teclas. Pero podemos tambin usar una tecla adicional para hacer aparecer o desaparecer estas teclas en la calculadora: por ejemplo, que al mantener pulsada la tecla mayscula el botn M+ cambie a ser un botn M- , y tambin que el botn RM se cambie por CM. Uno de los objetos del RealBasic, que aun no hemos considerado, es el teclado o "Keyboard". Es una de las puertas de comunicacin del usuario, y tiene una serie de propiedades interesantes. Por ejemplo, la propiedad del "keyboard" llamada 'AsyncShiftKey' devuelve una variable booleana que si es true indica que el usuario esta pulsando la tecla maysculas (Shift) y si devuelve false, indica que esta tecla modificadora no est pulsada. Para saber si el usuario pulsa o no la tecla maysculas, necesitamos preguntarselo al Keyboard de forma continua, es decir, realizar un chequeo continuo de la propiedad 'AsyncShiftKey' para saber si devuelve true o false. Esto se consigue utilizando un 'timer' o reloj. Un 'timer' es otro elemento u objeto del RealBasic que tiene utilidad en procesos de tiempo o continuos. Un timer tiene una SUB ACTION que se realiza cada cierto tiempo, el que nosotros queramos. Puede realizarse cada minuto, cada segundo, o varias veces por segundo. Todo depende de nuestra necesidad. Bueno, pues vamos a aadir un objeto timer sobre nuestra calculadora. El icono es un reloj tipo cronmetro. Este objeto es invisible cuando el programa corre, luego podemos ponerlo en cualquier posicin de la ventana, por ejemplo, encima del editfield panatalla. Lo aadimos a partir de la ventana de objetos. Una vez aadido en nuestra ventana, y seleccionado, podemos ver, en la ventana propiedades, que el nombre por defecto es timer1. En Esta misma ventana propiedades, en el apartado 'behavior', hay dos propiedades que debemos controlar: la primera es 'Mode' que pondremos en 'multiple', y la segunda es 'period', que por defecto pone 1000 y equivale al tiempo en milisegundos que se deja transcurrir hasta realizar automticamente la 'Sub action' del timer. Mil milisegundos es un segundo, luego si ponemos en 'period' un valor 200, la Sub action se realizar cada 200 milisegundos, es decir, 5 veces por segundo. Haciendo doble click sobre el 'timer' se nos abre la sub action en la que escribimos: SUB Action( ) if keyboard.asyncShiftKey = true then recuperaBt.caption = "CM" memoriaMasBt.caption= "M-"

else recuperaBt.caption= "RM" memoriamasBt.caption="M+" end End Sub Con este cdigo, si el usuario mantiene presionada la tecla maysculas, los botones 'recuperarBt' y 'memoriamasBt' cambian sus captions para figurar que son dos botones nuevos. Haciendo correr el proyecto modificado de la forma comentada, puede notarse como cambian los botones al presionar Shift. Tambin se puede experimentar poniendo tiempos mayores de 'period' para elegir la velocidad de respuesta del programa a la pulsacin de la tecla shift. nicamente nos falta el cdigo correspondiente a estos dos nuevos botones. Para ello, lo ms simple es modificar la Sub Action de cada uno de ellos para acomodar la nueva funcionalidad. La sub action del botn 'memoriaMasBt' quedar as: SUB ACTION( ) if me.caption = "M+" then memoria=str(val(memoria)+val(respuesta)) informacion.text=memoria else memoria = str(val(memoria) - val(respuesta)) informacion.text=memoria end END SUB es decir, dependiendo de su caption, suma o resta el resultado (respuesta) a la memoria. Y la sub action del botn 'RecuperarBt' queda as: SUB ACTION( ) if me.caption="RM" then entrada=entrada+ "(" + memoria + ")" pantalla.text=entrada else memoria="0" informacion.text="0" end END SUB Es interesante examinar con cuidado toda la informacin nueva, entenderla, y darse cuenta de la potencialidad que atesora. Con esto damos por terminado el proyecto de crear una calculadora.

Como ya se ha apuntado antes, no es un producto comercial, ni una calculadora fantstica, ni est completa: es, simplemente un ejercicio, ms o menos complejo, que nos ha permitido utilizar una serie de recursos del RealBasic, aprender sobre ellos, y sobre todo darse cuenta que detrs de una aplicacin, por simple que parezca, hay una gran cantidad de informacin, que a primera vista parece inabordable, pero que es asequible para los amateurs, como nosotros, si somos capaces de ir poco a poco asimilando la potencialidad de la programacin con RealBasic. Y creo que todo lo anterior es muy til, sobre todo, si despierta la vocacin de programar por programar, como aficin, que es la idea de estas sesiones.

En esta sesin vamos a examinar una importante funcionalidad del RealBasic de la que no hemos hecho mencin todava: los mens de las aplicaciones. Mens: una de las caractersticas de todos los programas es la presencia de un men en la parte superior que permite mediante la seleccin de los temms disponibles, realizar tareas muy diversas, como es el caso del men Edit, o Archivo, Fuentes, etc. Hasta ahora no hemos usado esta caracterstica en ninguno de nuestros proyectos previos. Vamos a hacerlo ahora. Empecemos ceando un nuevo proyecto. Lo primero que se nos abre es el contenido inicial del mismo, y siempre incluye, por defecto, una ventana y un men. Hacemos dobleclick sobre este ltimo y se nos abre una ventana en la que aparece, por defecto, un men con los apartados ms clsicos del sistema operativo: el men Apple (la manzanita), File (archivo) y Edit (Edicin). Si tocamos en el men File se despliegan los tems del mismo, y aparece siempre el tem Quit con la combinacin de teclado comando-Q. A la derecha del men Edit aparece un cuadrado, y si tocamos sobre l, se nos abre una ventana de propiedades en la que podemos dar nombre a un nuevo Men. Vamos a dejarlo sin nombre, y donde dice 'Text' escribamos 'Acciones'. Debajo de Acciones, aparece un cuadrado que corresponde al primer tem del men que hemos creado. Al tocar en este cuadrado se nos abre la ventana propiedades. En 'text' vamos a escribir "Mensaje" y en Behavior, donde pone CommandKey pondremos la letra que queremos que funcione como accin desde teclado, por ejemplo, la 'M'. Debajo de este tem, si tocamos en un cuadrado que aparece vaco, podemos crear otro tem de este men 'Acciones'. Vamos a crear dos ms, uno que llamaremos 'Aviso' y otro que llamaremos 'Msica', y con las letras asociadas 'S' y 'L' respectivamente. Ya tenemos creado un men pero todava no es funcional. Lo primero es saber que queremos que haga cada uno. Vamos a crear tres mtodos en la ventana inicial window1 que hagan algo diferente una de otra. Al primero le llamaremos 'ElMensaje' y no llevar parmetros asociados. Al segundo le llamaremos 'ElAviso" y al tercero 'LaMusica'. Haciendo dobleclick sobre 'ElMensaje' se nos abre una SUB en la que escribimos: SUB ElMensaje() msgbox "Hola, amigo, un saludo" END SUB o cualquier otro texto que nos apetezca.

En la sub de los otros dos mtodos escribiremos: SUB Aviso() dim i, a, b As integer for i = 1 to 3 a = ticks do b = ticks loop until b - a > 30 beep next END SUB SUB LaMusica() dim i,r,s,a,b as integer r = rnd*(128)+1 for i = 1 to 12 s = rnd*(70-50 +1) + 50 NotePlayer1.Instrument = r NotePlayer1.PlayNote(s,55) a = ticks do b = ticks loop until b - a > 20 notePlayer1.playNote(s,0) next END SUB En este ltimo mtodo aparece un nuevo objeto del RealBasic que an no hemos utilizado: el NotePlayer o intrprete musical. Lo primero, es aadir este objeto sobre la ventana inicial 'window1' . En la ventana 'propiedades' no aparece ms que la posicin y el behavior, y en este slo el 'instrument' que por defecto es el 1 (gran piano). Pero hay 128 instrumentos musicales: guitarras, oboes, celesta, armnica, etc. Por otra parte, el noteplayer slo tiene asociado un mtodo denominado 'playnote' que significa "interpreta_la_nota", que lleva dos parmetros: el primero, de 1 a 128 es el 'pitch' o escala de la nota que se va a emitir, y el segundo, que tambin va de 1 a 128, es el volumen en que se emite esta nota. En la sub de arriba, hemos aadido una funcin que nos proporciona un nmero al azar entre 1 y 128 para que cada vez que vayamos a la sub, se interprete un instrumento diferente tomado al azar. Esta funcin, RND es ms antigua que la variable tipo 'random' que utilizamos en una sesin anterior, pero el resultado, la generacin de nmeros al azar es la misma.

RND utiliza dos valores, el mnimo y el mximo entre los que sacamos un nmero azar. La sintaxis para conseguirlo sera: numero_al_azar (integer) = rnd * (mximo - mnimo +1) + mnimo. Para que el instrumento ejecute notas variadas, hemos hecho un ciclo de 12 vueltas y en cada vuelta se toma un nmero al azar entre 50 y 70 (en vez de entre 1 y 128 para evitar sonidos muy graves y muy agudos) y se interpreta con una intensidad de 55. Por cierto, para que una nota deje de interpretarse, es decir, deje de sonar, y poder hacer sonar otra, es preciso hacer una llamada especifica con intensidad cero; si no se hace, el sonido no para y es preciso interrumpir el programa. Para que las notas no se agolpen, hemos aadido un valores de la function 'ticks' y que solo 20 ticks, siendo un tick la sesentava un segundo). ciclo DO...LOOP que toma dos avanza cuando han transcurrido parte de un segundo (60 ticks =

Bueno, ya hemos creado tres mtodos, uno para cada tem del men 'acciones'. Ahora vamos a activar este men. Lo primero es entrar en el Editor del RealBasic (haciendo dobleclick en la ventana) e ir al men EDIT del RealBasic y elegir un tem denominado 'New Menu Handler...' Se no abre un dialogo para elegir uno de los tems creados anteriormente, apareciendo con el nombre del men seguido, sin espacios, por el nombre del tem. Seleccionamos uno de los tems y repetimos la misma accin con cada uno de los dos restantes. Vemos que en la ventana del editor, en el apartado 'MenuHandlers' aparecen los tres tems creados. Tocamos sobre el denominado 'AccionesMensaje' y aparece un texto en el que tecleamos el mtodo que queremos que se realice al seleccionar este tem del men: Function Action as boolean ElMensaje End Function Hacemos lo mismo con 'AccionesAviso': Function Action as boolean ElAviso End Function y con 'AccionesMusica' :

Function Action as boolean LaMusica End Function Ahora la accin de cada tem le lleva a un mtodo diferente. Tambin podramos haber escrito, en estas sub action, los cdigos que hemos escrito en cada mtodo, y funcionaramos igual. Si ahora hacemos correr el proyecto vemos que ni el men acciones ni sus tems estn disponibles, y aparecen en gris, es decir, deshabilitados. Esto es as, porque un men o un tem puede estar activado o no a gusto del programador. Por defecto, los que nosotros creamos estn inactivos; no ocurre as con el men Quit, que siempre, por defecto, est activo. Bueno, pues nos falta activarlos. (nota: en versiones recientes del RealBasic, por defecto estn activos). Vayamos al editor, y entremos en uno de los eventos de la ventana, el denominado 'EnableMenuItems' que como su nombre indica, es para habilitar o activar los diferentes mens que hemos preparado. En esta Sub escribiremos: SUB EnambleMenuItems( ) accionesMensaje.enabled=true accionesMsica.enabled=true accionesSonido.enabled=true END SUB y ahora ya est finalizado el proceso. Los mens son activos, y seleccionando uno se dispara el mtodo asociado a su MenuHandler, tal como queramos. Finalizamos aqu la sesin.

Los grficos son parte importante de toda aplicacin actual. Las fotos, los colores, los fondos de pantalla, los movimientos de figuras... son grficos estticos o dinmicos que estn presentes en cualquier actividad de nuestro ordenador. Los grficos son conjuntos de instrucciones que encienden o apagan o modulan los pxeles de pantalla, los elementos ms pequeos que constituyen la definicin de pantalla. Yo, como simple aficionado a la programacin, he utilizado muy poco las potencialidades grficas del RealBasic, por lo que slo puedo hacer una introduccin breve a este tema. Para profundizar en l, los interesados debern hacerse con algn libro especfico, acudir a foros de discusin, obtener rutinas apropiadas, profundizar en photoshop, etc. Una de las acciones ms simples que podemos hacer es aadir una imagen al fondo de una ventana. Supongamos que tenemos una imagen en formato 'jpeg', que es un formato comprimido muy utilizado en internet, y que puede tener desde muy escasa a muy amplia informacin. Esta imagen podemos aadirla a una ventana de nuestro proyecto como fondo o 'backdrop'. Hay al menos dos formas de hacerlo bastante fciles. En una de ellas, teniendo visible la imagen en el finder y teniendo visible la ventana de nuestro proyecto, consiste en arrastrar esta imagen sobre el proyecto, siendo el resultado la aparicin, en la ventana del proyecto, de un alias de la imagen. Si ahora seleccionamos la ventana y miramos en sus propiedades, veremos que en la propiedad 'backdrop' aparece un menu desplegable, y en el mismo el nombre de la imagen. Seleccionndolo, aparece la imagen como el fondo de la ventana. Para que la imagen rellene exactamente todo el fondo de la ventana, debe tener un tamao igual o mayor al de sta. Otra forma de acceder a una imagen es abrirla como si fuera un archivo de texto. Para ello definimos una variable 'folderitem' que luego abrimos mediante un dilogo 'GetOpenFolderItem'. Primero necesitamos definir el tipo de fichero en el menu Edit del RealBasic, en 'File types...'. Si nuestra imagen est en formato "jpeg" , elegiremos la opcin 'image/jpeg' como tipo de fichero. Para ver el resultado de una forma rpida, iniciemos un nuevo proyecto en RealBasic, y despus de aadir el tipo 'image/jpeg' como se indic antes, escribamos el siguiente y simple cdigo en la Sub Open de la ventana del proyecto: SUB Open( ) dim f as folderItem dim p as picture dim s as string f = GetOpenFolderItem("image/jpeg") p = f.OpenAsPicture self.backdrop = p End sub Al hacer correr al proyecto, se abre el dilogo de seleccin de un fichero, y una vez seleccionada una imagen en formato jpeg veremos como se rellena con ella el fondo de nuestra ventana.

En resumen, la imagen es un objeto especial que se maneja mediante una variable tipo picture. Si el tamao de la imagen es menor que el de ventana, habr una parte de esta ltima que quedar vaca. Por eso conviene que las dimensiones de la imagen sean iguales o mayores que el tamao de la ventana. Si no tenemos a mano una imagen podemos crearla con un programa de dibujo. Por ejemplo, con AppleWorks. Basta con seleccionar como programa inicial el de dibujo, y dentro de este aadir un rectngulo y rellenarlo con una trama, color, motivo, etc., de los que proporciona el programa AppleWorks. A la hora de grabar, cuando un dilogo nos pide el nombre del fichero, seleccionar en el menu desplegable 'Formato de archivo' la opcin "jpeg" (tambin podramos seleccionar PICT u otro formato). Sin embargo, la representacin de una imagen como fondo (backdrop) de una ventana no es el camino indicado para el manejo y representacin de imgenes en RealBasic. Hay un objeto que est especialmente diseado para representar imgenes: es el denominado 'canvas' . Sobre el proyecto anterior, podemos aadir un canvas, el cual aparece en la ventana de objetos como una cuadro con imagen. El nombre por defecto que aparece en la ventana de propiedades es 'canvas1'. Si hacemos dobleclick sobre el canvas se abre el editor y podemos ver los eventos asociados a este objeto. La mayora nos son conocidos, pero hay uno que destaca y que es el ms notable del canvas: el evento 'paint'. Este evento recibe una propiedad nueva que es la denominadas 'graphics'. Graphics es una clase del RealBasic o un tipo de variable especial, asociado al manejo de los pxels de una imagen o picture. En el interior de un canvas podemos realizar dibujos, tales como lneas, rectngulos, valos, pxels individuales, etc. Tambin, sobre un canvas, podemos aadir una imagen y convertirla en un objeto grfico de forma que los podamos manipular. Vamos a realizar alguna de estas opciones. En el proyecto anterior podemos 'cortar' el cdigo que habamos escrito en la Sub Open de la ventana inicial para aadirle un fondo, y aadirlo (pegarlo) en la Sub Open del canvas1. Vemos ahora que al correr el programa, es el objeto 'canvas' el que muestra de fondo la imagen jpeg. Vamos ahora a la SUB paint del canvas y escribamos: Sub Paint( g as Graphics) g.drawLine 10,10,300,400 END Sub

Ahora al correr el proyecto, en el canvas y por encima del fondo aparece una lnea cuyo inicio est en las coordenadas 10,10 (left,top) y finaliza en las coordenadas 300, 400 (right, bottom). La instruccin 'drawline' es propia de la clase graphics, y siempre va asociada a una variable de este tipo. Podemos darnos cuenta de que los dibujos 'graphics' aparecen encima de la imagen de fondo del canvas, es decir, una capa superior. Podemos hacer que la lnea sea ms ancha modificando la variable anchura de pincel como sigue: Sub Paint( g as Graphics) g.penWidth = 6 g.drawLine 10,10,300,400 END Sub Y podemos aadir otro dibujo, como un cuadrado: Sub Paint( g as Graphics) g.penWidth = 6 g.drawLine 10,10,300,400 g.drawRect 50,50,200,100 END Sub donde 'DrawRect' corresponde a dibujar un rectngulo cuyo vrtice izquierdo superior se inicia en las coordenadas 50,50 y tiene 200 pixels de anchura y 100 de altura. Como la instruccin 'penWidth' afecta a la anchura del lpiz de dibujo pero no afecta a su altura de dibujo, podemos aadir: Sub Paint( g as Graphics) g.penWidth = 6 g.penHeight = 6 g.drawLine 10,10,300,400 g.drawRect 50,50,200,100 END Sub Tambin podemos rellenar de color el rectngulo mediante la instruccin 'FillRect', pero antes debemos definir el color que deseamos usar. Los colores se definen bajo el sistema RGB que son las iniciales en ingls de Rojo, Verde y Azul. Los colores ya los tratamos en una sesin previa. Cada color se define por un valor integer, que va de cero a 255, siendo cero la iluminacin mnima del color y 255 la mxima. En el formato RGB, el orden de valores 0,255,0 indicara color verde, por ejemplo. La mezcla de los 3 colores 255,255,255 produce blanco, y 0,0,0 nos genera negro. Bueno pues vamos a escribir:

Sub Paint( g as Graphics) g.PenWidth = 6 g.penheight = 6 g.foreColor = rgb(0,222,0) g.drawline 10,10, 300,300 g.FillRect 50,50, 200,100 END Sub lo que nos genera un rectngulo relleno de color verde. Podemos hacer que el color de relleno sea verde, pero el color de los lados del rectngulo sea rojo. Para ello debemos ir cambiando el color (usando forecolor) antes de hacer un dibujo. Pero en lugar de definir el color de forma directa, tambin podemos dimensionarlo al inicio de la sub: Sub paint(g as Graphics) dim verde, rojo as color verde = rgb(0,222,0) rojo = rgb(100,0,0) g.PenWidth = 6 g.penheight = 6 g.foreColor = verde g.drawline 10,10, 300,300 g.FillRect 50,50, 200,100 g.foreColor = rojo g.drawrect 50,50,200,100 End sub Ahora aadamos un texto de tipo grfico: Sub paint(g as Graphics) dim verde, rojo as color verde = rgb(0,222,0) rojo = rgb(100,0,0) g.PenWidth = 6 g.penheight = 6 g.foreColor = verde g.drawline 10,10, 300,300 g.FillRect 50,50, 200,100 g.foreColor = rojo g.drawrect 50,50,200,100 g.textsize = 36 g.drawstring "HOLA QUE TAL", 40,222 End sub Es importante notar que los dibujos se van superponiendo unos a otros. Esto es as porque la superficie disponible del canvas va modificando las caractersticas de sus pxels segn las instrucciones que recibe. Entonces el orden en que enviamos los distintos comandos grficos es importante en el resultado que se obtiene.

La Sub Paint del canvas es especial, en el sentido de que el canvas se redibuja, o se refresca, siempre que parte del mismo es borrado por una ventana del proyecto. Es decir, si tenemos una ventana que aparece delante del canvas, al cerrarse la ventana, la Sub Paint refresca automticamente el dibujo. Comprobemos esta particularidad. Si ahora "cortamos" todo el cdigo escrito en esta Sub Paint, y lo pegamos en la Sub Open del mismo canvas (borrando cualquier instruccin anterior) y hacemos correr el proyecto se nos generar un error, ya que los elementos grficos (graphics) no estn definidos en esta Sub. Si la modificamos as: Sub Open( ) dim verde, rojo as color verde = rgb(0,222,0) rojo = rgb(200,0,0) me.graphics.PenWidth = 6 me.graphics.penheight = 6 me.graphics.foreColor = verde me.graphics.drawline 10,10, 300,300 me.graphics.FillRect 50,50, 200,100 me.graphics.foreColor = rojo me.graphics.drawrect 50,50,200,100 me.graphics.textsize = 36 me.graphics.drawstring "HOLA QUE TAL", 40,222 End Sub ahora s debe funcionar al hacer correr el proyecto. Pero vemos que esto no ocurre as, no hay error pero no se dibuja nada, o al menos no somos capaces de verlo. Podemos aadir un 'breakpoint' a partir del menu Debug del Realbasic antes de la lnea de cdigo me.graphics.drawline 10,10, 300,300 Si ahora hacemos correr el proyecto, el flujo del programa se nos detiene en el lugar donde insertamos el breakpoint, y si ahora avanzamos paso a paso veremos como se dibujan los distintos elementos definidos en el cdigo. Entonces, cual es la razn de que en un Run normal no veamos nada? La razn es que la Sub Paint del canvas continuamente borra y redibuja la imagen del canvas, de forma que la nica manera de mantener la imagen visible es que sea precisamente esta Sub paint la que lleve las instrucciones de dibujo grfico. Si tenemos una imagen inicial y queremos modificarla, es decir, que sus pixels sean accesibles a las instrucciones de tipo 'graphics', necesitamos dibujar esta imagen en el canvas. Para hacerlo se utiliza la instruccin 'g.drawpicture'. Si en la Sub Paint de un canvas aadimos el siguiente cdigo:

SUB Paint(g as Graphics) dim f as folderItem dim p as picture f = GetOpenFolderItem("image/jpeg") if f = nil then quit end p = f.OpenAsPicture g.drawPicture p,0,0,200,333 End sub la ltima instruccin permite dibujar la imagen jpeg en el canvas y podemos entonces modificarla con los mtodos grficos. Por ejemplo, podemos copiar parte de la imagen y dibujarla ampliada o reducida. La siguiente instruccin amplia un fragmento de la imagen, el fragmento que tiene 1,1 como coordenadas del vrtice superior izquierdo, y tamao 50, 50, lo ampla a tamao 300, 400 empezando a dibujarlo en 10,10: g.drawPicture p,10,10,300,400,1,1,50,50 Los mtodos grficos son diversos y requieren un aprendizaje por parte del usuario sobre todo si desea realizar animaciones o movimientos de imgenes. Vamos a examinar un tipo muy simple de animacin, que consiste en cargar una imagen como variable 'picture', y desplazarla por la pantalla como si estuviera animada. Empecemos por crear una imagen de tipo PICT en AppleWorks, de tamao pequeo, por ejemplo, 2 cm. de ancho por 3 cm de alto. Puede ser cualquier elemento, que se nos ocurra, ponindole relleno, o aadiendo en su interior una esfera de otro color, etc. A la hora de grabar lo llamamos cuadro y elegimos el formato PICT. Iniciamos un proyecto nuevo, y lo primero que hacemos es arrastrar sobre la ventana del proyecto, el fichero cuadro; esto nos crea un alias que permanece en el proyecto y que nos permite cargar esta imagen recin hecha. Abrimos la ventana inicial del proyecto (window1) y la alargamos para que ocupe la totalidad del monitor, o al menos una buena parte del mismo. Aadimos un elemento canvas que por defecto ser 'canvas1'. Lo colocamos arriba a la izquierda de la ventana, es decir, en posicin "left=10" y "top=10". En la propiedad 'backdrop' del canvas elegimos, del men desplegable, el nombre cuadro, con lo que nuestra imagen aparece rellenando el fondo del elemento canvas. Si el tamao del canvas es demasiado grande o pequeo respecto a la imagen, lo ajustamos manualmente. Aproximadamente, para una imagen de 2 x 3 centmetros el canvas debe tener unos 57 x 87 pixels. Bueno, pues la idea del proyecto es que esta imagen asociada a un elemento canvas, se mueva por la ventana siguiendo a nuestro ratn. Lo primero es que el usuario mueva el ratn y haga click encima de la imagen (del canvas) y que entonces el canvas se mueva siguiendo al ratn.

Sabemos que el ratn, en una ventana, est asociado a una Sub llamada MouseMove que devuelve las coordenadas del ratn en el interior de la ventana. Podemos escribir entonces: SUB MouseMove( X as integer, Y as integer) canvas1.left = x canvas1.top = y END SUB es decir, que al mover el ratn la posicin del canvas cambia, tomando como propiedades left y top las coordenadas de nuestro ratn. Pero antes de hacer correr el proyecto, vamos a poner una condicin de escape: SUB MouseMove( X as integer, Y as integer) canvas1.left = x canvas1.top = y If x > 400 then quit end END SUB con esto conseguimos que si desplazamos el ratn muy a la derecha y la variable X llega a 400 el programa se detiene. Probamos, y vemos que funciona; pero hay un pequeo problema, y es que la imagen salta de su posicin inicial 10,10 hasta el lugar que ocupa el ratn cuando hacemos el 'run' . Para evitar esto, podemos hacer que la SUB MouseMove slo nos funcione una vez el usuario haya hecho click sobre la imagen (sobre el canvas). Para lograr esto, definimos una variable boolean global para toda la ventana, y la llamaremos 'Inicio'. Por defecto queremos que esta variable inicio sea falsa, y queremos que sea cierta cuando el usuario haga click sobre el canvas. Entonces, una forma de conseguirlo es escribir en la Sub Open de la ventana o del canvas lo siguiente: SUB OPEN inicio = false End Sub y en la Function MouseDown del canvas que se activa al pulsar el botn del ratn escribimos: Function MouseDown(X as integer, Y as integer) as boolean inicio = true End function y finalmente, aadir en la MouseMove anterior: SUB MouseMove( X as integer, Y as integer) if inicio = false then

return end canvas1.left = x canvas1.top = y If x > 400 then quit end END SUB Ahora ya tenemos finalizado el proyecto, al menos hasta donde queramos llegar, que era la carga, exposicin y movimiento controlado de una imagen. Pero el movimiento de imgenes usando uno o ms elementos canvas no es el mejor mtodo de animacin. Hay un elemento del RealBasic que facilita el movimiento de imgenes: el denominado 'Sprite' , y hay otro elemento que viene a ser el espacio por donde ste elemento sprite se mueve, el denominado elemento 'spriteSurface'. Vamos a verlo en un nuevo proyecto. La idea es la siguiente: el 'Sprite' es una imagen que se mueve dentro del 'SpriteSurface' gracias a un mtodo denominado 'NextFrame' que se repite de forma continua hasta que se enva una seal de stop. En el mtodo 'NextFrame' es donde escribimos el cdigo para que la imagen, el 'sprite', se desplace por la superficie del 'SpriteSurface'. Entonces necesitamos una imagen para ser cargada como un 'Sprite'. Podemos usar la imagen del proyecto anterior, que era un fichero tipo PICT llamado "cuadro". Iniciamos un proyecto y arrastramos el fichero cuadro desde el Finder hasta la ventana del proyecto con lo cual se nos crea un alias en el proyecto. Sobre la ventana inicial del proyecto aadimos un objeto 'SpriteSurface' que tiene en su icono como un cohete. El nombre por defecto es 'SpriteSurface1' . En la ventana de propiedades del 'SpriteSurface' ponemos de dimensiones 800 de 'width' y 600 de 'height'. Tambin podemos observar, en behavior, una propiedad denominada 'ClickToStop'. Vamos a seleccionarla, porque nos da la opcin de detener el movimiento del 'sprite' haciendo click con el ratn. Si no lo detenemos as, slo lo podemos detener mediante cdigo usando el mtodo 'SpriteSurface1.stop'. Si no detenemos el movimiento de una de estas dos formas, mediante cdigo o mediante 'clickToStop', entramos en un ciclo sin fin del que no se puede salir, y no nos quedar ms remedio que forzar la salida del RealBasic para poder detener el proceso (cosa no recomendada). Por lo tanto, cuidado con esta cuestin. El rea de la SpriteSurface es normalmente negra, por lo que si queremos ver una imagen tal como la creamos, necesitamos aadir un fondo como 'backdrop', que puede ser una imagen simple de color blanco. Usamos de nuevo AppleWorks para crear una imagen PICT que tenga 800 x 600 pxels o 25 x 20 centmetros de ancho x alto. La grabamos con el nombre 'fondoblanco', y arrastramos el fichero correspondiente desde el Finder hasta la ventana del proyecto para crear un alias de este fichero.

Bueno, vayamos al cdigo. Lo primero es definir una variable global de ventana de tipo sprite. Dentro del editor, vayamos al menu Edit y seleccionemos New Property. Podemos darle por nombre 'muevete'. Vamos a crear otras dos variables globales, que llamaremos 'rX' y 'rY' y que sern ambas de tipo integer. Lo segundo es crear un sprite a partir de la imagen 'cuadro'. Podemos hacerlo dentro de la Sub Open del 'SpriteSurface1', siendo necesario usar el cdigo que se muestra: Sub Open( ) muevete = me.newSprite(cuadro, 10,10) End Sub Lo que hace el cdigo es asignar al nuevo sprite la imagen (picture) del fichero 'cuadro' y colocarlo dentro del SpriteSurface1 en las coordenadas 10,10 Vamos tambin a aadir en la misma sub el cdigo para el fondo del spritesurface y vamos a dar valores iniciales a las variables rX y rY iguales a las del sprite 'muevete' : Sub Open( ) muevete = me.newSprite(cuadro, 10,10) me.backdrop = fondoblanco rX = 10 rY = 10 End Sub Las variables rX y rY las vamos a usar para guardar las coordenadas del ratn cuando hagamos click en algn lugar de la ventana inicial. Vamos a aadir un botn en la ventana inicial, que llevar por caption 'Quit'. En la Sub Action de este botn escribiremos simplemente el comando 'quit'. Ahora vamos a aadir cdigo en la Function MouseDown del evento de ventana inicial: Function MouseDown(X as integer, Y as integer) as boolean rX = X rY = Y SpriteSurface1.run End Function Al tocar con el ratn en un punto de la ventana, las coordenadas de este punto pasan a las variables globales rX y rY. Y el mtodo 'SpriteSurface.run' dispara el inicio de un ciclo de repeticin continuada del mtodo NextFrame, y por consiguiente del cdigo que escribamos en el mismo. Si hacemos dobleclick sobre la ventana inicial o sobre uno de sus elementos se nos abre el editor, y en Controls aparece SpriteSurface1 y dentro de este la sub NextFrame, en la que escribimos:

Sub NextFrame() if muevete.x > rX then muevete.x = muevete.x - 5 elseif muevete.x < rX then muevete.x = muevete.x + 1 end if muevete.y > rY then muevete.y = muevete.y - 5 elseif muevete.y < rY then muevete.y = muevete.y + 1 end if muevete.x = rX and muevete.y = rY then me.stop end End Sub Vamos a examinar con detalle este cdigo. Muevete.x y muevete.y son las coordenadas de este sprite, mientras que rX y rY que se definieron inicialmente como 10,10, tomarn los valores que tenga el ratn al hacer click. Si la coordenada X de muevete es inferior a rX, su valor aumenta en una unidad en cada ciclo, y si es mayor disminuye en una unidad por ciclo. As hasta que se hacen iguales. Lo mismo para las coordenadas Y. Esto hace que el redibujado de 'muevete' se haga en distinta posicin en cada ciclo, dando la sensacin de movimiento de la imagen sobre la pantalla. La ltima condicin es que si las coordenadas X e Y coinciden, el SpriteSurface se detiene con la instruccin me.stop (equivalente a SpriteSurface1.stop). Tenemos ahora un mtodo para detener la animacin, por lo que podemos (y debemos) desactivar la propiedad 'ClickToStop' del spriteSurface, para que todo funcione adecuadamente. Buena suerte.

Potrebbero piacerti anche