PROGRAMACION DE COMPUTADORES
7. Glosario………………………………………………………………………..60
8. Bibliografía……………………………………………………………………62
1. PROGRAMACION DE COMPUTADORES
HORAS DE HORAS DE
TRABAJO ACOMPAÑAMIENTO
AUTONOMO TUTORIAL
Los computadores en su inicio fueron creados para realizar cálculos matemáticos de una manera más rápida. La
forma de darle ordenes al computador era conectando y desconectando cables, los tubos de vacio, con los que
funcionaban los computadores, se fundían frecuentemente. El funcionamiento de un computador se basa en el
sistema binario, y es lo único que entiende un PC. Cuando se programaba entonces un computador las
instrucciones eran representadas por números binarios ejemplo: 1110110101000111 esto podría significar darle un
valor a una variable, sumar dos números, o cualquier otra instrucción. Luego para hacer la programación mas
entendible y fácil se creó el asembler, el cual usa unas instrucciones básicas para desarrollar programas en
ambiente DOS (sistema operativo no grafico). Aunque este lenguaje era más sencillo que teclear dígitos binarios,
algunos programadores crearon compiladores mucho más fáciles de entender, lo que facilitaba realizar programas
más complejos. Es así como hoy en día conocemos lenguajes de programación dinámicos, tales como: PHP, ASP,
JAVA, ACTIVEX, JSCRIPT, GRAFICADORES, Programacion interactiva, Programación online que automatizan el
trabajo del programador. Compiladores que convierten el programa a su nivel más bajo (conjunto de unos y cero).
La mayor parte de los computadores que existen en la actualidad están diseñados de forma que puedan ejecutar
diversas tareas o programas. Estos programas pueden ir desde un procesador de textos, a un programa para la
animación de gráficos tridimensionales o distintos tipos de juegos.
Para su correcto funcionamiento deben ser además capaces de acceder a los recursos de que dispone el
computador, como por ejemplo escribir o leer datos en un disco duro, mostrar un gráfico por pantalla, etc. Es
evidente, que si cada programa actúa de una forma independiente, existirían graves problemas y conflictos, puesto
que, por ejemplo, tendrían libertad para escribir sus datos sobre los de otro, etc.
Para solucionar este tipo de problemas se desarrollaron los Sistemas Operativos, los cuales aportan unos
mecanismos y reglas básicas de funcionamiento, de forma que los programas puedan acceder a los recursos del
ordenador de una forma adecuada. Aunque ésta fue la funcionalidad inicial de los sistemas operativos, con el tiempo
se han añadido otras muchas, como la ejecución de programas, el control de la memoria del ordenador, la creación
y control de interfaces gráficas de usuario, etc.
La elaboración del presente módulo está basada en la norma de competencia 220501007 denominada ¨desarrollar
el sistema que cumpla con los requerimientos de la solución informática¨, donde se tienen en cuenta los aspectos
definidos por la universidad.
El módulo aborda temas de gran importancia para la formación del futuro técnico como son:
Evolución de los lenguajes de computación, generaciones de los lenguajes de programación, algoritmia, diagrama
de flujo y pseudocódigo.
La segunda unidad aborda los temas de lenguajes de progrmacion, divido el lenguajes orientdos a objetos(java,
visual basic) y lenguajes dinaicos ( a nivel del servidor: ASP y PHP; a nivel del cliente: JavaScript y
visualBasicScript).
En este curso el estudiante aprenderá como darle instrucciones al computador, y así crear aplicativos que cumplan
con los requerimientos identificados para una solución especifica. El estudiante aprenderá la lógica de la
programación, entendiendo que programar no es aprender un lenguaje, programar es resolver problemas y
comunicar la solución al computador a través de un lenguaje de programación, por esto queridos participantes los
invito que se motiven a aprender a programar, a desarrollar la lógica para resolver problemas, a no pensar en el
lenguaje sino en la solución.
Con este curso el estudiante estará en capacidad de dar soluciones informáticas efectivas, crear aplicaciones de
calidad en ambientes web y con un enfoque orientado a objetos, exhortando a las empresas a ser más
competitivas ya sean estas del sector privado o público, Siendo el desarrollador de aplicaciones Web quien genere
la toma de decisiones en todos los niveles de la empresa.
3. CONTEXTUALIZACION
Las organizaciones desde el punto de vista de la teoría de los sistemas, puede ser considerara como un sistema
abierto y por esta razón , la organización estará expuesta a los diversos cambios que se producen el medio
ambiente que la rodea.
El éxito o fracaso de una organización, cualquiera sea su rubro, dependerá de la capacidad que tenga la misma
para adaptarse a tales cambios.
Teniendo en cuenta el concepto anterior, podemos afirmar que existen diversas empresas que ante la necesidad de
un cambio o adaptación en el área de informática (manejo de tecnología e información), han implementado un
nuevo encuadre para el líder de la tecnología de información, es decir un cambio en la visión y misión que traen
durante una larga trayectoria los profesionales de sistemas (en particular los directores/gerentes del centro de
cómputo).
Por mucho tiempo el área de sistemas fue considerada como un gasto innecesario para la mayoría de las
compañías, eran un tanto más operativos: pues se les llamaba cuando los equipos de cómputo sufrían algún
desperfecto, y más que considerárseles como estrategas, siempre se les relegaba en la toma de decisiones...
Hoy por hoy esta situación ha cambiado y para bien, pues la dirección general ha tenido a bien reconocer la
importancia que la labor de los gerentes y directivos de sistemas tienen para lograr el éxito de una empresa
mediante la aplicación de las TIC de una forma innovadora para lograr la reducción de gastos operativos,
automatización de tareas, ahorro de tiempo y eficiencia de los procesos.
Asimismo, y a medida que ha aumentado su responsabilidad y su papel en la toma de decisiones en las estrategias
empresariales, también ha crecido su salario y prestaciones.
El estudiante debe aprender las instrucciones básicas de programación y el enfoque orientado a objetos, para poder
comunicarle al computador que debe hacer este. Debe buscar soluciones óptimas a problemas simples o complejos,
usando instrucciones entendibles por el computador.
El desarrollo de las capacidades de Hardware ha experimentado un auge desmesurado en los últimos años, pero el
aprovechamiento de estas posibilidades no es óptimo si no se dispone del software adecuado. Con este fin se han
diseñado diversos lenguajes de programación, unos de propósito general, es decir, para todo tipo de aplicaciones, y
otros de aplicación particular en algunos de los campos del ámbito informático.
Un lenguaje de programación es una notación para escribir programas, a través de los cuales podemos
comunicarnos con el hardware y dar así las órdenes adecuadas para la realización de un determinado proceso. Un
lenguaje está definido por una gramática o conjunto de reglas que se aplican a un alfabeto constituido por el
conjunto de símbolos utilizados.
Los distintos niveles de programación existentes nos permiten acceder al hardware, de tal forma que según
utilicemos un nivel u otro, así tendremos que utilizar un determinado lenguaje ligado a sus correspondientes
compiladores, depuradores y traductores.
Siendo la información un activo primario de la empresa , esta se origina a través de la manipulación de los datos, la
información oportuna, coherente, estable, segura y verídica es un muy buen indicador de gestión informática a favor
del recurso humano administrativo , permitiendo modelar procesos enfocados a la sistematización integral en la
toma de decisiones en bien de la empresa o la sociedad. Es por esto que se hace importante aprender a dar
soluciones informáticas efectivas programando los computadores usando el lenguaje de programación más
adecuado, para que estos nos entreguen la información en un ambiente web de manera confiable y oportuna
3.2.Planteamiento
La informática ha supuesto una revolución técnica y conceptual que ha impactado en prácticamente todas las áreas
de conocimiento. Consideramos que es una revolución técnica en cuanto que ha afectado la implementación y el
análisis de las tareas más diversas. De la misma manera, consideramos que es una revolución conceptual porque
ha provocado -con la generación de sistemas expertos, algoritmos genéticos, etc.- la desaparición y reducción de
incertidumbre de las teorías y modelos conceptuales de las disciplinas donde se ha implantado. Evidentemente
estas implicaciones son pertinentes en las ciencias de la actividad física y el deporte, en todas y cada una de sus
áreas de conocimiento e investigación.
Hasta los años sesenta, relativamente poca estructura se había impuesto a la forma en que escribían código los
programadores. No había estructuras bien definidas, y en consecuencia, el control de flujo a través de cientos o
miles de líneas resultaba casi imposible. Un ejemplo de esto, es el uso con frecuencia de instrucciones goto para
lograr saltos a otras partes de un programa.
La programación estructurada evolucionó en los años sesenta y setenta. El nombre se refiere a la práctica de
construir programas usando un conjunto de estructuras bien definidas. Una meta de la programación estructurada
es la eliminación de las instrucciones goto.
Los desarrolladores de software descubrieron que al utilizar la programación estructurada se obtiene una eficiencia
mejorada, pero se tienen inconvenientes en el proceso de construir software rápida y correctamente.
La reutilización es reconocida como la clave de la solución. Reutilizar código permite que los programas se
construyan rápida y correctamente. Las funciones, que son los bloques constructores de la programación
estructurada, son un paso a lo largo de este camino. En los años ochenta, la computación dio otro paso hacia
delante con la programación orientada a objetos (POO). Los bloques constructores de la POO, llamados objetos,
son reutilizables, son componentes modulares. Los expertos afirman que la POO será el enfoque dominante en la
programación durante un buen tiempo.
La Programación de computadores es la ciencia que permite a una persona programar una computadora para que
resuelva tareas de manera rápida. Un Programa de computador se puede definir como una secuencia de
instrucciones que indica las acciones o tareas que han de ejecutarse para dar solución a un problema determinado.
Programar computadores es indispensable en cualquier área de la ingeniería, ya que diferentes problemas que se
puedan presentar tardan tiempo resolverlos de manera manual. el computador resuelve problemas de acuerdo
como se le haya programado de manera rápida.
Para llegar a tener una secuencia de instrucciones que den solución a un problema es necesario ejecutar varias
etapas a saber :
Etapa de análisis. Etapa de Solución general. Etapa de prueba1. Etapa de implementación específica. Etapa de
rueba2.Etapa de uso o puesta en marcha.
Con el fin de determinar el grado de aprendizaje obtenido, es importante resolver las siguientes preguntas, para
luego compararlas con lo aprendido durante el desarrollo de este modulo.
¿Que es un algoritmo?
¿Que es un Diagrama de flujo?
¿Que es un Pseudocódigo?
¿Que es un compilador?
¿Que es un depurador?
¿Que es un traductor?
¿Que es un lenguaje de programación?
¿Para que sirven las variables en un lenguaje de programación?
¿Cuál es el alcance de las variables?
¿Para que sirven y cuáles son las instrucciones primitivas?
¿Para que sirven y cuáles son los tipos de datos en un lenguaje de programación?
¿Para que se utiliza los Tipos de operaciones matemáticas y lógicas. En la programación?
¿Que diferencia hay entre un lenguaje de programación y un software de propósito especifico?
Enumere tres diferencias entre lenguajes dinámicos y lenguajes orientados a objetos.
Diferencias entre prueba de caja blanca y prueba de caja negra.
4. COMPETENCIAS
5.IDEOGRAMA
6. UNIDADES DE APRENDIZAJE
6.1 UNIDAD DE APRENDIZAJE No. 1: INTRODUCCION A LA PROGRAMACION
Conocer una
Segunda lengua
Conocer las
tendencias futuras de
los computadores
Configurar de
manera física y lógica
un sistema
Interpretar
manuales de
operación de equipos
Conocer los
componentes básicos
de hardware y
software, periféricos
de entrada, salida y
almacenamiento. Que
son, para que sirven y
como se configuran
6.1.1 Resumen.
El desarrollo de cada una de las generaciones de los lenguajes de programación fue de la mano del desarrollo del
hardware.
En cuanto a su generación, esta clasificación se basa en la línea de tiempo histórica de los lenguajes de
programación.
Más recientes fueron las aportaciones en esta campo de Charles Babbage, quien entre los años 1820 y 1850,
diseñó dos máquinas para computar ninguna de las cuales fue terminada. La más interesante, ya que se parecía a
los computadores digitales modernos, fue la máquina analítica. Los programas para este primer computador
estaban escritos, básicamente, en lenguaje máquina y utilizaban unas ciertas tarjetas de operación y tarjetas de
datos. Junto a Babbage trabajó Ada Augusta, condesa de Lovelace, hija del famoso poeta Lord Byron, que
recientemente ha sido reconocida como la primera programadora y en su honor se llamó ADA al último lenguaje
desarrollado bajo el auspicio del Dpto. de Defensa de los USA.
Durante los años 30 y 40 surge un gran número de gente con ideas sobre notaciones para la programación. La
mayoría eran puramente teóricas. Algunos ejemplos son la máquina de Turing o el cálculo Lambda.
A principios de los años 50 se empezaron a construir máquinas con cierta capacidad de cálculo (aunque muy
limitadas y costosas), que trabajaban con lenguajes de tipo ensamblador.
Un autómata es cualquier mecanismo capaz de realizar un trabajo de forma autónoma (un reloj, una caja de música,
la cisterna del WC, un radiador con termostato).
Todos estos aparatos tienen en común que, una vez conectados, pueden realizar su función sin más intervención
externa. También comparten el hecho de que son bastante simples. Unos autómatas más flexibles serían un
organillo, un video, una lavadora, ya que al menos su repertorio de acciones posibles es más variado. El ejemplo del
organillo es revelador ya que en él aparecen las mismas fases que en el desarollo de un programa: una pieza de
música es "diseñada" por un compositor, codificada en un soporte físico y ejecutada por una máquina.
En estos términos, un ordenador es un autómata de cálculo gobernado por un programa, de tal modo que diferentes
programas harán trabajar al ordenador de distinta forma. Un programa es la codificación de un algoritmo, y un
algoritmo es la descripción precisa de una sucesión de instrucciones que permiten llevar a cabo un trabajo en un
número finito de pasos.
En esta unidad se pretende que el participante conozca el proceso de evolución a través de la historia de los
sistemas informáticos, con base a la evolución constante que han tenido los computadores actualmente,
teniendo en cuenta aspectos como características, diferencias de procesadores, memorias ram, tipos de
almacenamiento, sistemas operativos, entre otros aspectos siempre de la mano en los avances tecnológicos que se
dan a nivel de hardware.
Charles Babbage definió a mediados del siglo XIX lo que él llamó la máquina analítica. Se considera a esta
máquina el diseño del primer ordenador. La realidad es que no se pudo construir hasta el siglo siguiente. El caso es
que su colaboradora Ada Lovelace escribió en tarjetas perforadas una serie de instrucciones que la máquina iba a
ser capaz de ejecutar. Se dice que eso significó el inicio de la ciencia de la programación de ordenadores.
En la segunda guerra mundial debido a las necesidades militares, la ciencia de la computación prospera y con ella
aparece el famoso ENIAC (ElectronicNumerical Integrator And Calculator), que se programaba cambiando su
circuitería. Esa es la primera forma de programar (que aún se usa en numerosas máquinas) que sólo vale
para máquinas de único propósito. Si se cambia el propósito, hay que modificar la máquina.
No mucho más tarde apareció la idea de que las máquinas fueran capaces de realizar más de una aplicación. Para
lo cual se ideó el hecho de que hubiera una memoria donde se almacenaban esas instrucciones. Esa memoria se
podía rellenar con datos procedentes del exterior. Inicialmente se utilizaron tarjetas perforadas para introducir las
instrucciones.
Durante mucho tiempo esa fue la forma de programar, que teniendo en cuenta que las máquinas ya entendían sólo
código binario, consistía en introducir la programación de la máquina mediante unos y ceros. El llamado código
máquina.
Todavía los ordenadores es el único código que entienden, por lo que cualquier forma de programar debe de ser
convertida a código máquina.
Sólo se ha utilizado por los programadores en los inicios de la informática. Su incomodidad de trabajo hace que sea
impensable para ser utilizado hoy en día. Pero cualquier programa de ordenador debe, finalmente, ser convertido a
este código para que un ordenador pueda ejecutar las instrucciones de dicho programa.
Un detalle a tener en cuenta es que el código máquina es distinto para cada tipo de procesador. Lo que hace que
los programas en código máquina no sean portables entre distintas máquinas.
En los años 40 se intentó concebir un lenguaje más simbólico que permitiera no tener que programar utilizando
código máquina. Poco más tarde se ideó el lenguaje ensamblador, que es la traducción del código máquina a una
forma más textual. Cada tipo de instrucción se asocia a una palabra mnemotécnica (como SUM para sumar por
ejemplo), de forma que cada palabra tiene traducción directa en el código máquina.
Tras escribir el programa en código ensamblador, un programa (llamado también ensamblador) se encargará de
traducir el código ensamblador a código máquina. Esta traducción es rápida puesto que cada línea en ensamblador
tiene equivalente directo en código máquina (en los lenguajes modernos no ocurre esto).
La idea es la siguiente: si en el código máquina, el número binario 0000 significa sumar, y el número 0001 significa
restar. Una instrucción máquina que sumara el número 8 (00001000 en binario) al número 16 (00010000 en binario)
sería: 0000 00001000 00010000
Realmente no habría espacios en blanco, el ordenador entendería que los primeros cuatro BITS representan la
instrucción y los 8 siguientes el primer número y los ocho siguientes el segundo número (suponiendo que los
números ocupan 8 bits). Lógicamente trabajar de esta forma es muy complicado. Por eso se podría utilizar la
siguiente traducción en ensamblador: SUM 8 16
La ventaja de este lenguaje es que se puede controlar absolutamente el funcionamiento de la máquina, lo que
permite crear programas muy eficientes. Lo malo es precisamente que hay que conocer muy bien el funcionamiento
de la computadora para crear programas con esta técnica. Además las líneas requeridas para realizar una tarea se
disparan ya que las instrucciones de la máquina son excesivamente simples.
Tras varios intentos de representar lenguajes, en 1957 aparece el que se considera el primer lenguaje de alto nivel,
el FORTRAN (FORmula TRANslation), lenguaje orientado a resolver fórmulas matemáticos.
BASIC se creó en el año 1964 como lenguaje de programación sencillo de aprender en 1964 y ha sido, y es, uno de
los lenguajes más populares; En 1968 se crea LOGO para enseñar a programar a los niños. Pascal se creó con la
misma idea académica pero siendo ejemplo de lenguaje estructurado para programadores avanzados. El creador
del Pascal (Niklaus Wirdth) creo Modula en 1977 siendo un lenguaje estructurado para la programación de
sistemas (intentando sustituir al C).
En los años 70 se empezó a utilizar éste término para hablar de lenguajes en los que apenas hay código y en su
lugar aparecen indicaciones sobre qué es lo que el programa debe de obtener. Se consideraba que el lenguaje SQL
(muy utilizado en las bases de datos) y sus derivados eran de cuarta generación. Los lenguajes de consulta de
datos, creación de formularios, informes,... son lenguajes de cuarto nivel. Aparecieron con los sistemas de base de
datos.
Actualmente se consideran lenguajes de éste tipo a aquellos lenguajes que se programan sin escribir casi código
(lenguajes visuales), mientras que también se propone que éste nombre se reserve a los lenguajes orientados a
objetos.
En los 80 llegan los lenguajes preparados para la programación orientada a objetos todos procedentes
de Simula (1964) considerado el primer lenguaje con facilidades de uso de objetos. De estos destacó
inmediatamente C++.
A partir de C++ aparecieron numerosos lenguajes que convirtieron los lenguajes clásicos en lenguajes orientados a
objetos (y además con mejoras en el entorno de programación, son los llamados lenguajes visuales): Visual
Basic, Delphi(versión orientada a objetos de Pascal), Visual C++,...
En 1995 aparece Java como lenguaje totalmente orientado a objetos y en el año 2000 aparece C# un lenguaje que
toma la forma de trabajar de C++ y del propio Java.
La popularidad de Internet ha producido lenguajes híbridos que se mezclan con el código HTML con el que se
crean las páginas web. HTML no es un lenguaje en sí sino un formato de texto pensado para crear páginas web.
Éstos lenguajes se usan para poder realizar páginas web más potentes.
Son lenguajes interpretados como JavaScript o VB Script, o lenguajes especiales para uso en servidores
como ASP, JSP o PHP. Todos ellos permiten crear páginas web usando código mezcla de página web y
lenguajes de programación sencillos.
Los métodos de diseño e implementación de los lenguajes de programación han evolucionado rápidamente desde
los primeros lenguajes de alto nivel que aparecieron a principios de los años 30.
Los lenguajes de programación son muchos y en cada uno de los mismos se puede hacer un juego. Ya sea Java,
C, Visual Basic o el que se desee. Sin embargo los lenguajes poseen dos tipos de clasificaciones. El tipo de nivel y
su generación. Cabe aclarar que la idea de los diferentes tipos de lenguajes se debe a la necesidad de simplificar la
tarea de programar y de utilizar para el mismo un lenguaje que se acerque lo más posible al humano.
Primera generación
lenguaje de máquina 1940-1950. Consistía en sucesiones de dígitos binarios. Aún en la actualidad, es el único
lenguaje interno que entiende la computadora; los programas se escriben en lenguajes de mayor nivel y se traducen
a lenguaje de máquina
Antes de que un computador pueda ejecutar una tarea, debe programársele para que lo haga colocando en la
memoria principal un algoritmo apropiado, expresado en lenguaje máquina, que no es más que una secuencia de
números mediante los que se representan las operaciones a realizar y los operandos con los que operar.
Originariamente, este proceso de programación se realizaba por el laborioso método de expresar todos los
algoritmos en el lenguaje de máquina, enfoque que hacía más penosa la ya de por sí difícil tarea de diseñar un
programa, y en la mayoría de los casos daba pie a errores que era necesario localizar y corregir.
El primer paso para eliminar estas complejidades del proceso de programación fue la asignación de nombres
mnemónicos a los diversos códigos de operación, y usarlos en vez de la representación hexadecimal, aumentando
considerablemente la comprensibilidad de las secuencias de instrucciones de la máquina. Luego un programa
especial llamado ensamblador se encargaba la traducción de los códigos mnémonicos a instrucciones en lenguaje
máquina. A estos programas se les llamó ensambladores, pues su tarea era ensamblar instrucciones en lenguaje
máquina a partir de códigos de operación y operandos. Por extensión, a los lenguajes que utilizaban los
mnemónicos se les llamó lenguajes ensamblador.
Segunda generación
lenguajes ensambladores fines 1950. En lugar de usar códigos binarios, las instrucciones se representan con
símbolos fáciles de reconocer, conocidos como mnemotécnicos. Aún se utilizan estos lenguajes cuando interesa un
nivel máximo de eficiencia en la ejecución o cuando se requieren manipulaciones intrincadas.
En la época en que aparecieron los primeros lenguajes ensambladores, parecía que se había dado un gigantesco
salto hacia adelante en la búsqueda de mejores entornos de programación, y es por ello que se les comenzó a
llamar lenguajes de segunda generación, siendo la primera generación la compuesta por los lenguajes máquina.
Estamos en los primeros años 50 y ejemplos de estos lenguajes podrían ser AUTOCODER, SPS, BAL o
EASYCODER.
Una consecuencia importante de la íntima asociación entre los lenguajes ensambalador y de máquina es que
cualquier programa escrito en lenguaje ensamblador depende inherentemente de la máquina; esto es, las
instrucciones del programa se expresan en términos de los atributos de una máquina específica. Por tanto, un
programa escrito en lenguaje ensamblador no se puede transportar fácilmente a otra máquina porque se tiene que
reescribir de modo que se ajuste a la configuración de registros y al conjunto de instrucciones de la nueva máquina.
Otra desventaja de los lenguajes ensambladores es que el programador, aunque no tiene que codificar las
instrucciones en forma de patrones de bits, sí está obligado a pensar en térnimos de los pequeños pasos
incrementales del lenguaje de la máquina, y no puede concentrarse en la solución global de la tarea que está
realizando. En pocas palabras, las instrucciones elementales en que se debe expresar finalmente un programa no
son necesariamente las instrucciones que deben usarse al diseñarlo.
Tercera generación
Años '60. Los lenguajes de esta generación se dividen en tres categorías, según se orienten a: Procedimientos: la
forma en la que se programan. Problema: El problema que intentan resolver. Objeto: Como se encarara el objeto a
desarrollar. De acuerdo con esta idea, a mediados de los 50 se comenzaron a crear lenguajes de programación que
eran más propicios para la elaboración de software que los lenguajes ensamblador de bajo nivel. El resultado fue la
aparición de una tercera generación de lenguajes de programación que difería de las anteriores en que sus
instrucciones eran de alto nivel y además independientes de las máquinas. Una vez escrito el programa con
instrucciones de alto nivel, se utilizaba un programa llamado traductor que traducía a lenguaje máquina los
programas escritos en lenguajes de alto nivel. Estos programas son parecidos a los ensambladores de la segunda
generación, solo que a menudo tienen que compilar, reunir varias instrucciones de máquina para formar secuencias
cortas que simularan la actividad solicitada por la instrucción de alto nivel, y por esta razón se comenzó a llamar
compiladores a este tipo de programa.
Unos de los primeros lenguajes de la tercera generación son FORTRAN y COBOL, por lo que algunas
clasificaciones les colocan en la segunda generación. También está ALGOL60. Después de estos aparecen otros
como BASIC (1965), SNOBOL, APL, PL/1 y SIMULA, entre otros. En los 70 aparecen lenguajes de alto nivel como
PASCAL, C, MODULA y PROLOG. Más recientes son Eiffel, Smalltalk, ADA, ML, C++ y Java.
Con la aparición de los lenguajes de tercera generación se alcanzó, en gran medida la meta de la independencia
respecto a las máquinas. Como las instrucciones de estos lenguajes no hacían referencia a los atributos de ninguna
máquina en particular, se podían compilar con la misma facilidad en una u otras máquinas. Así, en teoría, un
programa escrito en un lenguaje de tercera generación se podía utilizar en cualquier máquina con sólo aplicar el
compilador apropiado. Sin embargo, la realidad no ha resultado ser tan simple.
Las tres primeras generaciones de lenguajes siguen una sucesión en el tiempo, mientras que a partir de ahí, las dos
últimas generaciones han evolucionado paralelamente y en campos bastantes distintos.
La cuarta generación
Las características generales de los lenguajes de cuarta generación son: Uso de frases y oraciones parecidas al
inglés para emitir instrucciones. No operan por procedimientos, por lo que permiten a los usuarios centrarse en lo
que hay que hacer no en cómo hacerlo. Al hacerse cargo de muchos de los detalles de cómo hacer las cosas,
incrementan la productividad. Ejemplo de esta generación son los lenguajes visuales.
Los lenguajes de cuarta generación pretenden superar los problemas surgidos de los lenguajes de tercera
generación:
Estos lenguajes permiten generar aplicaciones de cierta complejidad con un número de líneas menor que el que
tendríamos si usáramos un lenguaje de tercera generación. Para construir aplicaciones el programador contará,
aparte de un conjunto de instrucciones secuenciales, con una gran diversidad de mecanismos como son: el
rellenado de formularios, la interacción con la pantalla, etc. Un ejemplo de este tipo de lenguajes es SQL.
Quinta generación
La quinta generación de lenguajes se ha relacionado con los lenguajes que se utilizan en el campo de la inteligencia
artificial: sistemas basados en el conocimiento, sistemas expertos, mecanismos de inferencia o procesamiento del
lenguaje natural. Lenguajes como LISP o PROLOG han sido la base de este tipo de lenguajes.
Tipos de lenguajes
Lenguaje Maquina: es el lenguaje de los unos y ceros. Es decir como procesan la información los distintos
tipos de dispositivos de la computadora. Un lenguaje que entiende la maquina perfectamente pero que es
muy complicado de programar.
Lenguaje de Bajo nivel: Lenguajes que dependen de la arquitectura que se este manejando. En ellos se
poseen instrucciones básicas que son traducidas a lenguaje maquina. Su programación no es simple, pero se
obtiene un control absoluto de los dispositivos. El ensamblador es el ejemplo típico
Lenguaje de Alto nivel: Son independientes de la máquina y se pueden utilizar en cualquier computadora.
Los lenguajes de más alto nivel no ofrecen necesariamente mayores capacidades de programación, pero si
ofrecen una interacción programador/computadora más avanzada. Cuanto más alto es el nivel del lenguaje,
más sencillo es comprenderlo y utilizarlo. El C es el ejemplo típico de estos lenguajes
Lenguaje de Muy Alto nivel: En el se trata de obtener un dialogo mas "humano" con la maquina. Son los
lenguajes orientados a objetos como C++, Java o Visual Basic
En cada nuevo nivel se requieren menos instrucciones para indicar a la computadora que efectúe una tarea en
particular. Pero los lenguajes de alto nivel son sólo una ayuda para el programador. Un mayor nivel significa que son
necesarios menos comandos, debido a que cada comando o mandato de alto nivel reemplaza muchas instrucciones
de nivel inferior
Intérpretes
A la hora de convertir un programa en código máquina, se pueden utilizar dos tipos de software: intérpretes y
compiladores. En el caso de los intérpretes se convierte cada línea a código máquina y se ejecuta ese código
máquina antes de convertir la siguiente línea. De esa forma si las dos primeras líneas son correctas y la tercera
tiene un fallo de sintaxis, veríamos el resultado de las dos primeras líneas y al llegar a la tercera se nos notificaría el
fallo y finalizaría la ejecución.
El intérprete hace una simulación de modo que parece que la máquina entiende directamente las instrucciones del
lenguaje, pareciendo que ejecuta cada instrucción (como si fuese código máquina directo).
El BASIC era un lenguaje interpretado, se traducía línea a línea. Hoy en día la mayoría de los lenguajes integrados
en páginas web son interpretados, la razón es que como la descarga de Internet es lenta, es mejor que las
instrucciones se vayan traduciendo según van llegando en lugar de cargar todas en el ordenador.
Proceso
Un programa que se convierte a código máquina mediante un intérprete sigue estos pasos:
Ventajas
Se tarda menos en crear el primer código máquina. El programa se ejecuta antes.
No hace falta cargar todas las líneas para empezar a ver resultados (lo que hace que sea una técnica idónea
para programas que se cargan desde Internet)
Desventajas
El código máquina producido es peor ya que no se optimiza al valorar una sola línea cada vez. El código
optimizado permite estudiar varias líneas a la vez para producir el mejor código máquina posible, por ello no
es posible mediante el uso de intérpretes.
Todos los errores son errores en tiempo de ejecución, no se pueden detectar antes de lanzar el programa.
Esto hace que la depuración de los errores sea más compleja.
El código máquina resultante gasta más espacio.
Hay errores difícilmente detectables, ya que para que los errores se produzcan, las líneas de errores hay que
ejecutarlas. Si la línea es condicional hasta que no probemos todas las posibilidades del programa, no
sabremos todos los errores de sintaxis cometidos.
Compiladores
Se trata de software que traduce las instrucciones de un lenguaje de programación de alto nivel a código máquina.
La diferencia con los intérpretes reside en que se analizan todas las líneas antes de empezar la traducción.
Durante muchos años, los lenguajes potentes han sido compilados. El uso masivo de Internet ha propiciado que
esta técnica a veces no sea adecuada y haya lenguajes modernos interpretados o semi-interpretados, mitad se
compila hacia un código intermedio y luego se interpreta línea a línea (esta técnica la siguen Java y los lenguajes de
la plataforma .NET de Microsoft).
Ventajas
Se detectan errores antes de ejecutar el programa (errores de compilación)
El código máquina generado es más rápido (ya que se optimiza)
Es más fácil hacer procesos de depuración de código
Desventajas
El proceso de compilación del código es lento.
No es útil para ejecutar programas desde Internet ya que hay que descargar todo el programa antes de
traducirle, lo que ralentiza mucho su uso.
¿QUÉ ES ALGORITMO?
La palabra algoritmo se deriva de la traducción al latín de la palabra árabe alkhowarizmi, nombre de un matemático
y astrónomo árabe que escribió un tratado sobre manipulación de números y ecuaciones en el siglo IX.
Un algoritmo es una serie de pasos organizados que describe el proceso que se debe seguir, para dar solución a un
problema específico.
El origen de la palabra se piensa que es el nombre de un algebrista árabe llamado Mûsâ al-Khowârizmî, AD 825.
Un algoritmo es un procedimiento especificado paso a paso para resolver un problema en una cantidad finita de
tiempo.
Características:
1. Quitar la rueda.
1. Aflojar los tornillos.
2. Levantar el automóvil.
3. Extraer la rueda.
1. Retirar los tornillos.
2. Retirar la rueda.
2. Poner la rueda.
1. Colocar la rueda.
1. Presentar la rueda.
2. Poner los tornillos.
2. Bajar el coche.
3. Apretar los tornillos.
En el algoritmo anterior muchos de los pasos son demasiado vagos para ser considerados bien definidos; de modo
que habría que concretarlos más.
Los algoritmos se suelen expresar utilizando una manera mas o menos formal de lenguaje, llamado pseudocódigo,
que toma diversas formas, alguna de ellas más gráficas, y otras más cercanas al lenguaje humano.
Los primeros algoritmos conocidos están fechados entre los años 3000 y 1500 AC. Fueron encontrados en la zona
conocida como Mesopotamia (actualmente Irak) cerca de la ciudad de Babilonia. Estos algoritmos no tenían ni
condicionales (los expresaban escribiendo varias veces el algoritmo) ni iteraciones (extendían el algoritmo con
tantos pasos como fuera necesario). Probablemente más conocido, es el matemático griego Euclides, que hacia el
año 300 AC., definió un algoritmo para calcular el máximo común divisor de dos enteros positivos. Aunque en este
algoritmo se incluía la iteración, presentaba pocas mejoras respecto a los anteriores.
n=m
m=t
devolver n
TIPOS DE ALGORITMOS
Existen dos tipos y son llamados así por su naturaleza:
Cualitativos: Son aquellos en los que se describen los pasos utilizando palabras.
Cuantitativos: Son aquellos en los que se utilizan cálculos numéricos para definir los pasos del proceso.
Lenguajes Algorítmicos
Un Lenguaje algorítmico es una serie de símbolos y reglas que se utilizan para describir de manera explícita un
proceso.
Gráficos: Es la representación gráfica de las operaciones que realiza un algoritmo (diagrama de flujo).
No Gráficos: Representa en forma descriptiva las operaciones que debe realizar un algoritmo
(pseudocodigo).
INICIO
Edad: Entero
ESCRIBA “cual es tu edad?”
Lea Edad
SI Edad >=18 entonces
ESCRIBA “Eres mayor de Edad”
FINSI
ESCRIBA “fin del algoritmo”
FIN
El computador es una máquina que por sí sola no puede hacer nada, necesita ser programada, es decir, introducirle
instrucciones u ordenes que le digan lo que tiene que hacer. Un programa es la solución a un problema inicial, así
que todo comienza allí: en el Problema. El proceso de programación es el siguiente: Dado un determinado problema
el programador debe idear una solución y expresarla usando un algoritmo (aquí es donde entra a jugar); luego de
esto, debe codificarlo en un determinado lenguaje de programación y por último ejecutar el programa en el
computador el cual refleja una solución al problema inicial. Esto es a grandes rasgos lo que hace el programador de
computadores.
La parte que corresponde a este curso es la de: “Dado un determinado problema debemos idear una solución y
expresarla usando un ALGORITMO!”.
Esta fase está dada por el enunciado del problema, el cual requiere una definición clara y precisa. Es
importante que se conozca lo que se desea que realice la computadora; mientras esto no se conozca del todo
no tiene mucho caso continuar con la siguiente etapa.
Una recomendación muy práctica es el de colocarse en el lugar de la computadora y analizar qué es lo que
se necesita que se ordene y en qué secuencia para producir los resultados esperados.
Características:
3. Quitar la rueda.
1. Aflojar los tornillos.
2. Levantar el automóvil.
3. Extraer la rueda.
1. Retirar los tornillos.
2. Retirar la rueda.
4. Poner la rueda.
1. Colocar la rueda.
1. Presentar la rueda.
2. Poner los tornillos.
2. Bajar el coche.
3. Apretar los tornillos.
En el algoritmo anterior muchos de los pasos son demasiado vagos para ser considerados bien definidos; de modo
que habría que concretarlos más.
Los algoritmos se suelen expresar utilizando una manera mas o menos formal de lenguaje, llamado pseudocódigo,
que toma diversas formas, alguna de ellas más gráficas, y otras más cercanas al lenguaje humano.
Los primeros algoritmos conocidos están fechados entre los años 3000 y 1500 AC. Fueron encontrados en la zona
conocida como Mesopotamia (actualmente Irak) cerca de la ciudad de Babilonia. Estos algoritmos no tenían ni
condicionales (los expresaban escribiendo varias veces el algoritmo) ni iteraciones (extendían el algoritmo con
tantos pasos como fuera necesario). Probablemente más conocido, es el matemático griego Euclides, que hacia el
año 300 AC., definió un algoritmo para calcular el máximo común divisor de dos enteros positivos. Aunque en este
algoritmo se incluía la iteración, presentaba pocas mejoras respecto a los anteriores.
n=m
m=t
devolver n
Análisis
Programación
Codificación
Análisis: Consiste en el estudio detallado del problema con el fin de obtener una serie de documentos en los que
quede totalmente definido el proceso de la automatización.
Programación: Consiste en la realización de una solución o algoritmo del problema planteado. Esta solución se
diseña utilizando una notación intermedia (pseudocódigo) o bien mediante alguna de las notaciones gráficas.
Codificación: Consiste en la escritura en un lenguaje de programación de alto nivel de los algoritmos obtenidos en la
etapa de programación.
Edición
Compilación
Enlace
Prueba de ejecución
Explotación y mantenimiento
Edición: En esta etapa se transcribe el programa a la computadora, grabándose el mismo en la memoria auxiliar por
medio de un editor de programas o procesador de texto. A este programa almacenado en la computadora y escrito
en lenguaje de alto nivel se le denomina programa fuente.
Compilación: Consiste en obtener un programa objeto, codificado en lenguaje máquina, a partir del programa fuente.
Esta tarea se realiza de forma automática mediante el compilador del lenguaje, el cual, además de efectuar la
traducción, incluye un análisis sintáctico del programa, detectando posibles errores en su escritura y posibilitando la
corrección de los mismos.
Enlace: En esta fase se incluyen determinadas rutinas internas de la librería del lenguaje que sean necesarias en el
programa y si la aplicación consta de varios programas o módulos se enlazan todos ellos, obteniéndose lo que
denominamos programa ejecutable.
Prueba de ejecución: El programa ejecutable obtenido en la etapa anterior se somete a un juego de datos de prueba
capaz de detectar las posibles incorrecciones en su funcionamiento.
Explotación y mantenimiento: Una vez comprobada la corrección del programa y realiza su instalación en el sistema
informático, la aplicación queda a disposición de los usuarios, que la utilizarán hasta tanto se decida abandonarla o
cambiarla por otra. Esto se conoce como explotación de la aplicación. Paralelamente al uso de la aplicación se
realiza el mantenimiento de la misma, que consiste en su evaluación periódica por parte del personal informático,
así como la inclusión de las adaptaciones y modificaciones necesarias para mantenerla actualizada.
Errores
La presencia de errores, surgidos en alguna de las etapas antes descritas, suele ser inevitable. Por ello, es muy
importante saber detectarlos y corregirlos para asegurar la calidad del producto final.
Compilación
Ejecución
Lógica
Especificación
Compilación: También son denominados errores sintácticos, son los más fáciles de encontrar y corregir. Se
producen por el incumplimiento de las reglas sintácticas del lenguaje y son detectados por el programa compilador
indicando el lugar en que se encuentran y la clase de error.
Ejecución: Se detectan durante la ejecución del programa por la parada anormal del mismo, y suelen provenir de la
realización de operaciones no permitidas. Se producen o no, dependiendo de los datos de entrada empleados; por
ello, para encontrarlos es necesaria la prueba del programa con un conjunto de datos de ensayo lo suficientemente
amplio que abarque la mayoría de casos y posibilidades de ejecución.
De lógica: Se dice que un programa tiene un error de lógica si produce resultados que no son correctos. Para
detectarlos hay que realizar un número suficiente de ejecuciones con diferentes datos de prueba y comprobar los
resultados obtenidos.
De Especificación: Son los más difíciles de corregir, pues corresponden a incorrecciones sobrevenidas en la etapa
de análisis, por lo que hay que modificar gran parte del trabajo realizado.
Elementos de un programa
Variables
Un elemento que la mayoría de los lenguajes de programación tienen en común son las variables. La información se
almacena en localidades de memoria, a las cuales por simplicidad se les asigna un nombre, con el fin de poder
manejar en forma sencilla los datos contenidos en estas localidades de memoria.
10 A
Z 12.5
Algoritmos y Funciones
Los algoritmos son las series de pasos por los cuales se resuelven los problemas. Los algoritmos se han utilizado
para solucionar un amplio rango de problemas matemáticos.
Los algoritmos representan soluciones a los problemas. Los pasos para la solución (instrucciones) permanecen
iguales, ya sea que esté resolviéndolos por computadora o a mano.
También conocida como de arriba-abajo y consiste en establecer una serie de niveles de mayor a menor
complejidad (arriba-abajo) que den solución al problema. Consiste en efectuar una relación entre las etapas de la
estructuración de forma que una etapa jerárquica y su inmediato inferior se relacionen mediante entradas y salidas
de información. Este diseño consiste en una serie de descomposiciones sucesivas del problema inicial, que recibe el
refinamiento progresivo del repertorio de instrucciones que van a formar parte del programa.
Bottom Up
El diseño ascendente se refiere a la identificación de aquellos procesos que necesitan computarizarse con forme
vayan apareciendo, su análisis como sistema y su codificación, o bien, la adquisición de paquetes de software para
satisfacer el problema inmediato.
Cuando la programación se realiza internamente y haciendo un enfoque ascendente, es difícil llegar a integrar los
subsistemas al grado tal de que el desempeño global, sea fluido. Los problemas de integración entre los
subsistemas son sumamente costosos y muchos de ellos no se solucionan hasta que la programación alcanza la
fecha limite para la integración total del sistema. En esta fecha, ya se cuenta con muy poco tiempo, presupuesto o
paciencia de los usuarios, como para corregir aquellas delicadas interfaces, que en un principio, se ignoran. Aunque
cada subsistema parece ofrecer lo que se requiere, cuando se contempla al sistema como una entidad global,
adolece de ciertas limitaciones por haber tomado un enfoque ascendente.
Uno de ellos es la duplicación de esfuerzos para acceder el software y mas aún al introducir los datos.
Otro es, que se introducen al sistema muchos datos carentes de valor.
Un tercero y tal vez el mas serio inconveniente del enfoque ascendente, es que los objetivos globales de la
organización no fueron considerados y en consecuencia no se satisfacen.
La diferencia entre estas dos técnicas de programación se fundamenta en el resultado que presentan frente a un
problema dado.
Imagine una empresa, la cual se compone de varios departamentos (contabilidad, mercadeo, …), en cada uno de
ellos se fueron presentando problemas a los cuales se le dieron una solución basados en un enfoque ascendente
(Bottom Up): creando programas que satisfacían sólo el problema que se presentaba.
Cuando la empresa decidió integrar un sistema global para suplir todas las necesidades de todos los departamentos
se dio cuenta que cada una de las soluciones presentadas no era compatible la una con la otra, no representaba
una globalidad, característica principal de los sistemas.
Como no hubo un previo análisis, diseño de una solución a nivel global en todos sus departamentos, centralización
de información, que son características propias de un diseño Descendente (Top Down) y características
fundamentales de los sistemas; la empresa no pudo satisfacer su necesidad a nivel global.
La creación de algoritmos es basado sobre la técnica descendente, la cual brinda el diseño ideal para la solución de
un problema.
Diagrama de Flujo
Un diagrama de flujo es la representación gráfica de un algoritmo. También se puede decir que es la representación
detallada en forma gráfica de como deben realizarse los pasos en la computadora para producir resultados.
Esta representación gráfica se da cuando varios símbolos (que indican diferentes procesos en la computadora), se
relacionan entre si mediante líneas que indican el orden en que se deben ejecutar los procesos. Los símbolos
utilizados han sido normalizados por el instituto norteamericano de normalización (ANSI):
Símbolo Descripción
es el pseudocódigo y sus ventajas frente a los diagramas de flujos y las definiciones de los diagramas estructurados
y las estructuras algorítmicas.
Pseudocódigo
Mezcla de lenguaje de programación y español (o ingles o cualquier otro idioma) que se emplea, dentro de la
programación estructurada, para realizar el diseño de un programa. En esencial, el Pseudocódigo se puede definir
como un lenguaje de especificaciones de algoritmos.
El diagrama estructurado N-S también conocido como diagrama de chapin es como un diagrama de flujo en el que
se omiten las flechas de unión y las cajas son contiguas. Las acciones sucesivas se pueden escribir en cajas
sucesivas y como en los diagramas de flujo, se pueden escribir diferentes acciones en una caja. Un algoritmo se
represente en la siguiente forma:
Estructuras Algorítmicas
Las estructuras de operación de programas son un grupo de formas de trabajo, que permiten, mediante la
manipulación de variables, realizar ciertos procesos específicos que nos lleven a la solución de problemas. Estas
estructuras se clasifican de acuerdo con su complejidad en:
La estructura secuencial es aquella en la que una acción (instrucción) sigue a otra en secuencia. Las tareas se
suceden de tal modo que la salida de una es la entrada de la siguiente y así sucesivamente hasta el fin del proceso.
Asignación
La asignación consiste, en el paso de valores o resultados a una zona de la memoria. Dicha zona será reconocida
con el nombre de la variable que recibe el valor. La asignación se puede clasificar de la siguiente forma:
Consiste en mandar por un dispositivo de salida (p.ej. monitor o impresora) un resultado o mensaje. Esta instrucción
presenta en pantalla el mensaje escrito entre comillas o el contenido de la variable. Este proceso se representa así
como sigue:
La lectura o entrada de datos consiste en recibir desde un dispositivo de entrada (p.ej. el teclado) un valor o dato.
Este dato va a ser almacenado en la variable que aparece a continuación de la instrucción. Esta operación se
representa así:
La declaración de variables es un proceso que consiste en listar al principio del algoritmo todas las variables que se
usarán, además de colocar el nombre de la variable se debe decir qué tipo de variable es.
Contador: ENTERO
Edad, I: ENTERO
Direccion : CADENA_DE_CARACTERES
Salario_Basico : REAL
Opcion : CARACTER
En la anterior declaración de variables Contador, Edad e I son declaradas de tipo entero; Salario_Basico es una
variable de tipo real, Opcion es de tipo carácter y la variable Direccion está declarada como una variable
alfanumérica de cadena de caracteres.
Cuando se trabaja con algoritmos por lo general no se acostumbra a declarar las variables ni tampoco constantes
debido a razones de simplicidad, es decir, no es camisa de fuerza declarar las variables. Sin embargo en este curso
lo haremos para todos los algoritmos que realicemos, con esto logramos hacerlos más entendibles y organizados y
de paso permite acostumbrarnos a declararlas ya que la mayoría de los lenguajes de programación (entre ellos el
C++) requieren que necesariamente se declaren las variables que se van a usar en los programas.
Veamos algunos ejemplos donde se aplique todo lo que hemos visto hasta el momento sobre algoritmos:
Ejemplo 1: Escriba un algoritmo que pregunte por dos números y muestre como resultado la suma de estos. Use
Pseudocódigo y diagrama de flujos.
Ejemplo 2: Escriba un algoritmo que permita conocer el área de un triángulo a partir de la base y la altura. Exprese
el algoritmo usando Pseudocódigo y diagrama de flujos.
distintas estructuras poniendo ejemplos tanto en diagrama de flujo como en pseudocódigo.
Las estructuras condicionales comparan una variable contra otro(s)valor (es), para que en base al resultado de esta
comparación, se siga un curso de acción dentro del programa. Cabe mencionar que la comparación se puede hacer
contra otra variable o contra una constante, según se necesite. Existen tres tipos básicos, las simples, las dobles y
las múltiples.
Simples:
Las estructuras condicionales simples se les conoce como “Tomas de decisión”. Estas tomas de decisión tienen la
siguiente forma:
Dobles:
Las estructuras condicionales dobles permiten elegir entre dos opciones o alternativas posibles en función del
cumplimiento o no de una determinada condición. Se representa de la siguiente forma:
Donde:
Si:Indica el comando de comparación
Condición : Indica la condición a evaluar
Entonces : Precede a las acciones a realizar cuando se cumple la condición
Instrucción(es):Son las acciones a realizar cuando se cumple o no la condición
si no :Precede a las acciones a realizar cuando no se cumple la condición
Dependiendo de si la comparación es cierta o falsa, se pueden realizar una o más acciones.
Múltiples:
Las estructuras de comparación múltiples, son tomas de decisión especializadas que permiten comparar una
variable contra distintos posibles resultados, ejecutando para cada caso una serie de instrucciones especificas. La
forma común es la siguiente:
Realizar un algoritmo en donde se pide la edad del usuario; si es mayor de edad debe aparecer un mensaje
indicándolo. Expresarlo en Pseudocódigo y Diagrama de flujos.
Pseudocódigo:
INICIO
Not1, Not2, Not 3 :REAL
Def: REAL
LEA Nota1, Nota2, Nota3
Def ß (Not1 + Not2 + Not3) /3
Si Def < 3 entonces
Escriba “Reprobó el curso”
Sino
Escriba “Aprobó el curso”
Fin-Si
FIN
Diagrama de flujo:
Se desea escribir un algoritmo que pida la altura de una persona, si la altura es menor o igual a 150 cm envíe el
mensaje: “Persona de altura baja”; si la altura está entre 151 y 170 escriba el mensaje: “Persona de altura media” y
si la altura es mayor al 171 escriba el mensaje: “Persona alta”. Exprese el algoritmo usando Pseudocódigo y
diagrama de flujos.
Pseudocódigo:
INICIO
Altura: ENTERO
ESCRIBA “Cuál es tu altura? ”
LEA Altura
Si Altura <=150 entonces
ESCRIBA “persona de altura baja”
Sino
Si Altura <=170 entonces
ESCRIBA “persona de altura media”
Sino
Si Altura>170 ENTONCES
ESCRIBA “persona alta”
Fin-Si
Fin-Si
Fin-Si
FIN
Diagrama de flujo:
Dado un numero entre 1 y 7 escriba su correspondiente día de la semana así:
1- Lunes 2- Martes 3- Miércoles 4- Jueves 5- Viernes 6- Sábado 7- Domingo
Exprese el algoritmo usando Pseudocódigo y diagrama de flujos.
Pseudocódigo: Pseudocódigo:
INICIO
Dia: ENTERO
ESCRIBA “Diga un número para escribir su día”
LEA Dia
En-caso-de Dia haga
Caso 1: ESCRIBA “Lunes”
Caso 2: ESCRIBA “Martes”
Caso 3: ESCRIBA “Miércoles”
Caso 4: ESCRIBA “Jueves”
Caso 5: ESCRIBA “Viernes”
Caso 6: ESCRIBA “Sábado”
Caso 7: ESCRIBA “Domingo”
SINO: ESCRIBA “Escribió un numero fuera del rango 1-7”
Fin-Caso
FIN
Diagrama de flujo:
estructuras cíclicas; Para, mientras, repetir. Complementamos con tres ejemplos para la correcta
asimilación de estas estructuras.
Se llaman problemas repetitivos o cíclicos a aquellos en cuya solución es necesario utilizar un mismo conjunto de
acciones que se puedan ejecutar una cantidad específica de veces. Esta cantidad puede ser fija (previamente
determinada por el programador) o puede ser variable (estar en función de algún dato dentro del programa). Los
ciclos se clasifican en:
Ciclos con un Numero Determinado de Iteraciones
(Para): Son aquellos en que el número de iteraciones se conoce antes de ejecutarse el ciclo. La forma de
esta estructura es la siguiente:
Pseudocódigo Diagrama de Flujos
Dado un valor inicial exp1 asignado a la variable esta se irá aumentando o disminuyendo de acuerdo a la
exp3 hasta llegar a la exp2; si se omite el paso, significa que la variable aumentará de uno en uno.
Son aquellos en que el numero de iteraciones no se conoce con exactitud, ya que esta dado en función de un dato
dentro del programa.
Mientras Que: Esta es una estructura que repetirá un proceso durante “N” veces, donde “N” puede ser fijo o
variable. Para esto, la instrucción se vale de una condición que es la que debe cumplirse para que se siga
ejecutando. Cuando la condición ya no se cumple, entonces ya no se ejecuta el proceso. La forma de esta
estructura es la siguiente:
Repita-Hasta: Esta es una estructura similar en algunas características, a la anterior. Repite un proceso una
cantidad de veces, pero a diferencia del Mientras Que, el Repita-Hasta lo hace hasta que la condición se
cumple y no mientras, como en el Mientras Que. Por otra parte, esta estructura permite realizar el proceso
cuando menos una vez, ya que la condición se evalúa al final del proceso, mientras que en el Mientras Que
puede ser que nunca llegue a entrar si la condición no se cumple desde un principio. La forma de esta
estructura es la siguiente:
Realizar un algoritmo que muestre los números de uno en uno hasta diez usando una estructura Para. Exprese
el algoritmo usando Pseudocódigo y diagrama de flujos.
Pseudocódigo Diagrama de Flujos
Ejemplo 2:
Usando una estructura Mientras, realizar un algoritmo que escriba los números de uno en uno hasta 20
Realizar un algoritmo que pregunte al usuario un número comprendido en el rango de 1 a 5. El algoritmo deberá
validar el numero, de manera que no continúe la ejecución del programa mientras no se escriba un numero
correcto.
Todos los datos tienen un tipo asociado con ellos. Un dato puede ser un simple carácter, tal como ‘b’, un valor
entero tal como 35. El tipo de dato determina la naturaleza del conjunto de valores que puede tomar una variable.
Datos Numéricos:
Permiten representar valores escalares de forma numérica, esto incluye a los números enteros y los reales. Este
tipo de datos permiten realizar operaciones aritméticas comunes.
Datos lógicos:
Son aquellos que solo pueden tener dos valores (cierto o falso) ya que representan el resultado de una comparación
entre otros datos (numéricos o alfanuméricos).
Identificadores
Los identificadores representan los datos de un programa (constantes, variables, tipos de datos). Un identificador es
una secuencia de caracteres que sirve para identificar una posición en la memoria de la computadora, que permite
acceder a su contenido.
Ejemplo:
» Nombre
» Num_hrs
» Calif2
Constantes
Una constante es un dato numérico o alfanumérico que no cambia durante la ejecución del programa.
Ejemplo:
pi = 3.1416
Variable
Es un espacio en la memoria de la computadora que permite almacenar temporalmente un dato durante la ejecución
de un proceso, su contenido puede cambiar durante la ejecución del programa.
Para poder reconocer una variable en la memoria de la computadora, es necesario darle un nombre con el cual
podamos identificarla dentro de un algoritmo.
Ejemplo:
area = pi * radio ^ 2
Las variables son : el radio, el area y la constate es pi
Por su uso
Variables de Trabajo: Variables que reciben el resultado de una operación matemática completa y que se
usan normalmente dentro de un programa.
Ejemplo:
Suma = a + b /c
Contadores: Se utilizan para llevar el control del numero de ocasiones en que se realiza una operación o se
cumple una condición. Con los incrementos generalmente de uno en uno.
Acumuladores: Forma que toma una variable y que sirve para llevar la suma acumulativa de una serie de
valores que se van leyendo o calculando progresivamente.
Expresiones
Las expresiones son combinaciones de constantes, variables, símbolos de operación, paréntesis y nombres de
funciones especiales.
Por ejemplo:
a + (b + 3) / c
Cada expresión toma un valor que se determina tomando los valores de las variables y constantes implicadas y la
ejecución de las operaciones indicadas.
Una expresión consta de operadores y operandos. Según sea el tipo de datos que manipulan, se clasifican las
expresiones en:
Aritméticas
Relacionales
Lógicas
Operadores
Son elementos que relacionan de forma diferente, los valores de una o mas variables y/o constantes. Es decir, los
operadores nos permiten manipular valores.
Operadores Aritméticos
Los operadores aritméticos permiten la realización de operaciones matemáticas con los valores (variables y
constantes).
Los operadores aritméticos pueden ser utilizados con tipos de datos enteros o reales. Si ambos son enteros, el
resultado es entero; si alguno de ellos es real, el resultado es real.
Operadores Aritméticos
+ Suma
- Resta
* Multiplicación
/ División
mod Modulo (residuo de la división entera)
Ejemplos:
Expresión Resultado
7/2 3.5
12 mod 7 5
4 + 2 * 5 14
Todas las expresiones entre paréntesis se evalúan primero. Las expresiones con paréntesis anidados se evalúan de
dentro a fuera, el paréntesis más interno se evalúa primero.
Dentro de una misma expresión los operadores se evalúan en el siguiente orden:
1. ^ Exponenciación
2. *, /, mod Multiplicación, división, modulo.
3. +, - Suma y resta.
Los operadores en una misma expresión con igual nivel de prioridad se evalúan de izquierda a derecha.
Ejemplos:
4 + 2 * 5 = 14 23 * 2 / 5 = 9.2
3 + 5 * (10 - (2 + 4)) = 23 2.1 * (1.5 + 12.3) = 2.1 * 13.8 = 28.98
Operadores Relacionales
Se utilizan para establecer una relación entre dos valores. Luego compara estos valores entre si y esta comparación
produce un resultado de certeza o falsedad (verdadero o falso).
Los operadores relacionales comparan valores del mismo tipo (numéricos o cadenas). Estos tienen el mismo nivel
de prioridad en su evaluación.
Los operadores relaciónales tiene menor prioridad que los aritméticos.
Ejemplos:
Si a = 10, b = 20, c = 30
a + b > c Falso
a - b < c Verdadero
a - b = c Falso
a * b < > c Verdadero
Ejemplos no lógicos:
a < b < c
10 < 20 < 30
T > 5 < 30
(no es lógico porque tiene diferentes operandos)
Operadores Lógicos
Estos operadores se utilizan para establecer relaciones entre valores lógicos. Estos valores pueden ser resultado de
una expresión relacional.
Ejemplo:
Para los siguientes ejemplos T significa verdadero y F falso.
En este documento se analiza de manera adecuada las tecnias de la programación , empezando con los
elementos básicos para llegar a implementar un programa. Se maneja varios técnicas de ñrogramacion.
issuu.com/dianameneses/docs/programacion_tarea02
www.taringa.net/.../Aprender-Programacion-de-Computadoras_-Ciclos.html -
www.slideshare.net/.../introduccin-a-la-programacin-de-computadores -
programandoenc.over-blog.es/article-28741792.html .historia de la program
Esta lectura describe brevemente las herramientas de la programación inteactiva y demás técnicas y lenguajes
de programación..
http://www.programmingclass.co.uk/Beginners/1/IntroductionG01.htm
6.1.4 Material complementario.
El documento detalla de manera general como está conformado la programación, teniendo en cuenta los ciclos
para desarrollar un buen programa..
www.taringa.net/.../Aprender-Programacion-de-Computadoras_-Ciclos.html -
http://universidad21.blogspot.com/2011/02/c-curso-gratis-video-tutorial-online.html
Una vez resuelto estos interrogantes cada uno de los participantes deberá participar en uno de los grupos
conformados por el tutor. En cada grupo los participantes socializaran las respuestas dadas a las preguntas
anteriores, unificaran criterios y elaboraran un documento común con una única respuesta a cada pregunta la
cual se publicará en el foro para ser socializado.
Actividades previas. Realización de las lecturas requeridas, complementarias y observación de videos.
Competencias o indicador de competencias.
-Compartir el desarrollo de un trabajo.
-Participaren cada una de la actividades propuestas.
-Respetar las opiniones y puntos de vista de los demás participantes.
Producto a entregar. El documento publicado en la plataforma (foro) con la respuestas
Fecha de inicio y limite.
Fecha de inicio: Último día de la segunda semana
Fecha de entrega: Último día de la segunda semana
Porcentaje de valoración.
Foro 10%
EVALUACIÓN DE APRENDIZAJES
Tomar medidas de
seguridad y protección
para el entorno físico,
en el software
instalado, y en la
información
almacenada en uno o
varios equipos y/o
servidores.
Determinar técnicas
generales de gestión
de recursos del sistema
informático y las
características, que
utilizan los sistemas
operativos tanto a nivel
multiusuario como
monousuario.
Identifique la clase de Conocer los problemas Ser responsable en el
aplicaciones instaladas y que crea un sistema, momento de adquirir
su desempeño en las con la gestión de los aplicaciones para uso
actividades de un usuario. recursos de forma de la empresa.
Realizar pruebas de inadecuada y la Ser ético en su
funcionamiento al importancia de la profesión.
software instalado en los medición, Respetar las
equipos. contabilización del uso opiniones de los
. de recursos y la demás.
optimización de un Estar siempre
sistema en uso y dispuesto a la mejora
manejo. en las aplicaciones
Conocer los criterios de instaladas en las
mejora en el uso del unidades informáticas.
software instalado en
un sistema informático.
Identificar los Diagnosticar Ser responsable con
requerimientos y Problemas que puede pruebas realizadas a
necesidades de usuarios. presentar un sistema sistemas de
Organizar la información en general como información.
de archivos, carpetas de resultado de accesos y Ser ético en su
cada usuario, donde su usos indebidos. profesión.
acceso sea adecuada y Tomar medidas de Respetar las
que siempre se encuentre carácter preventivo y opiniones de los
disponible. correctivo. demás.
Realizar a modo de Estar dispuesto a
prueba diferentes organizar la utilización
aplicaciones para de los sistemas de
determinar cuales se información por parte
ajustan a las necesidades de los usuarios.
de la empresa.
6.2.1 Resumen.
En la unidad se presenta al participante las formas generales de programación de acuerdo a las habilidades y
destrezas del estudiante a la hora de implementar un programa.
La Información y Conocimiento son los dos elementos claves del nuevo milenio ninguna sociedad podrá alcanzar ni
puede ignorar este nuevo esquema ya las naciones no se miden por su riqueza industrial, ni sus activos físicos , ni
por su poder militar, sino por la cantidad de información que produce y consume, así como por la recombinación de
información nueva en un conocimiento de grado superior.
Nuevos sistemas de información, tienden a ser cada vez de mayor alcance y complejidad sobre todo cuando se
toman en cuenta la nuevas necesidades de información y conocimiento que demandan las nuevas organizaciones
Nuevos sistemas de información son costosos en tiempos y recursos, la solución moderna de sistemas de
información exigen herramientas y metodologías que resuelvan rápida, económica, eficiente y de manera global,
problemas de información y conocimiento planteados por las organizaciones.
Además el pleno potencial del hardware tampoco es aprovechado plenamente y existe un considerable retraso con
el software y sus aplicaciones generando lo que se conoce como “crisis del software”.
Antecedentes
Otro enfoque para la creación de programas es el paradigma orientado a objetos, OO. El término programación
orientada a objetos se refiere a un estilo de programación por lo que un lenguaje orientado a objetos puede ser tanto
imperativo como declarativo; lo que los caracteriza es la forma de manejar la información: clase, objeto y herencia.
En este enfoque, las unidades de datos se consideran objetos activos, en vez de las unidades pasivas
contempladas por el paradigma por procedimientos tradicional. Para aclarar esto, consideremos una lista de
nombres. En el paradigma por procedimientos, esta lista no es más que una colección de datos, y cualquier
programa que quiera trabajar con ella deberá incluir los algoritmos para realizar las manipulaciones requeridas. Así,
la lista es pasiva en el sentido de que la mantiene un programa controlador, en vez de tener la responsabilidad de
mantenerse ella misma. En cambio, en el enfoque orientado a objetos la lista se considera como un objeto formado
por la lista misma y por una serie de rutinas para manipularla. Por ejemplo, pueden ser rutinas para insertar una
nueva entrada en la lista, para detectar si la lista está vacía o para ordenar la lista. De este modo, un programa que
obtiene acceso a esta lista no necesita contener algoritmos para efectuar esas tareas; simplemente aprovecha las
rutinas suministradas en el objeto. En cierto sentido, en vez de ordenar la lista como en el paradigma por
procedimientos, el programa pide a la lista que se ordene a sí misma.
Muchas ventajas del paradigma orientado a objetos son consecuencias de la estructura modular que surge como
subproducto natural de la filosofía orientada a objetos, pues cada objeto se implanta como un módulo individual,
bien definido, cuyas características son en gran medida independientes del resto del sistema. Así, una vez
desarrollado un objeto que representa a una determinada entidad, es posible reutilizar ese objeto cada vez que se
requiera dicha entidad. De hecho, un rasgo primoridal de los lenguajes de programación orientados a objetos es la
capacidad de representar definiciones de objetos a modo de esqueletos, clases, que pueden usarse una y otra vez
para construir múltiples objetos con las mismas propiedades, herencia, o modificarse para construir nuevos objetos
con propiedades similares.
Lenguajes orientados a objetos los lenguajes de alto nivel se basan principalmente en la programación estructurada;
sin embargo, los lenguajes orientados a objetos se centran en los datos, objetos, indicando cómo
han de ser y definiendo las operaciones a las que se les va a someter. Existen varios lenguajes que soportan
programación orientada a objetos : Visual Basic, Object Pascal, Smalltalk, C++, C#, Visual C++, Visual J, etc.
La programación OO está adquiriendo popularidad a grandes pasos, y muchos creen que dominará el campo de la
programación en el futuro.
El lenguaje orientado a objetos más conocido es Smalltalk, que apareció en 1976. Es un lenguaje de tipo imperativo
donde se utilizó por primera vez el vocabulario que se ha hecho característico de este tipo de lenguajes. Un lenguaje
que se ha añadido a los llamados orientados a objetos es la extensión de C aparecida en 1986, C++. Aunque es
muy diferente a Smalltalk, ha sido muy popular por ser una extensión del lenguaje C. Uno de los últimos lenguajes
OO aparecidos es Java.
1.LENGUAJE C++
Aunque C++ es un superconjunto de C, existen algunas diferencias entre los dos. En primer lugar, en C cuando una
función no toma parámetros, su prototipo tiene la palabra void. Sin embargo en C++ void no es necesario(opcional).
Otra diferencia entre C y C++ es que en un programa de C++ todas las funciones deben estar en forma de prototipo,
en C los prototipos se recomiendan, pero son opcionales. También si una función de C++ es declarada para
devolver un valor obligatoriamente la sentencia return debe devolver un valor, en C no es necesario que se
devuelva.
Otra diferencia es el lugar donde se declaran las variables locales. En C, deben ser declaradas solo al principio del
bloque, mientras que en C++ las variables se pueden declarar en cualquier punto. Aunque es conveniente realizarlo
siempre al comienzo de la función.
Los programas estructurados se basan en estructuras de control bien definidas, bloques de código, subrutinas
independientes que soportan recursividad y variables locales. La esencia de la programación estructurada es la
reducción de un programa a sus elementos constituidos.
La programación orientada a objetos (POO), permite descomponer un problema en subgrupos relacionados. Cada
subgrupo pasa a ser un objeto autocontenido que contiene sus propias instrucciones y datos que le relacionan con
ese objeto. Todos los lenguajes POO comparten tres características: Encapsulación, Polimorfismo y Herencia.
ENCAPSULACIÓN: Es el mecanismo que agrupa el código y los datos que maneja. Los mantienen protegidos
frente a cualquier interferencia y mal uso. Cuando el código y los datos están enlazados de esta manera se ha
creado un objeto. Ese código y datos pueden ser privados para ese objeto o públicos para otras partes del
programa.
POLIMORFISMO: Es la cualidad que permite que un nombre se utilice para dos o más propósitos relacionados pero
técnicamente diferentes. El propósito es poder usar un nombre para especificar una clase general de acciones. Por
ejemplo en C tenemos tres funciones distintas para devolver el valor absoluto. Sin embargo en C++ incorpora
Polimorfismo y a cada función se puede llamar abs(). El Polimorfismo se puede aplicar tanto a funciones como a
operadores.
HERENCIA: Proceso mediante el cual un objeto puede adquirir las propiedades de otro objeto. La información se
hace manejable gracias a la clasificación jerárquica.
OBJETO: Conjunto de variables y funciones pertenecientes a una clase encapsulados. A este encapsulamiento es
al que se denomina objeto. Por tanto la clase es quien define las características y funcionamiento del objeto.
La base del encapsulamiento es la clase, a partir de ellas se le dan las características y comportamiento a los
objetos. Lo primero es crear la clase y después en la función main que sigue siendo la principal crearemos los
objetos de cada una de las clases. Las variables y funciones de una clase pueden
ser publicas, privadas o protegidas. Por defecto si no se indica nada son privadas.
Estos modificadores nos indican en que partes de un programa podemos utilizar las funciones y variables.
private: Solo tendrán acceso los de la misma clase donde estén definidos.
public: Se pude hacer referencia desde cualquier parte del programa.
protected: Se puede hacer referencia desde la misma clase y las subclases.
EJEMPLO: Declaramos una clase con una variable privada y dos funciones públicas. La clase recibe el nombre
de miclase.
class miclase{
int a;
public:
void funcion1(int num);
int funcion2();
}
Mi Primer Programa
Como ejemplo a lo anterior crearemos el primer programa utilizando objetos y clases para ver la teoría llevada a la
práctica. Seguiremos utilizando las mismas sentencias que usábamos en C, más adelante los programas tomarán la
estructura exclusiva de C++.
#include <stdio.h>
#include <conio.h>
class miclase{
int a;
public:
void pasar_a(int num);
int mostrar_a();
};
int miclase::mostrar_a()
{
return a;
}
void main()
{
miclase obj1, obj2;
clrscr();
obj1.pasar_a(10);
obj2.pasar_a(99);
printf("%d\n",obj1.mostrar_a());
printf("%d\n",obj2.mostrar_a());
getch();
}
Entrada y Salada por Consola en C++
En C++ se pueden seguir utilizando las mismas sentencias para mostrar información por pantalla o pedirla
mediante teclado. Pero a estas antiguas se añaden 2 nuevas de la misma potencia y mayor facilidad de uso. La
cabecera que utilizan estas dos sentencias es iostream.h.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
void main()
{
int i,j;
double d;
clrscr();
i=10;
j=15;
cout <<"Introducir valor: ";
cin>>d;
cout << "Estos son los valores: ";
cout << i << " "<< j << " "<< d;
getch();
}
INDICADORES DE FORMATO: Tres funciones miembro (width, precision y fill) que fijan formato de anchura,
precisión y carácter de relleno. Es necesario fijar la anchura, precisión y carácter de relleno antes de cada sentencia
de escritura.
ANCHURA: cout.width(ancho);
DECIMALES: cout.precision(nº digitos);
RELLENO: cout.fill('carácter');
EJEMPLO:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
void main()
{
double numero=123.1234567;
clrscr();
cout<< "hola" <<"\n";
cout.width(15);
cout<< "hola" <<"\n";
cout.width(15);
cout.fill('*');
cout<< "hola"<<"\n";
cout<<numero <<"\n";
cout.precision(4);
cout<<numero <<"\n";
cout.precision(10);
cout<<numero;
getch();
}
MODIFICADORES DE LA CLASE IOS: Estos modificadores son pertenecientes a la clase ios. Cuando se activan
su valor se mantiene, es decir hay que desactivarlos para volver al formato de salida origi nal.
Fijar indicador:
cout.setf(ios::identificador|ios::identificador2);
Anular identificador:
cout.unsetf(ios::identificador|ios::identificador2);
IDENTIFICADOR DESCRIPCIÓN
oct Devuelve un entero en octal.
EJEMPLO:
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
void main()
{
float num=200.0;
int num1=200;
clrscr();
cout<<num <<"\n";
cout.setf(ios::showpos|ios::showpoint);
cout<<num <<"\n";
cout.setf(ios::scientific);
cout<<num <<"\n";
cout.unsetf(ios::scientific|ios::showpoint|ios::showpos);
cout<<num <<"\n";
cout.setf(ios::hex);
cout<<num1 <<"\n";
getch();
}
En los programas hay partes que requieren inicialización. Esta necesidad de inicialización es incluso más común
cuando se está trabajando con objetos. Para tratar esta situación, C++ permite incluir una función constructora. A
estas funciones se las llama automáticamente cada vez que se crea un objeto de esa clase.
La función constructora debe tener el mismo nombre que la clase de la que es parte, no tienen tipo devuelto, es
ilegal que un constructor tenga un tipo devuelto. Pero si es posible pasarle valores a modo de parámetros.
Prototipo de la función:
nombre_fucion(parámetros);
Desarrollo de la función:
nombre_calse::nombre_funcion(parámetros){
cuerpo;
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class miclase{
int a;
public:
miclase();
void show();
};
miclase::miclase()
{
a=100;
}
void miclase::show()
{
cout << a;
}
void main()
{
clrscr();
miclase obj;
obj.show();
getch();
}
Técnicamente un constructor y un destructor se utilizan para inicializar y destruir los objetos, pero también se
pueden utilizar para realizar cualquier otra operación. Sin embargo esto se considera un estilo de programación
pobre.
PROTOTIPO DE LA FUNCIÓN:
~nombre_funcion(parámetros);
DESARROLLO DE LA FUNCION:
nombre_clase::nombre_funcion(){
cuerpo;
}
miclase::miclase()
{
a=100;
}
miclase::~miclase()
{
cout << "Destruyendo...\n";
getch();
}
void miclase::show()
{
cout << a;
}
void main()
{
clrscr();
miclase obj;
obj.show();
getch();
}
CONSTRUCTORES CON PARAMETROS: Es posible pasar argumentos a una función constructora. Para permitir
esto, simplemente añada los parámetros a la declaración y definición de la función constructora. Después, cuando
declare un objeto, especifique los parámetros como argumentos.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class miclase{
int a;
public:
miclase(int x);
void mostrar();
};
miclase::miclase(int x)
{
cout << "Constructor";
a=x;
}
void miclase::miclase()
{
cout <<"El valor de a es: ";
cout << a;
}
void main()
{
miclase objeto(4);
ob.show();
getch();
}
LA ventaja de las funciones insertadas es que se pueden ejecutar más rápidamente que las funciones normales. La
llamada y vuelta de una función normal tardan tiempo y si tienen parámetros incluso más. Para declarar este tipo de
funciones simplemente hay que preceder la definición de la función con el especificador inline.
Las llamadas a las funciones insertadas se realiza de la misma manera que cualquier función. Uno de los requisitos
es que se tiene que definir antes de llamarla, es decir definir y desarrollar antes de la función main.
Si el compilador no es capaz de cumplir la petición, la función se compila como una función normal y la solicitud
inline se ignora. Las restricciones son cuatro, no puede contener variables de tipo static, una sentencia de bucle,
un switch o un goto.
EJEMPLO: En este programa utilizamos una función inline pasando valores. No usa clases ni objetos.
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
inline int valor(int x) { return ¡!(X%2);}
void main()
{
int a;
cout <<"Introducir valor: ";
cin >> a;
if (valor(a))
cout << "Es par ";
else
cout << "Es impar";
}
valor_devuelto nombre_funcion(parametros){cuerpo;}
void main()
{
int a;
cout <<"Introducir valor: ";
cin >> a;
if (valor(a))
cout << "Es par ";
else
cout << "Es impar";
}
Aunque las estructuras tienen las mismas capacidades que las clases, se reserva el uso de struct para objetos que
no tienen funciones miembro. Una de las razones de la existencia de las estructuras es mantener compatibilidad con
los programas hechos C.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
struct tipo{
tipo(double b, char *n);
void mostrar();
private:
double balance;
char nombre[40];
};
void tipo::mostrar()
{
cout << "Nombre: " << nombre;
cout << ": $" << balance;
if (balance<0.0) cout << "****";
cout << "\n";
}
void main()
{
clrscr();
tipo acc1(100.12,"Ricardo");
tipo acc2(-12.34,"Antonio");
acc1.mostrar();
getch();
clrscr();
acc2.mostrar();
getch();
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class miclase{
int a,b;
public:
void obtener(int i, int j){a=i;b=j;}
void mostrar(){cout << a << " "<< b << "\n";}
};
void main()
{
miclase o1,o2;
o1.obtener(10,4);
o2=o1;
o1.show();
o2.show();
getch();
}
ARRAY DE OBJETOS: Los objetos son variables y tienen las mismas capacidades y atributos que cualquier tipo de
variables, por tanto es posible disponer objetos en un array. La sintaxis es exactamente igual a la utilizada para
declarar y acceder al array. También disponemos de arrays bidimensionales.
DECLARACIÓN:
nombre_clase nombre_objeto[nº elementos];
nombre_clase nombre_objeto[nº elementos]={elementos};
INICIALIZACIÓN:
nombre_objeto[índice].función(valores);
EJEMPLO: Unidimensional.
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class ejemplo{
int a;
public:
void pasar(int x){a=x;}
int mostrar() {return a;}
};
void main()
{
ejemplo ob[4];
int indice;
clrscr();
for(indice=0;indice<4;indice++)
ob[indice].pasar(indice);
for(indice=0;indice<4;indice++)
{
cout << ob[indice].mostrar();
cout << "\n";
}
getch();
}
EJEMPLO: Bidimensional.
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class bidi{
int a,b;
public:
bidi(int n, int m){a=n;b=m;}
int pasa_a(){return a;}
int pasa_b(){return b;}
};
void main()
{
clrscr();
int fil,col;
bidi objeto[3][2]={
bidi(1,2),bidi(3,4),
bidi(5,6),bidi(7,8),
bidi(9,10),bidi(11,12)};
for(fil=0;fil<3;fil++)
{
for(col=0;col<2;col++)
{
cout << objeto[fil][col].pasa_a();
cout << " ";
cout << objeto[fil][col].pasa_b();
cout << "\n";
}
}
getch();
}
PASO DE OBJETOS A FUNCIONES: Los objetos se pueden pasar a funciones como argumentos de la misma
manera que se pasan otros tipos de datos. Hay que declarar el parámetro como un tipo de clase y después usar un
objeto de esa clase como argumento cuando se llama a la función. Cuando se pasa un objeto a una función se hace
una copia de ese objeto.
Cuando se crea una copia de un objeto porque se usa como argumento para una función, no se llama a la función
constructora. Sin embargo, cuando la copia se destruye (al salir de ámbito), se llama a la función destructora.
PROTOTIPO DE FUNCIÓN:
tipo_devuelto nombre(nombre_clase nombre_objeto){
cuerpo;
}
LLAMADA A LA FUNCIÓN:
nombre_funcion(objeto);
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class objetos{
int i;
public:
objetos(int n){i=n;}
int devol(){return i;}
};
int sqr(objetos o)
{
return o.devol()*o.devol();
}
void main()
{
objetos a(10), b(2);
cout << sqr(a);
cout << sqr(b);
getch();
}
OBJETOS DEVUELTOS POR FUCIONES: Al igual que se pueden pasar objetos, las funciones pueden devolver
objetos. Primero hay que declarar la función para que devuelva un tipo de clase. Segundo hay que devolver un
objeto de ese tipo usando la sentencia return.
Cuando un objeto es devuelto por una función, se crea automáticamente un objeto temporal que guarda el valor
devuelto. Este es el objeto que realmente devuelve la función. Después el objeto se destruye, esto puede causar
efectos laterales inesperados.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
class ejemplo{
char cadena[80];
public:
void muestra(){cout<<cadena<<"\n";}
void copia(char *cad){strcpy(cadena,cad);}
};
ejemplo entrada()
{
char cadena[80];
ejemplo str;
cout<<"Introducir cadena: ";
cin>>cadena;
str.copia(cadena);
return str;
}
void main()
{
ejemplo ob;
ob=entrada();
ob.muestra();
getch();
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class miclase{
int a;
public:
miclase(int x);
int get();
};
miclase::miclase(int x)
{
a=x;
}
int miclase::get()
{
return a;
}
void main()
{
clrscr();
miclase obj(200);
miclase *p;
p=&obj;
cout << "El valor del Objeto es " << obj.get();
cout << "El valor del Puntero es " << p->get();
getch();
}
Funciones Amigas
Habrá momentos en los que se quiera que una función tenga acceso a los miembros privados de una clase sin que
esa función sea realmente un miembro de esa clase. De cara a esto están las funciones amigas. Son útiles para la
sobrecarga de operadores y la creación de ciertos tipos de funciones E/S.
El prototipo de esta funciones viene precedido por la palabra clave friend, cuando se desarrolla la función no es
necesario incluir friend. Una función amiga no es miembro y no se puede calificar mediante un nombre de objeto.
Estas funciones no se heredan y pueden ser amigas de más de una clase.
PROTOTIPO:
friend tipo_devuelto nombre(parametros);
DESARROLLO:
tipo_devuelto nombre(parametros){
cuerpo;
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class miclase{
int n,d;
public:
miclase(int i, int j){n=i;d=j;}
friend int factor(miclase ob);
};
void main()
{
miclase obj1(10,2), obj2(3,2);
if(factor(obj1))
cout << "es factor";
else
cout << "no es factor";
getch();
}
This es un puntero que se pasa automáticamente a cualquier miembro cuando se invoca. Es un puntero al objeto
que genera la llamada, por tanto la función recibe automáticamente un puntero al objeto. A este puntero se
referencia como this y solo se pasa a los miembros punteros this.
objeto.funcion(); // a la función recibe automáticamente el puntero this.
1.-
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
class stock{
char item[20];
double coste;
public:
stock(char *i,double c)
{
strcpy(item,i);
coste=c;
}
void muestra();
};
void stock::muestra()
{
cout<<item << "\n";
cout<<"PVP: " << coste;
}
void main()
{
clrscr();
stock obj("tuerca",5.94);
obj.muestra();
getch();
}
2.-
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
class stock{
char item[20];
double coste;
public:
stock(char *i,double c)
{
strcpy(this->item,i);
this->coste=c;
}
void muestra();
};
void stock::muestra()
{
cout<<this->item << "\n";
cout<<"PVP: " << this->coste;
}
void main()
{
clrscr();
stock obj("tuerca",5.94);
obj.muestra();
getch();
}
Hasta ahora si se necesitaba asignar memoria dinámica, se hacía con malloc y para liberar se utilizaba free. En C++
se puede asignar memoria utilizando new y liberarse mediante delete. Estas operadores no se pueden combinar
unas con otras, es decir debe llamarse a delete solo con un puntero obtenido mediante new. Los objetos también se
les puede pasar un valor inicial con la sentencia new.
SINTAXIS:
puntero=new tipo;
delete puntero;
puntero=new tipo(valor_inicial);
También se pueden crear arrays asignados dinámicamente, estos arrays pueden utilizar la sentencia new. La
sintaxis general es:
EJEMPLO:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
class cosas{
int i,j;
public:
void obten(int a,int b){i=a;j=b;}
int muestra(){return i*j;}
};
void main()
{
clrscr();
int *p_var;
p_var=new int;
//p_var=new int(9); se asigna un valor inicial.
cosas *p;
p=new cosas;
if(!p || !p_var)
{
cout<<"Error de asignacion\n";
exit(1);
}
*p_var=1000;
p->obten(4,5);
cout<<"El entero en p_var es: " <<*p_var;
cout<<"\nTotal: " <<p->muestra();
getch();
}
Referencias
C++ consta de una particularidad relacionada con los punteros, denominada referencia. Una referencia es un
puntero implícito que se comporta como una variable normal siendo un puntero. Existen tres modos de utilizar una
referencia. Se puede pasar a una función, ser devuelta de una función y crearse como una referencia independiente.
Lo que apunta una referencia no puede ser modificado. El caso de las referencias independientes es muy poco
común y casi nunca se utilizan, en este manual no se hace referencia a ellas.
En el ejemplo siguiente se compara un programa que utiliza un puntero normal y otro programa que realiza las
mismas operaciones utilizando una referencia que se pasa a una función.
EJEMPLO:
Utilizando punteros normal.
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
void f(int *n);
void main()
{
int i=0;
f(&i);
cout<<"valor i:" << i;
getch();
}
void f(int *n)
{
*n=100;
}
Utilizando referencias.
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
void f(int &n);
void main()
{
int i=0;
f(i);
cout<<"valor i:"<< i;
getch();
}
En el caso de las referencias devueltas por una función se puede poner el nombre de la función en el lado izquierdo
de la expresión. Es como asignar un valor a una variable. Hay que tener en cuenta el ámbito de la variable que se
comporta como una referencia.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
int &f();
int x;
void main()
{
clrscr();
f()=100;
cout<<"Valor de x: " <<x;
getch();
}
int &f()
{
return x;
}
Herencia
Para empezar, es necesario definir dos términos normalmente usados al tratar la herencia. Cuando una clase
hereda otra, la clase que se hereda se llama clase base. La clase que hereda se llama clase derivada. La clase
base define todas las cualidades que serán comunes a cualquier clase derivada. Otro punto importante es el
acceso a la clase base. El acceso a la clase base pude tomar 3 valores, public, private y protected.
Si el acceso es public, todos los atributos de la clase base son públicos para la derivada.
Si el acceso es private, los datos son privados para la clase base la derivada no tiene acceso.
Si el acceso es protected, datos privados para la base y derivada tiene acceso, el resto sin acceso.
void main()
{
miclase objeto(10,20);
clrscr();
objeto.c=30;
// objeto.b=30; error,sin acceso.
// objeto.a=30; error,sin acceso.
cout<<objeto.obten_a() <<"\n";
cout<<objeto.obten_b() <<"\n";
cout<<objeto.c;
getch();
}
void main()
{
clrscr();
derivada ob;
ob.obten_xy(10,20);
ob.muestra_xy();
// ob.obten_x(10); error,sin acceso.
// ob.muestra_x(); error,sin acceso.
getch();
}
HERENCIA MULTIPLE: Existen dos métodos en los que una clase derivada puede heredar más de una clase base.
El primero, en el que una clase derivada puede ser usada como la clase base de otra clase derivada, creándose una
jerarquía de clases. El segundo, es que una clase derivada puede heredar directamente más de una clase base. En
esta situación se combinan dos o más clases base para facilitar la creación de la clase derivada.
void main()
{
clrscr();
deriva_c ob(1,2,3);
ob.ver_todo();
cout<<"\n";
cout<<ob.ver_a()<<" "<<ob.ver_b();
getch();
}
El caso de los constructores es un poco especial. Se ejecutan en orden descendente, es decir primero se realiza el
constructor de la clase base y luego el de las derivadas. En las destructoras ocurre en orden inverso, primero el de
las derivadas y luego el de la base.
class B2{
int b;
public:
B2(int x){b=x;}
int obten_b(){return b;}
};
void main()
{
clrscr();
C1 objeto(1,2,3);
objeto.muestra();
getch();
}
Funciones Virtuales
Una función virtual es miembro de una clase que se declara dentro de una clase base y se redefine en una clase
derivada. Para crear una función virutal hay que preceder a la declaración de la función la palabra clave virtual.
Debe tener el mismo tipo y numero de parametros y devolver el mismo tipo.
Cada redefinición de la función virtual en una clase derivada expresa el funcionamiento especifico de la misma con
respecto a esa clase derivada. Cuando se redefine una función virtual en una clase derivada NO es necesaria la
palabra virtual.
EJEMPLO:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
class base{
public:
int i;
base(int x){i=x;}
virtual void func(){cout<<i<<"\n";}
};
void main()
{
base obj1(10);
derivada1 obj2(10);
derivada2 obj3(10);
obj1.func();
obj2.func();
obj3.func();
getch();
}
También es posible y es muy común sobrecargar las funciones constructoras. Hay 3 razones por las que
sobrecargar las funciones constructoras. Primero ganar flexibilidad, permitir arrays y construir copias de
constructores.
EJEMPLO:
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
int abs(int numero);
long abs(long numero);
double abs(double numero);
void main()
{
clrscr();
cout <<"Valor absoluto de -10 "<< abs(-10) <<"\n";
cout <<"Valor absoluto de -10L "<< abs(-10L) <<"\n";
cout <<"Valor absoluto de -10.01 "<< abs(-10.01) <<"\n";
getch();
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
void fecha(char *fecha);
void fecha(int anno, int mes, int dia);
void main()
{
clrscr();
fecha("23/8/98");
fecha(98,8,23);
getch();
}
void fecha(char *fecha)
{
cout<<"Fecha: "<<fecha<<"\n";
}
void fecha(int anno,int mes,int dia)
{
cout<<"Fecha: "<<dia<<"/"<<mes<<"/"<<anno;
}
EJEMPLO:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
void funcion(int a=0, int b=0)
{
cout<<"a: "<< a <<" b: "<< b <<"\n";
}
void main()
{
clrscr();
funcion();
funcion(10);
funcion(20,30);
getch();
}
Es muy similar a la sobrecarga de funciones, un operador siempre se sobrecarga con relación a una clase. Cuando
se sobrecarga un operador no pierde su contenido original, gana un contenido relacionado con la clase. Para
sobrecargar un operador se crea una función operadora que normalmente será una función amiga a la clase.
PROTOTIPO:
tipo_devuelto nombre_clase::operator operador(parametros)
{
cuerpo;
}
Se pueden realizar cualquier actividad al sobrecargar los operadores pero es mejor que las acciones de un operador
sobrecargado se ajusten al uso normal de ese operador. La sobrecarga tiene dos restricciones, no puede cambiar la
precedencia del operador y que el numero de operadores no puede modificarse. También hay operadores que no
pueden sobrecargarse.
OPERADORES
BINARIOS: La función solo tendrá un parámetro. Este parámetro contendrá al objeto que este en el lado derecho
del operador. El objeto del lado izquierdo es el que genera la llamada a la función operadora y se pasa
implícitamente a través de this.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class opera{
int x, y;
public:
opera() {x=0;y=0;}
opera(int i, int j) {x=i; y=j;}
void obtenxy(int &i,int &j) {i=x; j=y;}
opera operator+(opera obj);
};
void main()
{
opera obj1(10,10), obj2(5,3),obj3;
int x,y;
obj3=obj1+obj2;
obj3.obtenxy(x,y);
cout << "Suma de obj1 mas obj2\n ";
cout << "Valor de x: "<< x << " Valor de y: " << y;
getch();
}
LÓGICOS Y RELACIONALES: Cuando se sobrecargan dichos operadores no se deseará que las funciones
operadoras devuelvan un objeto, en lugar de ello, devolverán un entero que indique verdadero o falso. Esto permite
que los operadores se integren en expresiones lógicas y relacionales más extensas que admitan otros tipos de
datos.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class opera{
int x,y;
public:
opera() {x=0;y=0;}
opera(int i,int j) {x=i; y=j;}
void obtenerxy(int &i, int &j) {i=x; j=y;}
int operator==(opera obj);
};
int opera::operator==(opera obj)
{
if(x==obj.x && y==obj.y)
return 1;
else
return 0;
}
void main()
{
clrscr();
opera obj1(10,10), obj2(5,3);
if(obj1==obj2)
cout << "Objeto 1 y Objeto 2 son iguales";
else
cout << " Objeto 1 y objeto 2 son diferentes";
getch();
}
UNARIOS: El miembro no tiene parámetro. Es el operando el que genera la llamada a la función operadora. Los
operadores unarios pueden preceder o seguir a su operando, con lo que hay que tener en cuenta como se realiza la
llamada.
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
class opera{
int x, y;
public:
opera() {x=0;y=0;}
opera(int i, int j) {x=i;y=j;}
void obtenxy(int &i, int &j) {i=x; j=y;}
opera operator++();
};
opera opera::operator++()
{
x++;
y++;
}
void main()
{
clrscr();
opera objeto(10,7);
int x,y;
objeto++;
objeto.obtenxy(x,y);
cout<< "Valor de x: " << x <<" Valor de y: "<< y << "\n";
getch();
}
Ficheros
Para realizar E/S en archivos debe incluirse en el programa el archivo cabecera fstream.h. Un archivo se abre
mediante el enlace a un flujo. Tenemos 3 tipos de flujo: de entrada, desalida o de entrada-salida. Antes de abrir un
fichero debe obtenerse el flujo. Los 3 flujos tienen funciones constructoras que abren el archivo
automáticamente. Una vez realizadas las operaciones con los ficheros debemos cerrar el fichero mediante la
función close( ).
FLUJO DESCRIPCIÓN
ofstream out De salida.
ofstream in De entrada.
fstream io De salida-entrada.
En C++ podemos trabajar con 3 tipos de ficheros: secuencial, binario sin formato y acceso aleatorio. Todos
comparten el método de apertura, pero cada uno de ellos tienen métodos propios para ir escribiendo y leyendo.
SINTAXIS:
flujo("nombre_fichero.extension");
EJEMPLO: Fichero secuencial.
#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
ofstream out("fichero.tex");
if (!out)
{
cout << "El archivo no puede abrirse";
exit(1);
}
do
{
cout<<": ";
gets(cad);
out << cad << endl;
}while(*cad);
out.close();
}
BINARIOS SIN FORMATO: Las funciones E/S son read()y write(). La función read() lee numbytes del flujo asociado
y los coloca en la variable. La función write() escribe num bytes de la variable en el flujo asociado.
PROTOTIPOS:
in.read(variable,num_bytes);
out.write(variable,longitud_cadena);
EJEMPLO: Fichero binario. Escritura.
#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
ofstream out("texto.tex");
if (!out)
{
cout << "El archivo no puede abrirse";
exit(1);
}
in.close();
getch();
}
ALEATORIOS: También podemos realizar el acceso aleatorio. Las funciones que se utilizan son seekg() y seekp()
para posicionarnos y las funciones get() y put() para leer y escribir en el fichero. Las funciones de posicionamiento y
leer-escribir van emparejadas.
PROTOTIPOS:
out.seekp(posicion,lugar_de_comienzo);
out.put('char');
in.seekg(posicion,lugar_de_comienzo);
in.get(var_char);
LUGAR DESCRIPCIÓN
ios::beg Desde el principio.
ios::end Desde el final.
ios::cur Posición actual.
EJEMPLO: Fichero aleatorio. Escritura.
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
void main()
{
fstream out("texto1.txt",ios::in|ios::out);
if (!out)
{
cout << "El archivo no se puede abrir";
exit(1);
}
out.seekp(4,ios::beg);
out.put('z');
out.close();
}
Excepciones
Es un mecanismo de gestión de errores incorporado. Permite gestionar y responder a los errores en tiempo de
ejecución. Las excepciones están construidas a partir de tres palabras clave: try, catch y throw. Cualquier
sentencia que provoque una excepción debe haber sido ejecutada desde un bloque try o desde una función que
este dentro del bloque try.
Cualquier excepción debe ser capturada por una sentencia cath que sigue a la sentencia try, causante de la
excepción.
SINTAXIS:
try{
cuerpo;
}
catch(tipo1 arg){
bloque catch;
}
catch(tipo2 arg){
bloque catch;
}
catch(tipoN arg){
bloque catch;
}
EJEMPLO:
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
void main()
{
try{
cout<<"Dentro del bloque try\n";
throw 10;
cout<<"Esto se ejecuta si no hay problemas";
}
catch(int i){
cout<<"Capturado el error "<< i;
cout<<"\n";
}
Java es una tecnología que hace sencilla la construcción de aplicaciones distribuidas, programas que son
ejecutables por múltiples ordenadores a través de la red. En el estado del arte en la programación de red, Java
promete extender el papel de Internet desde el terreno de las comunicaciones hacia una red en la cual puedan
ejecutarse las aplicaciones completas. Su novedosa tecnología permitirá a los negocios proporcionar servicios de
transacción a gran escala y en tiempo real y contener informacion interactiva en Internet. Java simplifica también la
construcción de agentes software, programas que se mueven a través de la red y desempeñan funciones en
ordenadores remotos en nombre del usuario. En un futuro cercano, los usuarios podrán enviar agentes software
desde sus PCs hacia Internet para localizar información específica o para realizar transacciones en el menor tiempo
posible en cualquier lugar del mundo.
Java es un lenguaje originalmente desarrollado por un grupo de ingenieros de Sun, utilizado por Netscape
posteriormente como base para Javascript. Si bien su uso se destaca en el Web, sirve para crear todo tipo de
aplicaciones (locales, intranet o internet).
Java es un lenguaje:
de objetos
independiente de la plataforma
robusto
gestiona la memoria automáticamente
no permite el uso de técnicas de programación inadecuadas
multithreading
cliente-servidor
mecanismos de seguridad incorporados
herramientas de documentación incorporadas
Java llevará estos adelantos todavía más lejos haciendo posible suministrar aplicaciones completamente
interactivas vía Web. Las razones por las cuales se ha prestado tanta atención al lenguaje Java podrían resumirse
en la siguiente lista de posibilidades que Java ofrece a sus usuarios:
En particular, los programas Java se pueden incrustar en documentos Web, convirtiendo páginas estáticas en
aplicaciones que se ejecutan en el ordenador del usuario.
En 1990, Sun Microsystems comenzó un proyecto llamado Green para desarrollar software destinado a electrónica
de consumo. James Gosling, un veterano en el diseño de software de red, fue asignado al nuevo proyecto. Gosling
comenzó a escribir software en C++ para utilizarlo en aparatos como tostadoras, videos, etc. Este software se utilizó
para crear electrodomésticos más inteligentes, añadiéndoles displays digitales o utilizando inteligencia artificial para
controlar mejor los mecanismos. Sin embargo, pronto se dio cuenta de que C++ era demasiado susceptible a
errores que pueden detener el sistema. Y aunque todo el mundo está acostumbrado a que el ordenador se cuelgue,
nadie espera que su tostadora deje de funcionar.
La solución de Gosling a este problema fue un nuevo lenguaje llamado Oak. Oak mantuvo una sintaxis similar a C++
pero omitiendo las características potencialmente peligrosas. Para conseguir que fuese un lenguaje de
programación de sistemas controladores eficiente, Oak necesitaba poder responder a eventos provenientes del
exterior en cuestión de microsegundos. Tambén era necesario que fuese portátil; esto es, que fuese capaz de
ejecutarse en un determinado número de chips y entornos diferentes. Esta independencia del hardware podría
proporcionar al fabricante de una tostadora cambiar el chip que utiliza para hacerla funcionar sin necesidad de
cambiar el software. El fabricante podría utilizar también partes del mismo código que utiliza la tostadora para hacer
funcionar un horno. Esto podría reducir costes, tanto de desarrollo como de hardware, aumentando también su
fiabilidad.
Al mismo tiempo que Oak maduraba, la WWW se encontraba en su periodo de crecimiento y el equipo de desarrollo
de Sun se dio cuenta de que Oak era prefectamente adecuado para la programación en Internet. En 1994
completaron su trabajo en un producto conocido como WebRunner, un primitivo visor Web escrito en Oak.
WebRunner se renombró posteriomente como HotJava y demostró el poder de Oak como herramienta de desarrollo
en Internet.
Finalmente, en 1995, Oak se renombró como Java por razones de marketing y fue presentado en Sun World 1995.
Incluso antes de la primera distribución del compilador de Java en Junio de 1996, Java ya era considerado como el
estándar en la industria para la programación en Internet.
La Arquitectura Java
La fortaleza de Java reside precisamente en su arquitectura única. Los diseñadores de Java necesitaban un
lenguaje que fuera, sobre todo, sencillo de utilizar para el programador. A pesar de todo, y con el propósito de crear
aplicaciones de red eficientes, Java necesitaba también la posibilidad de ejecutarse de forma segura en la red y
trabajar en una amplísima gama de plataformas. Java cumple todos estos puntos y muchos más.
Cómo trabaja Java
Como muchos otros lenguajes de programación, Java utiliza un compilador para convertir el código fuente, legible
para el ser humano, en programas ejecutables. Los compiladores tradicionales genera código que puede ejecutarse
únicamente por un hardware específico. Los compiladores Java generan código binario o bytecode independiente
de la arquitectura. Estos bytecodes se ejecutarán exclusivamente en una Máquina Virtual Java, Virtual Machine, VM,
un procesador Java idealizado que normalmente se implementa por software, aunque la VM se ha implementado
también como un chip hardware por Sun y otros.
Los archivos binarios Java se denominan archivos de clases debido a que contienen clases simples Java. Para
ejecutar bytecodes, la máquina virtual utiliza cargadores de clases para obtener los bytecodes del disco o de la red.
Cada archivo de clases se lleva entonces a un verificador de bytecodes que se asegura de que la clase tienen un
formato correcto y que no llegará a corromper la memoria cuando se ejecute. Una vez verificados los bytecodes se
interpretan por un interprete.
Lenguaje de Objetos
Por qué puse "de" objetos y no "orientado a" objetos? Para destacar que, al contrario de otros lenguajes como C++,
no es un lenguaje modificado para poder trabajar con objetos sino que es un lenguaje creado para trabajar con
objetos desde cero. De hecho, TODO lo que hay en Java son objetos.
Qué es un objeto?
Bueno, se puede decir que todo puede verse como un objeto. Pero seamos más claros. Un objeto, desde nuestro
punto de vista, puede verse como una pieza de software que cumple con ciertas características:
encapsulamiento
herencia
Encapsulamiento significa que el objeto es auto-contenido, o sea que la misma definición del objeto incluye tanto los
datos que éste usa (atributos) como los procedimientos (métodos) que actúan sobre los mismos.
Cuando se utiliza programación orientada a objetos, se definen clases (que definen objetos genéricos) y la forma en
que los objetos interactúan entre ellos, a través demensajes. Al crear un objeto de una clase dada, se dice que se
crea una instancia de la clase, o un objeto propiamente dicho. Por ejemplo, una clase podría ser "autos", y un auto
dado es una instancia de la clase.
La ventaja de esto es que como no hay programas que actúen modificando al objeto, éste se mantiene en cierto
modo independiente del resto de la aplicación. Si es necesario modificar el objeto (por ejemplo, para darle más
capacidades), esto se puede hacer sin tocar el resto de la aplicación… lo que ahorra mucho tiempo de desarrollo y
debugging! En Java, inclusive, ni siquiera existen las variables globales! (Aunque parezca difícil de aceptar, esto es
una gran ventaja desde el punto de vista del desarrollo).
En cuanto a la herencia, simplemente significa que se pueden crear nuevas clases que hereden de otras
preexistentes; esto simplifica la programación, porque las clases hijas incorporan automáticamente los métodos de
las madres. Por ejemplo, nuestra clase "auto" podría heredar de otra más general, "vehículo", y simplemente
redefinir los métodos para el caso particular de los automóviles… lo que significa que, con una buena biblioteca de
clases, se puede reutilizar mucho código inclusive sin saber lo que tiene adentro.
Un ejemplo simple
Para ir teniendo una idea, vamos a poner un ejemplo de una clase Java:
public class Muestra extends Frame {
// atributos de la clase
Button si;
Button no;
// métodos de la clase:
public Muestra () {
Label comentario = new Label("Presione un botón", Label.CENTER);
si = new Button("Sí");
no = new Button("No");
add("North", comentario);
add("East", si);
add("West", no);
}
}
Esta clase no está muy completa así, pero da una idea… Es una clase heredera de la clase Frame (un tipo de
ventana) que tiene un par de botones y un texto. Contiene dos atributos ("si" y "no"), que son dos objetos del
tipo Button, y un único método llamado Muestra (igual que la clase, por lo que es lo que se llama unconstructor).
Independiente de la plataforma
En realidad, Java podría hacerse correr hasta sobre una Commodore 64! La realidad es que para utilizarlo en todo
su potencial, requiere un sistema operativo multithreading (como Unix, Windows95, OS/2…).
Al compilar un programa Java, lo que se genera es un seudocódigo definido por Sun, para una máquina genérica.
Luego, al correr sobre una máquina dada, el software de ejecución Java simplemente interpreta las instrucciones,
emulando a dicha máquina genérica. Por supuesto esto no es muy eficiente, por lo que tanto Netscape como
Hotjava o Explorer, al ejecutar el código por primera vez, lo van compilando (mediante un JIT: Just In Time
compiler), de modo que al crear por ejemplo la segunda instancia de un objeto el código ya esté compilado
específicamente para la máquina huésped.
Además, Sun e Intel se han puesto de acuerdo para desarrollar procesadores que trabajen directamente en Java,
con lo que planean hacer máquinas muy baratas que puedan conectarse a la red y ejecutar aplicaciones Java
cliente-servidor a muy bajo costo.
El lenguaje de dicha máquina genérica es público, y si uno quisiera hacer un intérprete Java para una Commodore
sólo tendría que implementarlo y pedirle a Sun la aprobación (para que verifique que cumple con los requisitos de
Java en cuanto a cómo interpreta cada instrucción, la seguridad, etc.)
Generación de números aleatorios
La clase Random proporciona un generador de números aleatorios. Es más flexible que la función random de la
clase Math, que vimos en funciones matemáticas...
La generación de números aleatorios adquiere gran relevancia para un programador, pudiendo tener distintas
aplicaciones como:
·Construcción preliminar de programas, en los que a falta de datos definitivos, introducimos datos aleatorios.
·Simulación de procesos aleatorios (número resultante de tirar un dado, elección de un color por parte de una
persona, número premiado en un sorteo de lotería, cantidad de personas que entran a un supermercado en una
hora...)
. Verificación de programas, y en particular lo que en verificación de algoritmos se conoce como verificación
aleatoria (probar el programa con distintos supuestos aleatorios).
·Otras aplicaciones.
Conviene recordar que "aleatorio" no puede confundirse con "cualquier cosa", "descontrol", "incierto", "impredecible",
etc. Usaremos el vocablo “aleatorio”, más en el sentido de “no predeterminado” que el de “no predecible”, ya que en
general, vamos a definir qué tipo de resultado queremos obtener y en qué rango de valores debe estar. Vamos a
imaginar que Java genera números aleatorios, como si fuera un robot lanzador de dardos muy preciso ( robot rnd).
De este modo, cuando se le dice que comience a tirar dardos en distintas posiciones, repite siempre los lugares. Por
ejemplo, si la diana está marcada con números, cada vez que le decimos que tire, genera la misma secuencia: 7, 5,
6, 3, etc. ¿Cómo conseguir convertir este proceso predefinido en aleatorio? Simplemente, poniendo a girar la diana
(mayordomo randomize), en este caso, a una velocidad que depende del segundo del día en que nos encontremos.
Así pues, el proceso lo dividimos al decirle al mayordomo que ponga a girar la diana y al indicarle al robot que
dispare. Bueno, un poco simple, pero ¿para qué complicarnos? Veamos los pasos sintácticos a emplear para crear
una secuencia de números aleatorios:
1. Proporcionar a nuestro programa información acerca de la clase Random. Al principio del programa
escribiremos la siguiente sentencia:
Import java.util.Random;
2. Crear un objeto de la clase Random:
La clase Random dispone de dos constructores, para crear un objeto. El primer constructor es:
Random rnd = new Random();
crea un generador de números aleatorios cuya semilla es inicializada automáticamente, en base al tiempo actual.
Esto conlleva que en cada ejecución la semilla cambie, es decir, que la secuencia de números aleatorios que se
genera en cada ejecución siempre será diferente.
El segundo constructor es:
Random rnd = new Random(inicializar_semilla);
nos permite inicializar la semilla manualmente con un número entero cualquiera. Si este número es el mismo en
cada ejecución, la secuencia de números aleatorios que se genera en cada ejecución será igual.
Hay cuatro funciones miembro diferentes que generan números aleatorios:
Función
Descripción Rango
miembro
En el caso de necesitar números aleatorios enteros en un rango determinado, podemos trasladarnos a un intervalo
distinto, simplemente multiplicando, aplicando la siguiente fórmula general:
(int) (rnd.nextDouble() * cantidad_números_rango + término_inicial_rango)
donde (int) al inicio, transforma un número decimal double en entero int, eliminando la parte decimal.
Por ejemplo, si deseamos números enteros comprendidos entre el rango [0,99], incluidos los extremos, la fórmula
quedaría de la siguiente manera:
(int)(rnd.nextDouble() * 100 + 0); --> (int)(rnd.nextDouble() * 100);
100 es la cantidad de números enteros en el rango [0,99] y 0 es el término inicial del rango.
En el caso de querer números aleatorios enteros comprendidos entre [1,6], que son los lados de un dado, la formula
quedaría así.
(int)(rnd.nextDouble() * 6 + 1);
6 es la cantidad de números enteros en el rango [1,6] y 1 es el término inicial del rango.
A continuación, daremos dos programas completos , como ejemplo para explicar el cambio de semilla en la
generación de números aleatorios:
importjava.util.Random;
public class Programa {
public static void main(String arg[ ]) {
Random rnd = new Random();
System.out.println("Primera
secuencia."+"\n");
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println("");
System.out.println("Segunda
secuencia."+"\n");
System.out.println(+rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
}
}
Salida
Primera secuencia.
0.477306442553755
0.6150676961227264
0.8217343290939352
Segunda secuencia.
0.6607147048099735
0.10104896936581531
0.2628223838639594
En este primer ejemplo, mostramos dos secuencias de tres números aleatorios, los cuales están en el rango [0,1[,
incluido el cero pero excluido el uno. Vemos que los números aleatorios en las dos secuencias, son distintos, ya que
en realidad, es una sola secuencia, que tiene como punto de partida la misma semilla. A continuación, lo
compararemos con el siguiente ejemplo, donde utilizaremos la función“setSeed(semilla_nueva)”, para el cambio
de semilla, función resaltada con un comentario flecha:
importjava.util.Random;
public class Programa {
public static void main(String arg[ ]) {
Random rnd = new Random();
rnd.setSeed(3816); //<---
System.out.println("Primera
secuencia."+"\n");
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println("");
rnd.setSeed(3816); //<---
System.out.println("Segundasecuencia."+"\n");
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
System.out.println(rnd.nextDouble());
}
}
Salida
Primera secuencia.
0.778983378859943
0.36474001734926775
0.9579995205698871
Segunda secuencia.
0.778983378859943
0.36474001734926775
0.9579995205698871
Observamos que las dos secuencias están formadas por los mismos números aleatorios, ya que a ambas
secuencias, les precede la función de cambio de semilla “rnd.setSeed(3816)”. En dicha instrucción, las dos
funciones aparecen inicializadas a propósito con la misma semilla “3816”, pudiendo haberse elegido cualquier otro
número, pero con la peculiaridad de que la semilla tiene que ser igual en ambas funciones para producir dos
secuencias con los mismos números aleatorios.
Algunas características…
Entre las características que nombramos nos referimos a la robustez. Justamente por la forma en que está diseñado,
Java no permite el manejo directo del hardware ni de la memoria (inclusive no permite modificar valores de
punteros, por ejemplo); de modo que se puede decir que es virtualmente imposible colgar un programa Java. El
intérprete siempre tiene el control.
Inclusive el compilador es suficientemente inteligente como para no permitir un montón de cosas que podrían traer
problemas, como usar variables sin inicializarlas, modificar valores de punteros directamente, acceder a métodos o
variables en forma incorrecta, utilizar herencia múltiple, etc.
Además, Java implementa mecanismos de seguridad que limitan el acceso a recursos de las máquinas donde se
ejecuta, especialmente en el caso de los Applets (que son aplicaciones que se cargan desde un servidor y se
ejecutan en el cliente).
También está diseñado específicamente para trabajar sobre una red, de modo que incorpora objetos que permiten
acceder a archivos en forma remota (via URL por ejemplo).
Además, con el JDK (Java Development Kit) vienen incorporadas muchas herramientas, entre ellas un generador
automático de documentación que, con un poco de atención al poner los comentarios en las clases, crea inclusive
toda la documentación de las mismas en formato HTML!
El Java Development Kit
Todo lo que puedan pedir para desarrollar aplicaciones en Java está en:
http://java.sun.com/aboutJava/index.html
http://java.sun.com/java.sun.com/products/JDK/1.0.2/index.html
(También les puede interesar en particular el Tool Documentation y alguno de los otros paquetes de la página)
Nota: en este site también hay un tutorial de Java, aunque es un poco difícil de seguir para el principiante.
El JDK (versión 1.0.2) está disponible para SPARC/Solaris, x86/Solaris, MS-Windows 95/NT, y MacOS.
También está disponible el fuente para el que quiera adaptarlo para otro sistema operativo, y he leído por ahí que
hay una versión dando vueltas para Linux y HP-UX.
También se puede bajar del mismo site un browser que soporta Java (y de hecho está escrito totalmente en Java),
el Hotjava.
Para instalarlo simplemente hay que descompactar el archivo (sugiero que creen un directorio java para eso), pero
tengan en cuenta NO DESCOMPRIMIR el archivo classes.zip!
Importante para los usuarios de Windows95: todas estas aplicaciones deben ejecutarse desde una ventana DOS. En
particular, utilizan nombres largos y distinguen mayúsculas de minúsculas, así que tengan en cuenta esto que es
fuente de muchos errores.
Una cosa muy importante: para que todo ande bien aceitado, agreguen:
Noten que en CLASSPATH agregué el directorio actual (.), para poder compilar y ejecutar desde cualquier
directorio.
Bueno, suponiendo que hayan instalado todo, y antes de comenzar a programar en Java, una pequeña
aclaración :
En sí los dos últimos son el mismo lenguaje, pero cambia un poco la forma en que se implementa el objeto
principal (la aplicación). Vamos a ver cómo crear las aplicaciones para que, sin cambios, se puedan ejecutar casi
igual en forma standalone o como applet (en realidad hay cosas que los applets no pueden hacer, como acceder a
archivos sin autorización).
Javascript
No vamos a detenernos mucho en Javascript, por las limitaciones antedichas; si les interesa podemos dedicarnos
un poco a este lenguaje en el futuro. Por ahora, sólo un ejemplo sencillo:
Calculadora en Javascript:
<HTML>
<HEAD>
<SCRIPT LANGUAJE="Javascript">
function calcula(form) {
if (confirm("¿Está seguro?"))
form.resultado.value = eval(form.expr.value)
else
alert("Vuelva a intentarlo...")
}
</SCRIPT>
</HEAD>
<BODY>
<FORM>
Introduzca una expresión:
<INPUT TYPE="text" NAME="expr" SIZE=15>
<INPUT TYPE="button" NAME="Boton" VALUE="Calcular" ONCLICK="calcula(this.form)">
<BR>
Resultado:
<INPUT TYPE="text" NAME="resultado" SIZE=15>
<BR>
</FORM>
</BODY>
</HTML>
Básicamente, el código se encuadra entre los tags <SCRIPT>…</SCRIPT>, y los parámetros se pasan al mismo
mediante un form (<FORM>…</FORM>). El lenguaje utilizado es muy parecido al C++, y básicamente el código
se ejecuta mediante una acción de un botón (…ONCLICK="calcula(this.form)").
http://www.c2.net/~andreww/javascript/
incluyendo decenas de calculadoras, juegos.
Mucho, no?
Ya veremos qué poner en "algunas_palabras" y "algo_más", por ahora sigamos un poco más.
La lista de atributos (nuestras viejas variables locales) sigue el mismo formato de C: se define primero el tipo y
luego el nombre del atributo, y finalmente el ";".
Finalmente, se aceptan comentarios entre /* y */, como en C, o bien usando // al principio del comentario (el
comentario termina al final de la línea).
Veamos un ejemplo:
// Implementación de un contador sencillo
// GRABAR EN UN ARCHIVO "Contador.java" (OJO CON LAS MAYUSCULAS!)
// COMPILAR CON: "javac Contador.java" (NO OLVIDAR EL .java!)
// ESTA CLASE NO ES UNA APLICACION, pero nos va a servir enseguida
// Atributos
int cnt; // Un entero para guardar el valor actual
// Métodos
public int incCuenta() { // Un método para incrementar el contador
cnt++; // incrementa cnt
return cnt; // y de paso devuelve el nuevo valor
}
public int getCuenta() { // Este sólo devuelve el valor actual
return cnt; // del contador
}
}
Cuando, desde una aplicación u otro objeto, se crea una instancia de la clase Contador, mediante la instrucción:
new Contador()
el compilador busca un método con el mismo nombre de la clase y que se corresponda con la llamada en cuanto al
tipo y número de parámetros. Dicho método se llama Constructor, y una clase puede tener más de un constructor
(no así un objeto o instancia, ya que una vez que fue creado no puede recrearse sobre sí mismo).
En tiempo de ejecución, al encontrar dicha instrucción, el intérprete reserva espacio para el objeto/instancia, crea
su estructura y llama al constructor.
O sea que el efecto de new Contador() es, precisamente, reservar espacio para el contador e inicializarlo en cero.
En cuanto a los otros métodos, se pueden llamar desde otros objetos (lo que incluye a las aplicaciones) del mismo
modo que se llama una función desde C.
Por ejemplo, usemos nuestro contador en un programa bien sencillo que nos muestre cómo evoluciona:
// Usemos nuestro contador en una mini-aplicación
// GRABAR EN UN ARCHIVO "Ejemplo1.java" (OJO CON LAS MAYUSCULAS!)
// COMPILAR CON: "javac Ejemplo.java" (NO OLVIDAR EL .java!)
// EJECUTAR CON: "java Ejemplo1" (SIN el .java)
En el capítulo III vamos a analizar este programa en detalle. Por ahora veamos la diferencia con un applet que
haga lo mismo:
// Applet de acción similar a la aplicación Ejemplo1
// GRABAR EN ARCHIVO: "Ejemplo2.java"
// COMPILAR CON: "javac Ejemplo2.java"
// PARA EJECUTAR: Crear una página HTML como se indica luego
import java.applet.*;
import java.awt.*;
// Constructor…
public Ejemplo2 () {
laCuenta = new Contador();
}
Ahora es necesario crear una página HTML para poder visualizarlo. Para esto, crear y luego cargar el archivo
ejemplo2.htm con un browser que soporte Java (o bien ejecutar en la ventana DOS: "appletviewer ejemplo2.htm"):
<HTML>
<HEAD>
<TITLE>Ejemplo 2 - Applet Contador</TITLE>
</HEAD>
<BODY>
<applet code="Ejemplo2.class" width=170 height=150>
</applet>
</BODY>
</HTML>
Además:
Con poco trabajo se pueden combinar ambos casos en un solo objeto, de modo que la misma clase sirva para
utilizarla de las dos maneras:
// Archivo: Ejemplo3.java
// Compilar con: javac Ejemplo3.java
import java.applet.*;
import java.awt.*;
import java.io.*;
public Ejemplo3 () {
laCuenta = new Contador();
}
Esta clase puede ejecutarse tanto con "java Ejemplo3" en una ventana DOS, como cargarse desde una página
HTML con:
<applet code="Ejemplo3.class" width=170 height=150>
</applet>
Notar que conviene probar el applet con el appletviewer ("appletviewer ejemplo3.htm"), ya que éste indica en la
ventana DOS si hay algún error durante la ejecución. Los browsers dejan pasar muchos errores, simplemente
suprimiendo la salida a pantalla del código erróneo.
Notar que en todo este desarrollo de las clases Ejemplo1, Ejemplo2 y Ejemplo3, en ningún momento volvimos a
tocar la clase Contador!
Estructura de clases
Vamos a comenzar analizando la clase Contador, para ir viendo las partes que forman una clase una por una y en
detalle. Este capítulo va a ser un poco aburrido por lo exhaustivo (aunque algunos puntos más complicados como
las excepciones y los threads los dejaremos para después), pero me parece bueno tener un resumen completo de la
sintaxis desde ahora.
Declaración de la clase
La clase se declara mediante la línea public class Contador. En el caso más general, la declaración de una clase
puede contener los siguientes elementos:
Definir una clase como pública (public) significa que puede ser usada por cualquier clase en cualquier paquete. Si
no lo es, solamente puede ser utilizada por clases del mismo paquete (más sobre paquetes luego; básicamente, se
trata de un grupo de clases e interfaces relacionadas, como los paquetes de biblioteca incluídos con Java).
Una clase final (final) es aquella que no puede tener clases que la hereden. Esto se utiliza básicamente por razones
de seguridad (para que una clase no pueda ser reemplazada por otra que la herede), o por diseño de la aplicación.
Una clase abstracta (abstract) es una clase que puede tener herederas, pero no puede ser instanciada. Es,
literalmente, abstracta (como la clase Number definida en java.lang). ¿Para qué sirve? Para modelar conceptos. Por
ejemplo, la clase Number es una clase abstracta que representa cualquier tipo de números (y sus métodos no están
implementados: son abstractos); las clases descendientes de ésta, como Integer o Float, sí implementan los
métodos de la madre Number, y se pueden instanciar.
Por lo dicho, una clase no puede ser final y abstract a la vez (ya que la clase abstract requiere descendientes…)
¿Un poco complejo? Se va a entender mejor cuando veamos casos particulares, como las interfases (que por
definición son abstractas ya que no implementan sus métodos).
Extends
La instrucción extends indica de qué clase desciende la nuestra. Si se omite, Java asume que desciende de la
superclase Object.
Cuando una clase desciende de otra, esto significa que hereda sus atributos y sus métodos (es decir que, a menos
que los redefinamos, sus métodos son los mismos que los de la clase madre y pueden utilizarse en forma
transparente, a menos que sean privados en la clase madre o, para subclases de otros paquetes, protegidos o
propios del paquete). Veremos la calificación de métodos muy pronto, a no desesperar!
Implements
Una interfase (interface) es una clase que declara sus métodos pero no los implementa; cuando una clase
implementa (implements) una o más interfases, debe contener la implementación de todos los métodos (con las
mismas listas de parámetros) de dichas interfases.
Esto sirve para dar un ascendiente común a varias clases, obligándolas a implementar los mismos métodos y, por
lo tanto, a comportarse de forma similar en cuanto a su interfase con otras clases y subclases.
Interface
Una interfase (interface), como se dijo, es una clase que no implementa sus métodos sino que deja a cargo la
implementación a otras clases. Las interfases pueden, asimismo, descender de otras interfases pero no de otras
clases.
Todos sus métodos son por definición abstractos y sus atributos son finales (aunque esto no se indica en el cuerpo
de la interfase).
Son útiles para generar relaciones entre clases que de otro modo no están relacionadas (haciendo que implementen
los mismos métodos), o para distribuir paquetes de clases indicando la estructura de la interfase pero no las clases
individuales (objetos anónimos).
Si bien diferentes clases pueden implementar las mismas interfases, y a la vez descender de otras clases, esto no es
en realidad herencia múltiple ya que una clase no puede heredar atributos ni métodos de una interface; y las clases
que implementan una interfase pueden no estar ni siquiera relacionadas entre sí.
El cuerpo de la clase
El cuerpo de la clase, encerrado entre { y }, es la lista de atributos (variables) y métodos (funciones) que
constituyen la clase.
No es obligatorio, pero en general se listan primero los atributos y luego los métodos.
Declaración de atributos
En Java no hay variables globales; todas las variables se declaran dentro del cuerpo de la clase o dentro de un
método. Las variables declaradas dentro de un método son locales al método; las variables declaradas en el cuerpo
de la clase se dice que son miembros de la clase y son accesibles por todos los métodos de la clase.
Por otra parte, además de los atributos de la propia clase se puede acceder a todos los atributos de la clase de la
que desciende; por ejemplo, cualquier clase que descienda de la clase Polygon hereda los
atributos npoints, xpoints e ypoints.
Finalmente, los atributos miembros de la clase pueden ser atributos de clase o atributos de instancia; se dice que
son atributos de clase si se usa la palabra clavestatic: en ese caso la variable es única para todas las instancias
(objetos) de la clase (ocupa un único lugar en memoria). Si no se usa static, el sistema crea un lugar nuevo para esa
variable con cada instancia (o sea que es independiente para cada objeto).
Java tiene 4 tipos de acceso diferente a las variables o métodos de una clase: privado, protegido, público o por
paquete (si no se especifica nada).
De acuerdo a la forma en que se especifica un atributo, objetos de otras clases tienen distintas posibilidades de
accederlos:
S: puede acceder
N: no puede acceder
X: puede acceder al atributo en objetos que pertenezcan a la subclase, pero no en los que pertenecen a la clase
madre. Es un caso especial ; más adelante veremos ejemplos de todo esto.
Static y final
Como ya se vio, static sirve para definir un atributo como de clase, o sea único para todos los objetos de la clase.
En cuanto a final, como en las clases, determina que un atributo no pueda ser sobreescrito o redefinido. O sea: no
se trata de una variable, sino de una constante.
Transient y volatile
Son casos bastante particulares y que no habían sido implementados en Java 1.0.
Transient denomina atributos que no se graban cuando se archiva un objeto, o sea que no forman parte del estado
permanente del mismo.
Con lo que vemos que cada vez que creamos una clase o interfase estamos definiendo un nuevo tipo.
Los tipos básicos son:
Los arrays son arreglos de cualquier tipo (básico o no). Por ejemplo, existe una clase Integer; un arreglo de
objetos de dicha clase se notaría:
Integer vector[ ];
Los arreglos siempre son dinámicos, por lo que no es válido poner algo como:
Integer cadena[5];
int días[ ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char letras[ ] = { 'E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D' };
String nombres[ ] = new String[12];
Nota al margen: no confundir un String (cadena de caracteres) con un arreglo de caracteres! Son cosas bien
distintas!
En Java, para todas las variables de tipo básico se accede al valor asignado a la misma directamente (no se conoce
la dirección de memoria que ocupa). Para las demás (arrays, clases o interfases), se accede a través de un puntero a
la variable. El valor del puntero no es accesible ni se puede modificar (como en C); Java no necesita esto y además
eso atentaría contra la robustez del lenguaje.
De hecho, en Java no existen los tipos pointer, struct o union. Un objeto es más que una estructura, y las uniones
no se hacen necesarias con un método de programación adecuado (y además se evita la posibilidad de acceder a
los datos incorrectamente).
Algo más respecto a los arreglos: ya que Java gestiona el manejo de memoria para los mismos, y lanza
excepciones si se intenta violar el espacio asignado a una variable, se evitan problemas típicos de C como acceder
a lugares de memoria prohibidos o fuera del lugar definido para la variable (como cuando se usa un subíndice más
grande que lo previsto para un arreglo…).
Y los métodos…
Básicamente, los métodos son como las funciones de C: implementan, a través de funciones, operaciones y
estructuras de control, el cálculo de algún parámetro que es el que devuelven al objeto que los llama. Sólo pueden
devolver un valor (del tipo TipoDevuelto), aunque pueden no devolver ninguno (en ese
caso TipoDevuelto esvoid). Como ya veremos, el valor de retorno se especifica con la instrucción return, dentro
del método.
Los métodos pueden utilizar valores que les pasa el objeto que los llama (parámetros), indicados con tipo1
nombre1, tipo2 nombre2… en el esquema de la declaración.
Estos parámetros pueden ser de cualquiera de los tipos ya vistos. Si son tipos básicos, el método recibe el valor del
parámetro; si son arrays, clases o interfases, recibe un puntero a los datos (referencia). Veamos un pequeño
ejemplo:
public int AumentarCuenta(int cantidad) {
cnt = cnt + cantidad;
return cnt;
}
¿Cómo hago si quiero devolver más de un valor? Por ejemplo, supongamos que queremos hacer un método dentro
de una clase que devuelva la posición del mouse.
Lo siguiente no sirve:
void GetMousePos(int x, int y) {
x = ….; // esto no sirve!
y = ….; // esto tampoco!
}
porque el método no puede modificar los parámetros x e y (que han sido pasados por valor, o sea que el método
recibe el valor numérico pero no sabe adónde están las variables en memoria).
El resto de la declaración
Public, private y protected actúan exactamente igual para los métodos que para los atributos, así que veamos el
resto.
Los métodos estáticos (static), son, como los atributos, métodos de clase; si el método no es static es un
método de instancia. El significado es el mismo que para los atributos: un método static es compartido por todas
las instancias de la clase.
Ya hemos hablado de las clases abstractas; los métodos abstractos (abstract) son aquellos de los que se da la
declaración pero no la implementación (o sea que consiste sólo del encabezamiento). Cualquier clase que contenga
al menos un método abstracto (o cuya clase madre contenga al menos un método abstracto que no esté
implementado en la hija) es una clase abstracta.
Es final un método que no puede ser redefinido por ningún descendiente de la clase.
Las clases native son aquellas que se implementan en otro lenguaje (por ejemplo C o C++) propio de la máquina.
Sun aconseja utilizarlas bajo riesgo propio, ya que en realidad son ajenas al lenguaje. Pero la posibilidad de usar
viejas bibliotecas que uno armó y no tiene ganas de reescribir existe!.
Finalmente, la cláusula throws sirve para indicar que la clase genera determinadas excepciones. También
hablaremos de las excepciones más adelante.
float precio;
Contador laCuenta;
Sólo que aquí no se declaran private, public, etc., sino que las variables definidas dentro del método sólo son
accesibles por él.
Asignaciones a variables
Se asigna un valor a una variable mediante el signo =:
laCuenta.cnt = 0;
El último caso es válido si cnt es una variable pública de la clase Contador. Personalmente no creo conveniente
acceder directamente a variables de otro objeto, ya que futuras modificaciones del objeto llamado o del que llama
puede propender la difusión de errores… Es mejor usar métodos como getCuenta o un
hipotéticoinicializarContador para ello. De hecho, algunos sugieren que todas las variables de una clase se
declaren como private.
Operaciones matemáticas
Hay varios tipos de operadores:
Por ejemplo: -cnt; // cambia de signo; por ejemplo si cnt es 12 el resultado es -12; cnt no cambia.
Binarios: + - * / % …..etc.
Nota: + sirve también para concatenar cadenas de caracteres; hablaremos de String y StringBuffer pronto. Cuando
se mezclan Strings y valores numéricos, éstos se convierten automáticamente a cadenas:
La siguiente es la precedencia de los operadores en expresiones compuestas. De todos modos, como en todos los
lenguajes, se recomienda usar paréntesis en caso de duda.
Multiplicativos * / %
Aditivos + -
Desplazamiento << >> >>>
Igualdad == !=
OR lógico ||
Condicional ? :
Algunos ejemplos:
<= devuelve "true" si un valor es menor o igual que otro: total <= maximo;
instanceof devuelve "true" si el objeto es una instancia de la clase: papa instanceof Comida;
Llamadas a métodos
Se llama a un método de la misma clase simplemente con el nombre del método y los parámetros entre paréntesis,
como se ve, entre otros, en el ejemplo en negrita:
// Archivo: Complejo.java
// Compilar con: javac Complejo.java
public final class Complejo extends Number {
// atributos:
private float x;
private float y;
// constructor:
public Complejo(float rx, float iy) {
x = rx;
y = iy;
}
// métodos:
public float Norma() {
return (float)Math.sqrt(x*x+y*y);
}
// obligatorios (son abstractos en Number):
public double doubleValue() {
return (double)Norma( );
}
public float floatValue() {
return Norma();
}
public int intValue() {
return (int)Norma();
}
public long longValue() {
return (long)Norma();
}
public String toString() {
return "("+x+")+i("+y+")";
}
}
Pueden probar la clase (mínima) con el siguiente ejemplo de aplicación; la línea en negrita es un ejemplo de un
llamado a un método de un objeto de otra clase. Notar que es este caso, es necesario llamar al método sobre un
objeto (instancia) existente, por lo que se indica:
Nombre_del_Objeto<punto>Nombre_del_Método(parámetros)
// Archivo: Ejemplo4.java
// Compilar con: javac Ejemplo4.java
// Ejecutar con: java Ejemplo4
import java.io.*;
En la clase Complejo tenemos también un ejemplo de un llamado a un método de clase, o sea static:
return (float)Math.sqrt(x*x+y*y);
Como el método es de clase, no hace falta llamarlo para un objeto en particular. En ese caso, en lugar del nombre
de un objeto existente se puede utilizar directamente el nombre de la clase:
Nombre_de_la_Clase<punto>Nombre_del_Método(parámetros)
if…[else]
La más común de todas, permite ejecutar una instrucción (o secuencia de instrucciones) si se da una condición
dada (o, mediante la cláusula else, ejecutar otra secuencia en caso contrario).
if (expresión_booleana) instrucción_si_true;
[else instrucción_si_false;]
o bien:
if (expresión_booleana) {
instrucciones_si_true;
}
else {
instrucciones_si_false;
}
Por ejemplo:
public final String toString() {
if (y<0)
return x+"-i"+(-y);
else
return +x+"+i"+y;
}
Switch…case…brake…default
Permite ejecutar una serie de operaciones para el caso de que una variable tenga un valor entero dado. La
ejecución saltea todos los case hasta que encuentra uno con el valor de la variable, y ejecuta desde allí hasta el
final del case o hasta que encuentre un break, en cuyo caso salta al final del case. El default permite poner una
serie de instrucciones que se ejecutan en caso de que la igualdad no se de para ninguno de los case.
switch (expresión_entera) {
case (valor1): instrucciones_1;
[break;]
case (valor2): instrucciones_2;
[break;]
…..
case (valorN): instrucciones_N;
[break;]
default: instrucciones_por_defecto;
}
Por ejemplo:
switch (mes) {
case (2): if (bisiesto()) dias=29;
else dias=31;
break;
case (4):
case (6):
case (9):
case (11): dias = 30;
break;
default: dias = 31;
}
While
Permite ejecutar un grupo de instrucciones mientras se cumpla una condición dada:
while (expresión_booleana) {
instrucciones…
}
Por ejemplo:
while ( linea != null) {
linea = archivo.LeerLinea();
System.out.println(linea);
}
Do…while
Similar al anterior, sólo que la condición se evalúa al final del ciclo y no al principio:
do {
instrucciones…
} while (expresión_booleana);
Por ejemplo:
do {
linea = archivo.LeerLinea();
if (linea != null) System.out.println(linea);
} while (linea != null);
For
También para ejecutar en forma repetida una serie de instrucciones; es un poco más complejo:
for ( instrucciones_iniciales; condición_booleana; instruccion_repetitiva_x ) {
instrucciones…
}
Si bien las instrucciones pueden ser cualquiera (el bucle se repite mientras la condición sea verdadera), lo usual es
utilizarlo para "contar" la cantidad de veces que se repiten las instrucciones; se podría indicar así:
for ( contador = valor_inicial; contador < valor_final; contador++ ) {
instrucciones…
}
Por ejemplo:
for ( i=0; i<10; i++ ) {
System.out.println( i );
}
Break y continue
Estas instrucciones permiten saltar al final de una ejecución repetitiva (break) o al principio de la misma
(continue).
La salida es:
antes 1
después 1
antes 2
antes 3
Por qué? "i" comienza en 1 (imprime "antes" y "después"); cuando pasa a 2, el continue salta al principio del bucle
(no imprime el "después"). Finalmente, cuando "i" vale 3, el break da por terminado el bucle for.
Otras...
Hay otras instrucciones que controlan el flujo del programa:
Ahora sí, podemos usar todo nuestro conocimiento sobre Java para ir creando algunas aplicaciones y de paso ir
viendo las bibliotecas estándar.
Para empezar, vamos a desarrollar un poquito una clase para trabajar con números complejos.
La clase Complejo
// grabar como Complejo.java
// compilar con "javac Complejo.java"
public final class Complejo extends Number {
// atributos:
private float x;
private float y;
// constructores:
public Complejo() {
x = 0;
y = 0;
}
public Complejo(float rx, float iy) {
x = rx;
y = iy;
}
// métodos:
// Norma
public final float Norma() {
return (float)Math.sqrt(x*x+y*y);
}
public final float Norma(Complejo c) {
return (float)Math.sqrt(c.x*c.x+c.y*c.y);
}
// Conjugado
public final Complejo Conjugado() {
Complejo r = new Complejo(x,-y);
return r;
}
public final Complejo Conjugado(Complejo c) {
Complejo r = new Complejo(c.x,-c.y);
return r;
}
// obligatorios (son abstractos en Number):
public final double doubleValue() {
return (double)Norma();
}
public final float floatValue() {
return Norma();
}
public final int intValue() {
return (int)Norma();
}
public final long longValue() {
return (long)Norma();
}
public final String toString() {
if (y<0)
return x+"-i"+(-y);
else
return x+"+i"+y;
}
// Operaciones matemáticas
public static final Complejo Suma(Complejo c1, Complejo c2) {
return new Complejo(c1.x+c2.x,c1.y+c2.y);
}
public static final Complejo Resta(Complejo c1, Complejo c2) {
return new Complejo(c1.x-c2.x,c1.y-c2.y);
}
public static final Complejo Producto(Complejo c1, Complejo c2) {
return new Complejo(c1.x*c2.x-c1.y*c2.y,c1.x*c2.y+c1.y*c2.x);
}
// Nos va a venir bien para aprender excepciones...
// como división por cero!
public static final Complejo DivEscalar(Complejo c, float f) {
return new Complejo(c.x/f,c.y/f);
}
public static final Complejo Cociente(Complejo c1, Complejo c2) {
float x = c1.x*c2.x+c1.y*c2.y;
float y = -c1.x*c2.y+c1.y*c2.x;
float n = c2.x*c2.x+c2.y*c2.y;
Complejo r = new Complejo(x,y);
return DivEscalar(r,n);
}
}
Primero: no hay include aquí, ya que la única biblioteca que usamos es java.lang y se incluye automáticamente.
Segundo: la clase es public final, lo que implica que cualquier clase en éste u otros paquetes puede utilizarla, pero
ninguna clase puede heredarla (o sea que es una clase estéril...).
Hagamos un resumen de los atributos y métodos de la clase:
// atributos:
private float x;
private float y;
Siendo privados, no podemos acceder a ellos desde el exterior. Como además la clase es final, no hay forma de
acceder a x e y. Además, al no ser static, cada instancia de la clase tendrá su propio x e y.
// constructores:
public Complejo()
public Complejo(float rx, float iy)
La clase tiene dos constructores, que se diferencian por su "firma" (signature), o sea por la cantidad y tipo de
parámetros. El primero nos sirve para crear un objeto de tipo Complejo y valor indefinido (aunque en realidad el
método lo inicializa en cero); con el segundo, podemos definir el valor al crearlo.
// métodos:
public final float Norma()
public final float Norma(Complejo c)
public final Complejo Conjugado()
public final Complejo Conjugado(Complejo c)
Estos métodos también son duales; cuando los usamos sin parámetros devuelven la norma o el conjugado del
objeto individual (instancia):
v = miComplejo.Norma(); // por ejemplo
otroComplejo = miComplejo.Conjugado();
...porque el método no es static, por lo tanto debe llamarse para una instancia en particular (en este
caso, unComplejo).
// obligatorios (son abstractos en Number):
public final double doubleValue()
public final float floatValue()
public final int intValue()
public final long longValue()
Estos métodos es obligatorio definirlos, ya que en la clase madre Number son métodos abstractos, o sea que
debemos implementarlos aquí.
Como todos los métodos de esta clase son final, o sea que no puede ser redefinido. No es importante en realidad
puesto que la clase no puede tener descendientes...
public final String toString()
Este método nos sirve para representar el complejo como una cadena de caracteres, de la forma x+iy.
// Operaciones matemáticas
public static final Complejo Suma(Complejo c1, Complejo c2)
public static final Complejo Resta(Complejo c1, Complejo c2)
public static final Complejo Producto(Complejo c1, Complejo c2)
public static final Complejo DivEscalar(Complejo c, float f)
public static final Complejo Cociente(Complejo c1, Complejo c2)
Aquí definimos varias operaciones matemáticas. Notar que se han definido como static, o sea que los métodos son
únicos independientemente de las instancias. Esto permite que los podamos ejecutar sobre una instancia o
directamente sobre la clase:
miComplejo = unComplejo.Suma(comp1,comp2); // vale
miComplejo = Complejo.Suma(comp1,comp2); // TAMBIEN VALE!
Por ejemplo, la siguiente aplicación nos muestra cómo podemos usar algunos de estos métodos:
// Archivo: Ejemplo5.java
// Compilar con: javac Ejemplo5.java
// Ejecutar con: java Ejemplo5
import java.io.*;
System.out.println("("+c1+")/4 :"+Complejo.DivEscalar(c1,4));
System.out.println("Suma : "+Complejo.Suma(c1,c2));
System.out.println("Resta : "+Complejo.Resta(c1,c2).toString());
System.out.println("Multip: "+Complejo.Producto(c1,c2).toString());
System.out.println("Divis : "+Complejo.Cociente(c1,c2).toString());
}
}
Hay varias cosas para notar: por ejemplo, que podemos declarar las variables a la vez que las creamos:
Complejo c1 = new Complejo(4,-3);
Ya que no podemos convertir así nomás un complejo en un entero, para implementar estos métodos hemos elegido
usar como valor de retorno la norma del complejo. En este caso, y dado que el método Norma() devuelve un float,
usamos typecasting, es decir, lo convertimos en entero precediéndolo con (int).
public final String toString() {
if (y<0)
return x+"-i"+(-y);
else
return x+"+i"+y;
}
Aquí representamos el complejo en forma de cadena de caracteres. Hemos usado el if para representar
adecuadamente el signo de la parte imaginaria. Noten también la asombrosa ayuda que nos brinda Java, al
convertir automáticamente las variables x e y a String para la concatenación (mediante el signo "+")!
public static final Complejo Cociente(Complejo c1, Complejo c2) {
float x = c1.x*c2.x+c1.y*c2.y;
float y = -c1.x*c2.y+c1.y*c2.x;
float n = c2.x*c2.x+c2.y*c2.y;
Complejo r = new Complejo(x,y);
return DivEscalar(r,n);
}
Aquí tengan en cuenta que las variables x e y, definidas como float, no tienen nada que ver con las variables
(atributos) de la clase que están definidas al principio de la misma, sino que son variables locales al método.
Qué pasa con r, el new Complejo(x,y) que creamos? Nada; cuando un objeto no se usa más, el "recogedor de
basura" de Java lo elimina automáticamente (tarde o temprano) de la memoria.
public final float Norma(Complejo c) {
return (float)Math.sqrt(c.x*c.x+c.y*c.y);
}
Aquí estamos usando otra clase, Math, que nos permite realizar varias operaciones matemáticas. Esta clase
dispone de las constantes E y PI, y los métodos:
abs(x) valor absoluto
acos(x) arco coseno
asin(x) arco seno
atan(x) arco tangente
atan2(x,y) componente angular de la representación polar de x,y
ceil(x) menor entero mayor que x
cos(x) coseno
exp(x) ex
floor(x) mayor entero menor que x
IEEEremainder(x,y) resto de la división x/y según el estándar IEEE 754
log(x) logaritmo natural
max(x,y) el mayor de x e y
min(x,y) el menor de x e y
pow(x,y) xy
random() número aleatorio entre 0 y 1
rint(x) entero más cercano a x (devuelve un doble)
round(x) entero más cercano a x (devuelve un entero o un long)
sin(x) seno
sqrt(x) raíz cuadrada
tan(x) tangente
Algunos de estos métodos disparan excepciones, como sqrt o log de números negativos. Más adelante veremos
cómo se usan las excepciones.
Otra clase que hemos estado usando mucho es la PrintStream, a la que pertenece el método println. En
System.out.println(...)
// Methods
.............
La interface Java dirige tanto a uno como a otro todos los eventos de teclado, mouse y foco que los afecten (en
seguida veremos cómo usar estos eventos).
El siguiente ejemplo crea una ventana que no hace nada pero contiene varios elementos; se puede usar
directamente (desde la ventana DOS o Unix con java Ejemplo7) o como applet dentro de una página HTML.
Si bien los elementos no disparan ninguna acción, se pueden utilizar con toda su funcionalidad (por ejemplo, editar
el texto dentro de los cuadros de texto o presionar el botón).
// grabar como "Ejemplo7.java"
// compilar con "javac Ejemplo7.java"
import java.awt.*;
Un poco de detalle
La clase desciende de Frame (o sea que será una ventana con borde, aunque no le vamos a poner menú).
Vamos a usar el flag inAnApplet para saber si se arrancó como applet o como aplicación standalone (hay que
cerrarla en manera diferente en cada caso)
public class Ejemplo7 extends Frame {
boolean inAnApplet = true;
Si se llama como aplicación standalone, lo primero que se ejecuta es main(...); en este caso la aplicación crea una
instancia de Ejemplo7 (ejecutando el constructorEjemplo7() a través de new), define que no es un applet, y llama
a tres métodos de la "abuela" window:
Para verlo más claro, se crea el panel (o espacio para contener objetos) con:
Panel panelAlto = new Panel();
que equivale a:
this.add("North", panelAlto);
Como nuestra clase Ejemplo7 desciende de Frame, ésta de Window, y ésta de Container, el método add lo está
heredando de... su bisabuela! Por otra parte,Panel es hija de Container, y usa el mismo método para agregar sus
componentes. Interesante, no? Veamos la estructura:
Object --- Component --- Container --+-- Panel
|
+-- Window --- Frame --- Ejemplo7
LayoutManager es una interface, y como tal debe implementarse a través de objetos no abstractos de los que hay
varios predefinidos en la librería java.awt:BorderLayout, CardLayout, FlowLayout,
GridBagLayout y GridLayout.
El Layout por defecto es BorderLayout, que define en el contenedor las áreas "North", "South", "West", "East" y
"Center" y es que usamos aquí. CardLayoutpermite "apilar" los componentes como cartas y ver uno por
vez, FlowLayout los ordena de izquierda a derecha como un texto, GridLayout los ordena en una cuadrícula
donde cada componente tiene un tamaño fijo y GridBagLayout los pone en una cuadrícula pero cada uno puede
tener el tamaño deseado.
Y los eventos...
Ahora vamos a ver un método que viene de la clase tatarabuela! Hace falta decir que me gusta esto de los objetos?
Vamos a redefinir handleEvent(Event), que es el método que analiza los eventos dirigidos al componente y toma
las acciones adecuadas.
La clase Event define básicamente una serie de métodos que permiten saber si hay alguna tecla de control
presionada y muchas constantes que indican si se presionó o movió el mouse, si se presionó alguna tecla en
particular, si se cambió el tamaño de la ventana, etc. En particular hay algunos atributos interesantes:
etc.
En los descendientes de Component, el método handleEvent se llama automáticamente cada vez que se produce
un evento sobre el componente. En este caso, simplemente vamos a mirar si el evento (sobre nuestro objeto de
clase Ejemplo7) fue "cerrar la ventana", que se identifica mediante event.id = WINDOW_DESTROY (una
constante estática de la clase Event, y como tal la podemos usar con el nombre de la clase
como Event.WINDOW_DESTROY):
public boolean handleEvent(Event ev) {
if (ev.id == Event.WINDOW_DESTROY) {
if (inAnApplet) {
dispose();
} else {
System.exit(0);
}
}
return super.handleEvent(event);
}
En ese caso, si nuestro ejemplo se disparó como aplicación llamamos al método System.exit(0), que cierra la
aplicación; y si era un applet llamamos a dispose(), implementación de un método de la
interface ComponentPeer que se encarga de remover todos los componentes y la propia ventana.
Noten que cualquier otro tipo de evento deja seguir hasta return super.handleEvent(event), que llama al
método handleEvent de la clase madre: así como el prefijo this. se refiere a un método de la propia clase, el
prefijo super. llama al método de la clase madre (aunque esté redefinido). En este caso, la llamada se remonta
hasta Component.handleEvent, que determina el tipo de evento y llama a uno de los métodos action,
gotFocus, lostFocus, keyDown, keyUp, mouseEnter, mouseExit, mouseMove, mouseDrag,
mouseDown o mouseUp según sea apropiado (y devuelve true). Si ningún método es aplicable, devuelve false.
Es muy común, al redefinir un método, tener en cuenta llamar antes o después al método de la clase antecesora
para inicializar o terminar alguna tarea.
import java.awt.*;
import java.applet.*;
public static void main (String arg[]) { // para poder llamarla con "java Ejemplo8"
new Ventana8("Ejemplo Standalone", true);
}
Con los parámetros que le pasamos a la clase Ventana8 le indicamos el título de la ventana y si se carga como
applet o no (ya que el método de cierre varía).
El ejemplo está basado en uno del libro "Programación Java" de Macary y Nicolas, aunque algo mejorado y
ampliado.
En nuestra ventana podremos entrar una fecha a mano o directamente mediante los botones Hoy y Mañana,
elegiremos la ciudad de salida y la de llegada de dos listas, y presionaremos luego un botón que nos mostrará los
servicios disponibles, nos permitirá comprar los pasajes, etc.
A medida que entramos los datos, en el botón se irá mostrando el detalle de lo que se fue seleccionando.
void ActualizaBoton() {
// aquí pondremos un método que servirá
// para actualizar el botón de compra de pasajes,
// ya que el texto del mismo se actualiza cada
// vez que se selecciona una ciudad o se cambia la fecha
}
void Activar() {
// y aquí un método para cuando se presione
// dicho botón, que se supone que va a consultar
// una base de datos y abrir una ventana
// para vendernos el pasaje
}
}
asignamos a nuestra variable enApplet de la clase el valor del parámetro que se pasó al constructor, que se llama
igual. El prefijo this, que se refiere a la instancia particular de la clase, permite diferenciar uno de otro (esto es
válido tanto para variables como para métodos).
ok = new Button("Viaje: de ? a ? el ?/?/?");
add("South",ok);
Aquí hemos creado un botón ubicado al pie de la ventana (por ahora lo único que pusimos), y luego
dimensionamos la ventana y la mostramos:
pack(); // dimensionamos la ventana
show(); // y la mostramos!
Preparando listas
Ahora vamos a empezar a crear otros objetos para ir completando nuestra aplicación. Comencemos con las listas
de ciudades.
Para eso, vamos a crear un objeto descendiente de Panel que simplemente contenga una lista de ciudades
predefinidas y un título que diga "Seleccione ciudad de", y a continuación "salida" o "llegada".
También agregaremos un método
import java.awt.*;
En el constructor, armamos el texto del título como un StringBuffer. Los objetos StringBuffer son similares a los
de clase String pero pueden ser modificados. En cambio los objetos String, una vez creados, no pueden ser
modificados directamente: sus métodos (concat, toLowerCase, etc.) simplemente crean un nuevo Stringcon el
nuevo valor.
Esto lo hicimos para introducir esta nueva clase; por supuesto hubiera sido más fácil poner, como pueden
comprobar, con el mismo resultado:
String tit = "Seleccione ciudad de "+salidaOllegada+": ";
add("North", new Label(tit));
Por otra parte, creamos el objeto listaPueblos como new List(4, false), que indica que la lista va a tener 4
renglones y sólo se puede seleccionar un ítem por vez. Agregamos luego 6 ítems mediante addItem y la
agregamos al panel.
Ahora ya podemos agregar las listas a nuestra ventana y poner un par de variables para guardarlas:
class Ventana8 extends Frame { // hija de Frame
...........................
Ya pueden ir probando cómo queda, aunque por ahora mucha funcionalidad no tenemos...
Agregando fechas
DiaPartida() {
setLayout (new GridLayout (4,1));
elDia = new TextField();
elDia.setText(GetHoy());
hoy = new Button ("Hoy");
diasiguiente = new Button ("Mañana");
add (new Label ("Día salida: "));
add (elDia);
add (hoy);
add (diasiguiente);
}
private String GetHoy() {
Date d = new Date();
int dia = d.getDate();
int mes = d.getMonth();
int ano = d.getYear();
return dia+"/"+mes+"/"+ano;
}
Este es un poco más largo pero no más complejo. Vamos por parte:
DiaPartida() {
setLayout (new GridLayout (4,1));
elDia = new TextField();
elDia.setText(GetHoy());
hoy = new Button ("Hoy");
diasiguiente = new Button ("Mañana");
add (new Label ("Día salida: "));
add (elDia);
add (hoy);
add (diasiguiente);
}
El constructor crea un panel con cuatro campos en forma de grilla vertical, donde mostrará el texto "Día salida: ",
el campo de entrada de texto elDia y los botoneshoy y diasiguiente.
Otra manera sería armar un array con los días de cada mes, corregir los días de febrero para los años bisiestos, y
comparar contra este array en lugar de usar unswitch. La idea siempre es la misma: devolver un String con la
fecha del día siguiente.
Notar algo interesante: como estas clases se cargan y ejecutan en la máquina cliente, la fecha que aparece es la
del cliente y no la del servidor (que puede ser diferente depende la hora y el lugar del mundo en que estén ambas
máquinas).
El método getDescription es público y se usa para acceder a la fecha que se ha ingresado desde las demás clases;
simplemente devuelve el contenido del campoelDia, de clase TextField.
Notar que sólo hemos considerado que haya algún evento y no un tipo de evento en particular; en realidad el
método va a actuar por ejemplo tanto al presionar el mouse sobre el botón como al soltarlo. Pero esto no nos
molesta.
super.handleEvent se encarga de otros eventos dirigidos al panel, como la entrada de datos por teclado al campo
de texto por ejemplo.
Bueno, ahora vamos a reunir las piezas que tenemos hasta ahora agregando estos métodos a nuestra
clase Ventana8 para ver cómo queda la ventana completa:
class Ventana8 extends Frame { // hija de Frame
...........................
Completando la ventana
Vamos a empezar por completar nuestro método ActualizaBoton, que modificará el texto del botón ok a medida
que seleccionemos las ciudades y la fecha:
void ActualizaBoton() {
StringBuffer b = new StringBuffer("Viaje: de ");
if (cs.getDescription() != null) b.append(cs.getDescription());
else b.append("?");
b.append(" a ");
if (cl.getDescription() != null) b.append(cl.getDescription());
else b.append("?");
b.append(" el ");
if (dp.getDescription() != null) b.append(dp.getDescription());
else b.append("?/?/?");
ok.setLabel(b.toString());
}
Nuestro método comienza por crear un StringBuffer con las palabras "Viaje: de ", y va agregando el resto:
Si en cualquier caso recibe un string nulo, pone un signo de pregunta (o ?/?/? para la fecha).
Veamos:
class SelecPueblo extends Panel {
private List listaPueblos;
............................
public String getDescription() {
return listaPueblos.getSelectedItem();
}
}
Sería mejor, para ser más consistente, modificar el constructor de Ventana8 para que arme el texto mediante el
método ActualizaBotón:
Ventana8 (String titulo, boolean enApplet) {
........................................
ok = new Button("cualquiera");
ActualizaBoton();
add("South",ok);
pack();
show();
}
Un poco de actividad
Simplemente, si detectamos un evento sobre alguno de nuestros paneles actualizamos el texto del botón; y si se
presiona dicho botón llamamos al método Activar que se supone que va a tomar los datos de la base de datos,
indicarnos servicios disponibles, etc.
Algo importante a notar es que el simple hecho de mover el mouse sobre uno de los paneles ya llama a
ActualizaBoton (se nota porque titila el texto, sobre todo en una máquina lenta). Además, si hacen click sobre el
botón Hoy o Mañana sin mover el mouse, el texto del botón ok no se actualiza ya que el evento va dirigido al
botón presionado y no al panel.
Una forma de filtrar sólo los eventos que nos interesan sería usar, por ejemplo:
if ((e.target=cs.listaPueblos) && (e.id==Event.LIST_SELECT)) ActualizaBoton();
que está dirigida a la lista y no al panel en general, y tiene en cuenta el tipo de evento.
Hay varias formas de mejorar esto sin cometer la torpeza de declarar pública a listaPueblos. Una posibilidad es
verificar, usando cs.getDescription(), si el texto cambió (y sólo en ese caso modificar el texto del botón).
Otra, es hacer que los objetos de la clase SelecPueblo pasen a sus padres cualquier evento sobre ellos, o mejor
solamente la selección de un elemento de la lista; para eso basta agregar a la clase SelecPueblo:
public boolean handleEvent(Event e) {
if ((e.target==listaPueblos) && (e.id==Event.LIST_SELECT)) {
e.target=this;
}
return super.handleEvent(e);
}
En resumen: si el evento en el panel es una selección de la lista (tanto con mouse como moviendo la selección con
las flechas), cambio el target del evento para que indique el panel (y no la lista); si no, lo paso a la clase
antecesora.
Esto es porque el código dependiente de la plataforma procesa los eventos de mouse antes de llamar
a handleEvent, pero procesa los de teclado después de llamar a handleEvent.
Lo que significa que, en el caso del campo de texto, handleEvent (y por lo tanto ActualizaBotón) se llama antes de
modificar el texto!
Para corregir esto, deberíamos procesar nosotros las teclas presionadas (lo que podríamos aprovechar para
verificar que se presiona una tecla válida).
Cuidado! En futuras versiones de Java podría implementarse el mismo comportamiento para el mouse, y por lo tanto
tendríamos que repensar la estrategia.
Para colmo, sólo los eventos que la plataforma envía llegan a Java; por ejemplo, Motif no envía eventos de
movimiento de mouse dentro de un campo de texto... lo que significa que nunca podríamos capturar ese tipo de
eventos. Sólo el componente Canvas pasa todos los eventos.
if ((e.target == elDia)&&(e.id==Event.KEY_PRESS)) {
if (e.key==10) e.target=this;
}
Ahora debemos modificar el método handleEvent en nuestra clase Ventana8 para que soporte todos estos eventos:
Obviamente, procesar todas las teclas nosotros sería bastante más complicado... de todos modos, el método
en DiaPartida sería más o menos así:
if ((e.target == elDia)&&(e.id==Event.KEY_PRESS)) {
// 1- leer el contenido del campo con: elDia.getText()
// 2- modificarlo de acuerdo a la tecla presionada: e.key
// 3- poner el resultado en el campo con: elDia.setText(texto)
// 4- modificar el objeto del evento al panel con: e.target=this;
// 5- enviar el evento al objeto padre (no la clase padre),
// en este caso Ventana8, mediante: getParent().deliverEvent(e)
// 6- evitar proceso posterior del evento mediante: result(true)
}
Me ahorro explicar estos dos últimos pasos; se complica bastante todo porque hay que manejar la posición del
cursor dentro del campo de texto, etcétera. Con lo que hicimos es bastante... creo!
Y para terminar...
Bueno, sólo nos queda por definir el método Activar(). Primero vamos a llamar a ActualizaBoton() por si alguien
lo último que hizo fue entrar un texto sin presionarEnter, y dejo para otro día más tranquilo consultar un archivo o
base de datos con lo que vamos a mostrar al usuario de nuestro programa.
Por ahora simplemente vamos a mostrar una ventana con la selección y un lindo botón de OK.
Primero vamos a hacer una muy pequeña modificación a ActualizaBoton() para que nos devuelva el valor del
texto del botón (para no calcularlo de nuevo):
String ActualizaBoton() {
StringBuffer b = new StringBuffer("Viaje: de ");
..............................................
ok.setLabel(b.toString());
}
Y ahora vamos a definir nuestro método, teniendo en cuenta que nuestro botón sólo actuará si se han entrado todos
los datos:
void Activar() {
if ( (cs.getDescription() != null) && (cl.getDescription() != null) )
// también podríamos verificar que la fecha sea válida aquí
Result8 resultado = new Result8("Resultado",ActualizaBoton());
else ok.setLabel("Especificación incompleta!");
}
Sólo nos falta definir una sencilla clase Result8 para nuestra ventanita resultado:
// archivo Result8.java, compilar con javac Result8.java
import java.awt.*;
Button r_ok;
Espero que se haya entendido! Esta aplicación costó bastante pero en el camino hemos tenido oportunidad de
aprender unas cuantas cosas... Si logran juntar todo el código y generar las varias clases que definimos, todo tiene
que andar sobre rieles e independientemente de la plataforma.
http://www.amarillas.com/rock/java/Ejemplo8.htm
Un paréntesis de Entrada/Salida
En Java hay muchas clases para leer y escribir archivos (u otros dispositivos de E/S). Están reunidos en la
biblioteca java.io.
Vamos a empezar como siempre con un pequeño ejemplo funcional y en seguida nos meteremos en el necesario
camino de las excepciones...
Primera Lectura
// archivo: Ejemplo9.java - compilar con "javac Ejemplo9.java", etc. etc.
import java.io.*;
El programa de ejemplo simplemente lee un archivo de texto y lo muestra en pantalla, algo así como el type del
DOS o el cat de Unix.
Si el archivo no existe (por ejemplo reemplacen "Ejemplo9.java" por alguna otra cosa, como "noexiste.txt"), al
ejecutarlo nos aparece un error:
C:\java\curso>java Ejemplo9
java.io.FileNotFoundException: noexiste.txt
at java.io.FileInputStream.<init>(FileInputStream.java:51)
at Ejemplo9.main(Ejemplo9.java:9)
Justamente, cuando el archivo al que quiero acceder no existe, Java "lanza" una excepción. Esto es, un aviso de
que algo falló y, si no se toma ninguna acción, detiene el programa.
¿Cómo capturar y tratar las excepciones? En seguida; primero terminemos con nuestro programa.
f = new DataInputStream(fptr);
La clase DataInputStream nos permite leer, en forma independiente del hardware, tipos de datos de una
"corriente" (stream) que, en este caso, es un archivo. Es descendiente
de FilterInputStream e implementa DataInput, una interface.
Al crear un objeto de tipo DataInputStream lo referimos al archivo, que le pasamos como parámetro (fptr); esta
clase tiene toda una serie de métodos para leer datos en distintos formatos.
En nuestro programa usamos uno para leer líneas, que devuelve null cuando se llega al final del archivo o
un String con el contenido de la línea:
do {
linea = f.readLine();
System.out.println(linea);
} while (linea != null);
En seguida de leer la línea la imprimimos, y repetimos esto mientras no nos devuelva null.
Capturando excepciones
Ahora sí, vamos a ver cómo nos las arreglamos con las excepciones para que no se nos pare el programa con un
mensaje tan poco estético...
En lugar de lanzar las excepciones al intérprete, vamos a procesarlas nosotros mediante la cláusula catch:
// Archivo: Ejemplo11.java
// Compilar con: javac Ejemplo11.java
// Ejecutar con: java Ejemplo11 <nombre_archivo>
import java.io.*;
try {
fptr = new FileInputStream(args[0]);
f = new DataInputStream(fptr);
do {
linea = f.readLine();
if (linea!=null) System.out.println(linea);
} while (linea != null);
fptr.close();
}
catch (FileNotFoundException e) {
System.out.println("Hey, ese archivo no existe!\n");
}
catch (IOException e) {
System.out.println("Error de E/S!\n");
}
}
}
También hicimos un cambio para elegir el archivo a imprimir desde la línea de comandos, en lugar de entrarlo fijo,
utilizando para eso el argumento del métodomain(arg[]), que consiste en una lista de Strings con los parámetros
que se pasan en la línea a continuación de java nombre_programa. Por ejemplo, si llamamos a este programa
con:
java Ejemplo11 archi.txt otro.xxx
Por supuesto, si llamamos a Ejemplo11 sin parámetros se lanzará otra excepción al intentar accederlo:
C:\java\curso>java Ejemplo11
java.lang.ArrayIndexOutOfBoundsException: 0
at Ejemplo11.main(Ejemplo11.java:10)
La cláusula try engloba una parte del programa donde se pueden lanzar excepciones. Si una excepción se produce,
Java busca una instrucción catch(nombre_de_la_excepción variable), y, si la encuentra, ejecuta lo que ésta
engloba. Si no encuentra un catch para esa excepción, para el programa y muestra el error que se produjo.
Por ejemplo, para evitar este último error bastaría con agregar:
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Debe ingresar un nombre de archivo!");
System.out.println("Ej.: java Ejemplo11 pepe.txt");
}
Hay que notar que cuando se lanza una excepción el programa igual se detiene, porque el código que sigue al
lanzamiento de la excepción no se ejecuta. Veremos luego cómo se comporta esto en un objeto que fue creado por
otro, y cómo usar la instrucción finally para poner una parte de código que se ejecute pase lo que pase.
import java.io.*;
import java.awt.*;
import java.applet.*;
/*
// -------- Esta clase es la que en realidad hace el trabajo
*/
class Ventana12 extends Frame {
TextArea contenido;
Button cerrar;
Ventana12() {
super("Ejemplo de E/S");
contenido = new TextArea();
cerrar = new Button("Cerrar");
CargarArchivo();
add("North",contenido);
add("South",cerrar);
pack();
show();
}
void CargarArchivo() {
FileInputStream fptr;
DataInputStream f;
String linea = null;
try {
fptr = new FileInputStream("Ejemplo12.java");
f = new DataInputStream(fptr);
do {
linea = f.readLine();
if (linea!=null)
contenido.appendText(linea+"\n");
} while (linea != null);
fptr.close();
}
catch (FileNotFoundException e) {
contenido.appendText("Hey, ese archivo no existe!\n");
}
catch (IOException e) {
contenido.appendText("Error de E/S!\n");
}
}
}
Mientras corramos esto en la misma máquina, no hay problema (anda muy bien!). Pero qué pasa si intentamos
cargarlo desde la red? Para los que no tengan server html puse una copia en:
http://www.amarillas.com/rock/java/Ejemplo12.htm
El archivo no aparece! En su lugar se produce una excepción; en la línea de estado del Microsoft Internet Explorer,
por ejemplo, se lee:
exception: com.ms.applet.AppletSecurityException: security.file.read: Ejemplo12.java
Esto es debido a una restricción de seguridad de Java: NO SE PUEDEN CARGAR ARCHIVOS QUE ESTEN EN
UNA MAQUINA DISTINTA A AQUELLA DESDE LA CUAL SE CARGO EL APPLET. El applet se corre en
el cliente, e intenta acceder a un archivo local. Eso es lo que provoca la excepción (que, por supuesto, puede
detectarse con un catch y tratarse...)
Por cuestiones de seguridad, los applets son más limitados que las aplicaciones Java locales. Las políticas de
seguridad las manejan los browsers (no Java), y generalmente los límites que se imponen a los applets son:
Reproducir sonidos
Pueden establecer conexiones con el servidor del que provienen
Pueden llamar fácilmente páginas HTML desde el browser
Pueden invocar métodos públicos de otros applets de la misma página
Si se cargan desde la propia máquina (localmente) no tienen ninguna de las
restricciones anteriores
Pueden seguir corriendo aunque se cambie de página en el browser
En realidad, la especificación de Java permite que los applets lean archivos en otras máquinas dando la URL
completa; sin embargo, los browsers no lo permiten. Veremos más adelante cómo intercambiar datos entre
máquinas para poder ver un archivo del server, por ejemplo.
Cargarlo con "appletviewer Ejemplo13" luego de haberlo compilado (o usar una página html desde un browser):
/*
// ----- Archivo: Ejemplo13.java
*/
import java.io.*;
import java.awt.*;
import java.applet.*;
/*
// -------- Esta clase es la que en realidad hace el trabajo
*/
TextArea contenido;
Botones13 pieVentana;
Ventana13() {
super("Ejemplo de E/S");
contenido = new TextArea();
pieVentana = new Botones13();
add("North",contenido);
add("South",pieVentana);
pack();
show();
}
/*
// -------- Esta es para los botones y el nombre del archivo
*/
TextField fname;
Button cargar;
Button grabar;
Button cerrar;
Botones13() {
setLayout(new GridLayout(1,4));
fname = new TextField();
cargar = new Button("Cargar");
grabar = new Button("Grabar");
cerrar = new Button("Cerrar");
add(new Label("Archivo:"));
add(fname);
add(cargar);
add(grabar);
add(cerrar);
}
/*
// ------- Para mostrar los errores...
*/
Error13(String error) {
add("Center",new Label(error));
add("South", new Button("Ok"));
pack();
show();
}
Volviendo al AWT
Para aprender un poquito más sobre la biblioteca gráfica (AWT), vamos a modificar nuestro último programa para
usar menús.
Vamos a volver a poner todo el código (que ampliamos para usar como applet o aplicación local) marcando las
diferencias más notables:
/*
// ----- Archivo: Ejemplo14.java
*/
import java.io.*;
import java.awt.*;
import java.applet.*;
/*
// -------- Esta clase es la que en realidad hace el trabajo
*/
TextArea contenido;
boolean enApplet; // para indicar si lo llamamos como applet
String nombreArchivo; // para guardar el nombre del archivo abierto
MenuItem mArchivoAbrir; // ACA ESTAN LOS ITEMS DE LOS MENUS
MenuItem mArchivoGrabar; // .
MenuItem mArchivoSalir; // .
MenuItem mEditCortar; // .
MenuItem mEditCopiar; // .
MenuItem mEditPegar; // .
MenuItem mEditTodo; // v
String clipboard; // buffer para cortar y pegar
boolean editado = false; // acá indicamos si modificamos el archivo
Ventana14(boolean enApp) {
super("Ejemplo de E/S");
enApplet = enApp; // recordamos si es applet o no
void CargarArchivo() {
FileInputStream fptr;
DataInputStream f;
String linea = null;
if (editado) System.out.println("Pedir confirmación!\n");
FileDialog fd = new FileDialog(this,"Abrir...",FileDialog.LOAD); // elijo archivo
fd.show(); // usando el diálogo estándar del sistema!
nombreArchivo = fd.getFile();
try {
fptr = new FileInputStream(nombreArchivo);
f = new DataInputStream(fptr);
contenido.setText(""); // vacío la ventana antes de cargar nuevo archivo
do {
linea = f.readLine();
if (linea!=null) contenido.appendText(linea+"\n");
} while (linea != null);
fptr.close();
editado=false; // archivo nuevo -> no editado
}
catch (FileNotFoundException e) {
new Error14("El archivo no existe!");
}
catch (IOException e) {
new Error14("Error leyendo archivo!");
}
catch (NullPointerException e) {
;
}
}
void GrabarArchivo() {
FileOutputStream fptr;
DataOutputStream f;
FileDialog fd = new FileDialog(this,"Grabar...",FileDialog.SAVE); // grabo archivo
fd.setFile(nombreArchivo); // usando el diálogo estándar del sistema!
fd.show();
nombreArchivo = fd.getFile();
try {
fptr = new FileOutputStream(nombreArchivo);
f = new DataOutputStream(fptr);
f.writeBytes(contenido.getText());
fptr.close();
editado=false; // recién grabado -> no editado
}
catch (IOException e) {
new Error14("Error grabando archivo!");
}
catch (NullPointerException e) {
;
}
}
}
/*
// ------- Para mostrar los errores...
*/
Error14(String error) {
add("Center",new Label(error));
add("South", new Button("Ok"));
pack();
show();
}
Menú a la Java
Bueno, lo primero que vamos a ver son los menús.
La barra de menú está compuesta por menúes, que a su vez están compuestos de ítems (que pueden también ser
menúes). Por ejemplo la barra de menú la declaramos con:
MenuBar barraMenu = new MenuBar();
Noten que el "&" no se visualiza, sino que la letra que le sigue aparece subrayada: Archivo, Edit. Esto permite que
se pueda seleccionar el menú tanto con el mouse como con la tecla alt- o meta-, seguida de la tecla subrayada.
A su vez, el método add está presente también en la clase Menú y nos permite agregar los ítems:
mArchivoAbrir = new MenuItem("&Abrir...");
mArchivoGrabar = new MenuItem("&Grabar...");
mArchivoSalir = new MenuItem("&Salir");
menuArchivo.add(mArchivoAbrir);
menuArchivo.add(mArchivoGrabar);
menuArchivo.add(new MenuItem("-"));
menuArchivo.add(mArchivoSalir);
A estos ítems los hemos declarado como globales en la clase para usarlos luego en los eventos. Noten además que
menuArchivo.add(new MenuItem("-"));
no agrega un ítem al menú sino una línea de separación, y no necesitamos crearlo como objeto permanente.
Finalmente, en nuestro manejador de eventos simplemente necesitamos verificar si se eligió un ítem probando si el
evento ocurrió sobre el ítem determinado:
if ((e.id==Event.WINDOW_DESTROY)||(e.target==mArchivoSalir)) {
if (editado) System.out.println("Pedir confirmación!\n");
if (enApplet) dispose();
else System.exit(0);
}
if (e.target==mArchivoAbrir) CargarArchivo();
................
if (e.target==mEditTodo) contenido.selectAll();
En resumen lo que hago es:
En todos los casos, si se modifica el texto del contenido lo indico poniendo editado en true; lo mismo si presiono
una tecla sobre el área de edición:
if ((e.id==Event.KEY_PRESS)&&(e.target==contenido)) editado=true;
Un par de aclaraciones:
Diálogos
En Java disponemos de la clase Dialog para crear diálogos, es decir, ventanitas temporarias para entradas de
usuario, que dependen de otra (de hecho la clase Dialoges heredera de la clase Window).
Si bien podemos crear diálogos a medida usando la clase Frame, se supone que usar diálogos debe ser más fácil.
La realidad es que por ahora no se puede usar mucho más que los diálogos estándar (y el único que vale la pena
es FileDialog), ya que las implementaciones actuales de Java tienen un problema: en algunas plataformas el
programa que abre el diálogo sigue, en lugar de esperar que se cierre el diálogo y devuelva la respuesta.
Por eso hemos puesto solamente una indicación adonde debería haber un diálogo de confirmación:
if (editado) System.out.println("Pedir confirmación!\n");
En ese lugar deberíamos llamar por ejemplo a un diálogo que nos permita decidir por sí o por no:
if (editado) {
sino = new ConfirmarDlg(this,"Archivo modificado!");
if (sino.getResponse()==true) ....;
else ....;
}
o algo así. Esto mismo lo podemos hacer de otras maneras, por ejemplo usando threads y comunicaciones entre
procesos, pero se complica mucho para esta altura del curso. Esperemos un poco más adelante, aunque Sun me
prometió que en la versión 1.1 ya va a estar corregido (sale para fines del '96).
Primero declaramos una variable de tipo FileDialog, y creamos la instancia con new. Como parámetros se pasa el
padre (this, o sea "esta ventana"), el título de la ventanita de diálogo, y una constante LOAD o SAVE (son static,
por lo que se denominan directamente con el nombre de la clase y no necesariamente de una instancia) que indica
si el diálogo es para cargar o grabar un archivo (Obviamente la tarea en sí de cargar o grabar el archivo la
tenenmos que hacer nosotros, el diálogo sólo espera que elijamos un nombre).
Finalmente, el diálogo se cierra pero no se elimina el objeto (posiblemente está implementado usando el
método hide(), que lo oculta de la vista pero no se pierde hasta no salir del método que lo creó, donde actuaría
el recogedor de basura de la memoria). Esto hace que aunque no lo veamos podamos llamar al
métodogetFile() sobre este objeto, que nos devuelve el nombre del archivo seleccionado (o null si se presionó
Cancel).
DibuJava
Además de los componentes estándar (botones, listas, etc.), hay un componente para dibujo "libre" que nos
permite implementar cualquier otro tipo de control: la claseCanvas. Típicamente se usa para dibujar, y
corresponde a una zona rectangular dentro de una ventana.
La clase en sí no hace prácticamente nada; el programador debe definir una subclase de Canvas a la que el AWT
le envía todos los eventos de mouse y teclado. Redefiniendo los métodos gotFocus, lostFocus, keyDown, keyUp,
mouseEnter, mouseExit, mouseMove, mouseDrag, mouseDown y mouseUp, el programador puede hacer lo
que se le ocurra dentro de ese rectángulo. Vamos a hacer uso de un Canvas para generar un applet donde habrá
una zona rectangular dentro de la que, haciendo click con el mouse y moviéndolo sin soltar el botón, dibujaremos
un rectángulo dinámicamente.
Esto nos permitirá ver cómo usar un Canvas para dibujar, capturar eventos, etc. El borde tiembla un poco al
redibujar, pero ya veremos cómo evitar eso.
Canvas en acción
Primero vamos a poner, como ya se está haciendo costumbre, el código del applet (Recordar que debe cargarse
desde una página html para verlo! Aquí no creamos ninguna ventana y no podremos verlo como aplicación
standalone) y luego intentaremos explicar cómo funciona.
import java.awt.*;
import java.applet.Applet;
El applet-container
En primer lugar hemos tenido en cuenta que un Applet es un Panel, y por lo tanto también un Container, así que
en lugar de crear una ventana aparte simplemente le agregamos dos componentes: un Label y un Canvas.
zonaDib.resize(new Dimension (200,200));
add("North", label);
add("Center", zonaDib);
resize(300,250);
El método rezise, sobre la clase miCanvas, nos permite redimensionar el mismo al tamaño deseado. Igualmente,
usamos resize sobre el applet para darle un tamaño adecuado. Si se modifica el tamaño de la ventana en el
appletviewer se observará un comportamiento algo extraño en cuanto al posicionamiento relativo del rectángulo y
el cartel, pero para simplificar esto bastará.
Simplemente hemos redefinido algunos métodos para actuar al presionar, arrastrar y soltar el mouse, para redibujar
el área de dibujo (canvas) y para recortar el rectángulo dibujado si nos vamos con el mouse fuera del espacio que
ocupa el canvas.
La variable global rectActual, de la clase Rectangle, contendrá las coordenadas del rectángulo que estamos
dibujando. El método Paint se llama automáticamente cada vez que es necesario redibujar el componente, o si
llamamos explícitamente al método repaint():
En primer lugar le asignamos a una variable d el tamaño del canvas usando el método size(), luego elegimos un
color (rojo) para dibujar un borde y dibujamos un rectángulo del tamaño del componente:
Dimension d = size();
g.setColor(Color.red);
g.drawRect(0, 0, d.width-1, d.height-1);
Dos atributos de la clase Dimension, width y height, se han cargado con el tamaño del canvas y son los que
usamos para dar el tamaño del rectángulo.
Luego, si se está dibujando un rectángulo (rectActual != null) simplemente lo recortamos (en caso de que
hayamos arrastrado el mouse fuera del canvas) y lo dibujamos.
El método que lo recorta a los límites del canvas, cortarRect, asigna a cuatro variables las coordenadas del
rectángulo (que se le pasaron como parámetro miRect al llamarlo):
int x = miRect.x;
int y = miRect.y;
int ancho = miRect.width;
int alto = miRect.height;
Si el ancho (o el alto) es negativo, simplemente lo cambia de signo y toma como coordenada x (y) de origen el otro
vértice del rectángulo, que corresponderá al x que se pasó menos el ancho y más uno (recordar que el origen de
coordenadas empieza en cero y no en uno). Si este vértice está fuera del canvas (x<0), lo pone en cero y le resta al
ancho la parte recortada (notar que ancho+=x, como x es negativo, es en realidad una resta).
if (ancho < 0) {
ancho = -ancho;
x = x - ancho + 1;
if (x < 0) {
ancho += x;
x = 0;
}
}
Si nos vamos del área de dibujo por la derecha (o por abajo), simplemente le recortamos al ancho (alto) el exceso
de modo que llegue hasta el borde del área de dibujo (que también hemos pasado al método como parámetro):
if ((x + ancho) > areaDib.width) {
ancho = areaDib.width - x;
Sólo nos quedan por ver los métodos que responden al mouse.
Cuando presionamos el mouse dentro del canvas, comenzamos la creación de un nuevo rectángulo de ancho y alto
cero que comienza en el punto en que hemos presionado el mouse, y redibujamos el canvas:
public boolean mouseDown(Event e, int x, int y) {
rectActual = new Rectangle(x, y, 0, 0);
repaint();
return false;
}
Como no se toma ninguna medida para guardar el rectángulo dibujado, al crear uno nuevo
(reasignando rectActual a un nuevo rectángulo), el anterior se pierde.
DibuJava II
Vamos a retocar un poquito nuestro ejemplo15 para que no se borren los rectángulos cuando queremos dibujar
uno nuevo. Aprenderemos algo sobre la claseVector, perteneciente al paquete java.util.
Vectores en acción
Los vectores nos permiten hacer arreglos de cualquier tipo de objeto, y referirnos individualmente a cualquier
elemento del vector, aunque para utilizarlos (debido a que para java el vector contiene objetos genéricos)
tendremos que decirle qué clase de objeto es mediante un "cast". Vamos a ver cómo quedan nuestras
clasesEjemplo16 (ex Ejemplo15) y miCanvas:
import java.awt.*;
import java.util.*;
import java.applet.Applet;
Les sugiero utilizar un HTML que reserve espacio suficiente para ver todo el applet, como:
<HTML>
<HEAD>
<TITLE>Ejemplo 16 - Ejemplo con canvas</TITLE>
</HEAD>
<BODY>
<applet code="Ejemplo16.class" width=300 height=250>
</applet>
</BODY>
</HTML>
Veamos los pasos ahora. En primer lugar creamos una variable (global a la clase) llamada v, de clase Vector, y sin
asignarle un tamaño definido:
Vector v = new Vector();
Para acceder a un atributo de un objeto del vector no basta utilizar directamente el vector, como:
v.lastElement().x
(lastElement() nos permite acceder al último elemento agregado al vector). Es necesario aclarar explícitamente
que el elemento en cuestión es un rectángulo, ya que el vector puede contener objetos de cualquier tipo. Para eso
usamos el casting:
(Rectangle)v.lastElement().x
Pero es más claro si usamos una variable local de clase Rectangle, le asignamos el mismo objeto que acabamos de
agregar al vector, y lo usamos en su lugar:
Rectangle r = (Rectangle)v.lastElement();
r.resize( x - r.x, y - r.y );
Finalmente, en el método paint() no podemos asignar el elemento hasta no saber que existe (originalmente el
vector estaba vacío!). Así que un if nos permite verificar que el tamaño del vector es mayor que cero (tiene
elementos), y un for nos permite dibujarlos uno por uno.
Se puede acceder a todos los elementos, uno por uno, mediante el método elementAt(x), que nos da el x-ésimo
elemento del vector. El método size() nos da la cantidad de elementos (el primero es el número 0, y así):
if (v.size() > 0)
for (i=0; i<v.size(); i++) {
Rectangle box = cortarRect( (Rectangle)v.elementAt( i ), d);
g.drawRect(box.x, box.y, box.width-1, box.height-1);
}
Aquí no hemos creado variables intermedias ya que igualmente es claro (eso creo...).
Flicker molesto!
Bueno, el problema que nos queda es el molesto "flicker", o sea la manera en que titila el dibujo cuando movemos el
mouse. Esto es porque cada vez que se llama apaint(), el fondo se borra y se redibuja todo el canvas.
Básicamente, la manera de evitarlo es reescribiendo el método update(), que es el que borra el fondo antes de
llamar a paint() para que no lo borre; otro método (que es el que vamos a usar) es dibujar no sobre la pantalla sino
sobre un "buffer" gráfico, y luego copiar ese buffer sobre la pantalla (lo que es mucho más eficiente que dibujar
sobre la misma).
Image es una clase abstracta, madre de todas las clases que representan imágenes gráficas. Graphics es también
abstracta y nos permite obtener un contexto en el cual dibujar.
Lo que vamos a hacer es modificar nuestro método paint() para que simplemente llame a update(), y redefinir el
método update():
public void paint(Graphics g) {
update(g);
}
El método update() es el que hará todo el trabajo y básicamente es como nuestro viejo paint() con algunos
agregados:
public void update(Graphics g) {
int i;
Dimension d = size();
if (grafBuff == null) {
imgBuff = createImage(d.width, d.height);
grafBuff = imgBuff.getGraphics();
}
grafBuff.setColor(getBackground());
grafBuff.fillRect(0, 0, d.width, d.height);
grafBuff.setColor(Color.red);
grafBuff.drawRect(0, 0, d.width-1, d.height-1);
grafBuff.setColor(Color.blue);
if (v.size() > 0) for (i=0; i<v.size(); i++) {
Rectangle box = cortarRect((Rectangle)v.elementAt(i), d);
grafBuff.drawRect(box.x, box.y, box.width-1, box.height-1);
}
g.drawImage(imgBuff, 0, 0, this);
}
Si no está creado todavía (grafBuff==null), creamos nuestro buffer de dibujo. Para crear dicho buffer gráfico (de
clase Graphics), primero creamos una imagen que en este caso tiene las mismas dimensiones que el canvas
(d.width x d.height), y luego asignamos a grafBuff el contexto de dicha imagen mediante el métodogetGraphics().
Imagínense que con createImage(...) crean una "pantalla virtual", y getGraphics() nos da una forma de acceder a
esa pantalla como si fuera real.
Utilizando dicho contexto, elegimos como color el mismo color de fondo del applet (getBackground()) y dibujamos un
rectángulo lleno (fillRect(...)), borrando así cualquier cosa que hubiera estado dibujada.
En itálica hemos indicado las modificaciones a nuestro método anterior. Simplemente, en lugar de usar el contexto
de la pantalla (el parámetro g del método), dibujamos sobre nuestro contexto-pantalla virtual.
Finalmente, y para poder visualizar nuestro dibujo, usamos el método drawImage sobre el contexto de la pantalla
real (g), que copia nuestro contexto imgBuff en las coordenadas (0,0) sobre la pantalla. Se hace también referencia
al canvas (...this): el cuarto parámetro de drawImage es un objeto de clase ImageObserver, una interface que sirve
para que el objeto dentro del cual se dibuja reciba mensajes asincrónicos que le indican cómo está siendo
construida la imagen, y cuándo está lista.
Animate!
Si bien puede ser un poco más complejo de entender que un dibujo directo sobre la pantalla, notarán que la
implementación es directa y no trae ningún problema. Esta misma aproximación puede utilizarse para crear
animaciones.
En este ejemplo, para manejar la ejecución cuadro a cuadro de la animación, usamos Threads. No se preocupen
por eso, lo veremos pronto. Únicamente tengan en cuenta que nuestro applet debe implementar la clase runnable, y
el thread se encarga de ejecutar el método run() que simplemente llama a repaint() y espera 100 milisegundos entre
cuadro y cuadro.
El trabajo de cálculo y dibujo lo hace update(). Se los dejo para que lo estudien; no es nada complicado y también
usa doble buffering (como el ejemplo anterior).
import java.awt.*;
import java.util.*;
import java.applet.Applet;
Thread animador;
Image imgBuff;
Graphics grafBuff;
double ang = 0.0;
Dimension d = size();
if (grafBuff == null) {
imgBuff = createImage(d.width, d.height);
grafBuff = imgBuff.getGraphics();
}
grafBuff.setColor(getBackground());
grafBuff.fillRect(0, 0, d.width, d.height);
grafBuff.setColor(Color.red);
grafBuff.drawRect(0, 0, d.width-1, d.height-1);
grafBuff.setColor(Color.blue);
dx = (int)(50 * Math.abs(Math.cos(ang)));
dy = (int)(50 * Math.abs(Math.sin(ang)));
ang = ang + 0.1;
if (ang>2*Math.PI) ang = 0.0;
grafBuff.drawRect(100-dx, 100-dy, 2*dx, 2*dy);
g.drawImage(imgBuff, 0, 0, this);
}
}
Java en hebras
La clase anterior usamos, en el último ejemplo, un concepto al que vamos a dedicar ahora nuestra atención:
los threads.
La traducción literal de thread es hilo o hebra, y se utiliza también para referirse al hilo de un discurso. El concepto
de threads en los ambientes y sistemas operativos es un poco complejo de explicar pero sencillo de entender:
independientemente del sistema elegido, puede pensarse que un thread es algo así como el lugar de ejecución de
un programa.
En la mayoría de los programas que hemos visto, hemos usado un solo thread; es decir que un programa comienza
y su ejecución sigue un camino único: como un monólogo.
Java es multithreading. Esto significa algo así como que tiene capacidad de diálogo, y más aún: puede ejecutar
muchos threads en paralelo, como si tratáramos de una conversación múltiple y simultánea.
No confundir aquí multithreading con la capacidad de ejecutar varios programas a la vez. Esta es una posibilidad,
pero también un mismo programa puede utilizar varios threads ("caminos de ejecución"?) simultáneamente.
Esto, por supuesto, depende fundamentalmente de la capacidad del sistema operativo para soportar multithreading,
y por esto Java no puede ejecutarse (al menos en forma completa) en sistemas que no lo soporten.
El uso de threads nos permite, por ejemplo, ejecutar simultáneamente varios programas que interactúen entre ellos;
o, también, que un programa, mientras por ejemplo actualiza la pantalla, simultáneamente realice una serie de
cálculos sin tener que hacer esperar el usuario.
Una forma sencilla de verlo es imaginar que tenemos un grupo de microprocesadores que pueden ejecutar, cada
uno, un solo thread; y nosotros asignamos programas (o partes de programas) a cada uno de ellos. Además,
podemos imaginar que esos microprocesadores comparten una memoria común y recursos comunes, de lo que
surgirá una serie de problemas importantes a tener en cuenta cuando se usan threads.
le asegura al compilador que nuestra clase (la que utilizará el thread para ejecutarse) dispone de método run().
Vamos a ver un par de ejemplos, primero una aplicación standalone y luego un applet.
Reunión de amigos
El siguiente ejemplo (Ejemplo19.java) usa threads para activar simultáneamente tres objetos de la misma clase,
que comparten los recursos del procesador peleándose para escribir a la pantalla.
class Ejemplo19 {
String mensaje;
Si ustedes están utilizando un sistema operativo no preemptivo, deben explícitamente indicarle al procesador
cúando puede ejecutar (dar paso) a otra tarea; para eso simplemente modifiquen el método run():
public void run() {
for (int i=1; i<6; i++) {
String msg = mensaje+i;
System.out.println(msg);
Thread.yield();
}
}
Esto es porque en seguida de imprimir estamos liberando al procesador para que pase a otro thread (si hay alguno
esperando). Noten la diferencia con el primer caso, sin usar yield(), para sistemas preemptivos: el procesador
reparte su trabajo en forma (aparentemente) impredecible, por eso el orden de los mensajes no será el mismo en
cualquier máquina o sistema operativo.
Ya lo vimos funcionar, pero sería bueno que lo entendamos! Por eso, vamos paso a paso.
Creando Threads
Thread es una clase básica en Java, que implementa la interface Runnable y dispone de unos cuantos métodos por
defecto. Lo importante a tener en cuenta que, para usar Threads, debemos crearlas como instancias y ponerlas a
"andar":
Thread Juan = new Thread (new Amigo("Juan"));
..............
Juan.start();
..............
Juan.join();
activo: está en ejecución, ya sea porque arrancó con start() o fue "despertado" con resume().
dormido: ha sido suspendida su ejecución momentáneamente mediante wait(), sleep() o suspend().
muerto: se ha detenido definitivamente, ya sea porque se terminó el programa o mediante el llamado a stop().
En este ejemplo hemos creado un thread asignándole simultáneamente un objeto que lo utiliza (new
Amigo("Juan")), y seguidamente lo hemos activado, llamando al método start(). Este método se encarga de
inicializar el thread y, finalmente, llamar al método run() que hemos implementado.
De este modo, todo ocurre como si los métodos run() de cada objeto se ejecutaran en paralelo, concurrentemente.
La forma de manejar esto depende del sistema operativo.
El método join() que llamamos al final hace que el programa principal espere hasta que este thread esté "muerto"
(finalizada su ejecución). Este método puede disparar la excepción InterruptedException, por lo que lo hemos
tenido en cuenta en el encabezamiento de la clase.
En nuestro ejemplo, simplemente a cada instancia de Amigo(...) que creamos la hemos ligado a un thread y puesto
a andar. Corren todas en paralelo hasta que mueren de muerte natural, y también el programa principal acaba.
La clase Amigo() es muy simple y con lo que hemos visto hasta ahora no creo que tengamos que explicar nada
más.
Y los applets...?
También podemos usar estos conceptos en los applets. Veamos un ejemplo para terminar la clase de hoy, muy
similar al anterior, donde tres contadores cuentan (en un sistema preemptivo) en forma simultánea. Recuerden
crear una página HTML con el tag
<applet code="Ejemplo20.class" width=300 height=100></applet>
para poder verlo en acción con el appletviewer o su browser favorito (que desde ya supongo que soporta Java! ;-)
El programa es extremandamente sencillo, y pueden verlo en acción si lo desean cargando via Internet la página:
http://www.amarillas.com/rock/java/Ejemplo20.htm
// Ejemplo de applet que usa multithreading
import java.awt.*;
import java.applet.*;
TextField tfa,tfb,tfc;
TextField texto;
String s;
throws InterruptedException {
tortuga.start();
liebre.start();
guepardo.start();
tortuga.join();
liebre.join();
guepardo.join();
}
class Animal extends Thread {
String nombre;
this.nombre = nombre;
setPriority(prioridad);
System.out.print( nombre );
yield();
System.out.println("\nLlega "+nombre );
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
Llega G
LTLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
Llega L
TTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Llega T
como se ve, a pesar de haber arrancado antes la tortuga, casi todo el tiempo de CPU lo usa primero el Guepardo,
luego la Liebre (aunque algo queda para la pobre tortuga, como se ve en la T marcada), y finalmente para la
Tortuga. No todas las corridas ni todos los sistemas dan igual salida, ya que ésta depende de la carga del
procesador y de la implementación de Java particular.
Este programa simplemente crea tres animales (clase Animal), asigna un thread a cada uno y los ejecuta. Este
ejemplo está hecho en base a uno del libro "Programación Java" de Macary y Nicolas.
valorImportante = valorImportante - 1;
..... sigue.....................
¿Cómo nos aseguramos que valorImportante no cambió entre el if y la línea resaltada? Otros threads pueden
haberlo modificado mientras tanto. Asimismo, puede suceder que dos threads estén ejecutando la misma porción
de código, y se pierda uno de los decrementos. Imaginen algo así:
(antes) valorImportante = 10
(thread 1) 10 -1 = 9
(thread 2) 10 -1 = 9
(después) valorImportante = 9
Como vemos, a pesar de haber restado dos veces, hemos perdido una de las restas. Aunque usemos -= en vez de la
resta es lo mismo, porque el código igualmente se resuelve en varios pasos (varias operaciones atómicas).
Para evitar esto, Java nos brinda la palabra clave Synchronized, que bloquea el acceso a una variable a todos los
threads menos el que lo está usando.
Vamos a ver un caso específico; se trata de dos contadores que usan el mismo sumador para sumar de a uno una
cantidad a. Supuestamente entre los dos deben llevar el sumador (a) hasta 20000.
// Archivo Ejemplo22.java, compilar con javac Ejemplo22.java, ejecutar con java Ejemplo22
C1.start();
C2.start();
try {
C1.join();
C2.join();
catch (Exception e) {
System.out.println(e);
}
Sumador s;
class Sumador {
int a = 0;
public void sumar() {
a += 1;
Ejecutando esto nos da más o menos así (cada corrida es diferente, dependiendo de cómo se "chocan" los threads y
la carga de la CPU):
C:\java\curso>java Ejemplo22
87
8926
10434
14159
17855
Esto se debe justamente a lo que explicábamos al principio: a veces los dos threads intentan ejecutar a +=
1 simultáneamente, con lo que algunos incrementos se pierden.
synchronized (s) {
s.sumar();
Con esto, sólo a uno de los dos threads se les permite ejecutar s.sumar() por vez, y se evita el problema. Por
supuesto, el otro thread queda esperando, por lo que más vale no utilizar esto con métodos muy largos ya que el
programa se puede poner lento o aún bloquearse.
0 <
10000 <
10000 (
20000 (
Esto es mejor porque la clase que llama a sumar() no necesita saber que tiene que sincronizar el objeto antes de
llamar al método, y si otros objetos (en otros threads) lo llaman, no necesitamos preocuparnos.
Más sincronización
Otra manera de sincronizar el acceso de los threads a los métodos, es lograr que éstos se pongan de acuerdo entre
sí, esperando uno hasta que otro realizó alguna tarea dada. Para esto se usan los métodos wait() y notify(). Cuando
un thread llama a wait() en un método de un objeto dado, queda detenido hasta que otro thread llame a notify() en
algún método del mismo objeto.
Por ejemplo, vamos a suponer cuatro empleados que se encuentran con su jefe y lo saludan, pero sólo luego de que
éste los salude primero.
pablo.start();
luis.start();
andrea.start();
pedro.start();
jefe.start();
try {
pablo.join();
luis.join();
andrea.join();
pedro.join();
jefe.join();
catch (Exception e) {
System.out.println(e);
class Saludo {
try {
wait();
catch (InterruptedException e) {
System.out.println(e.toString());
}
notifyAll();
String nombre;
Saludo saludo;
boolean esJefe;
nombre = n;
saludo = s;
esJefe = j;
}
System.out.println("("+nombre+" llega)");
if (esJefe)
saludo.saludoJefe();
else
saludo.esperarJefe(nombre);
Usé notifyAll() en lugar de notify(), porque en el segundo caso sólo se notificaría al primer thread (el primer
empleado en llegar) y no a los demás, que se quedarían en el wait().
Como se ve en la salida, a pesar de que los empleados están en condiciones de saludar, no lo hacen hasta que no
llega el jefe:
C:\java\curso>java Ejemplo23
(Pablo llega)
(Luis llega)
(Andrea llega)
(Pedro llega)
(JEFE llega)
Multimedia
Java permite cargar y visualizar archivos GIF o JPEG de imagen y AU de audio (solamente en mono, 8 bits,
8000Hz de muestreo).
Para el caso del sonido, un archivo de audio se carga mediante un objeto de la clase AudioClip, mediante el
método getAudioClip(URL, archivo), se ejecuta con los métodos play() o loop() y se detiene con stop().
Noten esto! Si bien dijimos que un applet no puede acceder al disco de la máquina cliente, SI puede leer archivos
del server desde donde se cargó. Por lo tanto, pasándole el URL de la máquina desde donde se cargó el applet,
podemos leer cualquier tipo de archivo a través de la red.
La forma más segura de indicar dicho URL es mediante el método getDocumentBase(), que nos da el URL
adecuado.
Por ejemplo, puedo cargar y reproducir audio con sólo dos líneas:
........
sonido.play();
.........
Por otra parte, una foto puede cargarse mediante un objeto de clase Image mediante el método getImage(URL,
archivo). Luego la mostramos en un objetoGraphics correspondiente al applet (o al área de dibujo)
mediante drawImage(imagen, x, y, observador). Observador es un objeto que implementa la interface
ImageObserver; los applets, por descender de Component (que implementa dicha interface) también la
implementan. Típicamente, la imagen se visualiza en el método paint(...) del applet:
.............
algunMetodo(...) {
..........
..........
}
...........
...............
El problema con las imágenes es asegurarse que fue cargada antes de mostrarla. Para eso se utiliza
un MediaTracker (también debería servir para los archivos de audio, pero en esta versión aún no está
implementado).
Mediante addImage( imagen, grupo) se agrega una imagen a la lista del MediaTracker, y hay métodos para
esperar que sea cargada (como waitForAll() owaitForID(grupo)), para verificar que se haya cargado
correctamente (como checkAll(), checkID(grupo), isErrorAny()...), etcétera.
El siguiente applet utiliza estos conceptos para cargar una imagen y un archivo de audio y mostrarlos:
// Ejemplo24.java
import java.awt.*;
import java.applet.*;
public class Ejemplo24 extends Applet {
MediaTracker supervisor;
Image imagen;
AudioClip audio;
Label titulo;
Panel cuadro;
archImagen = "javacero.gif";
archAudio = "tada.au";
// carga imagen
supervisor.addImage(imagen,0);
try {
}
catch (InterruptedException e) {
showStatus("Imagen cargada");
// carga sonido
// arma layout
setLayout(new BorderLayout());
add("South", titulo);
repaint();
audio.play();
}
public void paint(Graphics g) {
if (supervisor.isErrorAny()) {
g.setColor(Color.black);
return;
g.drawImage(imagen, 0, 0, this);
<HTML>
<HEAD>
</HEAD>
<BODY>
<applet code="Ejemplo24.class" width=150 height=200>
</applet>
</BODY>
</HTML>
Parametrizando un applet
Vamos a aprovechar este ejemplo, modificándolo un poco para indicarle desde el HTML qué archivos debe cargar,
mediante parámetros. Nuestro HTML modificado será:
<HTML>
<HEAD>
<TITLE>Ejemplo 24 - Multimedia</TITLE>
</HEAD>
<BODY>
</applet>
</BODY>
</HTML>
Para leer estos parámetros desde el applet, usamos el método getParameter(nombreParámetro), así que
podemos modificar nuestro applet simplemente modificando un par de líneas:
archImagen = getParameter("imagen");
archAudio = getParameter("sonido");
De esta manera podemos pasar cualquier valor como parámetro para un applet, haciéndolo más flexible.
Con esto hemos visto una gran parte de lo que es Java. No hemos profundizado demasiado en cada punto, pero
hemos hecho ejemplos que funcionan para ilustrar cada cosa.
Sin embargo, hemos dejado un punto importante y muy fuerte de Java, que es el de las comunicaciones entre
aplicaciones y, especialmente, el uso de sockets y la programación de aplicaciones cliente-servidor.
por la Red
Es muy sencillo acceder a archivos en la red utilizando Java. El paquete java.net dispone de varias clases e
interfaces a tal efecto.
En primer lugar, la clase URL nos permite definir un recurso en la red de varias maneras, por ejemplo:
Por otra parte, podemos establecer una conexión a un URL dado mediante openConnection:
Por ejemplo:
De este modo podemos escribir un pequeño programa para, por ejemplo, leer una página HTML desde una
dirección arbitraria de internet. El programa, luego de compilarse mediante javac Ejemplo25.java, se ejecuta
con java Ejemplo25 <url>; por ejemplo: java Ejemplo25
http://www.rockar.com.ar/index.html.
import java.io.*;
import java.net.*;
String s;
try {
System.out.println("Cargando "+argv[0]);
do {
s = datos.readLine();
if (s != null) System.out.println(s);
} while (s != null);
catch (ArrayIndexOutOfBoundsException e) {
catch (UnknownHostException e) {
catch (Exception e) {
e.printStackTrace();
Este programa muestra el HTML como texto en la pantalla, pero podríamos grabarlo a un archivo para guardarlo.
Inclusive, podríamos procesarlo a medida que lo recibimos, identificar los tags <A HREF=url>, guardarlos en un
vector, y seguidamente conectarnos y bajar los links que figuran en la página original hasta bajar un site completo.
Noten que esto no sólo sirve para establecer conexiones a páginas HTML. En realidad, un URL puede referirse
también a otros protocolos, como gopher, ftp, etcétera; si bien según la implementación de Java puede haber
problemas para conectarse a algunos tipos de URL.
Para ver los tipos de URL posibles les recomiendo leer la página:
http://www.ncsa.uiuc.edu/demoweb/url-primer.html
Los Sockets
Los sockets (zócalos, referido a los enchufes de conexión de cables) son mecanismos de comunicación entre
programas a través de una red TCP/IP. De hecho, al establecer una conexión via Internet estamos utilizando
sockets: los sockets realizan la interfase entre la aplicación y el protocolo TCP/IP.
Dichos mecanismos pueden tener lugar dentro de la misma máquina o a través de una red. Se usan en forma
cliente-servidor: cuando un cliente y un servidor establecen una conexión, lo hacen a través de un socket. Java
proporciona para esto las clases ServerSocket y Socket.
Los sockets tienen asociado un port (puerto). En general, las conexiones via internet pueden establecer un puerto
particular (por ejemplo, en http://www.rockar.com.ar:80/index.html el puerto es el 80). Esto casi nunca se
especifica porque ya hay definidos puertos por defecto para distintos protocolos: 20 para ftp-data, 21 para ftp, 79
para finger, etc. Algunos servers pueden definir otros puertos, e inclusive pueden utilizarse puertos disponibles
para establecer conexiones especiales.
Justamente, una de las formas de crear un objeto de la clase URL permite especificar también el puerto:
En el servidor, creamos un objeto de la clase ServerSocket y luego esperamos algún cliente (de clase Socket)
mediante el método accept():
Desde el punto de vista del cliente, necesitamos un Socket al que le indiquemos la dirección del servidor y el
número de puerto a usar:
Una vez establecida la conexión, podemos intercambiar datos usando streams como en el ejemplo anterior. Como
la clase URLConnection, la clase Socket dispone de métodos getInputStream y getOutputStream que nos dan
respectivamente un InputStream y un OutputStream a través de los cuales transferir los datos.
Un servidor atento
Vamos a crear un servidor Ejemplo26a.java (que podemos correr en una ventana) que atenderá a un cliente de la
misma máquina (lo vamos a correr en otra ventana). Para hacerlo simple, el servidor sólo le enviará un mensaje al
cliente y éste terminará la conexión. El servidor quedará entonces disponible para otro cliente.
Es importante notar que, para que el socket funcione, los servicios TCP/IP deben estar activos (aunque ambos
programas corran en la misma máquina). Los usuarios de Windows asegúrense que haya una conexión TCP/IP
activa, ya sea a una red local o a Internet.
El servidor correrá "para siempre", así que para detenerlo presionen control-C.
// servidor
import java.io.*;
import java.net.*;
ServerSocket servidor;
Socket cliente;
int numCliente = 0;
try {
do {
numCliente++;
cliente = servidor.accept();
cliente.close();
} while (true);
catch (Exception e) {
e.printStackTrace();
Utilizamos un PrintStream para enviar los datos al cliente, ya que es sencillo de utilizar para mandar Strings. El
método PrintStream.println maneja los datos comoSystem.out.println, simplemente hay que indicarle el stream
a través del cual mandarlos al crearlo (en este caso, el OutputStream del cliente, que obtenemos
concliente.getOutputStream()).
El cliente satisfecho
Ahora vamos a crear la clase cliente, Ejemplo26b.java. El cliente simplemente establece la conexión, lee a través
de un DataInputStream (mediante el métodoreadLine()) lo que el servidor le manda, lo muestra y corta.
// cliente:
import java.io.*;
import java.net.*;
InetAddress direccion;
Socket servidor;
int numCliente = 0;
try {
DataInputStream datos =
new DataInputStream(servidor.getInputStream());
System.out.println( datos.readLine() );
servidor.close();
}
catch (Exception e) {
e.printStackTrace();
para probar esto, asegúrense que los servicios TCP/IP estén activos, corran java Ejemplo26a en una ventana y
corran varias veces java Ejemplo26b en otra. Las salidas serán más o menos así:
Ventana servidor:
C:\java\curso>java Ejemplo26a
Llega el cliente 1
Llega el cliente 2
Llega el cliente 3
Ventana cliente:
C:\java\curso>java Ejemplo26b
Usted es mi cliente 1
C:\java\curso>java Ejemplo26b
Usted es mi cliente 2
C:\java\curso>java Ejemplo26b
Usted es mi cliente 3
C:\java\curso>java Ejemplo26b
java.net.SocketException: connect
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:223)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:128)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:115)
at java.net.Socket.<init>(Socket.java:125)
at java.net.Socket.<init>(Socket.java:101)
at Ejemplo26b.main(Ejemplo26b.java:12)
El ejemplo fue lo más sencillo posible, pero mediante el mismo método el servidor y los clientes pueden
intercambiar datosescribiendo en ambas direcciones. Inclusive, el servidor puede correr en una máquina y los
clientes en otras; además, si bien en este caso utilizamos aplicaciones standalone, se pueden utilizar applets.
LENGUAJES DINÁMICOS
1.1.LENGUAJE ASP
Un archivo de páginas Active Server (ASP) es un archivo de texto con la extensión .asp que contiene
cualquier combinación de :
• Texto
• Etiquetas HTML
• Secuencias de comandos del servidor
Un método rápido para crear un archivo .asp consiste en cambiar la extensión de los archivos HTML
(.html o .htm) por la extensión .asp. Si el archivo no contiene funciones ASP, el servidor prescinde del
proceso de secuencias de comandos ASP y envía el archivo al cliente. Como desarrollador Web, esta
opción proporciona una gran flexibilidad, ya que puede asignar a los archivos la extensión .asp incluso si
no piensa agregar funciones ASP hasta más adelante.
Para publicar el archivo .asp en Web, guarde el nuevo archivo en un directorio virtual de su sitio Web
(asegúrese de que el directorio tenga los permisos Secuencia de comandos o Ejecución). A
continuación, escriba en el explorador la dirección URL del archivo para pedirlo. (Recuerde, las páginas
ASP debe enviarlas el servidor, por lo que no puede pedirlas mediante su ruta física.) Cuando el archivo
se cargue en el explorador, observará que el servidor envió una página HTML. Al principio puede
parecer extraño, pero recuerde que el servidor analiza y ejecuta todas las secuencias de comandos ASP
del servidor antes de enviar el archivo. El usuario siempre recibe código HTML estándar.
Para crear archivos .asp, se puede utilizar cualquier editor de textos. A medida que avance, puede que
encuentre más productivo utilizar un editor más orientado a ASP, como Microsoft(r) Visual InterDev™.
(Para obtener más información, visite el sitio Web de Microsoft Visual InterDev en la dirección
http://msdn.microsoft.com/vinterdev/.)
Una secuencia de comandos del servidor es una serie de instrucciones que se utiliza para enviar al
servidor Web comandos de forma secuencial. (Si ya desarrolló antes sitios Web, probablemente
conozca las secuencias de comandos del cliente, que se ejecutan en el explorador Web.) En los
archivos .asp, las secuencias de comandos se separan del texto y de las etiquetas HTML mediante
delimitadores. Un delimitador es un carácter o una secuencia de caracteres que marca el principio o el
final de una unidad. En el caso de HTML, dichos delimitadores son los símbolos menor que (<) y mayor
que (>), que enmarcan las etiquetas HTML.
ASP utiliza los delimitadores <% y %> para enmarcar los comandos. Dentro de los delimitadores puede
incluir cualquier comando válido dentro del lenguaje de secuencia de comandos que esté utilizando. El
ejemplo siguiente muestra una página HTML sencilla que contiene un comando de secuencia de
comandos:
<HTML>
<BODY>
Esta página se actualizó por última vez el <%= Now ()%>.
</BODY>
</HTML>
La función Now() de VBScript devuelve la fecha y la hora actuales. Cuando el servidor Web procesa
esta página, reemplaza <%= Now ()%> con la fecha y la hora actuales, y devuelve la página al
explorador con el siguiente resultado:
Esta página se actualizó el 1/29/99 2:20:00 p.m.
A los comandos enmarcados por delimitadores se les llama comandos principales de secuencias de
comandos, que se procesan mediante el lenguaje principal de secuencia de comandos. Todos los
comandos utilizados dentro de los delimitadores de secuencias de comandos deben ser válidos en el
lenguaje principal de secuencia de comandos. De forma predeterminada, el lenguaje principal de
secuencia de comandos es VBScript, pero también puede establecer un lenguaje diferente. Consulte
Trabajar con lenguajes de secuencias de comandos.
Si ya conoce las secuencias de comandos del cliente, ya sabrá que la etiqueta HTML <SCRIPT> se
utiliza para delimitar las secuencias de comandos y las expresiones. También puede utilizar la etiqueta
<SCRIPT> para las secuencias de comandos del cliente, siempre que necesite definir procedimientos en
múltiples lenguajes en un archivo .asp. Para obtener más información, consulte Trabajar con lenguajes
de secuencias de comandos.
Si la condición es verdadera, es decir, si es antes del mediodía, el servidor Web envía al explorador el
código HTML que sigue a la condición (“Buenos días”); de lo contrario, envía el código HTML que sigue
a Else (“Hola”). Esta forma de combinar HTML y comandos de secuencia de comandos es cómoda para
continuar la instrucción If...Then...Else en varias líneas de texto HTML. El ejemplo anterior es más útil si
desea presentar un saludo en varias partes de una página Web. Puede asignar el valor de la variable
una única vez y después presentarla varias veces.
En lugar de mezclar texto HTML con comandos de secuencia de comandos, puede devolver texto HTML
al explorador desde dentro de los comandos de secuencia de comandos. Para devolver texto al
explorador, utilice el objeto integrado Response de ASP. El ejemplo siguiente produce el mismo
resultado que las secuencias de comandos anteriores:
<%
Dim dtmHour
dtmHour = Hour(Now())
If dtmHour < 12 Then
Response.Write "Buenos días"
Else
Response.Write "Hola"
End If
%>
Response.Write envía al explorador el texto que le sigue. Utilice Response.Write desde una
instrucción cuando desee generar de forma dinámica el texto devuelto al explorador. Por ejemplo, puede
generar una cadena de texto que contenga los valores de varias variables. Aprenderá más acerca del
objeto Response, y de los objetos en general, en Utilizar componentes y objetos y Enviar contenido al
explorador. Por ahora, observe simplemente que dispone de varias maneras de insertar comandos de
secuencias de comandos en las páginas HTML.
Puede incluir procedimientos escritos en su lenguaje predeterminado de secuencias de comandos
dentro de delimitadores ASP. Para obtener más información, consulte Trabajar con lenguajes de
secuencias de comandos.
Si va a trabajar con comandos JScript, puede insertar las llaves que indican un bloque de instrucciones
directamente en sus comandos ASP, incluso aunque estén entremezclados con etiquetas y texto HTML.
Por ejemplo:
<%
if (screenresolution == "low")
{
%>
Ésta es la versión de texto de la página.
<%
}
else
{
%>
Ésta es la versión multimedia de la página.
<%
}
%>
-O bien-
<%
if (screenresolution == "low")
{
Response.Write("Ésta es la versión de texto de la página.")
}
else
{
Response.Write("Ésta es la versión multimedia de la página.")
}
%>
ASP proporciona directivas que no forman parte de los lenguajes de secuencias de comandos: Dichas
directivas son la directiva de resultado y la directiva de proceso.
La directiva de resultado de ASP <%= expresión %> presenta el valor de una expresión. Dicha directiva
es equivalente al uso de Response.Write para presentar información. Por ejemplo, la expresión <%=
ciudad %> envía al explorador la palabra Barcelona (el valor actual de la variable).
La directiva de proceso de ASP <%@ palabra clave %> ofrece a ASP la información que necesita para
procesar un archivo .asp. Por ejemplo, la siguiente directiva establece VBScript como lenguaje principal
de secuencia de comandos de la página:
VBScript
VBScript no necesita declaraciones de variables, pero es conveniente declarar todas las variables antes
de utilizarlas. Para declarar una variable en VBScript, utilice la instrucción Dim, Public o Private. Por
ejemplo:
<% Dim NombreUsuario %>
Puede utilizar la instrucción Option Explicit de VBScript en los archivos .asp para hacer obligatoria la
declaración de variables con las instrucciones Dim, Private, Public y ReDim. La instrucción Option
Explicit debe aparecer después de las directivas ASP y antes del texto HTML o de los comandos de la
secuencia de comandos. Esta instrucción sólo afecta a los comandos ASP escritos en VBScript; no
afecta a los comandos escritos en JScript.
<% Option Explicit %>
<HTML>
<%
Dim strNombreUsuario
Public lngNumeroCuenta
%>
El alcance, o vida, de una variable determina qué comandos de secuencia de comandos pueden tener
acceso a dicha variable. Una variable declarada dentro de un procedimiento tiene alcance local; la
variable se crea y se destruye cada vez que se ejecuta el procedimiento. No se puede tener acceso a
ella desde fuera del procedimiento. Una variable declarada fuera de un procedimiento tiene alcance
global; su valor es accesible y modificable desde cualquier comando de secuencia de comandos de una
página ASP.
Nota Al limitar el alcance de la variable a un procedimiento mejorará el rendimiento.
Si declara variables, una variable local y una variable global pueden tener el mismo nombre. La
modificación del valor de una de ellas no afecta al valor de la otra. Sin embargo, si no declara las
variables, podría modificar inadvertidamente el valor de una variable global. Por ejemplo, los siguientes
comandos de secuencia de comandos devuelven el valor 1 incluso aunque haya dos variables llamadas
Y:
<%
Option Explicit
Dim Y
Y=1
SetLocalVariable
Response.Write Y
Sub SetLocalVariable
Dim Y
Y=2
End Sub
%>
Por el contrario, los comandos siguientes devuelven el valor 2 porque las variables no se han declarado
de forma explícita. Cuando la llamada al procedimiento asigna a Y el valor 2, el motor de secuencias de
comandos da por supuesto que el procedimiento pretende modificar la variable global:
<%
Option Explicit
Dim Y = 1
SetLocalVariable
Response.Write Y
Sub SetLocalVariable
Y=2
End Sub
%>
Para evitar problemas, adquiera el hábito de declarar explícitamente todas las variables. Lo cual es
especialmente importante si utiliza la instrucción #include para incluir archivos en su archivo ASP. La
secuencia de comandos incluida está contenida en un archivo aparte, pero se trata como si formara
parte del archivo contenedor. Es muy fácil olvidarse de que hay que utilizar nombres de variables
diferentes en la secuencia de comandos principal y en la secuencia de comandos incluida, a menos que
declare las variables.
Para recuperar la información del objeto Session, tenga acceso a la entrada con nombre mediante la
directiva de resultado (<%=) o Response.Write. En el ejemplo siguiente se utiliza la directiva de
resultado para presentar el valor actual de Session("Nombre"):
Reciba nuestra bienvenida,<%= Session("Nombre") %>
Puede almacenar las preferencias del usuario en el objeto Session y después tener acceso a dichas
preferencias para determinar qué página hay que devolver al usuario. Por ejemplo, puede permitir que
los usuarios especifiquen la versión en texto del contenido de la primera página de la aplicación y aplicar
esta opción a las siguientes páginas de la aplicación que el usuario visite.
<%
strScreenResolution = Session("ScreenResolution")
If strScreenResolution = "Low" Then
%>
Ésta es la versión de texto de la página.
<% Else %>
Ésta es la versión multimedia de la página.
<%End If %>
Nota Si hace referencia a una variable con alcance de sesión más de una vez en una secuencia de
comandos, piense en asignarle una variable local, como en el ejemplo anterior, para mejorar el
rendimiento.
Alcance de aplicación
Para asignar alcance de aplicación a una variable, almacénela en el objeto Application asignando un
valor a una entrada con nombre del objeto. Por ejemplo, el comando siguiente almacena en el objeto
Application un saludo específico de una aplicación:
<% Application("Saludo") = "¡Reciba nuestra bienvenida al Departamento de ventas!" %>
Para recuperar la información del objeto Application, utilice la directiva de resultado de ASP (<%=) o
Response.Write para tener acceso a la entrada con nombre desde cualquier página posterior de la aplicación. En el
ejemplo siguiente se utiliza la directiva de resultado para presentar el valor de
Application("Saludo"):
<%= Application("Saludo") %> De nuevo, si hace referencia a una variable con alcance de aplicación en su
secuencia de comandos
repetidamente, debe de asignarle una variable local para mejorar el rendimiento.
Utilizar constantes
Una constante es un nombre que representa un número o una cadena. Algunos de los componentes de
base que se proporcionan con ASP, como ActiveX Data Objects (ADO), definen constantes que se
pueden utilizar en las secuencias de comandos. Un componente puede declarar constantes en la
biblioteca de tipos del componente, un archivo que contiene información acerca de los objetos y los tipos
aceptados por un componente COM. Después de haber declarado una biblioteca de tipos en su archivo
.asp puede usar las constantes definidas en cualquier secuencia de comandos en el mismo archivo .asp.
Igualmente, puede declarar una biblioteca de tipos en el archivo Global.asa para usar las constantes
definidas en cualquier archivo .asp de la aplicación.
Para declarar una biblioteca de tipos, utilice la etiqueta <METADATA> en su archivo .asp o Global.asa.
Por ejemplo, para declarar la biblioteca de tipos de ADO, utilice las siguientes instrucciones:
<!--METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library" TYPE="TypeLib"
UUID="{00000205-0000-0010-8000-00AA006D2EA4}"-->
O bien, en lugar de hacer referencia al identificador único universal (UUID) de la biblioteca de tipos,
puede hacer referencia a la biblioteca de tipos mediante la ruta del archivo:
<!-- METADATA TYPE="typelib" FILE="c:\program files\common files\system\ado\msado15.dll"-->
Entonces puede usar las constantes ADO en el archivo .asp donde declaró la biblioteca de tipos o en un
archivo que reside en una aplicación que contiene un archivo Global.asa con la declaración de biblioteca
de tipos ADO. En el ejemplo siguiente, adOpenKeyset y adLockOptimistic son constantes ADO:
<%
'Crea y abre el objeto Recordset.
Set rsCustomersList = Server.CreateObject("ADODB.Recordset")
rstCustomerList.ActiveConnection = cnnPubs
rstCustomerList.CursorType = adOpenKeyset
rstCustomerList.LockType = adLockOptimistic
%>
En la siguiente tabla se enumeran las bibliotecas de tipos y los identificadores UUID que se utilizan con
más frecuencia:
Es posible aumentar la eficacia de ASP si se utiliza para generar o manipular secuencias de comandos
del cliente. Por ejemplo, puede escribir secuencias de comandos del servidor que construyan
secuencias de comandos del cliente basadas en variables específicas del servidor, el tipo del explorador
o los parámetros de la petición HTTP.
Si intercala instrucciones de secuencias de comandos del servidor en las secuencias de comandos del
cliente (delimitadas mediante etiquetas HTML <SCRIPT>), como se muestra en la plantilla del ejemplo
siguiente, puede inicializar de forma dinámica y alterar las secuencias de comandos del cliente en el
momento de realizar la petición:
<SCRIPT LANGUAGE="VBScript">
<!--
variable = <%=valor definido por el servidor %>
.
.
.
secuencia de comandos del cliente
<% secuencia de comandos del servidor que se utiliza para generar una instrucción del cliente %>
secuencia de comandos del cliente
.
.
.
-->
</SCRIPT>
Al incorporar estas funciones es posible crear algunas aplicaciones útiles e interesantes. Por ejemplo,
ésta es una sencilla secuencia de comandos del servidor (escrita en VBScript) que manipula una
secuencia de comandos del cliente (escrita en JScript):
<%
Dim dtmTime, strServerName, strServerSoftware, intGreeting
dtmTime = Time()
strServerName = Request.ServerVariables("SERVER_NAME")
strServerSoftware = Request.ServerVariables("SERVER_SOFTWARE")
'Genera un número aleatorio.
Randomize
GreetCondition = int(rnd * 3)
%>
<SCRIPT LANGUAGE="JScript">
<!--
//Llama a la función para mostrar el saludo
showIntroMsg()
function showIntroMsg()
{
switch(<%= intGreeting %>)
{
case 0:
msg = "Este es el servidor Web <%= strServerName%> con <%= strServerSoftware %>."
break
case 1:
msg = "Reciba nuestra bienvenida al servidor Web <%= strServerName%>. La hora local es <%=
dtmTime %>."
break
case 2:
msg = "Este servidor utiliza <%= strServerSoftware %>."
break
}
document.write(msg)
}
-->
</SCRIPT>
Escribir procedimientos
Un procedimiento es un grupo de comandos de secuencia de comandos que realizan una tarea
específica y puede devolver un valor. Puede definir sus propios procedimientos e invocarlos
repetidamente desde sus secuencias de comandos.
Puede poner las definiciones de los procedimientos en el mismo archivo .asp que llama a los
procedimientos o bien puede poner los procedimientos utilizados con más frecuencia en un archivo .asp
compartido y utilizar la directiva #include para incluirlo en otros archivos .asp que llamen a los
procedimientos. Como alternativa, puede encapsular dicha funcionalidad en un componente COM.
Definir procedimientos
Las definiciones de los procedimientos pueden encontrarse dentro de etiquetas <SCRIPT> y </SCRIPT>
y deben seguir las reglas del lenguaje de secuencias de comandos. Utilice el elemento <SCRIPT> para
los procedimientos escritos en lenguajes distintos del lenguaje principal para secuencias de comandos.
Sin embargo, utilice los delimitadores de las secuencias de comandos (<% y %>) en los procedimientos
escritos en el lenguaje principal de secuencias de comandos.
Cuando utilice la etiqueta HTML <SCRIPT>, debe emplear dos atributos para asegurar el proceso de la
secuencia de comandos por parte del servidor. La sintaxis de la etiqueta <SCRIPT> es la siguiente:
<SCRIPT LANGUAGE=JScript RUNAT=SERVER>
definición del procedimiento
</SCRIPT>
El atributo RUNAT=SERVER indica al servidor Web que procese la secuencia de comandos en el
servidor. Si no establece este atributo, la secuencia de comandos la procesará el explorador del cliente.
El atributo LANGUAGE determina el lenguaje de secuencia de comandos utilizado en este bloque.
Puede especificar cualquier lenguaje para el que haya instalado un motor de secuencias de comandos
en el servidor. Para especificar VBScript, use el valor VBScript. Para especificar JScript, use el valor
JScript. Si no asigna el atributo LANGUAGE, el bloque de la secuencia de comandos se interpretará en
el lenguaje principal de secuencia de comandos.
Los comandos del bloque de la secuencia de comandos deben componer uno o varios procedimientos
completos en el lenguaje de secuencia de comandos elegido. Por ejemplo, los comandos siguientes
definen el procedimiento JScript MiFuncion.
<HTML>
<SCRIPT LANGUAGE=JScript RUNAT=SERVER >
function MiFuncion()
{
Response.Write("Llamó a MiFuncion().")
}
</SCRIPT>
Importante No incluya en las etiquetas <SCRIPT> del servidor comandos de secuencias de comandos
que no formen parte de procedimientos completos. Los comandos que no formen parte de un
procedimiento pueden provocar resultados impredecibles puesto que deben ejecutarse en un orden
determinado. Además, no puede utilizar la directiva de resultado de ASP <%=%> dentro de los
procedimientos. En su lugar, utilice Response.Write para enviar contenido al explorador.
Llamar a procedimientos
Para llamar a procedimientos, incluya el nombre de los procedimientos en un comando. Si va a llamar a
procedimientos JScript desde VBScript, debe utilizar paréntesis después del nombre del procedimiento;
si el procedimiento no tiene argumentos, utilice paréntesis vacíos. Si va a llamar a procedimientos
VBScript o JScript desde JScript, utilice siempre paréntesis después del nombre del procedimiento.
En VBScript también puede utilizar la palabra clave Call para llamar a un procedimiento. Sin embargo, si
el procedimiento al que llama requiere argumentos, la lista de argumentos debe aparecer entre
paréntesis. Si omite la palabra clave Call, también debe omitir los paréntesis en los que se incluye la
lista de argumentos. Si utiliza la sintaxis Call para llamar a una función integrada o definida por el
usuario, se descartará el valor devuelto por la función.
El ejemplo siguiente ilustra la creación y la llamada a procedimientos en dos lenguajes para secuencias
de comandos diferentes (VBScript y JScript).
<%@ LANGUAGE=VBScript %>
<HTML>
<BODY>
<% Echo %>
<BR>
<% printDate() %>
</BODY>
</HTML>
<%
Sub Echo
Response.Write "<TABLE>" & _
"Response.Write "<TR><TH>Nombre</TH><TH>Valor</TH></TR>"
Set objQueryString = Request.QueryString
For Each strSelection In objQueryString
Response.Write "<TR><TD>" & p & "</TD><TD>" & _
FormValues(strSelection) & "</TD></TR>"
Next
Response.Write "</TABLE>"
End Sub
%>
<SCRIPT LANGUAGE=JScript RUNAT=SERVER>
function PrintDate()
{
var x
x = new Date()
Response.Write(x.toString())
}
</SCRIPT>
Nota Las llamadas de VBScript a las funciones JScript no distinguen entre mayúsculas y minúsculas.
Pasar matrices a procedimientos
Para pasar una matriz entera a un procedimiento en VBScript, utilice el nombre de la matriz seguido de
paréntesis vacíos; en JScript, utilice corchetes vacíos.
Los formularios HTML, el método más común para recopilar información desde el Web, consiste en un
conjunto de etiquetas HTML especiales que presentan elementos de interfaz de usuario en una página
Web. Los cuadros de texto, los botones y las casillas de verificación son ejemplos de elementos que
permiten que los usuarios intercalen con una página Web y envíen información a un servidor Web.
Por ejemplo, las siguientes etiquetas HTML generan un formulario en el que un usuario puede escribir su
nombre, apellido y edad, e incluye un botón para enviar la información a un servidor Web. El formulario
también contiene una etiqueta de entrada oculta (no presentada por el explorador Web) que puede
utilizar para pasar información adicional al servidor Web.
<FORM METHOD="Post" ACTION="Profile.asp">
<INPUT TYPE="text" NAME="Nombre">
<INPUT TYPE="text" NAME="Apellido">
<INPUT TYPE="text" NAME="Edad">
<INPUT TYPE="Hidden" NAME="EstadoUsuario" VALUE="Nuevo">
<INPUT TYPE="Submit" VALUE="Entrar">
</FORM>
Presentar con detalle el conjunto completo de etiquetas HTML para formularios se sale del ámbito de
este tema, sin embargo, hay numerosas fuentes de información que puede utilizar para aprender a crear
y utilizar formularios HTML. Por ejemplo, puede utilizar la posibilidad que ofrece su explorador para ver
el código fuente con el fin de examinar cómo se crean los formularios HTML en otros sitios Web.
También puede visitar el sitio Web de MSDN de Microsoft en la dirección http://msdn.microsoft.com/
para conocer las técnicas más recientes para utilizar los formularios HTML con otras tecnologías de
Internet.
Procesar datos de formularios con ASP
Después de crear el formulario HTML tendrá que procesar los datos proporcionados por el usuario, lo
que implica enviar la información a un archivo .asp para que la analice y manipule. De nuevo, examine el
código HTML del ejemplo anterior. Observe que el atributo ACTION de la etiqueta <FORM> hace
referencia a un archivo llamado Profile.asp. Cuando el usuario envía información HMTL, el explorador
utiliza el método POST para enviarla a un archivo .asp del servidor, en este caso Profile.asp. Este
archivo .asp puede contener archivos de comandos que procesen la información e interactúen con otras
secuencias de comandos, componentes COM o recursos, como una base de datos.
Existen tres formas básicas de recopilar información de un formulario HTML mediante ASP:
• Un archivo .htm estático puede contener un formulario que envíe sus valores a un archivo .asp.
• Un archivo .asp puede crear un formulario que envíe información a otro archivo .asp.
• Un archivo .asp puede crear un formulario que se envíe información a sí mismo; es decir, al
archivo .asp que contiene el formulario.
Los dos primeros métodos funcionan igual que los formularios que interactúan con otros programas de
servidor Web, con la única diferencia de que con ASP se simplifica mucho la tarea de recuperar y
procesar la información. El tercer método es especialmente útil y se muestra en la sección Validar los
datos de los formularios.
La colección QueryString
La colección QueryString recupera los valores del formulario pasados al servidor Web como texto a
continuación del signo de interrogación de la dirección URL de la petición. Los valores del formulario se
pueden anexar a la dirección URL de la petición mediante el método GET de HTTP o, manualmente, si
se agregan los valores del formulario a la dirección URL.
Si el ejemplo del formulario anterior utilizara el método GET (METHOD = "GET") y el usuario escribiera
Juan, Soto y 30, se enviaría la siguiente petición URL al servidor:
http://Workshop1/Painting/Profile.asp?Nombre=Juan&Apellido=Soto&Edad=30&EstadoUsuario=Nuevo
El archivo Profile.asp podría contener la siguiente secuencia de comandos para procesar formularios:
Hola, <%= Request.QueryString("nombre") %> <%= Request.QueryString("apellido") %>.
Tiene <%= Request.QueryString("edad") %> años.
<%
If Request.QueryString("EstadoUsuario") = "Nuevo" Then
Response.Write"Ésta es su primera visita a este sitio Web"
End if
%>
En este caso, el servidor Web devolvería el texto siguiente al explorador Web del usuario:
Hola Juan Soto. Tiene 30 años. Ésta es su primera visita a este sitio Web
La colección QueryString también tiene un parámetro opcional que puede utilizar para tener acceso a
uno de los múltiples valores que se encuentran en el cuerpo de la petición URL (con el método GET).
También puede utilizar la propiedad Count para contar el número de veces que aparece un determinado
tipo de valor.
Por ejemplo, un formulario que contenga un cuadro de lista con varios elementos puede generar la
siguiente petición:
http://OrganicFoods/list.asp?Comida=Manzanas&Comida=Aceitunas&Comida=Pan
Podría utilizar el siguiente comando para contar los diferentes valores:
Request.QueryString("Comida").Count
Para presentar los tipos de valores, Lista.asp podría contener la secuencia de comandos siguiente:
<%
lngTotal = Request.QueryString("Comida").Count
For i = 1 To lngTotal
Response.Write Request.QueryString("Comida")(i) & "<BR>"
Next
%>
La secuencia de comandos anterior mostraría:
Manzanas
Aceitunas
Pan
También puede mostrar la lista completa de valores como una cadena delimitada por comas, del modo
siguiente:
<% Response.Write Request.QueryString("Item") %>
Aparecería la cadena siguiente:
Manzanas, Aceitunas, Pan
Colección Form
Cuando utiliza el método GET de HTTP para pasar a un servidor Web valores de un formulario grande y
complejo, corre el riesgo de perder información. Algunos servidores Web tienden a restringir el tamaño
de la cadena de petición de URL, por lo que los valores de los formularios grandes pasados con el
método GET podrían quedar truncados. Si necesita enviar una gran cantidad de información desde un
formulario a un servidor Web, debe utilizar el método POST de HTTP. El método POST, que envía los
datos de los formularios en el cuerpo de la petición HTTP, puede enviar un número casi ilimitado de
caracteres a un servidor. Puede utilizar la colección Form del objeto Request de ASP para recuperar los
valores enviados mediante el método POST.
La colección Form almacena valores de manera similar a la colección QueryString. Por ejemplo, si un
usuario completa un formulario escribiendo una larga lista de nombres, se podrían leer los nombres con
la secuencia de comandos siguiente:
<%
lngTotal = Request.Form("Comida").Count
For i = 1 To lngTotal
Response.Write Request.Form("Comida")(i) & "<BR>"
Next
%>
Un formulario Web bien diseñado suele incluir una secuencia de comandos del cliente que valida los
datos proporcionados por el usuario antes de enviar la información al servidor. Las secuencias de
comandos de validación pueden comprobar si el usuario escribió un número válido o si un cuadro de
texto está en blanco. Imagine que su sitio Web incluye un formulario que permite calcular la tasa de
retorno de una inversión. Probablemente querrá comprobar si un usuario realmente escribió texto o
números en los campos apropiados del formulario, antes de enviar al servidor información que podría no
ser válida.
En general, lo mejor es realizar en el cliente tantas comprobaciones como sea posible. Además, de
poder preguntar antes al usuario por los errores, la validación en el cliente mejora el tiempo de
respuesta, reduce la carga del servidor y libera ancho de banda para otras aplicaciones.
La siguiente secuencia de comandos del cliente valida los datos escritos por el usuario (en este caso, la
secuencia de comandos determina si el número de cuenta que escribió el usuario es realmente un
número) antes de enviarlos al servidor:
<SCRIPT LANGUAGE="JScript">
function ComprobarNumero()
{
if (isNumeric(document.UserForm.AcctNo.value))
return true
else
{
alert("Escriba un número de cuenta válido.")
return false
}
}
//Función para determinar si el valor del formulario es un número.
//Nota: El método isNaN JScript es un método más elegante para determinar si
//un valor no es un número. Sin embargo, algunos exploradores no admiten este método.
function isNumeric(str)
{
for (var i=0; i < str.length; i++)
{
var ch = str.substring(i, i+1)
if( ch < "0" || ch>"9" || str.length == null)
{
return false
}
}
return true
}
</SCRIPT>
<FORM METHOD="Get" ACTION="balance.asp" NAME="FormularioUsuario" ONSUBMIT="return
CheckNumber()">
<INPUT TYPE="Text" NAME="NumCuen">
<INPUT TYPE="Submit" VALUE="Enviar">
</FORM>
Sin embargo, si la validación de un formulario requiere el acceso a una base de datos debe considerar la
utilización de la validación del formulario en el servidor. Una forma muy útil de realizar la validación en el
servidor es crear formularios que se envíen la información a sí mismos. Es decir, el archivo .asp contiene
en realidad el formulario HTML que recibe los datos del usuario. (Recuerde, puede utilizar ASP para
interactuar con secuencias de comandos del cliente y código HTML. Para obtener más información,
consulte Interactuar con secuencias de comandos del cliente.) Los datos escritos vuelven al mismo
archivo, que se encarga de validar la información y avisa al usuario si éstos no son correctos.
Mediante este método se pueden mejorar las características de uso y la respuesta de los formularios
basados en Web. Por ejemplo, si se incluye información del error junto al campo del formulario en el que
se escribió la información incorrecta, será más fácil para el usuario descubrir el origen del error.
(Normalmente, los formularios basados en Web reenvían las peticiones a una página Web
independiente que contiene información del error. Los usuarios que no comprendan esta información
podrían sentirse frustrados.)
Por ejemplo, la secuencia de comandos siguiente determina si un usuario escribió un número de cuenta
válido, para lo que se envía la información a sí misma (Verify.asp) y llama a una función definida por el
usuario que realiza una consulta a una base de datos:
<%
strAcct = Request.Form("Cuenta")
If Not AccountValid(strAcct) Then
ErrMsg = "<FONT COLOR=Red>El número de cuenta que ha escrito no es válido.</FONT>"
Else
Procesa los datos del usuario
.
.
.
Server.Transfer("Complete.asp")
End If
Function AccountValid(strAcct)
Aquí se incluirá una secuencia de comandos o una llamada a un método de un componente de
conexión con una base de datos.
End Function
%>
<FORM METHOD="Post" ACTION="Verify.asp">
Número de cuenta: <INPUT TYPE="Text" NAME="Cuenta"> <%= ErrMsg %> <BR>
<INPUT TYPE="Submit">
</FORM>
En este ejemplo, la secuencia de comandos se encuentra en un archivo llamado Verify.asp, el mismo
archivo que contiene el formulario HTML y, para enviarse la información a sí mismo, especifica
Verify.asp en el atributo ACTION.
ActiveX Data Objects (ADO) es una tecnología ampliable y de fácil uso para agregar a sus páginas Web
acceso a bases de datos. Puede utilizar ADO para escribir secuencias de comandos compactas y
escalables que le permitan conectarse a orígenes de datos compatibles con OLE DB, como bases de
datos, hojas de cálculo, archivos de datos secuenciales o directorios de correo electrónico. OLE DB es
una interfaz de programación de nivel de sistema que proporciona un conjunto estándar de interfaces
COM para que permitan exponer las funciones del sistema de administración de bases de datos. Con el
modelo de objetos ADO es fácil tener acceso a estas interfaces (mediante lenguajes de secuencias de
comandos, como VBScript o JScript) para agregar funciones de bases de datos a las aplicaciones Web.
Además, también puede utilizar ADO para tener acceso a bases de datos compatibles con la
Conectividad abierta de bases de datos (ODBC, Open Database Connectivity).
Si no tiene mucha experiencia en conectividad con bases de datos, encontrará que la sintaxis de ADO
es sencilla y fácil de utilizar. Si es un programador experimentado, agradecerá el acceso escalable de
alto rendimiento que proporciona ADO para una gran variedad de orígenes de datos.
El primer paso en la creación de una aplicación de datos en Web consiste en proporcionar un método
para que ADO encuentre e identifique el origen de datos. Para ello se utiliza una cadena de conexión,
una serie de argumentos separados mediante un punto y coma que definen parámetros como el
proveedor del origen de datos y la ubicación del mismo. ADO utiliza la cadena de conexión para
identificar el proveedor OLE DB y para dirigir al proveedor al origen de datos. El proveedor es un
componente que representa el origen de datos y que expone la información en la aplicación en forma de
conjuntos de filas.
En la tabla siguiente se enumeran las cadenas de conexión de OLE DB para varios orígenes de datos
habituales:
Para recuperar datos, examinar resultados y modificar su base de datos, ADO proporciona el objeto
Recordset. El objeto Recordset tiene las funciones necesarias para, dependiendo de las restricciones de
las consultas, recuperar y presentar un conjunto de filas, o registros, de una base de datos. El objeto
Recordset mantiene la posición de cada registro devuelto por la consulta, lo que permite recorrer los
resultados de uno en uno.
Recuperar un conjunto de registros
Las buenas aplicaciones de datos Web emplean el objeto Connection para establecer un vínculo, y el
objeto Recordset para manipular los datos devueltos. Al combinar las funciones especializadas de
ambos objetos puede desarrollar aplicaciones de bases de datos que realicen casi cualquier tarea de
tratamiento de datos. Por ejemplo, la siguiente secuencia de comandos del servidor utiliza el objeto
Recordset para ejecutar un comando SELECT de SQL. El comando SELECT recupera un conjunto
específico de información basándose en las restricciones de la consulta. La consulta también contiene
una cláusula WHERE de SQL, que se utiliza para establecer el criterio de selección de la consulta. En
este ejemplo, la cláusula WHERE limita la consulta a todos los registros que contengan el apellido Soto
en la tabla Customers de la base de datos.
<%
'Establece una conexión con un origen de datos.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Datos\Empleados.mdb"
Set cn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'Crea una instancia de un objeto Recordset.
Set rsCustomers = Server.CreateObject("ADODB.Recordset")
'Abre un objeto Recordset con el método Open
'y utiliza la conexión establecida por el objeto Connection.
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Soto' "
rstCustomers.Open strSQL, cnn
'Recorre el conjunto de los registros y presenta los resultados
'e incrementa la posición del registro con el método MoveNext.
Set objFirstName = rstCustomers("Nombre")
Set objLastName = rstCustomers("Apellido")
Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop
%>
Observe que en el ejemplo anterior, el objeto Connection estableció la conexión con la base de datos y
que el objeto Recordset utilizó la misma conexión para recuperar resultados de la base de datos. Este
método es útil cuando tenga que configurar con precisión la forma en que se establece el vínculo con la
base de datos. Por ejemplo, si necesitara especificar el tiempo de espera antes de anular un intento de
conexión, tendría que utilizar el objeto Connection para establecer dicha propiedad. Sin embargo, si sólo
desea establecer una conexión con las propiedades de conexión predeterminadas de ADO, podría
utilizar el método Open del objeto Recordset para establecer el vínculo:
<%
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Datos\Empleados.mdb"
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Soto' "
Set rsCustomers = Server.CreateObject("ADODB.Recordset")
'Abre una conexión con el método Open
'y utiliza la conexión establecida por el objeto Connection.
rstCustomers.Open strSQL, strConnectionString
'Recorre el conjunto de registros, presenta los resultados
'e incrementa la posición del registro con el método MoveNext.
Set objFirstName = rstCustomers("Nombre")
Set objLastName = rstCustomers("Apellido")
Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop
%>
Cuando establece una conexión con el método Open del objeto Recordset, está utilizando
implícitamente el objeto Connection para proteger el vínculo. Para obtener más información, consulte la
documentación acerca de Microsoft ActiveX Data Objects (ADO), disponible en el sitio Web de Microsoft
Universal Data Access en la dirección http://www.microsoft.com/data/.
Nota Para mejorar de forma significativa el rendimiento de las aplicaciones ASP de base de datos,
piense en la posibilidad de cambiar el estado del conjunto de registros a Application. Para obtener más
información, consulte Guardar datos en la memoria caché.
A menudo resulta útil contar el número de registros que se devuelven en un conjunto de registros. El
método Open del objeto Recordset permite especificar un parámetro opcional, cursor, que determina
cómo recupera y recorre el conjunto de registros el proveedor subyacente. Al agregar el parámetro de
cursor adOpenKeyset a la instrucción que se utiliza para ejecutar la consulta, permite que la aplicación
cliente recorra todo el conjunto de registros. Como resultado, la aplicación puede utilizar la propiedad
RecordCount para calcular con precisión el número de registros del conjunto. Vea el siguiente ejemplo:
<%
Set rsCustomers = Server.CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM NewOrders", "Provider=Microsoft.Jet.OLEDB.3.51;Data
Source='C:\PedidosClientes\Pedidos.mdb'", adOpenKeyset, adLockOptimistic, adCmdText
'Utiliza la propiedad RecordCount del objeto Recordset para realizar la cuenta.
If rs.RecordCount >= 5 then
Response.Write "Recibimos estos " & rs.RecordCount & " nuevos pedidos<BR>"
Do Until rs.EOF
Response.Write rs("NombreCliente") & " " & rs("ApellidoCliente") & "<BR>"
Response.Write rs("NumeroCuenta") & "<BR>"
Response.Write rs("Cantidad") & "<BR>"
Response.Write rs("FechaEntrega") & "<BR><BR>"
rs.MoveNext
Loop
Else
Response.Write "Hay menos de " & rs.RecordCount & " nuevos pedidos."
End If
rs.Close
%>
Las páginas Web que contienen formularios HTML pueden permitir que los usuarios consulten de forma
remota una base de datos y recuperen información concreta. Con ADO puede crear secuencias de
comandos sorprendentemente sencillas que recopilen información del formulario del usuario, creen una
consulta personalizada para la base de datos y devuelvan información al usuario. Mediante el objeto
Request de ASP puede recuperar la información escrita en los formularios HTML e incorporar dicha
información a sus instrucciones SQL. Por ejemplo, el siguiente bloque de secuencia de comandos
inserta en una tabla la información suministrada por un formulario HTML. La secuencia de comandos
recopila información del usuario con la colección Form del objeto Request.
<%
'Abre una conexión mediante el objeto Connection. El objeto Command
'no tiene un método Open para establecer la conexión.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Catálogo\Semillas.mdb"
Set cn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'Crea una instancia del objeto Command
'y utiliza la propiedad ActiveConnection para adjuntar
'la conexión al objeto Command.
Set cm= Server.CreateObject("ADODB.Command")
Set cmn.ActiveConnection = cnn
'Define la consulta SQL.
cmn.CommandText = "INSERT INTO MySeedsTable (Type) VALUES (?)"
'Define la información de configuración de los parámetros de la consulta.
cmn.Parameters.Append cmn.CreateParameter("type",adVarChar, ,255)
'Asigna el valor de la entrada y ejecuta la actualización.
cmn("type") = Request.Form("SeedType")
cmn.Execute ,,adCmdText + adExecuteNoRecords
%>
Para obtener más información acerca de los formularios y el uso del objeto Request de ASP, consulte
Procesar los datos introducidos por el usuario.
Server.Transfer envía peticiones desde un archivo .asp en ejecución a otro archivo. Durante la
transferencia, el archivo .asp que se pidió inicialmente finaliza inmediatamente la ejecución sin vaciar el
búfer de salir (para obtener más información, consulte la sección Almacenamiento en búfer del
contenido). La petición de información se pone a disposición del archivo de destino cuando éste
comienza la ejecución. Durante la ejecución, el archivo tiene acceso al mismo conjunto de objetos
intrínsecos (Request, Response, Server, Session y Application) que el archivo que se pidió
inicialmente.
También se puede utilizar Server.Transfer para realizar una transferencia entre archivos .asp que se
encuentren en diferentes aplicaciones. Sin embargo, al hacerlo el archivo se comportará como si
formara parte de la aplicación que inició la transferencia (es decir, el archivo sólo tendrá acceso a las
variables con alcance en la aplicación inicial, no en la aplicación en la que realmente reside el archivo).
Por ejemplo, si realiza una transferencia desde un archivo que se encuentra en la aplicación Ventas a
otro que se encuentra en Personal, la aplicación Ventas tomará prestado el archivo de la aplicación
Personal y lo ejecutará como si fuera parte de ella.
ASP proporciona también el comando Server.Execute que permite transferir un archivo, ejecutar el
contenido y volver al archivo que inició la transferencia. Si tiene conocimientos de VBScript, le ayudará
pensar en Server.Execute como análogo a una llamada a un procedimiento, con la diferencia de que en
lugar de ejecutar un procedimiento se ejecuta un archivo .asp completo.
Por ejemplo, la secuencia de comandos siguiente muestra cómo podría utilizar Server.Execute para
incluir archivos .asp de forma dinámica:
<%
.
.
If blnUseDHTML Then
Server.Execute("DHTML.asp")
Else
Server.Execute("HTML.asp")
End If
.
.
%>
Mientras el archivo de destino pertenezca a una aplicación del mismo servidor, la aplicación inicial se
transferirá a este archivo, ejecutará su contenido y continuará con la ejecución del archivo que inició la
transferencia. Igual que sucede con Server.Transfer, al ejecutar un archivo .asp éste se comporta como
si formara parte de la aplicación inicial. Sin embargo, Server.Execute, no funciona cuando los servidores
son distintos. Para obtener más información, consulte Server.Execute.
Enviar contenido al explorador
A medida que se procesa una secuencia de comandos ASP, el texto y los gráficos que no se encuentren
entre delimitadores ASP o etiquetas <SCRIPT> se devuelve directamente al explorador. También puede
enviar explícitamente contenido al explorador mediante el objeto Response.
Enviar contenido
Para enviar contenido al explorador desde delimitadores ASP o desde un procedimiento, utilice el
método Write del objeto Response. Por ejemplo, la instrucción siguiente envía un saludo diferente al
usuario dependiendo de si el usuario ha visitado la página con anterioridad o no:
<%
If blnFirstTime Then
Response.Write "<H3 ALIGN=CENTER>Reciba nuestra bienvenida a la página de introducción</H3>"
Else
Response.Write "<H3 ALIGN=CENTER>Gracias por volver a la página de introducción</H3>"
End If
%>
Fuera de un procedimiento, no tiene que utilizar Response.Write para devolver contenido al usuario. El
contenido que no se encuentra dentro de delimitadores de secuencia de comandos se envía
directamente al explorador, que da formato y presenta este contenido. Por ejemplo, la secuencia de
comandos siguiente produce el mismo resultado que la secuencia de comandos anterior:
<H3 ALIGN=CENTER>
<% If blnFirstTime Then %>
Reciba nuestra bienvenida a la página de introducción.
<% Else %>
Gracias por volver a la página de introducción.
<%End If %>
</H3>
Intercale secuencias de comandos y código HTML cuando tenga que devolver el resultado una vez o
cuando sea más cómodo agregar instrucciones a texto HTML existente. Utilice Response.Write cuando
no desee dividir una instrucción con delimitadores o cuando desee generar la cadena de texto que vaya
a devolver al explorador. Por ejemplo, podría generar una cadena de texto que creara una fila de una
tabla con los valores enviados por un formulario HTML:
Response.Write "<TR><TD>" & Request.Form("Nombre") _
& "</TD><TD>" & Request.Form("Apellido") & "</TD></TR>"
Request.Form devuelve los valores enviados por un formulario HTML (consulte Procesar los datos
introducidos por el usuario).
Nota El carácter & es el carácter de continuación de cadenas de VBScript. El carácter de subrayado (_)
es el carácter de continuación de línea de VBScript.
Secuencias de comandos sencillas
La siguiente secuencia de comandos ilustra las técnicas básicas que se utilizan en las secuencias de
comandos ASP. Si no tiene experiencia en el desarrollo de aplicaciones o nunca ha escrito secuencias
de comandos, éste es un buen lugar para empezar.
Elija un ejemplo en la siguiente lista:
• Variables: Muestra cómo crear y manipular variables en una secuencia de comandos ASP.
• Bucles: Proporciona un ejemplo de las tres construcciones más comunes para crear bucles, For
... Next, Do ... Loop y While ... Wend.
• Operadores condicionales: Ilustra el uso de los operadores condicionales, como If ... Then, en
las secuencias de comandos ASP.
• Matrices: Muestra cómo crear, administrar y tener acceso a matrices.
• Archivos de inclusión del servidor: Muestra el uso de los archivos de inclusión del servidor.
• Funciones y procedimientos: Muestra cómo crear y utilizar funciones y procedimientos en una
secuencia de comandos ASP.
Variables
código
Este ejemplo declara varios tipos diferentes de variables, realiza algunas operaciones sencillas en ellas
y las muestra al explorador cliente con los delimitadores especiales de secuencias de comandos <% =
...%>. Se asigna un entero a la variable intVariable, se suma a sí mismo y se envía el resultado al
explorador cliente. A la variable StrVariable se le asigna el nombre, se agrega a Soto y se envía al
explorador cliente. Del mismo modo se declaran o crean, inicializan, manipulan y muestran los valores
booleanos y las fechas.
Observaciones
El último paso de la demostración de la variable de fecha es especialmente interesante. En VBScript,
primero se asigna la variable a una cadena de fecha literal y después se muestra. Después se
restablece y se asigna el valor devuelto por la función Now de VBScript, que devuelve la hora actual del
sistema. El ejemplo de JScript utiliza la función Date de JScript para establecer el literal inicial, para lo
que pasa parámetros a la función, y establecer después la fecha actual del sistema en la variable, sin
pasar parámetros a la función.
<%@ LANGUAGE = VBScript %>
<% Option Explicit %>
<HTML>
<HEAD>
<TITLE>Variable Sample</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<!-- Display header. -->
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Variable Sample</B></FONT><BR>
<HR>
<H3>Integer Manipulation</H3>
<%
'Declare variable.
Dim intVar
'Assign the variable an integer value.
intVar = 5
%>
<P><%= intVar %> + <%= intVar %> = <%= intVar + intVar %></P>
<HR>
<H3>String Manipulation</H3>
<%
'Declare variable.
Dim strVar
'Assign the variable a string value.
strVar = "Jemearl"
%>
<P>This example was done by <%= strVar + " Smith" %></P>
<HR>
<H3>Boolean Manipulation</H3>
<%
'Declare variable.
Dim blnVar
'Assign the variable a Boolean value.
blnVar = true
'Output message based on value.
If (blnVar) Then
Response.Write "<P>The Boolean value is True.</P>"
Else
Response.Write "<P>The Boolean value is False.</P>"
End If
%>
<HR>
<H3>Date and Time</H3>
<%
'Declare variable.
Dim dtmVar
'Assign the variable a value.
dtmVar = #08 / 27 / 97 5:11:42pm#
%>
<P>The date and time is <%= dtmVar %>
<%
'Set the variable to the web server date and time.
dtmVar = Now()
%>
<P>The <STRONG>system</strong> date and time is <%= dtmVar %></P>
</BODY>
</HTML>
Bucles
Los bucles representan uno de los mecanismos más importantes de control de flujo en un lenguaje de
programación. Las construcciones en bucle proporcionan la base de cualquier aplicación que deba
realizar una tarea de forma repetitiva, como sumar 1 a una variable, leer un archivo de texto o procesar y
enviar un mensaje de correo electrónico.
código
VBScript y JScript proporcionan varios mecanismos para realizar bucles. Este ejemplo demuestra las
tres instrucciones más comunes para realizar bucles, For ... Next, Do ... Loop y While ... Wend. Estas
tres instrucciones son ligeramente diferentes y la situación indicará cuál de las tres es la más indicada.
Sin embargo, para este ejemplo, cada tipo de instrucción de bucle se utiliza para realizar la misma tarea:
imprimir un saludo cinco veces, cada una de ellas con una fuente mayor. En cada instrucción de bucle
se inicializa la variable i y se define la condición de prueba, de forma que i nunca sea mayor que 5. La
variable se incrementa en 1 unidad en cada iteración del bucle.
Operadores condicionales
Los operadores condicionales, junto con las variables y las construcciones de bucle, forman los pilares
básicos de los lenguajes de programación y, por tanto, de las aplicaciones. Las aplicaciones basadas en
Web que se implementan mediante secuencias de comandos ASP pueden aprovechar el control de flujo
que proporcionan los operadores condicionales, así como la interactividad y la sofisticación de HTML.
código
Este ejemplo demuestra las instrucciones If ... Then o if ... else en VBScript y JScript, así como las
instrucciones Select ... Case y switch ... case, más complejas. La demostración de cada una de estas
instrucciones realiza la misma tarea: enviar una página al explorador cliente con la fecha y la hora
actuales y un saludo. El texto del saludo será "Buenos días" o "Buenas tardes", dependiendo de si en el
reloj del sistema aparece a.m. o p.m.
<%@ LANGUAGE = VBScript %>
<% Option Explicit %>
<HTML>
<HEAD>
<TITLE>Conditional Operator Sample</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<!-- Display header. -->
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Conditional Operator Sample</B></FONT><BR>
<HR SIZE="1" COLOR="#000000">
<!-- If...Then example -->
<%
Dim varDate
varDate = Date()
%>
<P>The date is: <%= varDate %></P>
<%
'Select Case statement to display a message based on the day of the month.
Select Case Day(varDate)
Case 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Response.Write("<P>It's the beginning of the month.</P>")
Case 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
Response.Write("<P>It's the middle of the month.</P>")
Case Else
Response.Write("<P>It's the end of the month.</P>")
End Select
%>
<P>The time is: <%= Time %></P>
<%
'Check for AM/PM, and output appropriate message.
If (Right(Time,2)="AM") Then
Response.Write("<P>Good Morning</P>")
Else
Response.Write("<P>Good Evening</P>")
End If
%>
</BODY>
</HTML>
Funciones y procedimientos
Las funciones y los procedimientos proporcionan un método para evitar tener que escribir varias veces
un mismo bloque de código cada vez que desee realizar una tarea determinada. Tanto VBScript como
JScript permiten llamar a una función o a un procedimiento desde cualquier lugar de una secuencia de
comandos. Este ejemplo demuestra cómo puede crear y utilizar estas herramientas en secuencias de
comandos ASP.
Si no tiene ninguna función en la página ASP, el motor ASP se limita a procesar el archivo completo, de
principio a fin, cada vez que lo pide un explorador cliente. Sin embargo, las funciones y los
procedimientos se ejecutan sólo cuando se les llama, no con el resto del código.
En VBScript o JScript las funciones y los procedimientos se indican mediante la instrucción Function.
Además, VBScript establece una diferencia entre una función que devuelve un valor y otra que no lo
hace; la primera de ellas se indica con la instrucción Sub, que la identifica como una subrutina.
código
Este ejemplo define una función, PrintOutMsg, que toma como parámetros un mensaje y un número
que especifica cuántas veces se escribirá el mensaje en el explorador cliente mediante el método
Response.Write. Para este ejemplo, la función se limita a devolver al explorador cliente el número de
veces que se imprimió el mensaje.
Observaciones
Es importante tener en cuenta el atributo RUNAT de la etiqueta <SCRIPT>. SI no se incluye, ASP
asumirá que se trata de una secuencia de comandos del cliente y devolverá el código al explorador para
que lo procese. Esto haría que ASP no reconociera la llamada a la función PrintOutMsg, devolviera un
error y anulara la ejecución.
<%@ LANGUAGE = VBScript %>
<% Option Explicit %>
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
'Define Server Side Script Function.
Function PrintOutMsg(strMsg, intCount)
Dim i
'Output Message count times.
For i = 1 to intCount
Response.Write(strMsg & "<BR>")
Next
'Return number of iterations.
PrintOutMsg = intCount
End Function
</SCRIPT>
<HTML>
<HEAD>
<TITLE>Functions</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<!-- Display header. -->
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Server Side Functions</B></FONT><BR>
<P>
The function "PrintOutMsg" prints out a specific message a set number of times.<P>
<%
'Store number of times function printed message.
Dim intTimes
'Call function.
intTimes = PrintOutMsg("This is a function test!", 4)
'Output the function return value.
Response.Write("<p>The function printed out the message " & intTimes & "
times.")
%>
</BODY>
</HTML>
Probablemente, la forma más básica de interactividad Web es el formulario HTML. Es importante tener
en cuenta que ASP no sustituye a los formularios, sino que los mejora y hace que sea más fácil
implementarlos y administrarlos.
La etiqueta HTML <FORM> especifica qué método utilizará el formulario para comunicar la información
a la secuencia de comandos que la procesará. El atributo del método POST indica que la información
del formulario pasará a través de una conexión HTTP independiente a la secuencia de comandos o al
programa que la procesará. La secuencia de comandos o el programa pueden analizar la información y
realizar cualquier tarea que sea necesaria, y devolver el resultado al explorador cliente.
código
Este ejemplo muestra cómo implementar un formulario sencillo mediante el atributo del método POST de
HTTP, así como una de las principales ventajas de la creación de formularios mediante ASP: la
posibilidad de combinar el formulario y el código de proceso real en un mismo archivo. Este ejemplo crea
un pequeño formulario con dos cuadros de entrada de texto, uno para el nombre del usuario (fname) y
otro para el apellido (lname). Para obtener el valor de las variables fname y lname en la petición se tiene
acceso a la colección Request.Forms y después se muestran los resultados en la parte inferior de la
página.
La primera vez que se ejecuta la secuencia de comandos no aparece ningún texto debajo de la línea
horizontal. Esto se debe a que no había información disponible para pasarla a la secuencia de
comandos cuando se inició y ASP pasa por alto las búsquedas de Request.Forms si no existe
información. Sin embargo, si hace clic en el botón Enviar, se cargará de nuevo la página y la secuencia
de comandos ya dispondrá de la información que escribió en los cuadros de texto.
<%@ Language = VBScript %>
<% Option Explicit %>
<HTML>
<HEAD>
<TITLE>Form Posting</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<!-- Display header. -->
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>Form Posting</B></FONT><BR>
<HR>
<P>This page will take the information entered in the form fields, and use the POST
method to send the data to an ASP page.
<FORM NAME=Form1 METHOD=Post ACTION="Form_VBScript.asp">
First Name: <INPUT TYPE=Text NAME=fname><P>
Last Name: <INPUT TYPE=Text NAME=lname><P>
<INPUT TYPE=Submit VALUE="Submit">
</FORM>
<HR>
<% Response.Write Request.form("fname")%> <BR>
<% Response.Write Request.form("lname")%> <BR>
</BODY>
</HTML>
Puede utilizar formularios para recopilar datos de los usuarios, pero también puede utilizarlos para
mostrar información. Por ejemplo, si un explorador cliente tiene acceso al motor de búsqueda de su
directorio de teléfonos, querrá mostrar los resultados de la búsqueda. La secuencia de comandos de
búsqueda (que también puede implementar mediante ASP) acepta los datos introducidos por el usuario,
tiene acceso a la base de datos y envía el resultado al formulario de presentación en una cadena de
consulta. Este ejemplo es una demostración sencilla de cuál sería la apariencia del formulario.
Para este ejemplo, los datos se incluyen en el código de la secuencia de comandos pero, obviamente, la
información podría provenir de un formulario interactivo, de una base de datos o de un archivo de texto.
Al iniciarse el ejemplo se inicializan las variables. Después, crea un formulario con las etiquetas HTML
<FORM> y define cuatro cuadros de texto. Por último, con los delimitadores de secuencias de comandos
del servidor <%= ... %>, la secuencia de comandos llena los cuadros de texto con los valores
establecidos en la inicialización.
<%@ LANGUAGE = VBScript %>
<% Option Explicit %>
<%
'Create and set variables that will be used in populating 'the form. In a typical application, these
values would come from a database or text file.
Dim strFirstName
Dim strLastName
Dim strAddress1
Dim strAddress2
Dim blnInfo
strFirstName = "John"
strLastName = "Doe"
strAddress1 = "1 Main Street"
strAddress2 = "Nowhere ZA, 12345"
%>
<HTML>
<HEAD>
<TITLE>PopulateForm Sample</TITLE>
</HEAD>
<BODY BGCOLOR="White" TOPMARGIN="10" LEFTMARGIN="10">
<!-- Display header. -->
<FONT SIZE="4" FACE="ARIAL, HELVETICA">
<B>PopulateForm Sample</B></FONT><BR>
<HR SIZE="1" COLOR="#000000">
<FORM ACTION="">
<!-- Use ASP variables to fill out the form. -->
<P>First Name: <INPUT TYPE="TEXT" NAME="FNAME" VALUE="<%= strFirstName
%>"></P>
<P>Last Name: <INPUT TYPE="TEXT" NAME="LNAME" VALUE="<%= strLastName
%>"></P>
<P>Street: <INPUT TYPE="TEXT" NAME="STREET" VALUE="<%= strAddress1%>"></P>
<P>City State, Zip: <INPUT TYPE="TEXT" NAME="FNAME" VALUE="<%= strAddress2
%>"></P>
</BODY>
</HTML>
Conectividad con bases de datos
Si va a crear una aplicación basada en Web, lo más probable es que tenga formularios. Posiblemente,
también tendrá que conectarla de alguna forma con una base de datos. ActiveX® Data Objects (ADO)
proporciona un conjunto de eficaces herramientas que le permitirán tener acceso a orígenes de datos y
manipularlos.
Los ejemplos de esta sección ilustran las técnicas necesarias para utilizar ADO de forma efectiva y cómo
puede utilizar mejor estas funciones en una aplicación basada en Web.
• Consulta sencilla: Muestra cómo utilizar ADO y ASP para realizar consultas sencillas en una
base de datos.
• Limitar los resultados de una consulta: Muestra cómo es posible utilizar ASP y ADO en las
secuencias de comandos para limitar el número de filas devueltas en un conjunto de registros.
• Consulta desplazable: Muestra cómo realizar con ADO una consulta desplazable
multidireccional.
• Agregar o eliminar registros: Presenta las técnicas necesarias para agregar y eliminar registros
de un origen de datos mediante ASP y ADO.
• Actualizar registros: Muestra cómo utilizar ADO en una aplicación para actualizar los registros
existentes.
• Ejecutar procedimientos almacenados: Muestra cómo utilizar ADO con las secuencias de
comandos ASP para ejecutar procedimientos almacenados de la base de datos.
Para obtener más información acerca de ADO y de las herramientas de acceso a datos de Microsoft en
general, consulte la documentación de Microsoft Data Access.
Consulta sencilla
Introducción
Aunque una base de datos puede ser un sistema muy complicado y las herramientas de acceso a datos
deben ser eficaces y sensibles, es igualmente importante que las tareas sencillas de acceso a bases de
datos sean fáciles de realizar. Este ejemplo demuestra cómo ADO proporciona un método sencillo para
realizar este tipo de tareas.
Paseo por el código
El objetivo de esta aplicación de ejemplo es obtener un pequeño conjunto de registros de una base de
datos de Microsoft® Access e imprimir el resultado. El primer paso consiste en crear una instancia del
objeto Connection mediante el método Server.CreateObject. El ejemplo utiliza la instancia del objeto
Connection para abrir el proveedor de datos OLE DB y, después, para ejecutar un comando SELECT
de SQL y así obtener todos los registros de la tabla Autores. Para terminar, la secuencia de comandos
recorre la colección del conjunto de registros obtenido y muestra los resultados. Después se cierran el
conjunto de registros y la conexión con el origen de datos OLE DB.
Importante OLE DB debe estar correctamente configurado en el servidor para que este ejemplo
funcione correctamente.
<%@ LANGUAGE = VBScript %>
<% Option Explicit %>
<HTML>
<HEAD>
<TITLE>Simple ADO Query</TITLE>
</HEAD>
<BODY BGCOLOR="White" topmargin="10" leftmargin="10">
<!-- Display Header -->
<font size="4" face="Arial, Helvetica">
<b>Simple ADO Query with ASP</b></font><br>
<hr size="1" color="#000000">
Contacts within the Authors Database:<br><br>
<%
Dim oConn
Dim oRs
Dim filePath
Dim Index
' Map authors database to physical path
filePath = Server.MapPath("authors.mdb")
' Create ADO Connection Component to connect
' with sample database
Set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filePath
' Execute a SQL query and store the results
' within recordset
Set oRs = oConn.Execute("SELECT * From Authors")
%>
<TABLE border = 1>
<%
Do while (Not oRs.eof) %>
<tr>
<% For Index=0 to (oRs.fields.count-1) %>
<TD VAlign=top><% = oRs(Index)%></TD>
<% Next %>
</tr>
<% oRs.MoveNext
Loop
%>
</TABLE>
<%
oRs.close
oConn.close
%>
</BODY>
</HTML>
Ejemplo
Para los siguientes ejemplos, el archivo data.txt se encuentra en el directorio C:\Inetpub\Wwwroot\Script,
al igual que el archivo test.asp, que contiene las siguientes secuencias de comandos. El directorio
C:\Inetpub\Wwwroot se establece como directorio particular del servidor.
El siguiente ejemplo utiliza la variable de servidor PATH_INFO para asignar la ruta física al archivo
actual. La siguiente secuencia de comandos
<%= server.mappath(Request.ServerVariables("PATH_INFO"))%><BR>
produce el resultado
c:\inetpub\wwwroot\script\test.asp<BR>
Como los parámetros de la ruta de los siguientes ejemplos no empiezan con un carácter de barra
diagonal, se asignan de forma relativa al directorio actual, en este caso C:\Inetpub\Wwwroot\Script. Las
siguientes secuencias de comandos
<%= server.mappath("data.txt")%><BR>
<%= server.mappath("script/data.txt")%><BR>
producen el siguiente resultado
c:\inetpub\wwwroot\script\data.txt<BR>
c:\inetpub\wwwroot\script\script\data.txt<BR>
Los dos ejemplos siguientes utilizan el carácter de barra diagonal para especificar que la ruta que se
obtiene debe buscarse como ruta virtual completa del servidor. Las siguientes secuencias de comandos
<%= server.mappath("/script/data.txt")%><BR>
<%= server.mappath("\script")%><BR>
producen el siguiente resultado
c:\inetpub\wwwroot\script\data.txt<BR>
c:\inetpub\wwwroot\script<BR>
Los siguientes ejemplos muestran cómo puede utilizar una barra diagonal (/) o una barra diagonal
inversa (\) para obtener la ruta física al directorio particular. Las siguientes secuencias de comandos
<%= server.mappath("/")%><BR>
<%= server.mappath("\")%><BR>
producen el siguiente resultado
c:\inetpub\wwwroot<BR>
c:\inetpub\wwwroot<BR>
El siguiente documento es un manual de ASP, trata los principales comandos de ASP, desde lo mas
sencillo o lo intermedio, comandos y utilidades basicas para el desarrollo de paginas Web interactivas,
haciendo uso del Microsoft Internet Information Service.
Dicho manual fue tomado de los principales puntos de la ayuda de Windows 2000 Professional. P.P/p.p.
http://www.softdownload.com.ar
1.2.LENGUAJE PHP
Historia de PHP
PHP es un lenguaje creado por una gran comunidad de personas. El sistema fue desarrollado originalmente en el
año 1994 por Rasmus Lerdorf como un CGI escrito en C que permitía la interpretación de un número limitado de
comandos. El sistema fue denominado Personal Home Page Tools y adquirió relativo éxito gracias a que otras
personas pidieron a Rasmus que les permitiese utilizar sus programas en sus propias páginas. Dada la aceptación
del primer PHP y de manera adicional, su creador diseñó un sistema para procesar formularios al que le atribuyó el
nombre de FI (Form Interpreter) y el conjunto de estas dos herramientas, sería la primera versión compacta del
lenguaje: PHP/FI.
La siguiente gran contribución al lenguaje se realizó a mediados del 97 cuando se volvió a programar el analizador
sintáctico, se incluyeron nuevas funcionalidades como el soporte a nuevos protocolos de Internet y el soporte a la
gran mayoría de las bases de datos comerciales. Todas estas mejoras sentaron las bases de PHP versión 3.
Actualmente PHP se encuentra en su versión 4, que utiliza el motor Zend, desarrollado con mayor meditación
para cubrir las necesidades actuales y solucionar algunos inconvenientes de la anterior versión. Algunas mejoras de
esta nueva versión son su rapidez -gracias a que primero se compila y luego se ejecuta, mientras que antes se
ejecutaba mientras se interpretaba el código-, su mayor independencia del servidor web -creando versiones de PHP
nativas para más plataformas- y un API más elaborado y con más funciones.
Gráfica del número de dominios y direcciones IP que utilizan PHP.Estadística de Netcraft.En el último año, el
número de servidores que utilizan PHP se ha disparado,logrando situarse cerca de los 5 millones de sitios y 800.000
direcciones IP, lo que le ha convertido a PHP en una tecnología popular.
¿Qué es PHP?
El lenguaje PHP es un lenguaje de programación de estilo clásico, es decir, es un lenguaje de programación con
variables, sentencias condicionales, ciclos (bucles), funciones…. No es un lenguaje de marcado como podría ser
HTML, XML o WML. Está más cercano a JavaScript o a C, para aquellos que conocen estos lenguajes.
Pero a diferencia de JavaScript que se ejecuta en el navegador, PHP se ejecuta en el servidor, por eso nos permite
acceder a los recursos que tenga el servidor como por ejemplo podría ser una base de datos. El programa PHP es
ejecutado en el servidor y el resultado enviado al navegador. El resultado es normalmente una página HTML pero
igualmente podría ser una pagina WML.
Al ser PHP un lenguaje que se ejecuta en el servidor no es necesario que su navegador lo soporte, es
independiente del browser, pero sin embargo para que las páginas PHP funcionen, el servidor donde están alojadas
debe soportar PHP.
_ Instalar el servidor WEB. Trabajaremos con sistemas operativos Microsoft Windows (2000 Professional y XP
Professional), por lo que vamos a instalar un IIS (versión 5 para w2k y 5.1 para wXP).
_ Lo que sigue es elegir el tipo de instalación, cuenta con dos opciones, estándar y avanzado, para nuestras
necesidades elegiremos la forma estándar, por lo tanto seleccionamos el botón de radio que dice Standar.
_ Ahora tendremos que elegir el directorio en el cual se instalará el PHP, el instalador trae por default el directorio
C:\PHP, lo dejaremos así, por lo tanto presionamos Next.
_ Lo que nos pide la siguiente pantalla son los datos para el administrador del sistema por si falla algo en PHP, para
este curso solo presionamos Next, pero también puede introducir una dirección válida.
_ Ahora se nos pregunta el tipo de servidor que estamos utilizando, como ya había mencionado antes, asaremos IIS
versión 5 y 5.1, por lo tanto seleccionamos el botón de radio que tiene la opción de Microsoft IIS 4 or higher.
_ La siguiente pantalla nos avisa que ya esta listo para instalar PHP, así que
solo presionamos Next.
_ Veremos como va el proceso de la instalación.
_ La siguiente pantalla lo que nos dice es que seleccionemos que parte del IIS queremos que ejecute PHP, como
solo tenemos instalado el servicio de web, solo nos presenta esa opción, pero con eso es suficiente, así que
seleccionamos el checkbox que dice WWW Service Master Properties.
_ Por ultimo nos dice que la instalación se ha completado y estamos listo para
ejecutar PHP en nuestro servidor.
La forma de saber si se ha instalado correctamente el PHP en nuestro servidorhaciendo un pequeño programita
PHP, el mas básico que nos servirá de prueba para ver sise ha instalado correctamente, entonces abrimos un editor
de texto cualquiera (con el cualharemos nuestros programas PHP, puede ser el NotePad), y escribimos las
siguientes
líneas:
<?
phpinfo();
?>
después de escribir estas líneas guardamos nuestro archivo en el directorio c:\inetpub\wwroot\taller\ el cual va a
ser nuestro directorio de trabajo para este curso,(como información, el IIS utiliza como directorio raíz el directorio
c:\inetpub\wwroot), le pondremos al archivo prueba.php ahora tecleamos en la barra de direcciones de nuestro
Separación de instrucciones
Las instrucciones se separan igual que en C o Pascal terminando cada sentencia con un punto y coma.
La etiqueta de cierre ( ?> ) también implica el fin de la sentencia, así lo siguiente es equivalente:
<?php echo "Esto es una prueba"; ?>
<?php echo "Esto es una prueba" ?>
Comentarios en PHP
PHP soporta comentarios tipo 'C', 'C++' y Shell de Unix. Por ejemplo:
<?php
echo “Prueba"; // Comentario tipo C++ para una línea
?>
<?php
/*
Esto es un comentario multilínea
otra línea más de comentario
*/
echo "Esto es aún otra prueba"; ?>
<?php
echo "Prueba"; # Comentario tipo shell de Unix
?>
Variables
Antes de ver como se utilizan las variables en PHP veremos una pequeña introducción a las variables, para los que
no conozcan que es una variable. Una variable consiste en un elemento al cual le damos un nombre y le atribuimos
un determinado tipo de información. Las variables pueden ser consideradas como la base de la
programación.De este modo podríamos escribir en un lenguaje ficticio:
a="perro"
b="muerde"
La variable que nosotros llamamos "a" posee un elemento de información de tipo texto que es "perro". Asimismo, la
variable "b" contiene el valor "muerde". Podríamos definir una tercera variable que fuese la suma de estas dos:
c=a+b
Si introdujésemos una petición de impresión de esta variable en nuestro lenguaje ficticio:
imprimir(c)
El resultado podría ser:
perro muerde
Podríamos de la misma forma trabajar con variables que contuviesen números y construir nuestro programa:
a=3
b=4
c=a+b
imprimir(c)
El resultado de nuestro programa sería:7
En PHP las variables se representan como un signo de pesos seguido por el nombre de la variable. El nombre de la
variable es sensible a minúsculas y mayúsculas.
$var = "Santana";
$Var = "Pedro";
echo "$var, $Var";
// produce la salida “Santana, Pedro"
Variables variables
A veces es conveniente tener nombres de variables variables. Dicho de otro modo,son nombres de variables que se
pueden establecer y usar dinámicamente. Una variable normal se establece con una sentencia como:
$a = "Hola";
Una variable variable toma el valor de una variable y lo trata como el nombre de una variable. En el ejemplo anterior,
Hola, se puede usar como el nombre de una variableutilizando dos signos de peso. p.ej.
$$a = "mundo";
Probemos las siguientes sentencias:
echo "$a ${$a}";
echo "$a $Hola";
Los dos no regresarán “Hola mundo”
Tipos de datos
Enteros:
Los enteros se puede especificar usando una de las siguientes sintaxis:
$a = 1234; # número decimal
$a = -123; # un número negativo
$a = 0123; # número octal (equivalente al 83 decimal)
$a = 0x12; # número hexadecimal (equivalente al 18 decimal)
Cadenas:
El único operador de cadenas que existen es el de concatenación, el punto. Pero no
se preocupen, PHP dispone de toda una gama de funciones que nos permitirán trabajar
cómodamente con las cadenas.
$a = "Hola";
$b = $a . "Mundo"; // Ahora $b contiene "Hola Mundo"
En este punto hay que hacer una distinción, la interpretación que hace PHP de las
Caracteres protegidos
\n Nueva línea
\r Retorno de carro
\t Tabulación horizontal
\\ Barra invertida
\$ Signo del dólar
\" Comillas dobles
\[0-7]{1,3} La secuencia de caracteres que coincida con la expresión regular es
un carácter en notación octal
\x[0-9A-Faf]{
1,2}
La secuencia de caracteres que coincida con la expresión regular es
un carácter en notación hexadecimal
Operadores de Comparación:
$a < $b $a menor que $b
$a > $b $a mayor que $b
$a <= $b $a menor o igual que $b
$a >= $b $a mayor o igual que $b
$a == $b $a igual que $b
$a != $b $a distinto que $b
Operadores Lógicos:
Operadores de Asignación:
$a = $b Asigna a $a el contenido de $b
$a += $b Le suma a $b a $a
$a -= $b Le resta a $b a $a
$a *= $b Multiplica $a por $b y lo asigna a $a
$a /= $b Divide $a por $b y lo asigna a $a
$a .= $b Añade la cadena $b a la cadena $a
Los operadores bit a bit te permiten activar o desactivar bits individuales de un entero.
$a &
$b Y Se activan los bits que están activos tanto en $a como $b.
$a |
$b O Se activan los bits que están activos en $a o que lo están
en $b.
$a ^
$b Xor ("o exclusiva") Se activan los bits que están activos en $a o en $b pero
no en ambos a la vez.
~ $a No Se activan los bits que no están activos en $a.
$a
<<
$b
Desplazamiento a la izquierda Desplaza los bits de $a, $b posiciones hacia la izquierda
(por aritmética binaria, cada posición desplazada equivale a multiplicar por dos el valor de $a)
$a Desplazamiento a la Desplaza los bits de $a, $b posiciones hacia la derecha
>>
$b
derecha (por aritmética binaria, cada posición desplazadaequivale a dividir entre dos el valor de $a)
Para demostrar el uso de algunos operadores mostraré algunos ejemplos en PHP: El siguiente programa calcula el
salario de un trabajador con un impuesto
<html>
<body>
<?php
$SalarioTrabajador = 3500;
$Impuesto = 20; // Porcentaje
$SueldoReal = $SalarioTrabajador - (($SalarioTrabajador /
100) * $Impuesto);
echo “Sueldo del trabajador sin impuesto:
$SalarioTrabajador<BR>”;
echo “Con el impuesto :$SueldoReal”;
?>
</body >
</html>
Programa en PHP que calcula el área de un triangulo cuya formula es a=(b*h)/2
<?php
$Base=15;
$Altura=12;
$Area = ($Base * $Altura)/2;
printf (“El area del triangulo es: $Area”);
?>
Programa que dados 2 números calcule la suma, resta, multiplicación, división, y modulo.
<?php
$Num1=8;
$Num2=5;
printf(“La suma de $Num1 y $Num2 es: <b>%d</b><br>”, $Num1 +
$Num2 );
printf(“La resta de $Num1 y $Num2 es: <b>%d</b><br>”, $Num1
- $Num2 );
printf(“La multiplicación de $Num1 y $Num2 : <b>%d</b><br>”,
$Num1 * $Num2 );
printf(“La division de $Num1 y $Num2: <b>%0.2f</b><br>”,
$Num1 / $Num2 );
printf(“El modulo de $Num1 y $Num2 es <b>%0.1f</b><br>”,
$Num1 % $Num2 );
?>
Constantes
PHP define varias constantes y proporciona un mecanismo para definir más en tiempo de ejecución. Las constantes
son como las variables, salvo por las dos circunstancias de que las constantes deben ser definidas usando la
función define(), y que no pueden ser redefinidas más tarde con otro valor. Las constantes predefinidas (siempre
disponibles) son:
__FILE__
E_PARSE
El interprete encontró sintaxis inválida en el archivo de comandos. La
recuperación no es posible.
E_NOTICE
Ocurrió algo que pudo ser o no un error. La ejecución continúa. Los ejemplos incluyen usar una cadena sin comillas
como un índice "hash", o acceder a una variable que no ha sido inicializada. Las constantes E_* se usan
típicamente con la función error_reporting() para configurar el nivel de informes de error. Se pueden definir
constantes adicionales usando la función define(). Nótese que son constantes, con una constante sólo se pueden
representar datos escalares válidos. Veremos un ejemplo del uso de estas constantes:
<?php
function report_error($archivo, $linea, $mensaje) {
echo "Un error ocurrió en $archivo en la línea $linea:
$mensaje.";
}
report_error(__FILE__,__LINE__, "Algo esta mal!");
?>
Ahora veremos como definir nuestras propias constantes:
<?php
define("CONSTANTE", "Hola mundo.");
echo CONSTANTE; // muestra "Hola mundo."
?>
Sentencias de control
Las sentencias de control permiten ejecutar bloque de códigos dependiendo de unas condiciones. Para PHP el 0 es
equivalente a Falso y cualquier otro número es Verdadero.
if...else
La sentencia if...else permite ejecutar un bloque de instrucciones si la condición es Verdadera y otro bloque de
instrucciones si ésta es Falsa. Es importante tener en cuenta que la condición que evaluemos ha de estar encerrada
entre paréntesis (esto es aplicable a todas la sentencias de control).
if (condición) {
Este bloque se ejecuta si la condición es VERDADERA
} else {
Este boque se ejecuta si la condición es FALSA
}
Existe una forma sencilla de usar la sentencia IF cuando no tenemos que usar el else y solo tenemos que ejecutar
una línea de código.
if ($a > 4) echo "$a es mayor que 4";
Ahora realizaremos un ejemplo con mas con IF el cual consistirá en un pequeño juego de adivinanzas el cual
necesitará de dos archivos adivina.htm y adivina.php, en este ejemplo se utilizará un formulario, lo cual aun no
hemos visto, se usa solo para muestra, por el momento no es muy importante conocer esa teoría sino un poco mas
adelante.
adivina.htm
<HTML>
<BODY>
<FORM METHOD=GET ACTION="adivina.php">
En que numero del 1 al 10 estoy pensando?
<INPUT NAME="adivina" TYPE="Text">
<BR>
<BR>
<INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>
adivina.php
<HTML>
<HEAD></HEAD>
<BODY>
<?php
srand((double)microtime()*1000000);
$Numero = rand(1,10);
if ($adivina > $Numero) {
echo "Fue muy grande"; echo "<BR>Yo pensé el número
$Numero. Lo siento no ";
}
if ($adivina < $Numero) {
echo "Fue muy pequeño"; echo "<BR>Yo pensé el número
$Numero. Lo siento no ";
}
?>
GANASTE
</BODY>
</HTML>
if...elseif...else
La sentencia IF...ELSEIF...ELSE permite ejecutar varias condiciones en cascada. Para este caso veremos un
ejemplo, en el que utilizaremos los operadores lógicos.
<?php
if ($nombre == ""){
echo "Tú no tienes nombre";
} elseif (($nombre=="eva") OR ($nombre=="Eva")) {
echo "
echo "Tu nombre es EVA";
} else {
echo "Tu nombre es " . $nombre;
}
switch...case...default
Una alternativa a if...elseif...else, es la sentencia switch, la cuál evalúa y compara cada expresión de la sentencia
case con la expresión que evaluamos, si llegamos al final de la lista de case y encuentra una condición Verdadera ,
ejecuta el código de bloque que haya en default. Si encontramos una condición verdadera debemos ejecutar un
break para que la sentencia switch no siga buscando en la lista de case. Veamos un ejemplo.
<?php
switch ($dia) {
case "Lunes":
echo "Hoy es Lunes";
break;
case "Martes":
echo "Hoy es Martes";
break;
case "Miercoles":
echo "Hoy es Miercoles";
break;
case "Jueves":
echo "Hoy es Jueves";
break;
case "Viernes":
echo "Hoy es Viernes";
break;
case "Sábado":
echo "Hoy es Sábado";
break;
case "Domingo":
echo "Hoy es Domingo";
break;
default:
echo "Esa cadena no corresponde a ningún día de la
semana";
}
?>
while
La sentencia while ejecuta un bloque de código mientras se cumpla una determinada
condición.
<?php
$num = 1;
while ($num < 5) {
echo $num;
$num++
}
?>
Podemos romper un ciclo while utilizando la sentencia break.
<?php
$num = 1;
while ($num < 5) {
echo $num;
if ($num == 3){
echo "Aquí nos salimos \n";
break
}
$num++
}
?>
do...while
Esta sentencia es similar a while, salvo que con esta sentencia primero ejecutamos
el bloque de código y después se evalúa la condición, por lo que el bloque de código se
ejecuta siempre al menos una vez.
<?php
$num = 1;
do {
echo $num;
if ($num == 3){
echo "Aquí nos salimos \n";
break
}
$num++
} while ($num < 5);
?>
for
El ciclo for no es estrictamente necesario, cualquier ciclo for puede ser sustituido fácilmente por otro while. Sin
embargo, el ciclo for resulta muy útil cuando debemos ejecutar un bloque de código a condición de que una variable
se encuentre entre un valor mínimo y otro máximo. El ciclo for también se puede romper mediante la sentencia
break.
<?php
for ($num = 1; Snum <=5; $num++){
echo $num;
if ($num == 3){
echo "Aquí nos salimos \n";
break
}
}
?>
A continuación muestro las 4 formas en que se puede usar el ciclo for.
/* ejemplo 1 */
for ($i = 1; $i <= 10; $i++) {
print $i;
}
/* ejemplo 2 */
for ($i = 1;;$i++) {
if ($i > 10) {
break;
}
}
print $i;
}
/* ejemplo 3 */
$i = 1;
for (;;) {
if ($i > 10) {
break;
}
print $i;
$i++;
}
/* ejemplo 4 */
for ($i = 1; $i <= 10; print $i, $i++) ;
Hay que realizar los siguientes programas con ciclos.
· Imprima los números del 1 al 100
for ($i = 1; $i <= 100; print $i."<br>", $i++) ;
Las tablas (o array en inglés), son muy importantes en PHP, ya que generalmente, las funciones que devuelven
varios valores, como las funciones ligadas a las bases de datos, lo hacen en forma de tabla. En PHP disponemos de
dos tipos de tablas. El primero sería el clásico, utilizando
índices:
<?php
$ciudad[] = "París";
$ciudad[] = "México";
$ciudad[] = "Roma";
$ciudad[] = "Sevilla";
$ciudad[] = "Londres";
print ("yo vivo en " . $ciudad[1] . "<BR>\n");
?>
Esta es una forma de asignar elementos a una tabla, pero una forma más formal es
utilizando la función array
<?php
$ciudad = array("París", "Roma", "Sevilla", "Londres");
//contamos el número de elementos de la tabla
$numelentos = count($ciudad);
//imprimimos todos los elementos de la tabla
for ($i=0; $i < $numelentos; $i++)
{
print ("La ciudad $i es $ciudad[$i] <BR>\n");
}
?>
Sino se especifica, el primer índice es el cero, pero podemos utilizar el operador =>
para especificar el índice inicial.
Ahora bien, recorrer una tabla y mostrar su contenido es sencillo utilizando los índices, pero ¿cómo hacerlo en las
tablas asociativas?. La manipulación de las tablas asociativas se a hace través de funciones que actúan sobre un
puntero interno que indica laposición. Por defecto, el puntero se sitúa en el primer elemento añadido en la tabla,
hasta que es movido por una función:
current - devuelve el valor del elemento que indica el puntero.
pos - realiza la misma función que current
reset - mueve el puntero al primer elemento de la tabla
end - mueve el puntero al último elemento de la tabla
next - mueve el puntero al elemento siguiente
prev - mueve el puntero al elemento anterior
count - devuelve el número de elementos de una tabla.
Veamos un ejemplo de las funciones anteriores:
<?php
$semana = array("lunes", "martes", "miércoles", "jueves",
"viernes", "sábado", "domingo");
echo count($semana); //7
//situamos el puntero en el primer elemento
reset($semana);
echo current($semana); //lunes
next($semana);
echo pos($semana); //martes
end($semana)
echo pos($semana); //domingo
prev($semana);
echo current($semana); //sábado
?>
Recorrer una tabla con las funciones anteriores se hace un poco enredoso, para ello se
recomienda utilizar la función each().
<?php
$visitas = array("lunes"=>200, "martes"=>186,
"miércoles"=>190, "jueves"=>175);
reset($visitas);
while (list($clave, $valor) = each($visitas))
{
echo "el día $clave ha tenido $valor visitas<BR>";
}
?>
La función each() devuelve el valor del elemento actual, en este caso, el valor del
elemento actual y su clave, y desplaza el puntero al siguiente, cuando llega al final
devuelve falso, y termina el bucle while().
Tablas multidimensionales
Las tablas multidimensionales son simplemente tablas en las cuales cada elemento
es a su vez otra tabla.
<?php
$calendario[] = array (1, "enero", 31);
$calendario[] = array (2, "febrero", 28);
$calendario[] = array (3, "marzo", 31);
$calendario[] = array (4, "abril", 30);
$calendario[] = array (5, "mayo", 31);
while (list($clave, $valor ) = each($calendario)){
{
$cadena = $valor[1];
$cadena .= " es el mes número " . $valor[0];
$cadena .= "y tiene " . $varlor[2] . " días<BR>";
echo $cadena;
}
?>
La función list() es más bien un operador de asignación, lo que hace es asignar valores a unas lista de variables. En
este caso los valores son extraídos de una tabla por la función each().
Formularios
Los Formularios no forman parte de PHP, sino del lenguaje estándar de Internet, HTML, pero como éstos van a
aparecer muchas veces durante el curso, vamos a dedicar esta algunas líneas a ellos.
Todo formulario comienza con la etiqueta <FORM ACTION="lo_que_sea.php" METHOD="post/get">. Con
ACTION indicamos el script que va procesar la información que recogemos en el formulario, mientras que METHOD
nos indica si el usuario del formulario va ha enviar datos (post) o recogerlos (get). La etiqueta </FORM>
indica el final del formulario.
A partir de la etiqueta <FORM> vienen los campos de entrada de datos que pueden ser:
Botón de comando:
<input type="submit" value="enviar" name="enviar">
Cuadro de texto:
<input type="text" name="nombre" size="20" value="jose">
Veamos un ejemplo con PHP:
Las siguientes dos paginas tienen el objetivo de preguntar cual es tu equipo de fútbol
favorito y desplegar en otra pagina el seleccionado (equipo.htm y equipo.php).
equipo.htm
<html>
<title>Equipo Favorito</title>
<body>
<form method=post ACTION=”equipo.php”>
Cual es tu equipo de fútbol favorito ?
<input name=”equipo” type “TEXT”>
<br>
<br>
<input type=submit>
</form>
</body>
<html>
equipo.php
<html>
<body>
Tu equipo favorito es:
<?php Echo “<h1><B>$equipo</B></h1>”; ?>
</body>
</html>
Hay que poner especial atención en el parámetro name de un elemento del formulario ya que es el mismo nombre
con el que se le referenciará en php, como pudimos ver en el ejemplo anterior el elemento <input name=”equipo”
type “TEXT”> lo manejamos en php como $equipo, así es con todos los elementos de formularios.
Cuadro de texto con barras de desplazamiento:
<textarea rows="5" name="descripcion" cols="20">Es de color rojo</textarea>
Ahora veamos un ejemplo con PHP:
Programa PHP que pide WebSites favoritos y los muestra como salida (sites.htm y sites.php). sites.htm
<html>
<title>Web Sites Favoritos</title>
<body>
<form method=POST ACTION=”sites.php”>
Mencióname algunos de tus WebSites Favoritos:
<br>
<textarea name=”websites” cols=”50” rows=”5”>
http://
http://
http://
http://
</textarea>
<br>
<br>
<input type=submit>
</form>
</body>
<html>
sites.php
<html>
<body>
Tus webs favoritos son:<br>
Menú desplegable:
<select size="1” class="codigo"><select size="1" name="dia">
<option selected value="lunes">lunes</option>
<option>martes</option>
<option value="miercoles">miercoles</option>
</select>
Ahora veamos un ejemplo en PHP:
Programa que pregunta opciones para armar una computadora y despliega las
opciones elegidas (lista.htm y lista.php).
lista.htm
<HTML>
<HEAD></HEAD>
<BODY>
<FORM METHOD=GET ACTION=”lista.php”>
Elije la computadora a comprar
<BR>
<BR>
<SELECT NAME=”compu”>
<OPTION>Pentium</OPTION>
<OPTION>Celeron</OPTION>
<OPTION>K6</OPTION>
<OPTION>MAC</OPTION>
</SELECT>
<BR>
<BR>
Selecciona los dispositivos de la computadora?
<BR>
<BR>
<SELECT NAME=”dispo[]” MULTIPLE>
<OPTION>KIT MULTIMEDIA</OPTION>
<OPTION>QUEMADORA</OPTION>
<OPTION>WEB CAM</OPTION>
<OPTION>MICROFONO</OPTION>
</SELECT>
<BR>
<BR>
<INPUT TYPE=SUBMIT>
</FORM>
</BODY>
</HTML>
lista.php
<HTML>
<BODY>
<?php
Echo “Seleccionaste una computadora: <B>$compu</B>
con:<br>”;
Echo “$dispo[0]<br>”;
Echo “$dispo[1]<br>”;
Echo “$dispo[2]<br>”;
Echo “$dispo[3]<br>”;
?>
</BODY>
</HTML>
Campo oculto:
<input type="hidden" name="edad" value="55">
Este último tipo de campo resulta especialmente útil cuando queremos pasar datos ocultos en un formulario. Ahora
pasemos a ver ejemplos que necesitan mas código PHP, como son ciclos y arrays, implementándolos en conjunto
con los formularios. Para el uso del FOR un programita para créditos bancarios (banco.htm y banco.php).
banco.htm
<HTML>
<HEAD></HEAD>
<BODY>
<B>Crédito bancario</B>
<FORM METHOD=POST ACTION="banco.php">
<BR>
Cual de estos paquetes te interesa tomar?<BR><BR>
<INPUT NAME="valor" TYPE="Radio" VALUE=1000>Nuestro paquete
de $1,000 Con el 5.0% interes
<BR>
<INPUT NAME="valor" TYPE="Radio" VALUE=5000>Nuestro paquete
de $5,000 Con el 6.5% interes
<BR>
<INPUT NAME="valor" TYPE="Radio" VALUE=10000>Nuestro paquete
de $10,000 Con el 8.0% interes
<BR>
<BR>
Cuanto es lo que deseas pagar al mes ?
<INPUT NAME=pagomes TYPE=Text SIZE=5>
<BR>
<BR>
<INPUT TYPE=SUBMIT VALUE="Pulse aquí para calcular">
</FORM>
</BODY>
</HTML>
banco.php
<HTML>
<HEAD></HEAD>
<BODY>
<?php
$Duracion=0;
switch ($valor) {
case 1000:
$Interes = 5;
break;
case 5000:
$Interes = 6.5;
break;
case 10000:
$Interes = 8;
break;
default:
echo "No seleccionaste ningun paquete favor de presionar el boton back y seleccionar alguno";
exit;
}
while ($valor > 0)
{
$Duracion = $Duracion + 1;
$Mensualmente = $pagomes - ($valor * $Interes/100);
if ($Mensualmente<=0)
{
echo "Tu necesitas hacer pagos mas grandes!";
exit;
}
$valor = $valor - $Mensualmente;
}
echo "La duracion es de: $Duracion meses con un
porcentaje de intereses del $Interes.";
?>
</BODY>
</HTML>
El siguiente programa demuestra como se pueden trabajar los array como elementos
hash (estados.php y capital.php).
estados.php
<html>
<head>
<title>Estados de México</title>
</head>
<body bgcolor="#FFFFFF">
De que estado te gustaría conocer su capital?
<?
$Estados=array(1=>"Colima","Jalisco","Sinaloa");
echo "<form method=post action='capital.php'>";
echo "<select name='estado'>";
for ($counter=1; $counter<4; $counter++)
echo "<option value=$counter>$Estados[$counter]</option>";
echo "</select><br><br>";
echo "<input type=submit>";
echo "</form>";
?>
</body>
</html>
capital.php
<html>
<head>
<title>Capitales</title>
</head>
<body bgcolor="#FFFFFF">
<?php
$Capital=array(1=>"Colima","Guadalajara","Culiacan");
for ($counter=0;$counter<4;$counter++)
{
if ($counter==$estado)
{
echo "la capital del estado elegido es
&Capital[$counter]";
}
}
?>
</body>
</html>
Como podemos observar los dos archivos tienen extensión .php, esto se debe a que es necesario ejecutar código
php en los dos, para poder formar dinámicamente las dos páginas. Para tener más material con formularios
ealizaremos un programa PHP que contenga varios elementos de formulario juntos: Desarrollar un programa en
PHP que pida el Nombre (textbox), el apellido (textbox), la edad (textbox), domicilio (text area), seleccione el rango
de sueldo que le gustaría ganar (listbox) y que seleccione como considera así mismo su desempeño laboral (radio
button). El programa no aceptará curriculums que elijan un sueldo muy bajo, ni un sueldo extremo, ni tampoco si se
considera pésimo (minicu.htm y minicu.php).
minicu.htm
<HTML><HEAD></HEAD><BODY><B>Minicurriculum </B>
<FORM METHOD=POST ACTION="minicu.php">
Nombres:
<INPUT NAME="nombres" TYPE="Text">
Apellidos:
<INPUT NAME="apellidos" TYPE="Text">
Edad:
<INPUT NAME="edad" TYPE="Text"SIZE="3">
<BR>
<BR>
Domicilio:
<TEXTAREA NAME="Domicilio" ROWS=4 COLS=40>
</TEXTAREA>
<BR>
<BR>
Que salario deseas ganar?
<SELECT NAME="Salario">
<OPTION VALUE=0> Menos de $1000</OPTION>
<OPTION VALUE=1000>Entre $1,000 y $3,000</OPTION>
<OPTION VALUE=3000>Entre $3,000 y $5,000</OPTION>
<OPTION VALUE=5000>mas de $5,000</OPTION>
</SELECT>
<BR>
<BR>
Como consideras tu desempeño?<BR><BR>
<INPUT NAME="Desempe" TYPE="Radio" VALUE=0>Pesimo
<BR>
<INPUT NAME="Desempe" TYPE="Radio" VALUE=5>Regular
<BR>
<INPUT NAME="Desempe" TYPE="Radio" VALUE=10>Excelente
<BR>
<BR>
<INPUT TYPE=SUBMIT VALUE="Presione cuando este listo(a)">
<INPUT TYPE=RESET VALUE="Borra todo">
</FORM>
</BODY>
</HTML>
minicu.php
<HTML>
<BODY>
Sr(a) <?php Echo "$nombres $apellidos ";?>
en base a su edad (<?php Echo "$edad";?>) y sus aspiraciones <br>
económicas y su auto estimación hemos determinado que:<br>
<?php
echo "Salario deseado: $Salario <br>" ;
echo "Su desempeño elegido: $Desempe <br>";
if ((($Salario==0) OR ($Salario ==5000)) OR ($Desempe ==0))
{
Echo "Usted no cumple los requisitos para ser parte de
nuestra empresa";
}
else
{
Echo "Usted cumple satisfactoriamente nuestras
aspiraciones";
}
?>
</BODY>
</HTML>
Archivos
fopen
fopen -- Abre un archivo o una URL
contador.php
<?php
$contador_archivo="c:/inetpub/wwwroot/taller/conta.dat";
if (!($fp=fopen($contador_archivo,"r")))
die("No se encontro $contador_archivo");
$contador=(int)fread($fp,20);
fclose($fp);
$contador++;
echo "Eres el visitante número: <b>$contador</b>";
$fp=fopen($contador_archivo,"w");
fwrite($fp,$contador);
fclose($fp);
?>
La instrucción die envía a la salida un mensaje y finaliza la ejecución del script. No devuelve nada.
Bases de Datos
Hasta ahora hemos visto la funciones básicas de PHP, lo que viene a continuación ya es sobre la forma en como
podemos acceder a bases de datos, veremos como acceder a ellas en dos sistemas de bases de datos diferentes,
los cuales son MySQL Server y Microsoft Access.
El primer sistema que veremos es MySQL Server, pero antes de ver código PHP, aprenderemos un poco de este
sistema, para los ejemplos en PHP ya va a ser necesario que tengamos una base de datos creada por lo tanto
pondremos atención en las formas en que estas se crean.
Qué es MySQL
MySQL es un sistema Cliente/Servidor que consta de un servidor SQL multi-hilo que soporta diferentes backends,
variados programas cliente y de librerías, administrador de herramientas y un programa de interface.
MySQL contribución para muchos de los software disponibles Es mucho más probable que se encuentre que
diversas aplicaciones ya soportan MySQL. Los valores centrales de MySQL son :
• La mejor y más usada base de datos en el mundo.
• Disponible y Accesible para todos
• Fácil de usar
• Se está perfeccionando continuamente mientras permanece rápida y segura.
• Divertida para usar y perfeccionar.
• Libre de molestias.
Bien, ya conocemos que es MySQL, ahora procedamos a instalarlo en nuestro servidor para poder realizar los
programas PHP con bases de datos MySQL.
• Al iniciar el instalador veremos la pantalla de “preparándose para instalar”, en esta solo hay que esperar que
termine el 100%.
• Después tenemos la pantalla de bienvenida, solo hay que dar clic en Next.
• Ahora si ya lo tendremos ejecutándose siempre que el sistema inicie, y estará en la barra de inicio del sistema con
un icono de un semáforo, hay que darle clic en el icono para que nos muestre sus opciones. • Al darle clic en Show
Me aparecerá el administrador de MySQL, desde ahí podemos ver todas los componentes del sistema de bases de
datos. Con esto es suficiente sobre la instalación de MySQL Server, ahora veamos como crear bases de datos en
el.
El prompt indica que mysql está listo para recibir los comandos que ingrese el usuario. Algunas instalaciones de
MySQL admiten usuarios anonymous (sin nombre) cuando el servidor corre en el host local. En este caso, se debe
invocar a el servidor mysql sin ninguna opción:
shell>mysql
Una vez que se ha realizado la conexión con éxito, para desconectarse al servidor en
cualquiera de los dos casos anteriores se debe escribir QUIT o control-D.
Creando y usando una base de datos
Visualización de las bases de datos existentes en el servidor MySQL
Antes de crear una base de datos, se debe conocer que base de datos existen
actualmente en el servidor, para ello se utiliza el comando SHOW, de la siguiente manera:
mysql> SHOW DATABASES;
+----------+
| Database |
+----------+
| mysql |
| test |
| tmp |
+----------+
Esta lista probablemente no es igual en todas las máquinas, pero las bases de datos mysql y test están siempre
entre ellas. La base de datos mysql se requiere porque en ella se describe la información de los privilegios de
acceso a los usuarios. La base de datos test proporciona el espacio de trabajo para los usuarios.
Creación de tablas
Para crear las tablas que va a contener la base de datos, se realiza de la siguiente forma:
mysql> CREATE TABLE nombre_tabla(campo_1 tipo(tamaño), campo_2
tipo(tamaño),...,campo_n tipo(tamaño));
El campo indica el nombre de la columna y tipo(tamaño) específica el tipo de dato y el espacio que se va a
conservar para cada dato almacenado en esa columna. Ejemplo: codigo int(5), nombre char(25), fecha date, etc..
Cuando se trata de fechas no se específica el tamaño, puesto que ya está determinado. Para visualizar las tablas
que tiene una base de datos se usa el mismo comando utilizado para ver las bases de datos, pero con la diferencia
de que en vez de database se coloca tables, es decir:
mysql> SHOW TABLES;
Para verificar que la tabla ha sido creada de la forma indicada, se usa el comando DESCRIBE. Ejemplo: Se va a
crear una tabla llamada clientes, de la siguiente forma:
mysql> CREATE TABLE clientes( rut char(8),nombre char(25),
direccion char(50), telefono int(10));
mysql> DESCRIBE clientes;
+----------+-----------+------+-----+--------+-------+
| Field | Type | Null | Key | Default| Extra |
+----------+-----------+------+-----+--------+-------+
| rut | char(12) | YES | | NULL | |
| nombre | char(25) | YES | | NULL | |
| direccion| char(50) | YES | | NULL | |
| telefono | int(10) | YES | | NULL | |
+----------+-----------+------+-----+--------+-------+
Esto es muy útil cuando se olvida el nombre o tipo de una columna. El Field indica el nombre de la columna, Type es
el tipo de dato que acepta esa columna, Null indica si la columna puede contener valores NULL, Key indica la clave
por la cual la columna se va a indexar y Default específica el valor por defecto que tiene la columna.
Ingreso de Datos a las tablas
Para ingresar información a una tabla se puede hacer básicamente de dos maneras. La primera se utiliza cuando se
tiene mucha información a ingresar de una sola vez entonces es conveniente almacenar esta información en un
archivo de texto, es decir, .txt. Una vez que se tiene este archivo, se procede de la siguiente forma:
mysql> LOAD DATA LOCAL INFILE "nombre_archivo.txt" INTO TABLE
nombre_tabla;
Para el caso que se desee ingresar un solo registro, entonces la sentencia a seguir es:
mysql> INSERT INTO nombre_tabla VALUES
(``valor_1'',''valor_2'',....,
Los datos a ingresar se separan por comas y van entre comillas. Estos datos indican
los valores que va a tomar cada una de las columnas, según el orden en que fueron creadas.
En el caso que se quiera ingresar un valor NULL no es necesario las comillas, sólo se
coloca NULL.
Recuperación de la Información
Para recuperar la información que está contenida en una tabla, la sentencia general a
seguir es:
mysql> SELECT qué_es_lo_que_se_desea_ver FROM nombre_tabla WHERE
condiciones_a_satisfacer;
Para los casos en que, se requiera:
o Ver o seleccionar toda la información de una tabla:
o mysql> SELECT * FROM nombre_tabla;
o Seleccionar filas en particular:
o mysql> SELECT * FROM nombre_tabla WHERE nombre_columna="lo
que se desee buscar"
o Seleccionar columnas en particular:
o mysql> SELECT nombre_columna_1, nombre_columna_n FROM
nombre_tabla;
Esto es conveniente cuando no se desea ver toda la fila o registro, entonces solo se
seleccionan aquellas columnas en las que se esté interesado.
MySQL Front
Ya vimos como crear bases de datos y tablas de la manera tradicional de MySQL, pero como podemos ver es algo
complejo, y como ya estamos acostumbrados a interfaces gráficas (GUI por sus siglas en ingles), les mostraré como
crear bases de datos de una manera completamente visual para no tener que tocar línea de comandos
de MySQL, para esto utilizaremos el software MySQL Front desarrollado por Ansgar Becker con correo electrónico
chef@anse.de y dirección de su página http://my.anse.de/forum.php en Alemania, aunque yo personalmente he
intentado entrar a esa dirección y no he podido, pero son los datos que trae el programa.
Veamos como usarlo:
• La primera vez que lo corremos no presentara un formulario en blanco y sin forma de poder ingresar datos, es
necesario presionar el botón New, para habilitarlo.
• Una vez presionado New aparecen unos datos ya predefinidos, lo único que tenemos que cambiar es nuestro
usuario y contraseña.
• Ahora hay que crear una tabla donde almacenaremos los datos, asi que seleccionamos la nueva base y de nuevo
vamos al menú Extra solo que ahora seleccionamos Create Table…
• En la ventana que aparece ponemos el nombre de la tabla el cual será tablacurso, en esa misma pantalla
crearemos los campos, los cuales serán id (con propiedades de primario y auto incremento), nombre, direccion,
telefono, email e imagen (todos de tipo varchar), ya que los agregamos presionamos Create!
• Nos mostrará la tabla creada con sus respectivos campos y propiedades.
• También si nosotros lo deseamos podemos ingresar información a la base desde el mismo MySQL Front, pero
este no es el caso. Ahora que si nosotros deseamos usar el método de línea de comandos del MySQL la
información de la tabla es esta:
CREATE TABLE tablacurso (
id tinyint(3) unsigned NOT NULL auto_increment,
nombre varchar(30) DEFAULT '0' ,
direccion varchar(30) DEFAULT '0' ,
telefono varchar(30) DEFAULT '0' ,
email varchar(30) DEFAULT '0' ,
imagen varchar(30) DEFAULT '0' ,
PRIMARY KEY (id)
);
Después de tanta información sobre MySQL ya es tiempo de iniciar a hacer programas PHP para manejo de bases
de datos de MySQL.
(conectarse.php).
conectarse.php
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<?php
function Conectarse()
{
if
(!($link=mysql_connect("localhost","pecesama","pruebas")))
{
echo "Error conectando a la base de datos.";
exit();
}
if (!mysql_select_db("basecurso",$link))
{
echo "Error seleccionando la base de datos.";
exit();
}
return $link;
}
Conectarse();
echo "Conexión con la base de datos conseguida.<br>";
?>
</body>
</html>
Como podemos ver en el ejemplo anterior aislé lo necesario para la conexión en una
función, ahora esa función la pondremos en un archivo PHP solo (conec.php).
conec.php
function Conectarse()
{
if (!($link=mysql_connect("localhost","pecesama","pruebas")))
{
exit();
}
if (!mysql_select_db("basecurso",$link))
{
exit();
}
return $link;
}
Ya que tenemos la función en un archivo separado solo hay que mandarlo llamar cuando sea necesario, de esta
forma cuando tengamos aplicaciones complejas que use muchas páginas php y sea necesario cambiarle algo a la
conexión solo se le tenga que hacer el cambio a este pequeño archivo y no a todas las páginas.
Agregar registros
Veremos un ejemplo de agregar registros a la base de datos (insertareg.php y
agregar.php).
insertareg.php
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de uso de bases de datos con PHP y MySQL</H1>
<FORM ACTION="agregar.php">
<TABLE>
<TR>
<TD>Nombre:</TD>
<TD><INPUT TYPE="text" NAME="nombre" SIZE="20"
MAXLENGTH="30"></TD>
</TR>
<TR>
<TD>Direccion:</TD>
<TD><INPUT TYPE="text" NAME="direccion" SIZE="20"
MAXLENGTH="30"></TD>
</TR>
<TR>
<TD>Telefono:</TD>
<TD><INPUT TYPE="text" NAME="telefono" SIZE="20"
MAXLENGTH="30"></TD>
</TR>
<TR>
<TD>Email:</TD>
<TD><INPUT TYPE="text" NAME="email" SIZE="20"
MAXLENGTH="30"></TD>
</TR>
<TR>
<TD>Imagen:</TD>
<TD><INPUT TYPE="text" NAME="imagen" SIZE="20"
MAXLENGTH="30"></TD>
</TR>
</TABLE>
<INPUT TYPE="submit" NAME="accion" VALUE="Grabar">
</FORM>
<hr>
<?php
include("conec.php");
$link=Conectarse();
Modificar registros
Veremos un ejemplo de modificar registros a la base de datos, consta de tres archivos diferentes, el primero para
introducir la consulta por el campo nombre, el segundo para realizar los cambios necesarios y el tercero para
modificar la base de datos (consulta.htm, busca.php y modifica.php).
consulta.htm
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de modificar</H1>
<FORM ACTION="busca.php">
Nombre:
<INPUT TYPE="text" NAME="nombre" SIZE="20" MAXLENGTH="30">
<INPUT TYPE="submit" NAME="accion" VALUE="Buscar">
</FORM>
</body>
</html>
busca.php
<html>
<body>
<?php
include("conec.php");
$link=Conectarse();
$Sql="select * from tablacurso where nombre like '%$nombre%'";
echo $Sql;
$result=mysql_query($Sql,$link);
?>
<TABLE BORDER=1 CELLSPACING=1 CELLPADDING=1>
<TR>
<TD> Nombre</TD>
<TD> Dirección </TD>
<TD> Telefono </TD>
<TD> Email </TD>
<TD> Imagen </TD>
</TR>
<form name="form1" method="post" action="modifica.php">
<?php
while($row = mysql_fetch_array($result))
{
printf("<tr><td><INPUT TYPE='text' NAME='nombre' SIZE='20'
MAXLENGTH='30' value='%s'></td><td> <INPUT TYPE='text'
NAME='direccion' SIZE='20' MAXLENGTH='30'
value='%s'> </td><td> <INPUT TYPE='text'
NAME='telefono' SIZE='20' MAXLENGTH='30'
value='%s'> </td><td> <INPUT TYPE='text'
NAME='email' SIZE='20' MAXLENGTH='30'
value='%s'> </td><td> <INPUT TYPE='text'
NAME='imagen' SIZE='20' MAXLENGTH='30'
value='%s'> </td></tr>",
$row["nombre"],$row["direccion"],$row["telefono"],$row["email
"],$row["imagen"]);
}
mysql_free_result($result);
?>
</form>
</body>
</html>
modifica.php
<?php
include("conec.php");
$link=Conectarse();
$Sql="UPDATE tablacurso SET nombre='$nombre',
direccion='$direccion', email='$email', telefono='$telefono'
imagen='$imagen' WHERE nombre='$nombre'";
mysql_query($Sql,$link);
header("Location: consulta5.php");
?>
Eliminar registros
Pasemos a la eliminación de registros, este consta de dos archivos, los dos .php el primero es para elegir el
registros a borrar y el segundo lo borra (eliminareg.php y borra.php).
eliminareg.php
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de uso de bases de datos con PHP y MySQL</H1>
<?php
include("conec.php");
$link=Conectarse();
$result=mysql_query("select * from tablacurso",$link);
?>
<TABLE BORDER=1 CELLSPACING=1 CELLPADDING=1>
<TR>
<TD> Nombre</TD>
<TD> Dirección </TD>
<TD> Telefono </TD>
<TD> Email </TD>
<TD> Imagen </TD>
<TD> Borra </TD>
</TR>
<?php
while($row = mysql_fetch_array($result)) {
printf("<tr><td> %s</td><td> %s </td><td> 
;%s </td><td> %s </td><td> %s </td><
/td><td><a href=\"borra.php?id=%d\">Borra</a></td></tr>",
$row["nombre"],$row["direccion"],$row["telefono"],$row["email
"],$row["imagen"],$row["ID"]);
}
mysql_free_result($result);
?>
</table>
</body>
</html>
borra.php
<?php
include("conec.php");
$link=Conectarse();
mysql_query("delete from tablacurso where ID = $id",$link);
header("Location: eliminareg.php");
?>
Ya conocemos como manejar una base de datos de MySQL con PHP, pero que pasa si nosotros tenemos nuestra
base de datos en Microsoft Access y es una base de datos enorme, que nos llevaría mucho tiempo en convertirla en
MySQL, existe una solución para poder usarla en PHP, esta opción es ODBC, del cual les platicaré un poco.
La principal desventaja son las capas a través de las cuales tiene que pasar la consulta, esto hace que el tiempo de
respuesta hasta que se obtienen los datos se incremente. El proceso es que la petición ha de "traducirse" a ODBC,
para que éste entienda la consulta. ODBC determina que fuente de datos contiene los datos que se piden
y transmite la petición a la siguiente capa que es la fuente de datos ODBC (ODBC data source). La fuente de datos
analiza la petición y "traduce" de nuevo la consulta a un formato que pueda ser "comprendido" por la DBMS. Este
complejo proceso puede verse alterado por cualquier fallo en cualquiera de sus fases y por tanto la consulta no
tendría éxito.
Cabe añadir que, las fuentes de datos ODBC deben estar configuradas correctamente en el ODBC.INI y en el
ODBCINST.INI antes de poder ser usada. Si intentas crear un informe en un sistema y tratas de abrirlo con otro
sistema, probablemente no empleen el mismo ODBC data source, y por tanto no se establecerá la conexión.
Además hay que asegurarse que el SQL usado en el ODBC ha de estar basado en los estándares establecidos por
el American National Standards Institute (ANSI) para el lenguaje SQL. Ahora vamos a verlo gráficamente. Soy
usuario de una aplicación de PHP que usa bases de datos externas para almacenar información, esta aplicación
trabaja directamente con MySQL, pero mi intención es tener una conexión con una base de datos de Microsoft
Access, porque es más fácil; PHP no trabaja directamente con Access, pero puede entenderse con él usando ODBC
de por medio. Necesito crear un origen de datos en ODBC para que PHP sepa a qué base de datos me refiero
cuando le solicite información.
Primero vamos a buscar a ODBC, que está en el Panel de Control.
Bueno, y ahora, el Data Source Administrator del Open DataBase Conectivity, u ODBC. Lo que sigue es crear
una fuente u origen de datos, pero antes unas explicaciones: Vas a notar que las primeras tres pestañas se refieren
a User DSN, System DSN y File DSN. Perdón, pero tengo la versión en inglés, voy a traducir un poco:
User DSN, nombre del origen de datos para el usuario. A veces, una máquina es utilizada por más de un
usuario, los orígenes de datos declarados aquí son exclusivos del usuario.
System DSN, nombre del origen de datos para el sistema. Todos los usuarios de la máquina tienen acceso a
estos orígenes de datos.
User DSN, nombre del origen de datos en archivo. Se crea un archivo con la extensión DSN, que sirve como
origen de datos y puede ser distribuido a otros usuarios.
Este origen es el que usa Excel por omisión cuando hace consultas, cuidado con eso. Está otra pestaña importante
que es ODBC Drivers u Controladores ODBC. Aquí se ven todos los controladores disponibles en la máquina. De
está forma puedes consultar si dispones del controlador que necesitas y si es la versión conveniente. Regularmente
los controladores de bases de datos vienen con un programa SETUP que los instala y quedan dados de alta en esta
lista.
Las otras pestañas merecen artículos aparte pues sirven más a los administradores y desarrolladores de sistemas.
Para el fin de crear un origen de datos, con lo que hemos visto tenemos. Lo siguiente: Vamos a seleccionar la
pestaña System DSN, nombre de origen de datos del sistema y presionamos el botón Add…, agregar..
Luego señalamos el controlador o driver del tipo de base de datos que queremos accesar: Microsoft Access Driver
(o controlador, en la versión en español) y presionamos Finalizar; pero fíjate que todavía no acabamos.
Lo que tenemos que hacer ahora es darle al nuevo origen de datos un nombre peculiar y distintivo, como estamos
creando un origen de datos para una base de datos que se llama MyTown.mdb pues le llamo MiPueblo y le damos
una descripción (que en realidad no es necesaria).
Eso es todo, ahora solamente se debe cerrar el administrador de ODBC presionado el botón Aceptar. Tenemos un
origen de datos nuevo que le será útil a aplicaciones que de otra forma no podrían leer una base de datos Access El
controlador de ODBC de Microsoft Access se puede instalar, si es que no lo tienes, desde el CD de Office o de
Access sí lo tienes como versión independiente.
Para más información y recursos respecto a ODBC puedes visitar: Ya conocemos que es ODBC y como crear un
DSN, ahora veamos como usar esas bases con PHP:
Veamos como realizar una conexión con ODBC a un DSN de nombre base y
mostrar los resultados (conectarODBC.php).
conectarODBC.php
<?
$conexion = odbc_connect("base","","","");
$rs= odbc_exec($conexion,"select * from usuarios");
while (odbc_fetch_row($rs))
{
echo odbc_result($rs,"Nombre");
echo $idusuario=odbc_result($rs,"idusuario");
}
odbc_close_all();
?>
Agregar registro
Eliminar registro
Ahora que ya manejamos archivos y bases de datos, vamos a ver un poco más de
PHP, algo más avanzado, como las sesiones e incluso algunas funciones con protocolos de
Internet.
Funciones de red
Cookies
La principal utilidad de las cookies (galletas) es la de solventar el problema de la
falta de estado en la navegación a través de las paginas web.
Con las cookies, pequeñas porciones de información se quedan registradas en el
navegador permitiendo identificar a este a través de diferentes páginas de un mismo sitio e
incluso durante visitas entre distintos días.
Realmente las cookies no son mas que cadenas de texto que son enviadas desde el
servidor al cliente (navegador) y almacenadas en este, luego el navegador envía estas
cookies al servidor permitiendo así la identificación del cliente en el servidor.
Funcionamiento
La cookie es enviada al navegador desde el servidor y si este la acepta permanece en él.
Las páginas piden la cookie al navegador...
El navegador las envía, permitiendo la identificación del usuario por parte del
servidor.
A continuación vamos a ver como usar las cookies para nuestro beneficio.
En este ejemplo vamos a ver como establecer una cookie y cómo se recupera su valor.
Se establece la cookie ejemusuario, cuya duración es una hora (cookies.php).
cookies.php
<?php
setcookie("ejemusuario", “Pedro”, time()+3600,"/","");
?>
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de uso de cookie</H1>
Se ha establecido una cookie de nombre <b>ejemusuario</b> con el
valor: <b><? print $ejemusuario; ?></b> que será válida durante 1
hora.
</body>
</html>
Sesiones
¿Qué son las sesiones?, básicamente una sesión es la secuencia de páginas que un
usuario visita en un sitio web. Desde que entra en nuestro sitio, hasta que lo abandona.
El término sesión en PHP, session en inglés, se aplica a esta secuencia de navegación,
para ello crearemos un identificador único que asignamos a cada una de estas sesiones de
navegación. A este identificador de sesión se le denomina, comúnmente, como la sesión.
El proceso en cualquier lenguaje de programación podría ser algo así:
¿Existe una sesión?, si existe lo retomamos, si no existe la creamos y le damos un identificador único.
Y para que no perdamos el hilo de la navegación del usuario deberemos asociar esta sesión a todas las direcciones
(URLs) y acciones de formularios. Podemos también crear una cookie que incluya el identificador de sesión, pero es
conveniente recordar que la disponibilidad o no de las cookies depende del usuario, y no es conveniente fiarse de lo
que un usuario pueda o no tener habilitado. Lo contado hasta ahora es teoría pura y es aplicable a cualquier
lenguaje de programación C, Perl, etc. Los que programamos en PHP4 tenemos la suerte de que toda la
gestión de sesiones la hace el mismo PHP.
Por lo tanto lo comentado aquí sobre sesiones es solo aplicable a PHP4.
Inicialización de la sesión
Para utilizar sesiones en PHP lo primero es inicializarlas. Podemos hacerlo explícitamente, mediante la función
session_start(), o al registrar una variable en una sesiónmediante session_register('miVariable'). En ambos casos se
crea una nueva sesión, si no existe, o se retoma la sesión actual.
<?php
session_start();
echo "Se inició la sesión";
?>
Esta es la forma más básica, si el usuario tiene las cookies activadas, PHP habrá insertado de forma automática la
sesión y ésta será pasada de una página a otra sin hacer nada más. Desde un punto de vista práctico la sesión es
operativa, pero no vemos nada. Podemos obtener la sesión en cualquier momento mediante la función session_id().
<?php
session_start();
echo 'La sesión actual es: '.session_id();
?>
En este caso session_start() comprueba en las cookies que existe una sesión y continua con ella, session_id()
devuelve el identificador actual.
Veamos otro ejemplo que, tal vez, te lo aclare un poco más:
<?php
session_register('contador');
echo '<a href="'.$PHP_SELF.'?'.$SID.'">Contador vale:
'.++$contador.'</a>';
?>
Como dije anteriormente la sesión se crea si no existe o se recoge mediante
session_start(), o también cuando se registra una variable de sesión mediante
session_register().
Si no has utilizado nunca las sesiones, el concepto de variable de sesión, puede resultar
un poco extraño. Básicamente es una variable, como cualquiera de las que gestiona PHP4,
pero que reside en un espacio específico en el servidor, junto con el identificador de sesión,
y que pertenece únicamente a un usuario.
En nuestro ejemplo anterior, registramos la variable $contador en la primera línea del
script. En la segunda línea, entre otras cosas, cada vez que recarguemos la página o
hagamos click sobre el enlace, el valor de $contador se incrementará en 1.
En esta línea hacemos uso de la variable reservada $PHP_SELF, que hace referencia
al propio script en ejecución y una constante propia de PHP4, $SID, que contiene el
nombre de la sesión y el identificador de la misma.
Podemos averiguar también el nombre de la sesión, o modificarlo, mediante la función
session_name(). Veamos una prueba práctica (sesion.php):
sesion.php
<?php
session_name('misesion');
session_register('contador');
echo '<a href="'.$PHP_SELF.'?'.SID.'">Contador vale:
'.++$contador.'</a><br>';
Error común
Uno de los errores más comunes cuando se utilizan sesiones es dejar líneas en blanco
antes de la inicialización de PHP o enviar alguna salida a la pantalla. Para probarlo crea una
línea en blanco o con cualquier cosa antes de <?php.
Si tienes las cookies activadas, te encontrarás un error de este tipo:
Warning: Cannot send session cookie - headers already sent by (output
started at /taller/sesiones.php:2) in / taller/sesiones.php on line 4
PHP está informando de que no puede activar las cookies en el navegador del usuario,
porque las cabeceras ya han sido enviadas. Simplemente por la existencia de una línea en
blanco. Como medida práctica, no dejes espacios ni antes del inicio del script, ni después de
la finalización.
Si después de todo lo comentado aún no entiendes para que sirven las sesiones,
veamos un ejemplo práctico. Imagina que quisieras crear un sistema de carrito de compras
Carrito de compra
Si después de todo lo comentado aún no entiendes para que sirven las sesiones,
veamos un ejemplo práctico. Imagina que quisieras crear un sistema de carrito de compras,
en su forma básica podría ser algo así (carrito.php):
carrito.php
<?php
session_start();
session_register('itemsEnCesta');
if ($item){
if (!isset($itemsEnCesta)){
$itemsEnCesta[$item]=$cantidad;
}else{
foreach($itemsEnCesta as $k => $v){
if ($item==$k){
$itemsEnCesta[$k]+=$cantidad;
$encontrado=1;
}
}
if (!$encontrado) $itemsEnCesta[$item]=$cantidad;
}
}
?>
<html>
<body>
<tt>
<form action="<?=$PHP_SELF."?".SID?>" method="post">
Dime el producto <input type="text" name="item" size="20"><br>
Cuantas unidades <input type="text" name="cantidad" size="20"><br>
<input type="submit" value="Añadir a la cesta"><br>
</form>
<?
if (isset($itemsEnCesta)){
echo'El contenido de la cesta de la compra es:<br>';
foreach($itemsEnCesta as $k => $v){
echo 'Artículo: '.$k.' ud: '.$v.'<br>';
}
}
?>
</tt>
</body>
</html>
Una breve explicación. En la línea 4 comprobamos si el usuario ha pasado algún artículo, desde el formulario. En la
5 si el array itemsEnCesta no existe, lo creamos con el nuevo producto y la cantidad indicada. Si el array existe
recorremos su contenido, entre las líneas 8 y 13, y si encontramos un artículo igual, añadimos la cantidad en la línea
10. Si no lo encontramos, es un nuevo artículo, por lo tanto, añadimos el nuevo producto con la
correspondiente cantidad a itemsEnCesta en la línea 14. Y a continuación imprimimos el formulario y los resultados,
si los hubiera, a partir de la línea 18, donde empieza el HTML.
¿Te imaginas las posibilidades de un sistema de almacenamiento de información de estas características?. No
necesitas archivos, ni bases de datos, ni tienes que andar pasando valores de una página a otra. PHP va
gestionando estos datos por nosotros, hasta el momento en que decidamos almacenar la información donde más
nos interese.
Envió de e-mails
PHP nos ofrece la posibilidad de enviar emails de una manera sencilla y fácil, para ello el lenguaje nos proporciona
la instrucción mail( )
<?php
mail(destinatario, tema, texto del mensaje);
?>
En el parámetro destinatario pondremos la dirección de email a donde se enviará el
mensaje, en el parámetro tema el tema o subject del mensaje y el parámetro texto del
mensaje el cuerpo del mensaje en formato texto plano.
Existe una sintaxis extendida de la instrucción mail( ) que nos permite añadir
información adicional a la cabecera del mensaje.
<?php
mail(destinatario, tema, texto del mensaje, información adicional de
cabecera);
?>
En la información de cabecera podremos incluir parámetros adicionales al mensaje
como Reply-To:, From:, Content-type:... que nos permiten tener un mayor control sobre el
mensaje.
Ahora veamos un pequeño ejemplo de cómo enviar un correo electrónico con PHP
(email.htm y email.php).
email.htm
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de envió de email</H1>
Introduzca su direccion de email:
<FORM ACTION="email.php" METHOD="GET">
<INPUT TYPE="text" NAME="direccion"><BR><BR>
Formato: <BR>
<INPUT TYPE="radio" NAME="tipo" VALUE="plano" CHECKED> Texto
plano<BR>
<INPUT TYPE="radio" NAME="tipo" VALUE="html"> HTML<BR><BR>
<INPUT TYPE="submit" VALUE="Enviar">
</FORM>
</body>
</html>
email.php
<html>
<head>
<title>Ejemplo de PHP</title>
</head>
<body>
<H1>Ejemplo de envió de email</H1>
<?
if ($direccion!=""){
if ($tipo=="plano"){
// Envio en formato texto plano
mail($direccion,"Ejemplo de envió de
email","Ejemplo de envió de email de texto
plano\n\n\nhttp://www.pecesama.com","FROM: Pedro
<pedro.santana@pecesama.com>\n");
} else {
// formato HTML
mail($direccion,"Ejemplo de envió de
email","<html><head><title>PecesamaSoft. Taller de
PHP</title></head><body>Ejemplo de envió de email
de HTML<br><br>
nhttp://www.pecesama.com</body></html>","Contenttype:
text/html\n", "FROM: Pedro
<pedro.santana@pecesama.com>\n");
}
echo "Se ha enviado un email a la direccion:
",$direccion," en formato <b>",$tipo,"</b>.";
}
?>
<br>
</FORM>
</body>
</html>
Introducción
De todos los servicios que ofrece INTERNET, no cabe duda de que el más popular es la WWW (World Wide Web).
La WWW no es más que millones de páginas en formato electrónico, con los contenidos y temáticas más diversas a
las que podemos acceder gracias a un computador + modem + browser (navegador).
Una página WEB no es más que un fichero de texto (ASCII), escrito en formato HTML (Hyper Text Markup
Language = lenguaje etiquetado de hipertexto).
La programación en HTML no tiene ninguna utilidad para un usuario normal, ya que en el mercado existen
herramientas que evitan la necesidad de tener que introducir manualmente los “tags”: HotMetal, FontPage, Word,
etc.Lo que sí tienen sentido es el estudio de la programación en JavaScript.
JavaScript es un lenguaje de programación creado por la empresa Netscape (creadora de uno de los navegadores
más conocido) Es el lenguaje de programación más utilizado en Internet para añadir interactividad a las páginas web
No confundir el JavaScript con el Java. El Java es un lenguaje de programación de propósito general como lo son
el C++ o el Visual Basic. Un programa en JavaScript se integra en una página Web (entre el código HTML) y es el
navegador el que lo interpreta (ejecuta). Es decir el JavaScript es un lenguaje interpretado, no compilado (no se
genera ningún tipo de fichero objeto o exe).
Para programar en JavaScript sólo necesitamos un editor de texto (utilizaremos el Bloc de Notas del Windows) y
un navegador (utilizaremos el Microsoft Internet Explorer) para ejecutarlo.
El HTML es un lenguaje basado en pares de tags (etiquetas). Un tag es un código entre<>, si es de apertura o un
código entre </ > si es de cierre.
Los browsers (navegadores de Internet), son capaces de traducir estas etiquetas (tags) de
forma que presentan visualmente la página.
Un programa “JavaScript” se escribe integrado en una página HTML, por lo tanto no es más que un fichero de texto
que contiene una serie de pares de tags correspondientes a la página Web (como mínimo el par: <HTML>,
</HTML>), además del par de tags característico de un programa JavaScript. Dicho fichero se ha de grabar
necesariamente con la extensión HTM (característica de una página HTML).
Un programa “JavaScript” no es más que una secuencia de ordenes, que deben terminar en punto y coma, entre
los tags:
<SCRIPT LANGUAGE=”JavaScript”>
y
</SCRIPT>
• En nuestro Prog001.htm, hemos incluido el programa en la cabecera (HEAD) de la página, pero podríamos
colocarlo en cualquier parte del fichero htm , Nuestro primer programa JavaScript contiene una única sentencia:
alert(“”¡Hola
Mundo!”);
Que “abre” una ventana con el mensaje que tenemos entre comillas. Al hacer clic en el [Aceptar] de la ventana
“alert”, se acaba el programa JavaScript (se encuentra el tag </SCRIPT>) y continua ejecutándose la página
HTML.
- Utilizando el “Bloc de Notas” escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG002.HTM
var nom;
nom=prompt("Escribe tu nombre ","Paco");
alert("Mucho gusto "+ nom);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog002.htm
- Ejecútalo varias veces, observando detenidamente lo que sucede.
- Estudio del Prog002.htm
1º) Primera y última línea: <HTML> y </HTML>
Es decir: página html mínima que necesitamos para incluir un programa JavaScript.
2º) Segunda y penúltima líneas: <SCRIPT LANGUAGE=.....> y </SCRIPT>, es decir
programa en JavaScript
3º) Primera sentencia del programa: // PROG002.HTM
Única línea del programa que no es necesario acabarla con punto y coma.
Todas las líneas que empiezan por // son comentarios para el programador, es decir no forman parte del programa,
dicho de otra forma: el navegador si encuentra una línea que empieza por //, la salta.
4º) var nom;
Definimos una variable de nombre nom
5º) nom = prompt(“Escribe tu nombre”,”Paco”);
Aparece un recuadro con un mensaje y un campo donde podemos escribir algo; el mensaje corresponde a lo que
escribimos en el primer argumento de la función prompt, encerrado entre comillas. El segundo argumento del
prompt contiene el valor que aparece por defecto en el campo del cuadro de diálogo.
El valor del prompt es nom, es decir lo que nosotros escribamos en el cuadro será el valor que tomará la variable
nom. Si no escribimos nada y hacemos click en [Aceptar], el prompt, es decir la variable nom
tomará el valor de Paco, porque es el valor que aparece por defecto.
6º) alert("Mucho gusto "+nom); Aparece un cuadro con el mensaje "Mucho gusto" y a continuación el valor de la
variable "nom", que será lo que hemos escrito en el primer cuadro que nos ha aparecido.
En definitiva:
- La función prompt nos permite introducir "valores", dichos valores se han de guardar en
variables, que previamente hemos de declarar con la palabra reservada "var"
- La función "alert" muestra mensajes y/o valores de variables.
- Utilizando el "Bloc de Notas del Windows" escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG003.HTM
/*Programa que sirve para calcular
el área de un rectángulo */
var base,altura;
base=prompt("Escribe la base del Rectángulo","");
altura=prompt("Escribe la altura del Rectángulo","");
alert("El área del Rectángulo es = "+(base*altura));
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog003.htm
- Ejecútalo varias veces. Sería conveniente utilizar números enteros y también decimales (5.72, 0.531: observa que
has de utilizar el punto decimal inglés).
- Si has ejecutado el programa una vez, para volverlo a ejecutar, no es necesario que
"cierres" el navegador, basta que hagas:
Menú Ver
Actualizar o si quieres ir más rápido, pulsa la tecla [F5]
- Es importante que tengas claro este programa:
• Declaramos dos variables (var), que necesitamos para introducir la base y la altura
del rectángulo, a través de dos "prompts":
base= prompt......
altura= prompt.....
• Por último necesitamos dos "alerts" que nos muestre el resultado del programa,
que es simplemente el producto base * altura
- El único elemento nuevo que aparece en el Prog003.htm es:
/*Programa que sirve para calcular
el área de un rectángulo */
Todo lo que aparece escrito entre /* y */ no es más que un comentario para el programador, igual que pasaba con
las líneas que empezaban por // La diferencia entre // y /* */ está en que esta última forma de incluir un comentario,
nos permite colocarlo de forma que ocupe más de una línea.
Variables
- Declaración de variables
Una variable se puede declarar en JavaScript, de dos formas:
• Forma Explícita: var nombre Variable;
• Forma Implícita: var nombre Variable= valor;
En el último caso no es imprescindible escribir var, pero es conveniente, ya que de esta forma
localizamos rápidamente todas las variables del programa.
El "JavaScript" es un lenguaje de programación "Case Sensitive", esto es: no es lo mismo las
mayúsculas que las minúsculas. Es decir, para el JavaScript: pepe es distinto de Pepe y distinto de pEpe.
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE=''JavaScript''>
// PROG004.HTM
/* Programa que utiliza una variable explícita
y dos implícitas */
var Expli;
var pi=3.141592;
var radio=7;
Expli=pi*radio*radio;
alert("Área del Círculo = "+Expli);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog004.htm
- Ejecútalo
Tipos de Datos
Cuando declaramos una variable, ésta no pertenece a ningún tipo de dato en concreto, se dice
que es Undefined. Es al asignarle un valor cuando pasa a ser de uno u otro tipo, según el dato
que albergue.
Existen 6 tipos de datos:
String: cadenas de texto Object: objetos.
Number: valores numéricos Null: nulo.
Boolean: true o false Undefined: no definido.
Podemos averiguar el tipo de dato que contiene una variable si utilizamos la función incorporada typeof
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE=''JavaScript''>
// PROG005.HTM
var Pepe;
var PEPE="Hola que tal ";
var pepE=75.47;
var pEpe=" ¿Como estás?";
Pepe=PEPE+pEpe;
alert("PEPE="+PEPE);
alert("PEPE es "+typeof(PEPE));
alert("pepE="+pepE);
alert("pepE es "+typeof(pepE));
alert("pEpe="+pEpe);
alert("pEpe es "+typeof(pEpe));
alert("Pepe="+Pepe);
alert("Pepe es "+typeof(Pepe));
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog005.htm
- Ejecútalo tantas veces como quieras.
En JavaScript los textos se denotan por comillas dobles o comillas simples, pero no ambas a la vez.
Variable1 = "Pepito"
Variable2 = 'Paquito'
Podemos incluir un carácter de control en una cadena de texto, si utilizamos el llamado carácter de escape que
es: \
Los caracteres de control más usados son:
\n salto de línea
\t tabulador
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG006.HTM
var num;
alert("Hola que tal");
alert("Hola \nque tal");
alert("Hola\t"+"que"+"\n"+"tal");
alert("Hola\n que\n t\nal");
num=prompt("Escribe un número: ","");
alert("El \ndoble\n es: \n"+(num*2));
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog006.htm
- Ejecútalo, observando detenidamente la acción de \n y \t
- Si no introducimos un número en el "prompt", en el "alert" correspondiente al doble del número, aparecerá NaN,
que quiere decir que no es un número.
Podemos guardar indistintamente en una variable number un número entero, decimal, positivo o negativo.
Ejemplos:
var numNatural= 1234;
var numEntero = -479;
var numDecimal = 3.141592;
var numDecimal2 = -0.123;
- Bases de Numeración en JavaScript (números enteros)
Por defecto, el sistema de numeración es el decimal.
• Base Hexadecimal (base 16): anteponemos el prefijo 0X
• Base Octal (base 8): anteponemos un cero
Dígitos del sistema decimal: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Dígitos del sistema hexadecimal: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A (que corresponde al 10 en base
decimal), B (que corresponde al 11 en decimal), C (12), D (13), E (14), F (15)
Ejemplo:
FF32 en base 16 es 2 + 3*16 + 15*162 + 15*163 = 65330 en sistema decimal
Es decir: 0xFF32 (número en base 16, según notación de JavaScript) = FF3216 = 6533010
123458 = 5 + 4*8 + 3*82 + 2*83 + 1*84 = 534910
Es decir: 012345 (número en base 8, según notación de JavaScript) = 123458 = 534910
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE=''JavaScript''>
// PROG007.HTM
salida=salida+x+y+z;
salida=salida+x1+" "+y1;
salida=salida+num1+" "+num2;
salida=salida+" ,ya me he cansado";
alert(salida);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog007bb.htm y ejecútalo.
- Observa de qué forma acumulamos muchos datos en un solo “alert” (ésta será la forma de
proceder, cuando necesitemos una “salida” con muchos valores):
• definimos una variable “vacía”: var salida=””;
• acumulamos a la variable salida todo lo que queramos: salida=salida+ lo que sea
• “lo que sea” puede ser una cadena (un texto) o una variable (sea numérica o de
texto).
salida=salida + x1 + “ “ + y1;
salida=salida + “ya me he cansado”;
• Para acabar, un solo “alert”: alert(salida);
Variables nulas.
Contadores
Uno de los instrumentos más utilizados en todo lenguaje de programación es el llamado contador
Observa:
var x= 10;
x = x+1;
x = x-5;
Declaramos una variable "x", que es numérica y que inicialmente es 10.
La línea "x = x+1" es un contador, que hemos de leer: El nuevo valor de "x" es igual al
anterior valor de "x" más una unidad. Es decir, que en estos momentos nuestra variable "x"
es igual a 11.
La siguiente línea: "x = x-5" es otro contador que hemos de leer: el nuevo valor de "x" es
igual al anterior valor de "x" menos 5 unidades. Es decir, que el valor de la variable "x" es
ahora 11 - 5 = 6
- Haz un programa para comprobar lo que hemos dicho sobre los contadores, es decir:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG009.HTM
var x=10;
alert("El valor inicial de x es "+x);
x=x+1;
alert("Después de x=x+1, x="+x);
x=x-5;
alert("Después de x=x-5, x="+x);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog009.htm y ejecútalo.
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG010.HTM
var num1="30";
var num2="15";
// Observa que definimos dos cadenas de texto
alert("30+15= "+(num1+num2));
alert("30*15= "+(num1*num2));
</SCRIPT>
</HTML>
- Graba el programa en TuCarpeta con el nombre Prog010.htm
- Ejecútalo.
- La conclusión está clara:
• Si sumamos dos cadenas (aunque contengan números) de texto se produce la concatenación (unión) de los dos
textos.
• Si multiplicamos (o hacemos cualquier operación aritmética que no sea la suma), dos cadenas de texo que en
realidad contienen números, se produce una conversión implícita de las cadenas a números y aparece el producto
aritmético de los números.
- ¿Qué sucede si introducimos dos números a través de la función prompt?. Vamos a verlo:
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
//PROG011.HTM
var num1,num2;
num1=prompt("Escribe un número","");
num2=prompt("Escribe otro número","");
alert("La suma es ="+(num1+num2));
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta, con el nombre Prog011.htm
- Ejecútalo. No funciona como deseamos debido a que el resultado de un prompt, siempre es una cadena de texto.
El problema que tenemos pendiente, es ¿cómo sumar en JavaScript?
parseInt(cadena, número)
Devuelve números enteros, el segundo argumento nos permite escoger la base de numeración (entre 2 y 36)
parseInt ("ABC",16) = 2748 ABC16 = 274810 Si no especificamos el segundo argumento, por defecto es 10.
Si la cadena empieza por 0x y no existe el segundo argumento, se entiende que es 16. Si la cadena empieza por 0 y
no existe el segundo argumento, se entiende que es 8
toString(argumento)
Si argumento = número
Devuelve una cadena que contiene el número Puede haber un argumento opcional:
(13).toString(16) =”d” siendo 1310 = d16 ,(13).toString(2) = “1101” siendo 1310 = 11012
- Vamos a hacer un programa que sume números en JavaScript.
Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
//PROG012.HTM
var num1,num2;
num1=prompt("Escribe un número","");
num1=parseFloat(num1);
num2=prompt("Escribe otro número","");
num2=parseFloat(num2);
alert("La suma es ="+(num1+num2));
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog012.htm
- Ejecútalo, utilizando números enteros, naturales y decimales.
A partir de este momento hemos de tener claro si los “prompts” corresponden a números
enteros, decimales o de texto:
- Si “x” ha de ser un número entero escribiremos:
x = parseInt(prompt(“Escribe un número entero”,””));
- Si “x” ha de ser un número decimal escribiremos:
x = parseInt(prompt(“Escribe un número entero o decimal”,””));
- Si “x” ha de ser una cadena de texto escribiremos:
x = prompt(“Escribe el texto correspondiente”,””);
- Escribe el siguiente programa:
<HTML>
JavaScript Fermí Vilà 15
<SCRIPT LANGUAGE="JavaScript">
// Prog012b.htm
var x,y;
x=parseInt(prompt("Escribe un entero ",""));
y=parseInt(prompt("Escribe otro entero ",""));
alert("La suma de "+ x +" + " + y +" es =" + (x+y) +"\n"+
"El producto de "+ x +" y "+ y +" = "+(x*y)+"\n"+
"El promedio de "+ x +" y "+ y +" es "+ (x+y)/2);
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog012b.htm, y ejecútalo.
En el ejercicio Prog007.htm habíamos visto una forma de convertir un número en base 8 o
base 16 en base 10. Pero dichos números debíamos de escribirlos implícitamente, es decir en
el programa. Nos gustaría hacer un programa que:
- Nos preguntara un número en base 16 (prompt)
- Nos diera como resultado el número anterior pero en base 10
Vamos a ver si lo conseguimos:
- Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// Prog012bb.htm
var m,n,x;
m=prompt("Escribe un número en base 16","");
n=parseInt(m,16);
alert("El número "+m+" en base 16, es igual a "+n+" en base 10");
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog012bb.htm en TuCarpeta y ejecútalo para el número “FF32”, a
ver si es verdad que nos da “65330” como resultado.
Observa el funcionamiento del programa Prog012bb.htm:
• m = prompt(“Escribe un número en base 16”, “”)
Lo que escribamos (un número en base 16), se guardará en la variable “m” como texto
(ya que no hemos puesto ningún “parseInt” ni “parseFloat”).
• n =parseInt(m,16)
La variable “n” guardará el número en base 10, Es decir: parseInt(cadena, 16), transforma la “cadena”, en nuestro
ejemplo un número escrito en base 16, en el correspondiente número (no cadena) pero en base decimal.
Vamos a ver si el procedimiento sirve para cualquier otra base...
Antes de todo veamos unos cuantos números en diferentes bases:
367 = 6 + 3.7 = 27 en base 10
1234 = 3 + 2.4 + 1.42 = 27 en base 10
51346 = 4 + 3.6 + 1.62 + 5.63 = 1138 en base 10
- Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// Prog012bbb.htm
var m7,n7;
var m4,n4;
var m6,n6;
m7=prompt("Escribe un número en base 7","");
n7=parseInt(m7,7);
m4=prompt("Escribe un número en base 4","");
n4=parseInt(m4,4);
m6=prompt("Escribe un número en base 6","");
n6=parseInt(m6,6);
alert("El número "+m7+" en base 7, es igual a "+n7+" en base 10\n"+
"El número "+m4+" en base 4, es igual a "+n4+" en base 10\n"+
"El número "+m6+" en base 6, es igual a "+n6+" en base 10");
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog012bbb.htm y ejecútalo, probándolo con los números
anteriores. Veamos el problema inverso: dado un número en base 10, nos interesa convertirlo a base 7,
por ejemplo.Matemáticamente:
Sea 593 un número en base 10
59310 = 15057 , porque:
En JavaScript deberíamos hacerlo de la siguiente forma,
escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// Prog012bbbb.htm
var m,n;
n=parseInt(prompt("Escribe un número entero en base 10",""));
m=(n).toString(7);
alert("El número "+n+" en base 10, es igual a "+m+" en base 7");
</SCRIPT>
</HTML>
Grábalo con el nombre Prog012bbbb.htm y ejecútalo, probando su funcionamiento con el número 593
Significado:
Si se cumple la condición, se ejecutan las sentencias 1, 2 y 3 y si no se cumple se ejecutan las
sentencias 4, 5, 6. La opción “else” es opcional.
- Observa la diferencia entre “=” y “==”
a = 3*9 es una asignación, es decir la variable “a” es 27. En cambio if(a==5) es una condición:
si “a” es idéntico a 5 (si el valor de “a” es el número 5)…
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG014.HTM
var a,b;
a=parseFloat(prompt("Escribe el primer número",""));
b=parseFloat(prompt("Escribe el segundo número",""));
if(a==b) alert("Los dos números son iguales");
if(a != b) alert("Los dos números son distintos");
if(a>b)
{
alert("El primer número es mayor que el segundo");
}
else
{
alert("El primer número no es mayor que el segundo");
}
if((a>b) && (100>a))
{
alert("El primero es mayor que el segundo");
alert("Además los dos son menores de 100");
}
else
{
alert("El primero no es mayor que el segundo");
alert("O uno de los dos números es mayor o igual a 100");
}
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog014.htm en TuCarpeta.
- Ejecuta el programa para los siguientes casos, observando detenidamente lo que aparece:
1) a=70, b=2
2) a=50, b=30
3) a=7, b=11
4) a=100, b=50
5) a=50, b=100
- Observa:
a==b “a” es igual a “b”
a != b “a” es diferente a “b”
(a>b) && (100>a)
“a” es mayor que “b” y además “100 es mayor que –a-“
El else correspondiente a la condición anterior, sería equivalente a no(a>b) ||
no(100>a), es decir la negación de la primera condición o la negación de la segunda (o las dos
negaciones a la vez).
JavaScript Fermí Vilà 26
Sintaxis:
while(condición)
{
setencia1;
sentencia2;
sentencia3;
}
Significado:
“Mientras” se cumpla la condición, se irán repitiendo las sentencias 1, 2 y 3.
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG015.HTM
var x=0;
while(x<6)
{
alert("El valor de x es= "+x);
x=x+1;
}
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog015.htm en TuCarpeta y ejecútalo.
- Estudio del Prog015.htm
• En “palabras”, nuestro programa nos dice: “mientras” la x sea inferior a 6;
escribe el valor de “x”;
incrementa en una unidad el valor de “x”;
• Al principio x=0
Se cumple la condición del while: x<6
Aparece escrito x=0
Al pasar por el contador x=1
Se cumple la condición x<6
Aparece escrito x=1
Al pasar por el contador x=2
Aparece escrito x=2
…
…
Cuando x=6 no se cumple la condición y por lo tanto se acaba el programa.
<SCRIPT LANGUAGE="JavaScript">
// PROG017.HTM
var nom;
var indice=1;
var num;
var respuesta=" ";
nom=prompt("Escribe tu nombre","");
num=prompt("Cuántas veces quieres que lo repita","");
num=parseInt(num,10); // era una cadena y ahora es un número
while (indice <= num)
{
respuesta=respuesta+nom+"\n";
indice++;
}
alert(respuesta);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog017.htm y ejecútalo
- Recuerda que en el “ParseInt” no es necesario escribir el 10, ya que por defecto (si no lo
escribimos), es base 10.
Programa que acumula la suma y el producto de los números que queramos
- Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG018.HTM
var num;
var sum=0;
var pro=1;
var respuesta="";
num=prompt("Escribe un número diferente de cero=","");
num=parseFloat(num);
while(num != 0)
{
sum=sum+num;
pro=pro*num;
respuesta=respuesta+num+"\tsuma parcial:"+sum+"\tproducto
parcial:"+pro+"\n";
num=prompt("Escribe otro número (para acabar introduce cero)","");
num=parseFloat(num);
}
alert(respuesta);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta con el nombre Prog018.htm y ejecútalo.
- Observa como acumulamos la suma y el producto:
Contador que acumula la suma de los números “num”: sum=sum+num;
Hemos de inicializar a 0 la variable “sum”.
Contador que acumula el producto de los números “num”: pro=pro*num
Hemos de inicializar a 1 la variable “pro”.
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG019.HTM
var texto;
var num;
var salida="";
texto=prompt("Escribe un texto","");
num=prompt("Cuántas veces quieres que lo repita","");
num=parseInt(num,10);
for(i=1;i<=num;i++)
{
salida=salida+texto+"\n";
}
alert(salida);
</SCRIPT>
</HTML>
- Graba el fichero en TuCarpeta, con el nombre Prog019.htm y ejecútalo unas cuántas
veces.
Programa que calcula todos los múltiplos de 11 menores de 3000 y por último nos da la suma de todos
ellos.
- Escribe el siguiente programa:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG020.HTM
var salida="";
var sum=0;
for(multi=11;multi<3000;multi=multi+11)
{
salida=salida+multi+" ";
sum=sum+multi;
}
alert(salida+"\nLa Suma de todos ellos es= "+sum);
</SCRIPT>
</HTML>
- Grábalo en TuCarpeta, con el nombre Prog020.htm y ejecútalo.
if (x1>=x2)
{
alert("No tiene sentido lo que intentas hacer");
}
else
{
paso=prompt("Escribe el incremento de x","");
paso=parseFloat(paso);
if (paso<=0)
{
alert("No tine sentido lo que intentas hacer");
}
else
{
for (i=x1;i<=x2;i=i+paso)
{
y=i*i-5*i+10;
salida=salida+i+" "+y+"\n";
}
alert(salida);
}
}
</SCRIPT>
</HTML>
- Grábalo con el nombre Prog024.htm en TuCarpeta y ejecútalo, convendría probar los
casos x1>=x2 y paso<0
- Observa de qué forma salimos del programa si introducimos datos que no tienen sentido.
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG025.HTM
var cat1,cat2,hipo;
cat1=prompt("Escribe el valor de un cateto","");
cat2=prompt("Escribe el valor del otro cateto","");
cat1=parseFloat(cat1);
cat2=parseFloat(cat2);
hipo=Math.sqrt(cat1*cat1+cat2*cat2);
alert("La hipotenusa del triángulo de catetos "+cat1+" y "+cat2+" es
"+hipo);
</SCRIPT>
</HTML>
- Graba el fichero con el nombre Prog025.htm en TuCarpeta y ejecútalo unas cuantas
veces.
Programa que calcula tantas hipotenusas como queramos
- Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG026.HTM
var opcion="S";
var cat1,cat2,hipo;
while(opcion=="S" || opcion=="s")
{
cat1=prompt("Escribe el valor de un cateto","");
cat2=prompt("Escribe el valor del otro cateto","");
cat1=parseFloat(cat1);
cat2=parseFloat(cat2);
hipo=Math.sqrt(cat1*cat1+cat2*cat2);
alert("La hipotenusa del triángulo de catetos "+cat1+" y "+cat2+" es
"+hipo);
opcion=prompt("¿Quieres calcular otra hipotenusa? (S/N)","");
}
alert("Adiós muy buenas");
</SCRIPT>
</HTML>
- Graba el programa en TuCarpeta con el nombre Prog026.htm y ejecútalo.
Programa que resuelve una ecuación de segundo grado
- Escribe:
<HTML>
<SCRIPT LANGUAGE="JavaScript">
// PROG027.HTM
var a,b,c;
var discri;
var x1,x2;
a=prompt("Escribe el coeficiente de la x^2","");
a=parseFloat(a);
b=prompt("Escribe el coeficiente de la x","");
b=parseFloat(b);
c=prompt("Escribe el término independiente","");
c=parseFloat(c);
discri=b*b-4*a*c;
if(discri<0) alert("Soluciones Imaginarias");
if(discri==0)
{
x1=-b/(2*a);
alert("Solución doble que es "+x1);
}
if(discri>0)
{
x1=(-b+Math.sqrt(discri))/(2*a);
x2=(-b-Math.sqrt(discri))/(2*a);
alert("Las soluciones son = "+x1+" y "+x2);
}
</SCRIPT>
</HTML>
- Graba el programa en TuCarpeta con el nombre Prog027.htm
- Ejecútalo para los casos:
a= 1, b= 1, c= 1
a= 2, b=-6, c= -20
a= 1, b= 4, c= 4
Visual-Basic script es una herramienta de diseño de aplicaciones para Windows, en la que estas se desarrollan en una gran parte a partir
del diseño de una interface gráfica. En una aplicación Visual - Basic, el programa está formado por una parte de código puro, y otras partes
asociadas a los objetos que forman la interface gráfica.
Es por tanto un termino medio entre la programación tradicional, formada por una sucesión lineal de código estructurado, y la programación
orientada a objetos. Combina ambas tendencias. Ya que no podemos decir que VB pertenezca por completo a uno de esos dos tipos de
programación, debemos inventar una palabra que la defina : PROGRAMACION VISUAL.
- Creación de un interface de usuario. Este interface será la principal vía de comunicación hombre máquina, tanto para salida de datos
como para entrada. Será necesario partir de una ventana - Formulario - a la que le iremos añadiendo los controles necesarios.
- Definición de las propiedades de los controles - Objetos - que hayamos colocado en ese formulario. Estas propiedades
determinarán la forma estática de los controles, es decir, como son los controles y para qué sirven.
- Generación del código asociado a los eventos que ocurran a estos objetos. A la respuesta a estos eventos (click, doble click,
una tecla pulsada, etc.) le llamamos Procedimiento, y deberá generarse de acuerdo a las necesidades del programa.
- Generación del código del programa. Un programa puede hacerse solamente con la programación de los distintos
procedimientos que acompañan a cada objeto. Sin embargo, VB ofrece la posibilidad de establecer un código de programa
separado de estos eventos. Este código puede introducirse en unos bloques llamados Módulos, en otros bloques llamados
Funciones, y otros llamados Procedimientos. Estos Procedimientos no responden a un evento acaecido a un objeto, sino que
responden a un evento producido durante la ejecución del programa.
No es necesario entender de momento lo anterior. Visual Basic introduce un concepto nuevo de programación, y es necesario cambiar
hasta el argot del programador. Posiblemente se le habrán acumulado demasiados términos de una sola vez. Es normal. A poco que siga
leyendo verá las cosas mas claras cuando se explique una por una.
Basic, desde siempre, al contrario de otros sistemas de programación, no exigió la definición previa de una variable. Una variable, como
Vd. seguro que conoce, es un nombre que en el programa le asignamos a un dato. Ese dato podrá cambiar. Piense por ejemplo, en un
programa consistente en la toma de datos de los alumnos de un centro escolar. Existirán varias variables para poder introducir los datos de
los alumnos. Estas variables pueden tener nombre tales como:
Nombre
Apellido1
Apellido2
Dirección
Teléfono
DNI
La variable Nombre tomará valores distintos según vayamos introduciendo los datos de los distintos alumnos. Es posible, que a lo largo de
la ejecución del programa, esta variable Nombre valga:
José
Pedro
María
Luis
Espero que su intuición o conocimiento anterior le lleve a conocer el concepto de variable. Mas adelante lo verá mas claro.
Decíamos que Basic no exige la definición previa de las variables. Otras herramientas exigen que se haga así. Por lo tanto es normal
encontrar, en otros sistemas de programación, que un programa comienza de la siguiente forma:
Declare Nombre As String Le dice que Nombre es una sucesión de letras
Declare Apellido1 As String
Declare Apellido2 As String
Declare Dirección As String
Declare Teléfono As String Le dice que Teléfono es una sucesión de letras
Declare DNI As Número Le dice que DNI es un número
Mediante estas declaraciones, el programa sabe de que tipo de dato se trata y por tanto cómo debe trabajar con él. En otros sistemas de
programación distintos de Basic, es necesario realizar esta declaración antes de introducir una variable.
Basic permite que no se declaren. Cuando a lo largo del programa le introducimos una variable nueva, asume que es una variable y que el
tipo es el adecuado para el valor que le estamos introduciendo en ese momento.
DNI=50000000
Nombre ="Pedro"
Teléfono = "1234567"
entiende que DNI, Nombre y Teléfono son variables, que DNI es un número (No hemos metido su valor entre comillas), y que Nombre y
Teléfono son sucesiones de caracteres alfanuméricos (su valor está entre comillas)
Esta particularidad de no necesitar declarar las variables hace que sea sencillo introducir una variable nueva. Sin embargo entraña un gran
peligro. Imagínese que en un paso posterior del programa, le mandamos escribir esos tres datos anteriores con la instrucción PRINT
Print DNI
Print Nombre
Print Telwfono
Habrá observado en tercer lugar la palabra Telwfono, que por error ha introducido el programador. Basic interpreta que Telwfono es una
variable e irá a leer en memoria el valor que tiene. No tendrá ningún valor. Por lo tanto no escribirá nada y encima no dará ningún aviso de
que se ha cometido un error. Nada es gratis en esta vida, y la facilidad para introducir variables se paga con la posibilidad de un error.
Basic ha pensado en ese problema, y se puede solucionar con esta que será la primera instrucción BASIC que vamos a estudiar:
OPTION EXPLICIT
Obliga a declarar previamente las variables que se vayan a usar. De no haberla declarado antes de usarla, el programa
dará una comunicación de error.
TIPOS DE VARIABLES
Las variables pueden ser de los siguientes tipos: (El número indicado en segundo lugar indica el número de Bytes que ocupa en memoria.)
(*) Una variable tipo String ocupa el mismo número de bytes que caracteres tenga la cadena.
(**) Una variable tipo Variant ocupa 16 bytes si se trata de un número y 22 bytes + longitud de la cadena si se trata de un dato tipo cadena
de caracteres.
Existen también variables definidas por el usuario (Ya verá la sentencia Type). En este tipo de variables se pueden introducir muchos datos
de distinto tipo. Los bytes necesarios para almacenar esa variable dependerá de los datos que se hayan definido.
Dentro de las variables Objet (variables que se refieren a objetos) existe una gran variedad que a estas alturas del curso no debemos
complicarnos con ellas. Pero para adelantar algo, veremos que una variable puede ser del tipo Form - Formulario - , tipo Picture, etc. etc.
Cada tipo de variable ocupa unos determinados bytes. Si no se define una variable, VB toma como tipo por defecto para la variable el tipo
Variant. Este tipo ocupa mas bytes que, por ejemplo, un integer. Si el tipo de dato que vamos a introducir en una variable es un integer, y no
la hemos declarado como tal, VB asumirá para esa variable que es del tipo Variant, lo que le llevará a gastar mas bytes de memoria (16)
que los que necesitaría (2) si la hubiésemos declarado previamente. Si esa variable va a estar en el rango de 0 a 255, y no declaramos
previamente que la variable va a se del tipo Byte, o la declaramos como integer, p. e., estamos desperdiciando memoria RAM y
posiblemente, retardando la ejecución del programa. Lo mismo podemos decir del resto de las variables, y lo importante que es definirlas y
definirlas bien.
NOTA. Observe en la lista anterior que un dato Booleano ocupa 2 Bytes, mientras que un dato tipo Byte ocupa un byte. En muchas
ocasiones declaramos variables tipo Boolean con la intención de que ocupen menos espacio. Paradoja del VB. Si la declaramos como Byte
ocupamos menos espacio en memoria. Declarar una variable como Boolean tiene también sus ventajas (escribirá menos código por lo
general cuando necesite leer o escribir una variable tipo Boolean), pero tenga presente esta observación respecto a los datos Boolean.
Puede declarar el tipo de la variable mediante un carácter después del nombre de la variable. Esta técnica, obligatoria en Quick-Basic, está
en desuso en VB. No es recomendable definir el tipo de esta forma, pues existe un serio peligro de error. De cualquier forma, eso es
potestativo del programador y de sus costumbres.
En Visual Basic, cuando declaramos una variable como String (Cadena de caracteres), no es necesario declarar su longitud. VB aceptará
cualquier número de caracteres. Si desea evitar que se puedan introducir más de un determinado número de caracteres, debe declarar su
número. Por ejemplo :
En este segundo caso, si se introduce como Var2 una cadena de caracteres con mas de 15 caracteres, Var2 tomará solamente los 15
primeros. Visual basic no presenta ningún aviso de que esa variable ha omitido los caracteres que han sobrepasado la cifra de 15. Si
desea que el usuario conozca esa circunstancia, debe introducir el código oportuno para producir el aviso.
La declaración de variables tipo String con número de caracteres predefinido presenta también inconvenientes a la hora de tratar esa
cadena de caracteres con sentencias tales como Mid, Left y Right, o a la hora de añadir una cadena a otra. La experiencia nos indica que
NO merece la pena declarar variables tipo String con el número de caracteres prefijado.
En una gran parte de los casos una variable que se compone de números debe declararse como una variable de cadena de caracteres
(String), y no como numérica. Cuando pensamos por ejemplo en un número de DNI, compuesto por 7 u 8 cifras, un código postal, el
número de una calle, el piso de un edificio, parecen invitar a que la variable que los contenga sea una variable de tipo numérico (Byte,
Integer, Long, ...). Estas variables, aunque su contenido sean números, siempre se deben declarar como String, ya que se tratan en
realidad de cadenas de caracteres, aunque estos sean números. Para aclarar mas estas ideas, piense en el número del DNI con la letra del
NIF incluido, o que el lugar del DNI se deba rellenar con el número del permiso de residencia, (lleva letras). Piense en el código postal de
una provincia que comienza por 0 ( 08XXX = Barcelona ) . Si la variable que va a contener ese código postal se declara como numérica, el
cero de la izquierda lo desprecia, por lo que ese código postal quedaría reducido al 8XXX, número de 4 cifras que el cartero nunca
reconocería como un código postal, que necesariamente ha de tener 5 cifras. Para terminar, piense la forma de introducir en una variable
numérica el número 32Bis de una calle o el piso S2 de un edificio. O piense en una variable que va a contener un código de un producto.
Ese código siempre va a ser un número, por ejemplo de 9 cifras. ¿Ha pensado como trataría el ordenador una variable numérica que
contiene el código 000100123 ?. El resultado sería que convertiría ese código en la cifra 100123, y Vd. deberá buscarse la vida para añadir
los ceros iniciales a la hora de sacarlo a una impresora, por ejemplo.
En todos los casos anteriores, el número no representa una cantidad numérica, sino un nombre. Lo que ocurre es que ese nombre contiene
solamente números.
¿Qué variables debemos declarar entonces como numéricas ? La respuesta es bien sencilla : Aquellas que van a contener datos con lo
que vamos a realizar operaciones matemáticas.
Las variables booleanas (True/False) pueden en muchos casos sustituirse por una variable del tipo Byte. Si ese datos True / False se va a
introducir en una base de datos o en fichero en el disco, puede ser mas prudente poner 0 en vez de False y 1 en vez de True.
Una variable byte ocupa muy poco, simplemente 1 byte como su nombre indica. Pero no puede contener números mayores de 255 ni
números negativos.
Cada vez que declare una variable numérica piense en los valores que puede tener, sobre todo cuando esa variable va a ser el resultado
de una operación matemática. Recuerde el escaso margen de una variable tipo Integer ( de -32768 a 32767)
Si la aplicación va a tratar moneda, piense en la forma de expresar los números decimales y el número de ellos permitidos, así como el
redondeo. La variable correcta para este caso es Currency, pero Currency le añade automáticamente el tipo de moneda de cada país (Pts.
Para España) lo que con frecuencia es un engorro. Los datos del tipo de moneda los toma del sistema operativo del ordenador, por lo que
no se extrañe si le expresa el número de pesetas en dólares. Cambie el país en su S. O.
Declarando una variable con la sentencia DIM, en un formulario, Función, procedimiento o módulo, el entorno de la variable será el
explicado anteriormente para una variable declarada como Privada. Es decir, esa variable no sale del formulario, procedimiento ó módulo
donde se declaró. Cada vez que entremos al formulario, procedimiento o módulo, esa variable tomará el valor cero (si es numérica) o nulo
(si es string).
Declarando una variable mediante la sentencia PRIVATE en un Formulario o Módulo, esa variable puede usarse en todo ese Formulario o
Módulo (En todos sus Procedimientos y Funciones), pero NO fuera del Formulario o Módulo donde se declaró.
Declarando una variable de esta forma en la sección de declaraciones de un Módulo, esa variable puede usarse en cualquier parte del
programa citándola simplemente por su nombre.
Si se declara de esta forma en la sección de declaraciones de un Formulario, esa variable puede usarse en toda el programa. Para
nombrarla, si estamos en el Formulario donde se declaró basta con citarla por su nombre. Si no estamos en ese Formulario, habrá que
citarla por el nombre del Formulario, seguido del nombre de la variable, separados por un punto :
NombreFormulario.Nombrevariable
Sentencia GLOBAL Declara una variable que es válida en todo el programa. La sintaxis es:
Mediante la sentencia Global la variable puede usarse en todo el espacio del programa.
Sentencia STATIC
Como se dijo anteriormente, una variable declarada en un procedimiento pierde su valor al salir de él. Lo peor es que una vez que el
programa vuelva a entrar en ese procedimiento, la variable estará puesta a cero. Afortunadamente, esto último tiene solución. Si
declarásemos una variable en un procedimiento o función, como estática, esa variable, aunque no la podremos utilizar fuera de ese
procedimiento o función, cuando volvamos a él conservará el valor que tenía cuando lo abandonamos. Esta declaración como estática se
realiza mediante la intrucción Static
El nombre de una variable puede ser tan largo como queramos. hasta un máximo de 40 caracteres. En la versión VB para España se
pueden usar incluso la Ñ y vocales acentuadas. Es indiferente usar mayúscula ó minúsculas. No se sorprenda, si por ejemplo, la ha
declarado con mayúsculas y luego la cita con minúsculas al escribir el código, que automáticamente se cambie a mayúsculas. El nombre de
una variable siempre debe comenzar por una letra.
No hay problema por utilizar variables largas. Al compilar el programa no se lleva el nombre, es decir, no le va a ocupar mas espacio. Utilice
siempre nombres que le definan la variable con algún sentido. Es muy útil a la hora de acordarse como se llaman, y sobre todo, a la hora de
rehacer un programa que realizó hace seis meses.
Pese a que Visual Basic no obliga a declarar variables, es muy útil hacerlo. De esta forma se tiene control sobre el programa. La
experiencia se lo irá demostrando.
En un Procedimiento, como permanente (La variable no puede usarse fuera de este procedimiento, y dentro de él conserva el valor
aunque se salga y se vuelva a entrar)
En un Módulo
Esta declaración está MAL hecha. Visual Basic interpretará que Variable1, Variable2 y Variable3 son del tipo Variant, y solamente Variable4
la supone como tipo String
La forma correcta de hacerlo, si queremos declarar esas variables un una sola línea, es la siguiente :
Sentencias condicionales.
Llamamos sentencias condicionales a aquellas que se realizan si se cumple una determinada condición. Son las sentencias por las que
empieza cualquier texto de Basic, y este no va ser menos.
Si no se cumple
Fin de la sentencia.
Así de fácil es programar en Basic. Lo que ocurre es que esta herramienta habla inglés, y lo descrito anteriormente toma la forma:
If condición Then
Instrucciones
Else
Otras instrucciones
End If
En este ejemplo, la condición era que, o se cumple una condición y ejecuta unas determinadas instrucciones, o no se cumple, y ejecuta
otras condiciones distintas. Puede ocurrir que, caso de no cumplirse la condicione primera, se abra un abanico de dos o tres posibilidades.
La sentencia condicional tendría entonces la forma:
If condición 1 Then
Instrucciones
ElseIf Condición 2
Otras instrucciones
ElseIf Condición 3
Otro juego de instrucciones
Else
Instrucciones que debe realizar caso de no cumplir las condiciones 1, 2 y 3.
End If
Como decíamos anteriormente, este es el tipo de sentencia condicional mas usada. Existe otra:
Select Case
Su nombre casi nos define lo que es: Selecciona, dependiendo del caso, un determinado juego de instrucciones:
Select Case variable ' variable es una variable que puede tomar los valores (p.e.) de 1 a 4
Case 1
Instrucciones a ejecutar en caso de que variable = 1
Case 2
Instrucciones a ejecutar en caso de que variable = 2
Case 3
Instrucciones a ejecutar en caso de que variable = 3
Case 4
Instrucciones a ejecutar en caso de que variable = 4
End Select
Este procedimiento resulta mucho mas sencillo y rápido que las sentencias If Then Else
vistas anteriormente, cuando el margen de elección es mayor que 2.
Cuando lo que queremos es elegir un valor, no ejecutar instrucciones como hacíamos anteriormente, disponemos de otras dos funciones:
Choose y Switch.
Switch toma una serie de parámetros, todos por parejas. El primer término de cada pareja es la expresión a evaluar. El segundo es el valor
que tiene que devolver. En realidad Switch es una función (las funciones las veremos muy pronto)
Esta instrucción obtiene un valor para A que dependerá del valor que tome B entre los valores posibles (1, 2 ó 3)
La sentencia Choose es casi igual, cambia solamente la forma. La misma intrucción anterior puede realizarse con Choose de la siguiente
forma:
A = Choose ( B, 5, 7, 11 )
En estas sentencias, Switch y Choose, si el valor de B no coincide con ninguno de los valores que se le habían establecido (1, 2 ó 3 en
nuestro caso), la sentencia devuelve el valor Nulo ( Null ). Esto puede producir algún error si no se contempla esa posibilidad.
Con estas sentencias condicionales es posible realizar bifurcaciones del programa, cambiar las propiedades de un objeto, obtener
resultados de operaciones, ....
Sentencias de bucle.
Es muy común utilizar bucles a lo largo de un programa. Un bucle es una sucesión repetitiva de instrucciones, que se estarán realizando
mientras se cumpla una condición o mientras no se cumpla otra condición. Es tan sencillo como esto:
Mientras condición
Instrucciones
Existen dos formas de bucle: Una, que realiza un número determinado de recorridos por el bucle. Es el denominado bucle por contador.
Otra, realiza el bucle hasta que se cumpla (o deje de cumplirse) una condición. Es el llamado bucle por condición.
Realiza el bucle tantas veces como le indiquemos. Por ejemplo, en este bucle nos va a presentar las 26 letras mayúsculas del
alfabeto inglés
For N=65 To 90
Label1.caption = Chr ( N )
Next N
Este "programa" nos presentará en una caja (Label) los caracteres cuyo número ASCII vaya desde el 65 (A) al 90 (Z) Comenzará
presentando el correspondiente al número 65, e irá presentando sucesivamente el 66, el 67, etc., hasta llegar al 90, donde se parará.
X=0
Do While X < 1000
X=X+1
Loop
El programa toma una variable ( X ) que previamente tuvimos la curiosidad de ponerla a cero, e incrementa su valor una unidad. Analiza si
el valor de X es menor que 1000, y si es cierto, vuelve a realizar el bucle. Así hasta que X ya no sea menor que 1000. Al dejar de cumplirse
que X sea menor que 1000, sale del bucle. Acabamos de realizar un temporizador, y también de exponer las sentencias condicionales y los
bucles, inicio de cualquier curso de Basic. Como final de lección, se propone un problema. Con el primer bucle, donde visualizábamos los
caracteres A a la Z, posiblemente no nos diese tiempo de ver cada una de las letras que iban apareciendo en la pantalla, en la etiqueta
Label1, dado que cambiaría con mucha velocidad, y solamente veríamos la Z, que es donde se detuvo el programa. Podemos poner un
temporizador cada vez que presente una letra, y así nos dará tiempo a verla. Con los dos bucles vistos anteriormente ya podemos hacerlo.
Si lo que queremos es que el programa se ejecute mientras no se cumpla una determinada condición, la sentencia será:
X=0
Do Until X > 1000
X=X+1
Loop
Observe que la diferencia entre una y otra es la condición, While para indicar Mientras se cumpla que ... y Until para indicar
Mientras no se cumpla que ....
Para terminar bien el programa anterior utilizaremos la condición de While (Mientras se cumpla la condición)
For N=65 To 90
Label1.caption = Chr ( N )
Label1.RefreshN ' Refresca la etiqueta
X=0
Do While X < 1000
X=X+1
Loop
Next N
Este es nuestro primer programa en BASIC. En VISUAL BASIC es idéntico, pero nos falta la interface gráfica. Para realizarla basta con
abrir el VB y sobre el formulario que aparece al abrirlo, introducir una etiqueta, (Label) que llevará el nombre por defecto de Label1. Solo
nos queda pensar donde introducimos el código anterior. Podemos introducir un botón de comando (Command Button) que saldrá con el
nombre por defecto de Command1. Haga doble click sobre el botón. Aparecerá el procedimiento Click. Este procedimiento es el que se
realiza cuando hacemos click sobre ese botón. Escriba en ese procedimiento este código.
Visual Basic puede operar con números tal como lo haría cualquier persona. Conoce las 4 reglas, y puede utilizar paréntesis de la misma
forma que los escribimos sobre el papel.
+ Suma
- Resta
* Multiplicación
/ División
\ División sin decimales
Mod Resto de una división
^ Eleva a un exponente
Ejemplos
Existen otras operaciones que se pueden realizar con números: comparaciones. Los operadores que realizan comparaciones se denominan
Operadores relacionales. El resultado de las operaciones realizadas con estos operadores solamente admiten dos resultados: True
(Cierto) o False (Falso) Estos operadores son:
= Igual que
<> No igual que
< Mayor que
<= Mayor o igual que
> Menor que
=> Igual o menor que
Estos operadores se suelen utilizar en estructuras de programa donde se tome una decisión.
Operadores Lógicos
Estos operadores sólo tienen sentido cuando hablemos de variables Booleanas, es decir, aquellas que solamente pueden tomar los valores
cero y uno.
Trigonométricas
Randomize (Numero) Inicia el generador aleatorio tomando como dato de partida el Numero. Devuelve
el resultado en una variable llamada Rnd.
NOTA MUY IMPORTANTE.- Los números aleatorios generados de esta forma son siempre iguales, eso sí, dependiendo del
número que se le introduzca como parámetro. Esta generación de números no produce números aleatorios pues como se dijo,
dependen del numero que se meta como parámetro, y si este se repite, se repite la sucesión de números que nos crea el
generador aleatorio.
La forma de obtener números realmente aleatorios es introducir como parámetro un número que sea variable con el tiempo. Ese número no
puede ser otro que el número timer visto antes. Y siempre con la precaución de que medie mas de un segundo entre dos instrucciones
Randomize. La función toma entonces la forma:
Randomize Timer
La función Randomize devuelve una variable Rnd con un número comprendido entre 0 y 1 (Nunca será 0 ni 1) Leyendo el valor de
la variable sucesivas veces, se puede obtener una sucesión de números aleatorios. No es necesario ejecutar la instrucción Randomize
Timer cada vez que se quiera obtener un dato de la variable Rnd.
Supongamos que tenemos un formulario con una etiqueta de nombre Label1, un botón de comando de nombre Command1. Cuando
hagamos click sobre el botón de comando deberá generar un número comprendido entre el 1 y el 49. En el procedimiento click de
Command1 pondremos el siguiente código:
Randomize Timer
A = Rnd
A = Rnd * 100
A = CInt(A)
Do While A > 49
A = A - 49
Loop
Do While A < 1
A = A + 49
Loop
Label1.caption = A
End Sub
Realice este pequeño programa, con la instrucción Randomize Timer y sin ella.
Tras esta pequeña introdución al lenguaje Basic ya estamos en disposición de encender el ordenador y comenzar a trabajar con Visual-
Basic. Se supone que su PC tiene instalado el programa Visual basic, bien en su versión de 16 bits si dispone de Windows 3.xx o la de 32
bits si dispone ce Win95 ó Windows NT.
esto
Este es el comienzo del programa . Observe que en esta pantalla existen varias cosas. En la parte superior , la barra de título del
programa Visual Basic, con el texto :
Por debajo de esta barra de Título del VB, encontramos la barra de menú de VB, con las leyendas :
Por debajo de esta barra de menú tenemos la barra de herramientas, donde podrá ver varios iconos, que cada uno representa un
determinada operación que Vd. puede realizar. Estas operaciones está todas en la línea de menú, y puede acceder a ellas abriendo los
menús desplegables que existen en cada una de las palabrea Archivo Edición Ver ...... de esta línea de menú. El hecho de colocar las
operaciones mas usuales en un icono en la barra de herramientas se hace para mayor comodidad del usuario.
A la izquierda de la pantalla tiene una caja rectangular con tres columnas de iconos. Esa caja es la Caja de Herramientas (No la confunda
con la barra de herramientas de la parte superior)
Esta caja de herramientas es, salvando las distancias, lo mismo que una caja de herramientas real que pueda tener un mecánico para
realizar su trabajo. En ella están los iconos que representan a los controles con los que Vd. va a desarrollar su aplicación VB. No están
todos los que pueden estar, al igual que en una caja de herramientas de un mecánico no están todas las herramientas que puede usar.
Están solamente las mas usuales. Si necesita alguna mas, puede cogerla de otra parte (barra de Menú, Herramientas, Controles
personalizados) y agregarlos a esa caja de herramientas, al igual que lo haría un mecánico con una herramienta especial, que la metería en
su caja sólo cuando va a realizar un trabajo determinado para el que la necesite.
Posiblemente esta caja de herramientas no le aparezca tal y como la ve en estos apuntes. Eso depende si Ud. tiene la versión personal o la
profesional, o si usa la versión de 16 ó 32 bits. Esa caja de herramientas puede personalizarla a su gusto. Para ello, deberá cargar un
proyecto ya existente en los discos de distribución de Visual Basic, llamado AUTO32LD.VBP (versión 32 bits) ó AUTO16LD.VBP (Versión
16 bits) que se encontrará en el directorio donde haya cargado el programa Visual Basic. Este proyecto no tiene otra función que determinar
las herramientas con las que quiere abrir el VB. Para introducir herramientas nuevas en la caja de herramientas, basta con desplegar el
menú Herramientas de la barra de menú, e ir a Controles personalizados. Haciendo click en esta línea de controles personalizados,
podemos seleccionar nuevos controles para añadir a la caja de herramientas, marcando la casilla que está a la izquierda del nombre del
control que quiere introducir. Una vez seleccionados todos los nuevos controles, haga click en ACEPTAR, y podrá observar que esos
nuevos controles ya se le han añadido a la caja de herramientas. Para que esos nuevos controles le aparezcan de entrada cuando inicia
una sesión de VB, debe salir de Visual basic guardando los cambios. Vuelva a entrar y observará que ya le aparecen esos nuevos controles
en la caja. No es prudente meter muchos controles en la caja. Ponga solamente los que necesite normalmente en sus aplicaciones.
Ocupará menos memoria y tardará menos tiempo en cargar el programa VB. Además, cuando realice una aplicación y la distribuya una vez
compilada, Visual Basic entregará en los disquetes de distribución las DLL’s u OCX’s correspondientes a todos los controles
personalizados que Vd. tenga en la caja de herramientas, los necesite el programa o no los necesite. Esto le va a suponer que está
cargando subprogramas inútiles en el ordenador destino de su aplicación. A la hora de compilar el programa (Crear archivo .EXE) quite
todos los controles personalizados que no necesite su aplicación. (Sólo los controles personalizados. Los controles comunes -
CommandButton, Label, TextBox, etc.-, no se pueden eliminar de la caja de herramientas)
Para quitar controles de su caja de herramientas, debe proceder de forma análoga, cargando el programa AUTOxxLD.VBP, abriendo menú
de herramientas, Controles personalizados, quitando la marca al cuadro situado en la parte izquierda del control a eliminar, y guardando el
proyecto al salir.
En el centro, y ocupando casi toda la pantalla, tenemos el Formulario. Este Formulario es la interface gráfica de su aplicación, sobre el que
podrá añadir los controles que necesite. Lo veremos mas adelante con todo detalle.
Observa dos ventanas, una denominada Ventana de Propiedades, donde puede ver las propiedades del formulario, Form1, y otra,
denominada Ventana de Proyecto. Existe otra ventana, que no está en la figura anterior, la Ventana de Depuración. Por cada formulario
y cada control que introduzca en el proyecto, le aparecerá otra ventana, denominada ventana de código.
No se extrañe de que esta presentación gráfica del Visual Basic coincida con otros sistemas de desarrollo (Delphi, p.e.). La lógica de
desarrollo de una aplicación en Windows ha llevado a varios fabricantes de software a utilizar un entorno gráfico similar (diríamos idéntico).
A Visual basic le queda el orgullo de ser el primero en utilizarlo.
Con lo descrito anteriormente ya tenemos, al menos, fijado el argot con el que expresarnos para comenzar a estudiar el VISUAL BASIC.
Veamos con un poco mas detalle la Ventana de Código.
Esta figura le muestra un Formulario con su ventana de código. Cada objeto gráfico de VB tiene su propia ventana de código. Así, si en
este formulario hubiésemos introducido un Label y dos CommandButton, todos ellos tendrían su propia ventana de código. La ventana de
código la podemos ver haciendo doble click sobre cualquier objeto de nuestro proyecto. En este caso hemos hecho doble click sobre el
único objeto que teníamos : el formulario.
Observe las dos cajas de la parte superior, uno con la inscripción Objeto : que en el momento que le sacamos la foto tenía Form, y el otro
con la inscripción Proc : (procedimiento), que en el momento de la foto tenía Load. A estas cajas les denominamos Lista de Objetos y
Lista de Procedimientos respectivamente.
Haciendo click sobre la flecha de cada lista, se despliega un menú, en la lista de objetos se desplegará una lista con los nombres de cada
objeto existente en ese momento dentro del formulario. Haciendo click sobre uno de los nombres, nos presentará la ventana de código de
ese objeto. Todos los objetos gráficos (controles) existentes dentro de un formulario y el propio formulario aparecerán en la misma lista de
objetos.
Haciendo click sobre la flecha de la lista de procedimientos, se despliega la lista con todos los procedimientos posibles para ese objeto.
Siempre saldrá uno. Si tenemos escrito código en uno de los procedimientos, saldrá por defecto ese procedimiento para el cual hemos
escrito el código. Si no hay código en ninguno de los procedimientos, saldrá el que tenga por defecto cada objeto.
Solamente nos queda por decir, para cerrar este capítulo, que es un procedimiento.
Para ello vamos a explicar lo que es un evento. Un Evento es algo que le puede ocurrir a un objeto. En una internase gráfica, lo que le
puede ocurrir a un objeto es que se le haga click, doble click, que se pase el cursor del ratón por encima, etc. Este es el Evento. El
Procedimiento es la respuesta por parte de ese objeto, al evento que le está sucediendo.
Esa respuesta, esa forma de Proceder del objeto al evento que le está sucediendo, debemos programarla según nuestras necesidades, es
decir, debemos escribir el código que necesite nuestra aplicación como respuesta al evento que acaba de ocurrir. Posiblemente, no
queramos ninguna respuesta a muchos de los eventos que pueden acaecer a un objeto. Cada objeto tiene muchos eventos y solamente
queremos aprovechar los que nos interesan. Para que un evento no produzca ningún efecto, basta con dejar sin código el procedimiento
correspondiente a ese evento. En los eventos que queramos que realice alguna operación, le escribiremos en su procedimiento el código
necesario para que esa operación se realice. Sin darnos cuenta, hemos comenzado a escribir el código de la aplicación.
Observará que el primer elemento del menú desplegable de la lista de objetos se denomina General. Este no es en realidad ningún objeto,
sino un apartado existente en cada formulario, que, al desplegar su lista de procedimientos tiene la sección de declaraciones, donde
debemos declarar las variables que queremos que afecten a todo el formulario y sus controles, y tendrá además, los nombres de todos los
procedimientos que introduzcamos (véase un poco mas adelante). En este menú desplegable de la lista de procedimientos del General
verá con frecuencia cosas que Vd. no puso allí. Cosas tales como Command1_click, y en la ventana un determinado código. Esto ocurre
cuando se borra algún control que tenía escrito código en alguno de sus procedimientos. Visual Basic sabe lo mucho que cuesta escribir el
código asociado a un control. Si borramos un control de nuestro formulario accidentalmente, después de haber introducido todo el código
asociado a él, Visual Basic nos sorprende con que ese código no lo tira inmediatamente, sino que lo reserva como un procedimiento en ese
apartado General del formulario. Si en realidad queríamos borrar el control y todo su código, debemos quitarlo de ese apartado General de
nuestro formulario, pues en realidad, si no lo queremos, no hará otra cosa que estorbar. Para quitarlo basta con borrar todo el código que
aparece en la ventana de código cuando hacemos click sobre el nombre del control eliminado. Deberemos borrar todo el código, incluida la
cabecera donde figura el nombre del control eliminado, y la parte final, que siempre termina con EndSub.
El primer estorbo lo observará si crea otro control con el mismo nombre, cosa fácil ya que VB da un nombre por defecto a cada control
(Command1, Command2....). El código asociado al control eliminado pasará automáticamente al nuevo control con el mismo nombre.
Una aplicación puede tener todo su código escrito en los sucesivos procedimientos del formulario y de los controles que tenga ese
formulario.
Puede ocurrir que un determinado evento no esté entre los posibles eventos de los controles de nuestra aplicación. Piense por ejemplo, el
evento de que la variable A sea igual a la variable B. No existe en ninguno de los controles ese procedimiento. No se preocupe, puede crear
un procedimiento que se ejecute cuando su programa lo decida. Podemos añadir cuantos procedimientos queramos. Estos procedimientos
se añaden al formulario, y deberán definirse por un nombre que Vd. debe elegir. Para que se ejecuten las instrucciones (código) incluido en
ese procedimiento, basta simplemente con nombrarlo por ese nombre.
Para insertar un procedimiento debe ir a la barra de menú, hacer click sobre Insertar, y en el menú que le desplegará, volver a hacer click
sobre Procedimiento. VB le presentará un cuadro donde le pedirá el nombre, si quiere que sea un procedimiento, una función o una
propiedad. A lo largo del curso irá viendo que es cada cosa.
Escribiendo el código en los sucesivos procedimientos, bien en los propios de cada objeto, bien en los procedimientos que vayamos
creando, es posible completar la aplicación. Pero en una aplicación larga esta forma de escribir el código no sería la mas adecuada. Es
mas, posiblemente sería demasiado engorroso escribirla de esta forma, y muy probablemente deberíamos escribir el mismo código para
varios procedimientos, lo que alargaría inútilmente el programa y el tiempo de desarrollo.
Para disponer de un sitio donde escribir parte (o la mayor parte) de su programa, puede introducir uno o varios módulos. Expliquemos lo
que es un módulo.
Un Módulo es una parte del programa donde solamente puede escribir código. Es igual que un formulario, sin interface gráfica. Un profesor
de Visual Basic lo expresaba diciendo que un Módulo es un Formulario sin cara. En un módulo pueden existir procedimientos al igual que
en los formularios, pero como un módulo no tiene interface gráfica, esos procedimientos debe introducirlos el programador tal y como
explicamos un poco mas atrás. El módulo tiene su propia ventana de código, al igual que un formulario, con un objeto único, el apartado
General. Aquí también tenemos la sección de declaraciones, al igual que los formularios. En esta sección de declaraciones se comporta de
manera similar a la de los formularios, pero permite algo que no nos permite la sección de declaraciones de un formulario : Declarar
variables que se pueden utilizar en todo el programa. Esto ya lo ha visto mas atrás, con las sentencia de declaración Global y Public.
Los módulos se emplean para la declaración de variables globales, y para escribir el código de la aplicación que sea común a varios
formularios. Esto nos evita tener que repetir código inútilmente. Ese código común se escribirá en un procedimiento que previamente
habremos insertado en este módulo, y lo citaremos por su nombre desde cualquier parte del programa.
¿Cual es el nombre de un procedimiento existente dentro de un módulo ? Depende. Si estamos ejecutando código escrito en otro
procedimiento dentro del mismo módulo, es decir, si estamos dentro de ese mismo módulo, basta con citarlo por su nombre : p.e., si en el
MóduloA tenemos un procedimiento llamado Procedimiento1, y queremos llamarle desde una línea de código dentro de ese mismo módulo,
basta con referirse a él con :
Procedimiento1
Si la línea de código donde nos vamos a referir a él está fuera de MóduloA, deberemos referirnos a ese procedimiento con :
MóduloA.Procedimiento1
Lo mismo podemos decir para cualquier procedimiento insertado en un formulario. Desde dentro del formulario basta con referirse a él
citándolo por su nombre. Desde fuera de ese formulario deberemos citarle como :
Formulariox.Procedimientoy
donde damos por hecho que Formulariox es el nombre del formulario que lo contiene, y Procedimientoy es el nombre del procedimiento.
Fíjese en el punto usado como separador entre el nombre del formulario y el nombre del procedimiento. VB usa como separador un punto.
Usa el separador para separar el nombre de un control y una de sus propiedades (Label1.Caption), para separar el nombre del formulario
del nombre de uno de sus controles (Formulario1.label1.caption) Se irá familiarizando con la terminología VB según vayamos avanzando
en el curso.
Funciones
Al igual que introducimos Procedimientos, podemos introducir Funciones en nuestra aplicación. Una Función es un Procedimiento al que le
pasamos uno o varios parámetros. (O Ninguno) Verá los Procedimientos y funciones mas adelante (Cap. 15). Al igual que los
Procedimientos, pueden ser públicas (se verán en toda la aplicación) o privadas (se verán solamente en el formulario donde estén.
Main
Merece la pena pararse un poco para estudiar el Procedimiento Main. Para verlo con mas detalle, comentaremos como comienza a
trabajar una aplicación realizada en Visual Basic.
Imaginemos una aplicación que tiene 3 Formularios. En cada uno de ellos tiene código. Logicamente la aplicación tendrá que presentar uno
de ellos en primer lugar. Deberemos decirle a Visual Basic cual es el formulario inicial, y será ese por el que empiece. En ese formulario
dispondremos el código necesario para que la aplicación se ejecute en el orden deseado.
Si hacemos click en la Barra de Menú de Visual Basic, en Herramientas | Opciones obtendremos el siguiente cuadro de diálogo :
Verá que tiene 4 pestañas, y actualmente tiene abierta la pestaña correspondiente a Proyecto, y tiene desplegada una lista donde nos pide
el Formulario Inicial. En esa lista figura también la expresión Sub Main. Si ponemos como formulario inicial uno de los formularios, la
aplicación comenzará por ese formulario. Si en uno de los Módulos existentes en el proyecto, ponemos un procedimiento llamado Main,
podemos comenzar la ejecución de la aplicación justamente por ese procedimiento. En ese procedimiento pondremos el código necesario
para que, posteriormente, se muestre uno de los formularios. Esto es muy practico cuando queremos hacer una función previa a mostrar
cualquier formulario (abrir una base de datos, por ejemplo). Para comenzar la aplicación por Main se elige esa opción en la lista Formulario
Inicial.
¡ Recuerde que Main debe estar en un Módulo !
El cuadro de diálogo anterior sirve además para otras cosas. Entre ellas poner el nombre del proyecto (nombre que no aparecerá por
ninguna parte, solo en los datos internos de la aplicación) y su descripción.
En otra pestaña podemos configurar varias prestaciones del entorno de trabajo :
Guardar la aplicación antes de ejecutar. Esta prestación nos va a evitar muchos disgustos. Es muy práctico guardar la aplicación antes
de ejecutarla, pues de esta forma evitamos que, si nuestra aplicación tiene un error tal que hagamos colgarse a Windows, siempre
tendremos la aplicación metida en el disco duro. Pero también es una pequeña pesadez tener que esperar a que se guarde cada vez que la
ejecutamos.
Si tenemos la activada la casilla Declaración de variables requerida nos pondrá automáticamente Option Explicit en el encabezamiento
de todas las secciones de declaraciones de la aplicación.
Podemos elegir también las ventanas que queremos que estén siempre visibles, y que verifique automáticamente la sintaxis de una
instrucción en el momento de escribirla.
La pestaña de Editor nos permite fundamentalmente 2 cosas :
Ver solamente el código correspondiente al procedimiento que estamos escribiendo ó Ver el código del Módulo (o Formulario) completo. En
este último caso es un poco mas difícil de manejar la ventana de código, sobre todo si el programador no está muy habituado a ello. Le
presenta procedimiento tras procedimiento, separados por una línea. Para seleccionar una u otra opción hay que seleccionar o
deseleccionar la casilla Ver módulo completo.
Cambiar el color de la letra y del fondo del código, según el tipo que sea (código, comentario, error devuelto, etc.). Los alumnos mas
aventajados y con ganas de marear al profesor y, lo que es peor, a sus compañeros, conocen la forma de poner como invisible una parte
del texto del código. Si observa comportamientos raros en el texto donde escribe el código, revise el cuadro de Colores de Código.
FORMULARIO
____________
El primer objeto Visual Basic con que nos encontramos es el FORMULARIO. De hecho, cada vez que iniciamos Visual Basic (VB) nos
presenta en pantalla un nuevo formulario, que tiene por defecto el nombre de Form1
El Formulario es un objeto, que sirve de soporte de otros objetos. El nombre de FORMULARIO lo toma precisamente porque, al igual que
un formulario de papel contiene textos escritos, lugares donde podemos escribir, figuras, cajas donde podemos elegir una u otra opción,
etc., en este cuadro gráfico que llamamos formulario, podemos introducir textos escritos, lugares donde podemos escribir, figuras, cajas
donde podemos elegir una u otra opción ....
En realidad un formulario es lo que normalmente conocemos por VENTANA. El nombre de formulario le viene muy bien cuando ese
formulario es una ventana donde vamos a introducir datos alfanuméricos. Cuando en vez de introducir datos, lo que tenemos es, por
ejemplo, una ventana donde se reproducen exactamente los controles de operación de una máquina, parece en principio que sería mas
correcto el nombre de "ventana". De alguna forma lo hay que llamar, y esa forma es FORMULARIO. Posiblemente a lo largo de estos
apuntes nos referiremos al formulario con el nombre de ventana, o incluso, pantalla. Procuraremos usar el nombre apropiado:
FORMULARIO.
PROPIEDADES.
Name Nombre
Define al objeto durante la ejecución del programa. Se introduce en tiempo de diseño y no se puede variar durante la ejecución.
Nombre por defecto: Form1 (Form2 y sucesivos) Este nombre por defecto debe cambiarse, (debería cambiarse por norma en el
momento de introducir el formulario), ya que de no hacerlo corremos el riesgo de borrar el código existente de otro formulario del
mismo nombre en el momento de guardar la aplicación.
Caption Título
Es el texto que aparecerá en la barra de Título cada vez que aparezca en pantalla este formulario. No tiene otra función dentro del
programa. El programa no accede a este formulario por el título, sino por el nombre. Puede cambiarse en tiempo de ejecución.
Control Box Control “menos” del Formulario Valor por defecto : True
Propiedad booleana que admite los valores de true (verdadero) o False (Falso). Si esta propiedad es True, aparecerá en la esquina
superior izquierda el "menos" para desplegar el menú de control de este formulario. Si esta propiedad se pone como False, no
existirá dicho "menos" y por tanto no se puede desplegar dicho menú.
MinButton
MaxButton Valor por defecto: True
Botones (flechas) de minimizar y maximizar este formulario. Son igualmente propiedades booleanas, que admiten el valor True o
False. Si están en true, aparecerá la flecha correspondiente. Si están en False, no aparecerá dicha flecha. Deben configurarse de
una u otra forma, dependiendo si se quiere minimizar / maximizar este formulario durante la ejecución.
Nota. En los formularios MDI child, es necesario poner a true las propiedades ControlBox, MinButton y MaxButton para poder
maximizar el formulario hijo. De no ponerlas a true, sí se pretende maximizar el formulario hijo, (Propiedad WindowState=2) el formulario
no aparece.
Define el tipo de borde que tendrá el formulario durante la ejecución. No se puede cambiar en tiempo de ejecución,
Admite los siguientes valores:
1 - Fixed Single
El formulario tendrá un borde fino, y no podrá cambiarse su tamaño durante el tiempo de ejecución. Con este valor,
el formulario puede tener un menú de control, barra de título y botones de maximizar y minimizar. Solo podrá
cambiarse de tamaño utilizando estos botones.
2-Sizable
El formulario tendrá borde grueso, y se podrá cambiar su tamaño en tiempo de ejecución mediante los botones de
maximizar y minimizar, y mediante el arrastre de uno de los bordes con el ratón.
3 - Fixed Dialog
El formulario tendrá borde grueso, y no se podrá redimensionar durante la ejecución. No puede tener los botones
de maximizar ni minimizar.
4 - Fixed ToolWindow
En las versiones de 16 bits de Windows y Windows NT 3.51 y anteriores se comporta como Fixed Single. No puede
cambiar de tamaño. En Windows 95 muestra el botón Cerrar, y el texto de la barra de titulo aparece con un tamaño
de fuente reducido. El formulario no aparece en la barra de tareas de W95.
5 - Sizable ToolWindow
En las versiones de 16 bits se comporta como Sizable. En W95 muestra el botón Cerrar y el texto de la barra de
titulo aparece con un tamaño de fuente reducido. El formulario no aparece en la barra de tareas de W95.
Nota: Al cambiar a determinados valores, las propiedades MaxButton y MinButton se ponen a False. Pueden
cambiarse a True posteriormente.
Admite los valores 0 (=Flat, plano) y 1 (=3D) Si tiene el valor 1 (3D), el formulario aparecerá con cierto efecto tridimensional, y los
controles que le introduzcamos a este formulario aparecerán como esculpidos dentro de él. Con valor 0 (Flat) en esta propiedad, el
formulario aparecerá durante la ejecución como una superficie plana. El color de fondo se ve afectado al cambiar esta propiedad. Si
se cambia a 3D, el fondo (Backcolor) toma el color definido en Windows en el Panel de Control. Si se cambia a Flat, toma el color
blanco
Propiedad booleana. Esta propiedad, estando en True, permite actualizar el contenido del formulario y de sus controles incluso
cuando no están visibles. Imaginemos que en este formulario existe un texto, una etiqueta (Label) o caja de texto (Text Box) cuyo
texto se haya cambiado, bien por programa, bien por una entrada, mientras este formulario no estaba visible. Lo mismo podemos
decir de las propiedades de cualquier otro control. Si esta propiedad Autoredraw está en False, al hacer visible este formulario,
aparecerá igual que cuando se ocultó. Si esta propiedad está en True, aparecerá actualizado.
Establece el color del fondo del formulario. Puede cambiarse en tiempo de ejecución.
Propiedad Booleana. Establece si un evento Paint vuelve a dibujar el objeto entero (True) o si solamente dibujan las partes que han sufrido
cambios (False)
DrawMode
Establece un valor que determina el aspecto de la salida de un método gráfico o el aspecto de un control Shape o Line. Verá mas adelante
los efectos de esta propiedad.
Propiedad booleana. Si está en True, el formulario está activado y se puede interactuar con él. Si está en False, se desactiva el formulario,
impidiendo de esta forma, que se pueda trabajar con él.
ForeColor Valor por defecto: Negro
Establece el color del primer plano del formulario. Es el color que tendrán las letras si escribimos en él, o los dibujos, si lo que hacemos es
dibujar. En tiempo de diseño, determina el color de la rejilla,.
Establece el modo de rellenar controles Shape, o figuras (círculos o cuadrados) creados con los métodos gráficos Circle y Line.
Valores: 0 - Continuo
1 - Transparente
2 - Línea Horizontal
3 - Línea Vertical
4 - Diagonal hacia arriba
5 - Diagonal hacia abajo
6 - Cruzado
7 - Diagonal cruzada
Especifica el tipo y tamaño de la letra que se usará en el formulario. Al seleccionar esta propiedad en la ventana de propiedades,
aparece un cuadro de dialogo donde se eligen ambos parámetros.
Cuando introduzca nuevos controles en el Formulario, la propiedad Font de estos controles tomará el valor que tenga esta
propiedad en el Formulario. Puede servirle este pequeño truco para utilizar en todos los controles una determinada fuente sin tener
que teclearla para cada control.
Establece si el texto o gráfico de fondo del formulario se muestra (True) o no se muestra entre los caracteres de texto escritos en el
propio formulario.
Permiten, en tiempo de ejecución, cambiar un texto a negrita, cursiva, tachado y subrayado. Son propiedades booleanas True /
False
Define la altura del formulario. El valor de esta propiedad no se introduce normalmente como un dato numérico, sino que toma el
valor automáticamente, dependiendo de las dimensiones del formulario durante el tiempo de diseño. Puede cambiarse durante el
tiempo de ejecución.
Establece un número de contexto asociado para este formulario. Este número se aplica para determinar la ayuda interactiva
asociada a este formulario. Vea mas adelante, el tema Ayuda de Windows.
Esta propiedad define el icono que va a representar a este formulario cuando esté minimizado. Si el formulario es el formulario
padre o formulario de inicio de una aplicación, este icono es el que toma el Asistente de Instalación para colocarlo como icono de
apertura del programa en el grupo de programas Windows correspondiente. Como valor de esta propiedad se le puede asignar
directamente el icono o el nombre de un archivo (con su path correspondiente) que lo contiene, haciéndolo directamente sobre la
caja de propiedades.
Propiedad Booleana. Cuando un formulario tiene dentro de sí varios controles, uno de ellos es el que está activo. En estas condiciones, si
se pulsa una tecla, esa pulsación la recibe en primer lugar el control que esté activo, y si éste no la procesa, pasa esa pulsación al
formulario. Para hacer que esa pulsación pase directamente al formulario, debe ponerse esta propiedad en True.
Permite que una aplicación destino inicie una conversación DDE con el formulario (origen de datos). Puede tomar los siguiente
valores:
LinkTopic
Establece el tema al que este formulario va a responder a una conversación DDE, cuando funciona como origen. Es por este tema
por el que se debe llamar a este formulario cuando actúa de origen en una conversación DDE
Establece que este formulario es un formulario Hijo dentro de un formulario MDI. No se puede cambiar en tiempo de ejecución. Es
una propiedad booleana
True = es formulario hijo False =No lo es
Establece un icono personalizado para el puntero del ratón cuando esté encima de este Formulario. Este icono puede ser un bit-
map de los existentes en el directorio Icons de Visual Basic o cualquiera que tengamos. Si se pone 99 como valor de la propiedad
MousePointer (siguiente), cada vez que el puntero del ratón pase por este Formulario, cambiará su forma y adoptará la del icono
elegido.
Determina la forma del puntero del ratón cuando se coloca encima del formulario. Puede elegirse uno de los punteros
preestablecidos (15 en total) o el personalizado visto en la propiedad anterior. Para elegir ese icono personalizado, debemos poner
en esta propiedad el valor 99.
Picture Gráfico Valor por defecto: No existe
Mediante esta propiedad podemos poner un gráfico como fondo del formulario. El gráfico puede ser un bit-map o un fichero .ICO
Indican la unidad de medida de dimensión de altura y anchura del Formulario. ScaleMode indica en qué unidades de medida se
van a medir esas dimensiones. Acepta Twips (1), Point(2), Pixel (3), Character (4), Pulgadas (Inch) (5), Milímetros (6), Centímetros
(7). Si colocamos la propiedad ScaleMode en cualquiera de estos valores, las propiedades ScaleHeight y ScaleWidth nos
vendrán dadas automáticamente dependiendo del ancho del Formulario, y no se extrañe si encuentra para estas propiedades
valores tan peregrinos como 4815 y 7423. Al haber elegido la unidad de medida, los valores de ancho (ScaleWidth) y alto
(ScaleHeight) serán los que tengan que ser, medidos en la unidad que hemos elegido. Podemos elegir una cifra para el ancho y el
alto del Formulario de forma que podamos controlar mejor las distintas posiciones que van a ocupar en él los controles, los textos o
los dibujos. Podemos poner, por ejemplo, que el Formulario mida 400 de ancho (ScaleWidth = 400) y 300 de alto (ScaleHeight =
300) forzándole estas propiedades, bien en tiempo de diseño en la caja de propiedades, o en tiempo de ejecución mediante código.
Entonces sabemos que el formulario, independientemente de las dimensiones físicas que tenga sobre la pantalla, medirá 400 de
ancho y 300 de alto, y si en estas condiciones queremos colocar un control o un dibujo justo en el medio del Formulario, sabemos
que tenemos que colocarle en las coordenadas 200, 150. ¿Que unidad de medida estaremos utilizando entonces en el Formulario ?
Unas definidas por el usuario (distintas para el ancho y el alto) que serán las necesarias para que el Formulario mida de ancho lo
que le hayamos puesto en la propiedad ScaleWidth y de alto lo que le hayamos puesto en la propiedad ScaleHeight. Observe que
la propiedad ScaleMode se ha cambiado automáticamente a User (0) al introducir las dimensiones de ancho y alto que nosotros
queremos.
Estas unidades de medida afectarán a los controles que metamos en este Formulario. Se medirán en su ancho y alto con la unidad
de medida definida para el ancho y alto del Formulario. Lógicamente también afectará a las propiedades Left y Top de los
controles, pero estas propiedades se verán afectadas además por las propiedades ScaleLeft y ScaleTop del Formulario que se
verán a continuación.
ScaleLeft, ScaleTop
Estas propiedades, medidas en la unidad de medida elegida para el ancho y alto mediante las propiedades ScaleMode,
ScaleWidth y ScaleHeight anteriores, expresan las coordenadas iniciales de la parte izquierda y de la parte superior
respectivamente del Formulario. Estas propiedades no afectan a la posición del Formulario en la pantalla (Si está maximizado
seguirá ocupando toda la pantalla, si está en “Normal” ocupará el mismo sitio que se dio en tiempo de diseño). Supongamos que
se le asigna a un Formulario, las propiedades ScaleWidth = 400, y ScaleHeight = 300. Si colocamos un control justamente en el
centro del Formulario tendrá sus propiedades Top =150 y Left=200. Si ponemos ahora las propiedades del Formulario ScaleLeft a
30 y ScaleTop a 10, ese control, para seguir en el centro del Formulario deberá tener sus propiedades Top a 160 (150 + 10) y Left
a 230 (200 + 30).
Recuerde que las medidas de un formulario crecen, desde la esquina superior izquierda, según avanzamos hacia abajo y hacia la
derecha.
Como aclaración de las relaciones entre distintas unidades de medida, puede ver en la siguiente table la correspondencia entre
cada una de ellas y la unidad imaginaria Twip.
1 Point=20 Twips ; 1Pixel=15 Twips : 1 Charecter=240 Twips ; 1 Inch (pulgada) =1440 Twips 1mm=56,52 Twips 1 cm=566 Twips
Esta propiedad no la usa directamente Visual-Basic. Sirve para asociar al formulario información adicional para fines externos a la
programación. Pero también le puede servir para almacenar en ella una variable para que la use un código ajeno al formulario. El
autor de estos apuntes tiene por costumbre utilizar la propiedad Tag del formulario inicial para guardar el parámetro que se le pasa
a algunos programas para acceder a ellos con unos determinados privilegios. Resumiendo, está ahí para lo que el programador
quiere.
Esta propiedad establece la posición del borde superior del formulario. Normalmente no se introduce como valor numérico sino que
lo toma automáticamente de la posición que tenga el Formulario durante el tiempo de diseño Este valor puede cambiarse durante
la ejecución para, conjuntamente con Left, variar la posición del Formulario. Los valores de Top y Left definen la esquina superior
izquierda del Formulario.
Propiedad Booleana. Asignándole el valor True la pantalla es visible, y asignándole el valor False, no se ve. Este valor puede
cambiarse durante el tiempo de ejecución para ocultar y hacer visible el formulario.
Define la anchura del formulario. Normalmente no se introduce como valor numérico sino que lo toma automáticamente del tamaño
que tenga el formulario durante el tiempo de diseño. Juntamente con Height define el tamaño del formulario. Puede cambiarse
durante el tiempo de ejecución.
WindowState
Establece el estado en el que aparecerá el formulario cuando se activa y presenta en pantalla. Admite tres opciones:
0 - Normal El formulario recupera la posición y tamaño que tenía en el tiempo de diseño.
1 - Minimizado El formulario aparece minimizado, representado por su icono.
2 - Maximizado El formulario aparece maximizado, ocupando toda la pantalla.
PROCEDIMIENTOS
Un Formulario sirve, fundamentalmente, de contenedor de controles. Es la ventana de Windows de nuestra aplicación. Una aplicación
puede tener varios Formularios y dentro de cada uno de ellos, los controles necesarios para cada paso o estado de la aplicación.
CONTROLES
Una vez introducido un Formulario, se pueden colocar los objetos (controles) que forman parte de la aplicación. Estos controles se irán
viendo en próximos capítulos.
Las Propiedades definen las características del Control. Los Procedimientos definen la forma de actuar (la forma de proceder) de un
control frente a un evento.
Tanto las propiedades como los procedimientos deben ser definidos por el programador. Las propiedades dejan un pequeño margen de
actuación, los procedimientos son en su totalidad, definidos por el programador. Estos procedimientos forman parte del programa. Podría
incluso hacerse una aplicación que no tuviese mas código que el introducido en los procedimientos.
Para colocar un control en un Formulario, basta con “tomarlo” de la caja de herramientas existente en la parte izquierda de la pantalla de VB
y llevarlo al Formulario. Si no existiese el control deseado en la caja de herramientas, deberemos ir a “cogerlo” a Controles
personalizados que está en el menú desplegable Herramientas de la barra de Menú de VB. Se elige el nuevo control, marcando la caja
de opción a la izquierda de su nombre, y haciendo click en ACEPTAR. Este control ya pasa a la caja de herramientas.
El Command Button es un objeto que sirve para introducir datos a través de la pantalla. El Botón de Comando tiene la siguiente forma:
El botón de comando puede usarse para la entrada de datos con el ratón, o para validar cualquier operación. El tamaño puede cambiarse a
voluntad, pero la forma siempre es rectangular. En la figura anterior vemos dos botones de comando, uno de ellos (el Command2) marcado
con unos puntos en su contorno. Estos puntos nos permiten variar su tamaño en tiempo de diseño. También puede cambiarse su tamaño y
posición en tiempo de ejecución.
PROPIEDADES
Name Nombre
Es el nombre que define a este objeto durante la ejecución del programa. No se puede cambiar en tiempo de
ejecución. El nombre por defecto es Command1, Command2, etc. Estos nombres por defecto deberían cambiarse
por otros que nos indiquen algo respecto a este control, aunque en este caso no es tan imprescindible como para
los formularios.
Caption Título
Es el texto que aparece en el botón. Puede cambiarse en tiempo de ejecución. No tiene otra función dentro del
programa.
Appearance Apariencia
Determina la forma del botón. Admite los valores de Flat (Plano) y 3D. No se aprecia en gran medida la
diferencia.
Backcolor Color de fondo
Es el color de un pequeño cuadrado que aparece rodeando el título, NO el color del botón, que es invariable.
Puede cambiarse en tiempo de ejecución.
Cancel
Establece un valor que indica si un botón de comando es el botón Cancelar de un formulario. Es una propiedad
booleana, y admite los valores True o False. Puede utilizar la propiedad Cancel para dar al usuario la opción de
cancelar los cambios que no se han hecho efectivos y devolver el formulario a su estado anterior. En un formulario
sólo puede haber un botón de comando con la propiedad Cancel = True.
Default
Establece un valor que determina el control CommandButton que es el botón de comando predeterminado de un
formulario. Sólo un botón de comando de un formulario puede ser el botón de comando predeterminado. Cuando
Default se define a True para un botón de comando, se define automáticamente a False para el resto de los
botones de comando del formulario. Cuando la propiedad Default del botón de comando está establecida a True y
su formulario primario está activo, el usuario puede elegir el botón de comando (invocando su evento Click)
presionando ENTRAR. Cualquier otro control que tuviera el enfoque no recibe evento de teclado (KeyDown,
KeyPress o KeyUp) de la tecla ENTRAR a menos que el usuario haya movido el enfoque a otro botón de comando
del mismo formulario. En este caso, al presionar ENTRAR se elige el botón de comando que tiene el enfoque en
lugar del botón de comando predeterminado.
DragIcon
Establece el icono que se presenta como puntero en una operación de arrastrar y colocar.
DragMode
Establece un valor que determina si se usa el modo de arrastre manual o automático en una operación de arrastrar
y colocar. Los valores posibles de número son:
0 Manual (Predeterminado)
1 Automático
Enabled Habilitado
Propiedad Booleana que habilita o deshabilita el botón. Cuando está deshabilitado (Enabled = False), el botón no
tiene efecto, y su apariencia varía, presentando un tono pálido tanto en su cuerpo como en su título. Puede variarse
en tiempo de ejecución.
Font Fuente
Es el tipo de letra para el título. Puede cambiarse en tiempo de ejecución.
Height Altura
Establece la altura del botón. Normalmente esta propiedad no se introduce numéricamente, sino que la toma
automáticamente de las dimensiones que se le den al botón en tiempo de diseño. Puede cambiarse, cambiando el
valor a esta propiedad, en tiempo de ejecución.
HelpContextID
Establece un número de contexto asociado para este control. Este número se aplica para determinar la ayuda
interactiva.
Index Indice
En el caso de que se tengan varios botones que realicen una función similar (Las teclas numéricas de una
calculadora, p.e.) puede hacerse un array con estos botones de comando. Todos tendrán el mismo nombre, y se
diferencian por un índice. Esta propiedad Index toma el número de ese índice.
Left
Posición de su parte izquierda. Indica la posición del botón, concretamente de la parte izquierda del mismo.
Normalmente esta propiedad no se introduce numéricamente, sino que la toma automáticamente de la posición que
se le de al botón en tiempo de diseño. Puede cambiarse, cambiando el valor a esta propiedad, en tiempo de
ejecución.
Tag
Esta propiedad no la usa directamente Visual-Basic. Sirve para asociar a este control alguna información adicional
para fines externos a la programación. Similar a la del formulario.
Top
Indica la coordenada de la parte superior del control. Puede variarse durante el tiempo de ejecución. Esta
propiedad, juntamente con Left definen la esquina superior izquierda del botón de comando. Normalmente esta
propiedad no se introduce numéricamente, sino que la toma automáticamente de la posición que se le den al botón
en tiempo de diseño. Puede cambiarse, cambiando el valor a esta propiedad, en tiempo de ejecución.
Visible Visible
Propiedad Booleana. Si es true, el botón se ve, si es False el botón no se ve. Puede cambiarse en tiempo de
ejecución. De hecho, es un recurso muy usado para dejar visibles en un formulario, solamente los objetos
(controles) necesarios.
Devuelve o establece un número de contexto asociado a un objeto. Se utiliza para dotar a las aplicaciones de
Ayuda interactiva con el menú emergente ¿Qué es esto? de la Ayuda de Windows 95.
Width Ancho
Define el ancho del botón. Con Height determina la dimensión del botón.
LABEL ETIQUETA
____________________
Una etiqueta es un control que nos permite presentar un texto. La etiqueta debe usarse en aquellos casos en los que exista una información
estática o dinámica que no deba ser cambiada por el operador.
Puede adoptar estas formas: con borde tridimensional, borde plano o sin borde, y el texto justificado a la izquierda, a la derecha o
centrado.
Se ha incluido la trama para poder observar los límites de la etiqueta sin borde.
PROPIEDADES
Alignment Justificación
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta.
Autosize Tamaño
Propiedad booleana. Si se pone a True, el tamaño de la etiqueta se ajusta al texto que contiene.
Caption Título
Es el texto de la etiqueta. Puede cambiarse en tiempo de ejecución, lo que permite usar la etiqueta como
dispositivo de presentación de textos. No se puede cambiar por el procedimiento de arrastrar con el ratón, por lo
que es el control adecuado cuando se quiere presentar un texto que no se pueda cambiar por el operador.
DataField DataSource
Establecen la base de datos y el campo donde está el texto Datos que se llevará a la propiedad Caption. Estas
propiedades permiten presentar los datos de una Base de Datos mediante un procedimiento muy sencillo, con la
ayuda de un control Data (Se verá mas adelante)
DragIcon
Establece el icono que se presenta como puntero en una operación de arrastrar y colocar.
DragMode
Establece un valor que determina si se usa el modo de arrastre manual o automático en una operación de arrastrar
y colocar. Los valores posibles de número son:
0 Manual (Predeterminado)
1 Automático
Enabled Habilitado
Propiedad Booleana que habilita o deshabilita la etiqueta Cuando está deshabilitado (Enabled = False), no tienen
efecto los eventos que se produzcan sobre ella, y su apariencia varía, presentando un tono pálido tanto en su
cuerpo como en su título. Puede variarse en tiempo de ejecución.
Font Fuente
Es el tipo de letra para el título. Puede cambiarse en tiempo de ejecución.
ForeColor
Es el color de la letra de la etiqueta. Puede cambiarse en tiempo de ejecución.
Height Altura
Establece la altura de la etiqueta. Normalmente esta propiedad no se introduce numéricamente, sino que la toma
automáticamente de las dimensiones que se le den a la etiqueta en tiempo de diseño.
Index Indice
En el caso de que se tengan varios etiquetas que realicen una función similar puede hacerse un array con
etiquetas. Todas tendrán el mismo nombre, y se diferencian por un índice. Esta propiedad Index toma el número
de ese índice.
Name Nombre
Es el nombre de la etiqueta con el que se le conocerá a lo largo del programa
TabIndex Nº de orden
Al igual que para los botones de comando, la etiqueta tiene propiedad TabIndex. Sin embargo, una etiqueta
NUNCA tomará el foco. Vea la propiedad UseMneumonic mas adelante.
Tag
Esta propiedad no la usa directamente Visual-Basic. Sirve para asociar a este control alguna información adicional
para fines externos a la programación.
Top
Indica la coordenada de la parte superior del control. Puede variarse durante el tiempo de ejecución. Esta
propiedad, juntamente con Left definen la esquina superior izquierda del botón de comando. Normalmente esta
propiedad no se introduce numéricamente, sino que la toma automáticamente de la posición que se le den a la
etiqueta en tiempo de diseño. Puede cambiarse, cambiando el valor a esta propiedad, en tiempo de ejecución.
UseMneumonic
Devuelve o establece un valor que indica si al incluir el signo (&) en el texto de la propiedad Caption del control
Label se define una tecla de acceso. Es una propiedad Booleana.
True (Predeterminado) Los caracteres (&) que aparezcan en el texto de la propiedad Caption definen al carácter
siguiente como tecla de acceso. El signo (&) no aparece en la interfaz del control Label.
False Los caracteres (&) que aparezcan en el texto de la propiedad Caption aparecen como tales en la interfaz del
control Label.
En tiempo de ejecución, al presionar ALT+ la tecla de acceso definida en la propiedad Caption del control Label, el
enfoque se desplaza al control siguiente al control Label en el orden de tabulación.
Visible Visible
Propiedad Booleana. Si es true, la etiqueta se ve, si es False no se ve. Puede cambiarse en tiempo de ejecución.
WhatThisHelpID (Propiedad, Windows 95)
Devuelve o establece un número de contexto asociado a un objeto. Se utiliza para dotar a las aplicaciones de
Ayuda interactiva con el menú emergente ¿Qué es esto? de la Ayuda de Windows 95.
Width Ancho
Define el ancho de la etiqueta. Con Height determina la dimensión de la misma.
WordWrap
Devuelve o establece un valor que indica si un control Label con el valor True en su propiedad AutoSize se
expande vertical u horizontalmente para adaptarse al texto especificado en su propiedad Caption. Es una
propiedad Booleana.
True El control Label se expande o contrae horizontal y verticalmente para adaptarse al texto y al tamaño de la
fuente. Contempla para la expansión horizontal la colocación de los espacios del texto.
False (Predeterminado) El texto no se ajusta a la siguiente línea; el control Label se expande o contrae
horizontalmente para adaptarse a la longitud del texto y verticalmente para adaptarse al tamaño de la fuente y al
número de líneas.
Nota Si se establece False en AutoSize, el texto siempre se ajustará a la línea siguiente, independientemente del
tamaño del control Label y del valor de la propiedad WordWrap. Esto puede ocultar parte del texto, ya que el
control Label no se expande en ninguna dirección.
La caja de texto no se debe usar nunca para presentar textos que el operador de la aplicación no deba cambiar. Úsese para ello la etiqueta,
control no bidireccional, que además tiene la ventaja de ocupar menos memoria de programa.
Las cajas de texto pueden tener una o varias líneas, según esté la propiedad Multiline. La capacidad máxima de una caja de textos es de
64 Kbytes.
La forma de una caja de texto es la siguiente, dependiendo de las propiedades BorderStyle y Appearance:
PROPIEDADES
Alignment Justificación
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta. Esta propiedad
solamente tiene efecto cuando la propiedad Multiline está a True, ignorándose en caso contrario. Es decir, permite
colocar el texto justificado a la derecha cuando ese texto puede ser de varias líneas. Para una única línea, se
justifica siempre a la izquierda.
Esta propiedad no puede cambiarse en tiempo de ejecución, pero sí puede leerse en que condición está.
Appearance Apariencia
Plana o tridimensional.
Backcolor Color de fondo
Es el color de fondo de la caja de texto. Puede cambiarse en tiempo de ejecución.
DataField
DataSource Fuente de Datos
Establecen la base de datos y el campo donde está el texto que se llevará a la propiedad Text. Estas propiedades
permiten presentar de una forma muy sencilla datos de una Base de Datos. Se verán cuando se estudie el control
Data y el motor de bases de datos
DragIcon
Establece el icono que se presenta como puntero en una operación de arrastrar y colocar.
DragMode
Establece un valor que determina si se usa el modo de arrastre manual o automático en una operación de arrastrar
y colocar. Los valores posibles de número son:
0 Manual (Predeterminado)
1 Automático
Enabled Habilitado
Propiedad Booleana que habilita o deshabilita la etiqueta Cuando está deshabilitado (Enabled = False), no tienen
efecto los eventos que se produzcan sobre el TextBox. No se puede escribir el él ni pasarle el foco, pero sí se le
puede cambiar el texto mediante el programa. Puede ser una buena alternativa para impedir que el usuario pueda
cambiar un determinado texto. Esta propiedad puede variarse en tiempo de ejecución.
Font Fuente
Es el tipo de letra que se utilizará en el TextBox. Puede cambiarse en tiempo de ejecución.
HelpContextID
Establece un número de contexto asociado para este control. Este número se aplica para determinar la ayuda
interactiva.
Index Indice
En el caso de que se tengan varias cajas de texto que realicen una función similar puede hacerse un array con
ellas. Todas tendrán el mismo nombre, y se diferencian por un índice. Esta propiedad Index toma el número de ese
índice.
Locked
Establece si el texto se puede editar, es decir, cambiar. Cuando se pone esta propiedad a True, el texto existente
en la caja puede resaltarse con el ratón, e incluso copiarlo al portapapeles, pero no puede variarse tecleando un
nuevo texto. Se puede cambiar por programa, cambiando la propiedad Text.
Si está en False, puede cambiarse el texto mediante teclado.
MaxLenght
Indica, si se establece, la longitud máxima del texto.
MouseIcon Puntero del ratón personalizado
MousePointer Puntero ratón
Determina la forma del puntero del ratón cuando éste pasa por encima de la caja de texto. Puede elegirse uno de
los punteros preestablecidos en esta propiedad, (15 en total) e incluso un puntero personalizado en la propiedad
MouseIcon. Para que aparezca este puntero personalizado, MousePointer debe ponerse al valor 99. Lo típico
para esta propiedad es el I-Beam (barra vertical)
Name Nombre
Es el nombre de la caja de texto con el que se le conocerá a lo largo del programa
PasswordChar
En ocasiones, es conveniente que no se pueda leer lo que se escribe en la caja de texto, caso por ejemplo de la
entrada de un password o palabra de paso. Esta propiedad nos permite indicar un carácter que sustituye a
cualquier carácter que tenga la caja de texto. (Típicos el * o ?). El texto que tenga en la propiedad Text no cambia
por el hecho de presentar en pantalla un carácter distinto. Esta propiedad puede cambiarse en tiempo de ejecución.
Para quitar el PasswordChar basta con forzarlo al carácter nulo : Text1.PasswordChar = “”
ScrollBars
Cuando la propiedad Multiline de la caja de texto está a True, se pueden colocar barras de desplazamiento del
texto hacia arriba y abajo, o hacia los lados. Esto nos permite tener una caja de texto de tamaño reducido y poder
leer en ella un texto mayor que la propia caja. Esta propiedad puede tomar los siguiente valores :
0 - No salen barras
1 - Barras de desplazamiento horizontal
2 - Barras de desplazamiento vertical
3 - Ambas barras.
Tag
Esta propiedad no la usa directamente Visual Basic. Sirve para asociar a este control alguna información adicional
para fines externos a la programación.
Top
Indica la coordenada de la parte superior del control. Puede variarse durante el tiempo de ejecución. Esta
propiedad, juntamente con Left definen la esquina superior izquierda de la caja de texto. Normalmente esta
propiedad no se introduce numéricamente, sino que la toma automáticamente de la posición que se le de en tiempo
de diseño. Puede cambiarse, cambiando el valor a esta propiedad, en tiempo de ejecución.
Visible Visible
Propiedad Booleana. Si es true, la caja de texto se ve, si es False no se ve. Puede cambiarse en tiempo de
ejecución.
Devuelve o establece un número de contexto asociado a un objeto. Se utiliza para dotar a las aplicaciones de
Ayuda interactiva con el menú emergente ¿Qué es esto? de la Ayuda de Windows 95.
Width Ancho
Define el ancho de la caja de texto. Con Height determina la dimensión de la misma.
FRAME RECUADRO
Un control Frame proporciona un agrupamiento identificable para controles. También puede utilizar un Frame para subdividir un formulario
funcionalmente por ejemplo, para separar grupos de controles OptionButton.
Para agrupar controles, en primer lugar trace el control Frame y, a continuación, meta los controles dentro de Frame. De este modo podrá
mover al mismo tiempo el Frame y los controles que contiene. Si traza un control fuera del Frame y, a continuación, intenta moverlo dentro
de éste, el control se colocará sobre el Frame, pero no pertenecerá a el. Es decir, si es un OptionButton este se comportará como si
estuviese fuera del Frame, aunque físicamente esté dentro de el.
Cuando un control Frame tiene dentro otros controles, y hacemos invisible al Frame, mediante su propiedad Visible = False, los controles
interiores al Frame quedan también invisibles.
PROPIEDADES
Las señaladas con (*) no presentan novedades respecto a las ya comentadas para los controles precedentes.
Appearance (*)
Backcolor (*)
ClipControls
Si esta propiedad está a True, los métodos gráficos en eventos Paint vuelven a dibujar el objeto entero. Antes del
evento Paint se crea una zona de recorte alrededor de los controles no gráficos del formulario. Si esta propiedad
está a False dibujarán solamente las áreas últimamente expuestas. En tiempo de ejecución, esta propiedad es de
sólo lectura.
DragIcon (*)
DragMode (*)
Enabled
Cuando esta propiedad está a False, tanto los procedimientos asociados al propio control Frame como todos los
controles dentro del Frame estarán inhabilitados. Si esta propiedad está a True, todos ellos están habilitados.
Font
En esta propiedad, el tipo de letra afecta solamente al título del Frame, no a los controles internos a el.
ForeColor
Color de las letras del título del Frame.
Height (*)
HelpContextID (*)
Index (*)
Left (*)
MouseIcon (*)
MousePointer (*)
Name (*)
TabIndex (*)
Tag (*)
Top (*)
Visible
Cuando un Frame está con la propiedad Visible = False, tanto el propio Frame como todos los controles interiores
a el serán invisibles.
WhatsThisHelpID (*)
Width (*)
MouseMove MouseUp
El control CheckBox, o casilla de verificación, permite elegir una opción (activada/desactivada, True/False) que el usuario puede establecer
o anular haciendo click. Una X en una casilla de verificación indica que está seleccionada, activada, o con valor True. Cada casilla de
verificación es independiente de las demás que puedan existir en el formulario, pudiendo tomar cada una de ellas el valor True o False, a
voluntad del operador.
Un control OptionButton muestra una opción que se puede activar o desactivar, pero con dependencia del estado de otros controles
OptionButton que existan en el formulario.
Generalmente, los controles OptionButton se utilizan en un grupo de opciones para mostrar opciones de las cuales el usuario sólo puede
seleccionar una. Los controles OptionButton se agrupan dibujándolos dentro de un contenedor como un control Frame, un control
PictureBox o un formulario. Para agrupar controles OptionButton en un Frame o PictureBox, dibuje en primer lugar el Frame o
PictureBox y, a continuación, dibuje dentro los controles OptionButton. Todos los controles OptionButton que están dentro del mismo
contenedor actúan como un solo grupo, e independientes de los controles OptionButton de otros grupos distintos.
Aunque puede parecer que los controles OptionButton y CheckBox funcionan de forma similar, hay una diferencia importante: Cuando un
usuario selecciona un OptionButton, los otros controles del mismo grupo OptionButton dejan de estas disponibles automáticamente. Por
contraste, se puede seleccionar cualquier número de controles CheckBox.
En el ejemplo de la figura, existen tres grupos de OptionButton, uno en un PictureBox, que actúa, al tiempo que como cuadro de imagen,
como contenedor de controles OptionButton. Otro grupo está en el interior de un control Frame, y el otro grupo está en el formulario. Los
tres grupos son independientes entre sí, pero interiormente al grupo solamente puede seleccionarse uno de los OptionButton que lo
componen.
En el formulario también existen tres CheckBox, que como puede verse, se pueden seleccionar los que se desee, sin ningún tipo de
exclusión entre ellos.
PROPIEDADES
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya comentadas
para los controles precedentes.
0 - Left Justify
1 - Right Justify
Cuando se elige el valor 0, justificado a la izquierda, el título del control aparece a la derecha del botón, pegado a la figura del botón.
Cuando se elige el valor 1, justificado a la derecha, el título (Caption) aparece a la izquierda del botón, comenzando en la parte izquierda
del cuerpo total del control, es decir, no tiene porqué aparecer con su parte derecha pegado al botón, caso que el cuerpo total del control se
haya hecho mas largo que la palabra del título.
Appearance (*)
Backcolor (*)
Caption (*).
DragIcon (*)
DragMode (*)
Enabled (*)
Font (*)
ForeColor (*)
HelpContextID (*)
Index (*)
Left (*)
MouseIcon (*)
MousePointer (*)
Name (*)
TabIndex (*)
TabStop (*)
Tag (*)
Top (*)
Value Común a ambos controles
El valor de esta propiedad indica si el control está seleccionado (Value = 1) o no seleccionado (Value = 0 ó Value
= False). Esta propiedad puede cambiarse en tiempo de ejecución. Mediante esta propiedad, podemos tanto forzar
el valor como leerlo.
Atención. Presenta una diferencia entre uno y otro control respecto a la forma de expresarse respecto a su valor
cuando está seleccionado. Para forzar que el control NO esté seleccionado, o para leer el Value cuando no está
seleccionado, podemos utilizar tanto Value = 0 como Value = False. Sin embargo, cuando lo que se quiere es
poner la propiedad a True hay una diferencia entre ambos controles.
Para el OptionButton podemos utilizar indistintamente las siguiente formas :
Check1.value = 1
El poner como Value el valor True nos dará en este control un error.
Para la lectura del Value, existe una diferencia entre el valor devuelto por el CheckBox y el devuelto por el
OptionButton.
Visible (*)
WhatsThisHelpID (*)
Width (*)
PROCEDIMIENTOS
Click DblClick (Solo OptionButton) DragDrop DragOver GotFocus
Un control ListBox muestra una lista de elementos en la que el usuario puede seleccionar uno o más. Si el número de elementos supera el
número que puede mostrarse, se agregará automáticamente una barra de desplazamiento al control ListBox.
Un control ComboBox combina las características de un control TextBox y un control ListBox. Los usuarios pueden introducir información
en la parte del cuadro de texto y seleccionar un elemento en la parte de cuadro de lista del control. En resumen, un ComboBox es la
combinación de un ListBox, que se comporta como si de un ListBox se tratase, y de un TextBox, con comportamiento análogo a un
TextBox sencillo, con la particularidad aquí de que el texto se le puede introducir por teclado, o elegir uno de los que figuran en la parte
ListBox del Combo.
La lista tiene varios elementos. Cada línea de esta lísta es un elemento de la lista. Como el número de elementos de la lista tiene mas
elementos de los que le podían caber, generó automáticamente la barra de desplazamiento vertical.
El ComboBox está normalmente sin desplegar. Se despliega cuando se hace click con el ratón en la flecha que tiene en su parte derecha
(véase fig. Anterior). Al desplegarse, muestra la lista con todos sus elementos. Haciendo click con el ratón en cualquiera de sus elementos,
el elemento elegido pasa a la parte TextBox del Combo y la lista vuelve a replegar.
El ListBox (y por tanto el ComboBox) tiene unas propiedades y métodos particulares que solamente se pueden aplicar durante el tiempo
de ejecución :
Para seleccionar un elemento de la lista, basta con hacer click con el ratón sobre él. Ese elemento se resaltará con fondo en azul. Una vez
seleccionado un elemento, la propiedad ListIndex tomará el valor del número de orden que ocupa ese elemento en la lista, comenzando
por el 0 para el elemento que ocupa el primer lugar. Si no se selecciona ningún elemento, el valor de la propiedad ListIndex será -1. El
primer elemento de la lista es ListIndex 0, y el valor de la propiedad ListCount siempre es uno más que el valor mayor de ListIndex.
En el ComboBox la propiedad Text contiene el texto que contenga la parte TextBox del Combo, bien haya sido introducida desde teclado
o mediante la recuperación de un elemento la parte ListBox del mismo.
Ejemplos
Supongamos que tenemos un ListBox llamado List1, y un ComboBox llamado Combo1. Se enumeran distintas formas de obtener
información de ellos.
Variable = List1.Listcount
Variable contendrá un número con el número total de elementos de la lista List1.
Variable = List1.ListIndex
Variable contendrá un número con el número de orden del elemento de la lista seleccionado en ese momento.
Variable = “VISUALBASIC”
List1.AddItem Variable
Añade un elemento a List1. En este caso, el elemento añadido es la palabra VISUALBASIC.
Variable = List1.Text
Variable contendrá el elemento que estaba seleccionado en List1. (Variable será una cadena de caracteres)
List1.RemoveItem (n)
Elimina el elemento n de List1.
List1.RemoveItem (List1.ListIndex)
Elimina el elemento que estaba seleccionado en ese momento.
List1.listIndex = n
Selecciona el elemento n de List1 (Se resalta en azul el elemento n)
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya comentadas para los controles
precedentes.
Appearance (*)
Backcolor (*)
Columns Propiedad de ListBox solamente.
Determina si los elementos se presentan en una sola columna o en varias columnas, y la forma de presentar los elementos en el ListBox. Si
esta propiedad se pone a 0 la lista tendrá solamente una columna, y presentará los elementos uno debajo de otro. Cuando los elementos
sean mas que los que se pueden presentar en la lista, aparecen automáticamente unas barras de desplazamiento vertical.
Si la propiedad se pone a un número distinto a 0, el ListBox es de tipo multicolumna, presentará en cada columna los elementos que le
quepan dependiendo de su dimensión vertical, y tendrá tantas columnas como sea necesario para albergar el número de elementos que
tenga. Presentará en su cuadro tantas columnas como se le indique en el valor de esta propiedad, y si no puede presentar todos los
elementos en las columnas que muestra, le aparecerán barras de desplazamiento horizontales para poder movernos por todas las
columnas que tenga.
Recuerde : El número que se le asigna a la propiedad Columns no indica el número de columnas que tendrá el ListBox sino el número de
columnas que presenta.
Esta propiedad puede asignarse en diseño, mediante la caja de propiedades, o en tiempo de ejecución mediante una instrucción como
esta :
Nombrelista.Columns = número
.
Esta propiedad no puede definirse a 0 o cambiada desde 0 en tiempo de ejecuciones decir, no se puede convertir en tiempo de ejecución
un ListBox de múltiples columnas en un ListBox de columna única o un ListBox de columna única en un ListBox de múltiples columnas. Sin
embargo, sí es posible cambiar durante la ejecución el número de columnas de un ListBox de múltiples columnas.
DataField DataSource .
Establecen la base de datos y el campo donde están los datos que se llevarán al TextBox o ComboBox para
presentar datos procedentes de una Base de Datos.
DragIcon (*)
DragMode (*)
Enabled (*)
Font (*)
ForeColor (*)
Height (*)
HelpContextID (*)
Index (*)
IntegralHeight No aplicable a ListBox o ComboBox
ItemData Propiedad muy importante.
Devuelve o establece un número específico para cada elemento de un control ComboBox o ListBox.
Sintaxis
objeto.ItemData(índice) [= número]
Comentarios
La propiedad ItemData es una matriz de valores enteros largos cuyo número de elementos es el valor de la propiedad ListCount del control.
Los números asociados con cada elemento se pueden usar para cualquier fin. Por ejemplo, se puede usar en la confección de una lista de
teléfonos, el número de identificación de un empleado, etc. Cuando se rellena el ListBox, también se rellena los elementos
correspondientes de la matriz ItemData con los números correspondientes.
La propiedad ItemData se usa a menudo como índice de una matriz de estructuras de datos asociados con los elementos de un control
ListBox.
Nota Cuando se inserta un elemento en una lista con el método AddItem, el elemento también se inserta automáticamente en la matriz
ItemData. Sin embargo, el valor no se reinicializa a cero; retiene el valor que estaba en esa posición antes agregar el elemento a la lista.
Cuando se usa la propiedad ItemData, asegúrese de establecer su valor al agregar nuevos elementos a la lista.
Left (*)
MouseIcon (*)
MousePointer (*)
Name (*)
Sorted
Establece o devuelve un valor que indica si los elementos de un ListBox o ComboBox se colocan automáticamente en orden
alfabético. Los valores que puede adoptar son True o False.
True Los elementos de la lista se ordenan alfabéticamente (sin distinguir entre mayúsculas y minúsculas).
False (Predeterminado) Los elementos de la lista no se ordenan alfabéticamente.
Cuando esta propiedad tiene el valor True, Visual Basic se encarga de casi todo el procesamiento de cadenas necesario para
mantener el orden alfabético, incluyendo el cambio de los números de índice cuando se agregan o eliminan elementos.
Nota El uso del método AddItem para agregar un elemento en una posición específica de la lista puede romper el orden
alfabético, y los elementos agregados con posterioridad pueden no ordenarse correctamente.
TabIndex (*)
TabStop (*)
Tag (*)
Top (*)
Visible (*)
WhatsThisHelpID (*)
Width (*)
PROCEDIMIENTOS
Click Change (Solo ComboBox) DblClick DragDrop DragOver
El procedimiento Change del ComboBox solamente se efectúa cuando el cambio se produce mediante la entrada de un texto DESDE EL
TECLADO, no por un cambio en la parte Text de este control, producido al llevar un elemento desde la parte List a la parte Text.
Son dos controles similares, para introducir un dato cuasi-analógico en una aplicación. Se toman directamente de la caja de herramientas, y
tienen un aspecto parecido al de un control de volumen de un equipo de música. El HScrollBar está en posición horizontal, y el VScrollBar
en posición vertical.
Mediante estos controles se pueden introducir datos variando la posición del cursor.
Las señaladas con (*) son comunes a ambos controles y no presentan novedades respecto a las ya comentadas para los controles
precedentes.
DragIcon (*)
DragMode (*)
Enabled (*)
Height (*)
HelpContextID (*)
Index (*)
LargeChange
Esta propiedad establece la variación de la propiedad Value cada vez que se hace click en el interior de la barra de
desplazamiento, en la parte por donde pasa el cursor.
Left (*)
Max
Esta propiedad establece el valor máximo para la propiedad Value, es decir, el valor de esta propiedad cuando el cursor
está en su parte máxima. (Recuerde que el cursor está en el máximo, cuando está mas a la derecha, caso del HScrollBar,
o cuando está en la parte mas baja, caso del HScrollBar.
Min
Esta propiedad establece el valor mínimo para la propiedad Value, es decir, el valor de esta propiedad cuando el cursor
está en su parte mínima. (Recuerde que el cursor está en el mínimo, cuando está mas a la izquierda, caso del HScrollBar,
o cuando está en la parte mas alta, caso del HScrollBar.
MouseIcon (*)
MousePointer (*)
Name (*)
SmallChange
Esta propiedad establece la variación de la propiedad Value cada vez que se hace click en las flechas superior o inferior de
la barra de desplazamiento.
TabIndex (*)
TabStop (*)
Tag (*)
Top (*)
Value
Esta propiedad lee o establece el valor dado por la posición del cursor. Este valor tiene un mínimo, establecido por Min y
un máximo, establecido por Max. Esta propiedad es la que se debe leer para conocer la posición del cursor.
Visible (*)
WhatsThisHelpID (*)
Width (*)
Comentario El Procedimiento Change se produce cuando, tras mover el cursor, se suelta el botón del ratón. Esto produce el efecto de
que el cambio que se tenga que producir con el movimiento del cursor no se realiza de una manera continua. El procedimiento Scroll se
realiza en el instante que se está moviendo el cursor. Por lo tanto, es este procedimiento el que se debe usar para conseguir el efecto de un
cambio continuo mientras se está moviendo el cursor.
TIMER TEMPORIZADOR
Este objeto permite establecer temporizaciones. Presenta una novedad respecto a los controles estudiados hasta ahora. El control Timer
solamente se ve durante el tiempo de diseño. En tiempo de ejecución, el control permanece invisible.
La temporización producida por el Timer es independiente de la velocidad de trabajo del ordenador. (Casi independiente. El timer no es un
reloj exacto, pero se le parece)
Enabled (*)
Index (*)
Interval
El valor de esta propiedad nos dará el intervalo de tiempo (en milisegundos) en que se producirá un evento Timer y consecuentemente,
realizará el procedimiento asociado a este evento. Si el valor de la propiedad Interval está a 0 (Predeterminado), no se produce el evento
Timer. (El control Timer está deshabilitado cuando se pone la propiedad Interval = 0)
Left (*)
Name (*)
Tag (*)
Top (*)
PROCEDIMIENTOS
Timer
SHAPE
Shape es un control gráfico que se muestra como un rectángulo, un cuadrado, una elipse, un círculo, un rectángulo redondeado o un
cuadrado redondeado.
Utilice controles Shape en tiempo de diseño en lugar o además de invocar los métodos Circle y Line en tiempo de ejecución. Puede dibujar
un control Shape en un contenedor, pero no puede actuar como contenedor. (Esto quiere decir que un control Shape nunca le servirá, por
ejemplo, para albergar varios OptionButton y pretender que sean independientes de otros controles OptionButton que se encuentren
fuera del control Shape.
Este control no tiene Procedimientos. En realidad, solamente sirve para mostrar un determinado gráfico, envolver gráficamente a otros
controles, pero no tiene ninguna aplicación en cuanto a programa. Es un “adorno” para sus aplicaciones.
PROPIEDADES
Backcolor (*)
BackStyle
Esta propiedad establece si Shape permite ver a su través (Transparent) o n lo permite (Opaque)
BorderColor
Establece el color del borde.
BorderStyle
Establece el tipo de borde. Puede ser : Transparent, (No se ve el borde), Solid, (Borde de línea continua),Dash, (línea a
rayas), Dot, (línea a puntos), Dash-Dot, (línea de raya - punto), dash-Dot-Dot, (línea de raya - punto - punto), InsideSolid,
(raya continua)
El efecto de establecer la propiedad BorderStyle depende del valor de la propiedad BorderWidth. Si BorderWidth no es 1 y
BorderStyle no es 0 o 6, BorderStyle se establece como 1.
BorderWidth
Establece el ancho de la línea.
DrawMode (*)
FillColor (*)
FillStyle (*)
Height (*)
Index (*)
Left (*)
Name (*)
Shape
Establece la forma del control. Puede ser : Rectangular, cuadrado, redondo, ovalado, cuadrado con esquinas redondeadas
y rectangular con esquinas redondeadas.
Tag (*)
Top (*)
Visible (*)
Width (*)
PROCEDIMIENTOS No tiene.
.LINE
Line, al igual que Shape, es un control gráfico que solamente sirve para poner una línea en un formulario. Del mismo modo, no tiene
procedimientos, por lo que no sirve para aportar código al programa. Solo sirve para aportar una característica gráfica, es un adorno.
PROPIEDADES
BorderColor
Establece el color de la línea.
BorderStyle
Establece el tipo de línea : Puede ser : Transparent, (No se ve la línea), Solid, (Línea continua),Dash, (línea a rayas), Dot,
(línea a puntos), Dash-Dot, (línea de raya - punto), dash-Dot-Dot, (línea de raya - punto - punto), InsideSolid, (raya
continua)
BorderWidth
Establece el ancho de la línea.
DrawMode (*)
Index (*)
Left (*)
Name (*)
Tag (*)
Visible (*)
X1, X2 Establece las coordenadas x del inicio y final.
Y1, Y2 Establece las coordenadas y del inicio y final
PROCEDIMIENTOS No tiene.
CONTROL GAUGE
Este control presenta una información numérica de forma gráfica, bien como un display lineal (típico por ejemplo en ecualizadores de
audio ), o como una aguja. No está normalmente en la caja de herramientas, por lo que hay que traerla desde los Controles Personalizados
(Menú desplegable de Herramientas). Se denomina MicroHelp Gauge Control. El archivo que lo contiene se denomina GAUGE16.OCX,
(Ver. 16 bits) GAUGE32.OCX (Ver. 32 bits)
Mediante este control, podemos presentar una magnitud numérica de una forma cuasi-analógica. Podríamos decir que es un control similar
al HScrollBar, que en vez de meter información a la aplicación, la presenta.
Este control puede servir, por ejemplo, para presentar el tanto por ciento de ejecución de una tarea, como elemento tranquilizante. Puede
presentar el nivel de un depósito de agua, etc.
Nota para la distribución Cuando cree y distribuya aplicaciones con controles Gauge, tendrá que instalar el archivo apropiado en el
subdirectorio SYSTEM de Windows del cliente. El Kit para instalación que incluye Visual Basic, le proporciona herramientas para escribir los
programas que instalan las aplicaciones correctamente.
PROPIEDADES
PROCEDIMIENTOS
El CommonDialog es un control del que se libran muy pocas aplicaciones. Dada la importancia de este control, se le dedica un capitulo
único en esta Guía del Estudiante.
Este control no se presenta en tiempo de diseño mas que con un simple icono :
El cuadro de diálogo, CommonDialog se utiliza para varias funciones :
Abrir Ficheros
Guardar Ficheros
Elegir colores
Seleccionar Impresora
Seleccionar Fuentes
Mostrar el fichero de Ayuda
En realidad el cuadro de diálogo permite conocer datos con los cuales, y mediante el código adecuado, abriremos o guardaremos ficheros,
elegiremos colores o seleccionaremos fuentes. Es decir, el CommonDialog NO realiza mas funciones que mostrar ficheros existentes,
fuentes disponibles, colores, para que, mediante código, abramos esos ficheros o usemos una determinada fuente.
Dependiendo de la aplicación para la que vaya a usarse se deberá activar de distintas formas. Si el cuadro de diálogo se va a usar para
seleccionar la impresora y para otras aplicaciones, es recomendable usar uno exclusivamente para seleccionar la impresora.
Esta última recomendación se debe a que, para el control de la impresora, el CommonDialog SI realiza las funciones de selección de
impresora predeterminada. Esta diferencia operativa hace que si usamos el mismo CommonDialog para seleccionar impresora y abrir
ficheros, por ejemplo, se “cuelgue” el CommonDialog.
El control CommonDialog es un control personalizado (Microsoft CommonDialog Control COMDLG16.OCX / COMDLG32.OCX), y como
casi todos los controles personalizados presenta un asistente de propiedades propio. Puede accederse a las propiedades mediante el
cuadro de propiedades típico de otros controles, o mediante el asistente, pulsando el botón derecho del ratón con el puntero colocado
encima del icono del cuadro de diálogo.
Analizando las propiedades, vemos que tiene gran cantidad de ellas. Esto es porque agrupa todas las propiedades correspondientes a la
cinco funciones que puede desarrollar. Se detalla a continuación la forma de usar el CommonDialog para cada aplicación.
Se entiende que el nombre - Name - que se ha puesto para el cuadro de diálogo en todos los ejemplos es CD1)
FUENTES
Para mostrar el cuadro de diálogo correspondiente a Tipos de Letra ( Fonts ), debe ejecutarse la instrucción:
CD1.ShowFont
y haber puesto, en la propiedad Flags del cuadro de diálogo, el valor de 1, 2 ó 3, correspondiente respectivamente a los tipos de letra de la
pantalla, de la impresora o ambos. (Véase la propiedad Flags mas adelante) Si no pone uno de estos valores, le dirá que no tiene fuentes
instaladas.
En el ejemplo que acompaña a este capítulo, puede ver como se introducen las características de una determinada fuente elegida en un
cuadro de texto.
COLOR
CD1.ShowColor
(La parte derecha del cuadro puede no salir. Depende del valor de la propiedad Flags. Se saca haciendo click en Definir colores
personalizados, si está activado. También depende de la propiedad Flags)
El número correspondiente al color elegido se puede conocer analizando la propiedad color de cuadro de diálogo. En nuestro ejemplo, lo
obtendríamos con
Variablecolor = CD1.Color
Para establecer un color por medio de código, se pondrá un valor de color a la propiedad correspondiente de ese objeto. El valor del color
puede establecerse de tres formas que se comentan a continuación.
Visual Basic acepta para especificar un color, tres procedimientos: Mediante el número de color, mediante la sentencia RGB ( rojo, verde,
azul ) o mediante la función QBColor.
Por número
El número que representa el color en VB está formado por la suma de la componente roja, la componente verde y la componente azul.
Podríamos verlo muy bien en numeración Hexadecimal:
Color = Hex XX YY ZZ
Donde ZZ es un número Hexadecimal que representa la cantidad del color rojo. El mínimo estaría en 0 (H00) y el máximo en 255 (HFF)
YY representaría la cantidad de color verde y XX la de color azul, ambos con los mismos límites explicados para el rojo.
Una mezcla de un poco de rojo (HB1), otro poco de verde (H56) y otro poco de azul (H1F) daría el siguiente número:
Hex(1F56B1) = 2053809
El número de color puede estar comprendido entre 0 (correspondiente al negro) y el 16777215 (correspondiente al blanco. Observe que
esa cantidad, 16.777.215 (FFFFFF en hexadecimal) corresponde a los famosos 16 millones de colores de las tarjetas gráficas.
Si queremos poner el color de fondo a un control Label, usaremos la propiedad Backcolor. Si el Label se llama Label1, pondríamos la
instrucción
Label1.Backcolor = 12345678
Se puede expresar el color, poniendo simplemente RGB (rojo, verde, azul), donde rojo es un número entre 0 y 255 que indica la cantidad de
color rojo que se aporta al color, verde un número comprendido entre 0 y 255 indicando la cantidad de verde, y lo mismo para azul.
Esta es la forma mas sencilla de poner la propiedad color, y con la que mejor controlaremos el mismo.
Si queremos poner al Label anterior un color mediante la sentencia RGB, ejecutaríamos la sentencia :
Esta función se ha puesto en Visual Basic para compatibilidad con los colores que se usan en Quick-Basic y Qbasic. Mediante esta función
se obtienen solamente 16 colores.
Sintaxis Objeto.QBColor(color)
0 Negro 8 Gris
1 Azul 9 Azul claro
2 Verde 10 Verde claro
3 Aguamarina 11 Aguamarina claro
4 Rojo 12 Rojo claro
5 Fucsia 13 Fucsia claro
6 Amarillo 14 Amarillo claro
7 Blanco 15 Blanco brillante
Para el mismo Label anterior, usaríamos la sentencia :
IMPRESORAS
Nota: Si utiliza un CommonDialog para impresoras y otras aplicaciones, puede tener problemas. Utilice un CommonDialog
exclusivamente para impresoras.
CD2.ShowPrinter
(A este cuadro de dialogo le hemos llamado CD2 para evitar los problemas referidos en la nota).
Nombredelaimpresora = Printer.DeviceName
Para que la impresora quede como impresora por defecto de Windows, debe tener a True la propiedad PrinterDefault del cuadro de
diálogo.
En este cuadro puede observarse, que además de los botones de ACEPTAR y CANCELAR, existe otro, INSTALAR. Haciendo click en este,
podemos cambiar la impresora por cualquier otra que tenga instalada.
Posiblemente las opciones mas usadas del cuadro de diálogo. Para presentar el cuadro de diálogo correspondiente a Abrir Archivo, debe
ejecutar la instrucción:
CD1.ShowOpen
Si lo que necesita es abrir el cuadro de diálogo para guardar un fichero, debe ejecutar la instrucción :
CD1.ShowSave
pero antes deberá introducir el filtro o filtros de archivos que necesite. Ojo, ¡ ANTES !
Un filtro sirve para que en el cuadro de diálogo se presenten solamente los ficheros de nuestro interés. Se pueden seleccionar por el
nombre, la extensión o las dos cosas. La sintaxis para introducir un filtro es la siguiente:
donde "nombre" puede ser un nombre o usar caracteres comodín. Lo mismo para "extensión"
Por ejemplo, para buscar archivos ejecutables, con cualquier nombre y extensión .EXE
Observe el carácter separador entre la descripción de los ficheros (Ficheros ejecutables) y el parámetro de busca (*.EXE). No ponga
ningún espacio entre el separador y los caracteres de busca. El separador es el carácter ASCII 124.
Puede buscar varios tipos de ficheros, separando los caracteres de busca por medio del carácter punto y coma (;)
Puede también introducir dos filtros, separados por el separador | (En una línea solamente).
¡ No se pueden poner dos líneas con filtros, se quedaría solamente con la última !
En este caso, cuando se presente el cuadro de diálogo, solamente presentará uno de los filtros, y deberá seleccionar manualmente el otro
en un cuadro situado en la parte inferior izquierda del cuadro de diálogo. Para predeterminar cuál de los dos filtros saldrá sin tener que
seleccionarlo, deberá ejecutar esta instrucción, ANTES de invocar el cuadro de diálogo
CD1.FilterIndex = 2
En este caso, aparecerá por defecto el filtro escrito en segundo lugar. El orden de los filtros comienza por 1.
El cuadro de diálogo deberá presentar un directorio. Este directorio con el que, por defecto, aparece el cuadro de diálogo, se puede
introducir mediante la propiedad InitDir, que deberá contener el nombre del directorio y su path. Si no se especifica, comenzará por el
directorio actual.
Nombrefichero= CD1.filename
El nombre del fichero, Nombrefichero en la sentencia anterior, viene con su path, es decir, nombre y dirección completa, por lo que puede
emplearse directamente la salida del CommonDialog para abrir un fichero.
Si desea otra leyenda en la barra de título, puede cambiarla usando el asistente de propiedades, que lo obtendrá colocando el cursor del
ratón sobre el icono del CommonDialog y pulsando el botón derecho. Haga click sobre Propiedades en el popmenú que se presenta.
Aparecerá esto :
PRESENTAR AYUDAS
Mediante el CommonDialog se puede presentar un fichero de ayuda. (Ficheros del tipo .HLP de Windows)
Pese a que se pueden presentar estos ficheros basándonos en el CommonDialog, es preferible usar directamente el programa
WinHelp.Exe, que puede ejecutarlo mediante la función Shell :
Para mostrar el fichero de ayuda debe poner el nombre (y Path) del fichero de ayuda en la propiedad HelpFile del CommonDialog
CD1.HelpFile = "C:\MiCarpeta\MiFicheroAyuda.HLP"
Puede mostrar el índice, o una página concreta de ese fichero. Para ello debe jugar con la propiedad HelpCommand, que le va a indicar al
CommonDialog qué ayuda debe mostrar.
CD1.HelpCommand =Valor
Las opciones para valor son:
1 &H1 cdlContext
Muestra la Ayuda de un contexto determinado. Cuando se usa esta valor, también se debe especificar un contexto con la propiedad
HelpContext.
2 &H2 cdlQuit
Notifica a la aplicación Ayuda que el archivo de Ayuda especificado ya no se está utilizando.
3 &H3 cdlContents
Muestra el tema de contenido de ayuda, definido con la opción Contents de la sección [OPTION] del archivo .HPJ.
3 &H3 cdlIndex
Muestra el índice del archivo de Ayuda especificado. Las aplicaciones sólo deben utilizar este valor para un archivo de Ayuda con
índice único.
4 &H4 cdlHelpOnHelp
Muestra la Ayuda para utilizar la propia aplicación Ayuda.
5 &H5 cdlSetContents
Determina el tema de contenido a mostrar cuando el usuario presiona la tecla F1.
5 &H5 cdlSetIndex
Establece el contexto especificado en la propiedad HelpContext como índice actual para el archivo especificado en la propiedad
HelpFile. Este índice seguirá siendo el actual hasta que el usuario acceda a un archivo de Ayuda distinto. Utilice este valor sólo
para los archivos de Ayuda con más de un índice.
8 &H8 cdlContextPopup
Muestra en una ventana emergente un tema de Ayuda determinado, identificado por un número de contexto definido en la sección
[MAP] del archivo .HPJ.
9 &H9 cdlForceFile
Asegura que WinHelp muestre el archivo de Ayuda correcto. Si se muestra el archivo correcto, no sucede nada. Si se muestra un
archivo incorrecto, WinHelp abrirá el correcto.
257 &H101 cdlKey
Muestra la Ayuda sobre una palabra reservada determinada. Al usar esta opción, deberá especificar también una palabra reservada
con la propiedad HelpKey.
258 &H102 cdlCommand
Ejecuta una macro de Ayuda.
261 &H105 cdlPartialKey
Muestra el tema de la lista de palabras claves que coincide con la palabra pasada en el parámetro dwData, si sólo se encuentra
uno. Si se encuentra más de uno, aparecerá el cuadro de diálogo Buscar mostrando los temas encontrados en el cuadro de lista Ir
a. Si no se encuentra ninguno, se mostrará el cuadro de diálogo Buscar. Para que aparezca el cuadro de diálogo Buscar sin pasar
una palabra reservada, utilice un puntero largo a una cadena vacía.
Si queremos que se muestre el índice de la ayuda, pondríamos esta propiedad de la forma :
CD1.HelpCommand = cdlHelpIndex
Para mostrar la página que se ha puesto en el fichero de ayuda como Contexto 2 (En Sección [MAP] del fichero .HPJ (Vea Creación de
Ficheros de Ayuda),
CD1.HelpCommand = cdlHelpContext
CD1.HelpContext = 2
CD1.HelpCommand = cdlHelpHelpOnHelp
Una vez establecidas estas propiedades, mostraremos la ayuda con el Método ShowHelp
CD1.ShowHelp
Repitiéndole que no se debe usar el CommonDialog para mostrar ayudas, pero para cumplir el objetivo de plasmar en este texto la mayor
información acerca de cada control, se enumeran a continuación el resto de propiedades que afectan a la presentación de ayuda :
HelpFile
HelpContext
HelpKey
La Propiedad Action
La propiedad Action se incluye en la versión 4 de VB solamente por motivos de compatibilidad con anteriores versiones. Realiza las mismas
funciones que ShowFont, ShowColor, ShowPrinter, ShowOpen y ShowSave. No debe usarse esta propiedad, sino los equivalentes
citados, en previsión de que pueda ser eliminada en futuras versiones.
0 Ninguna acción.
1 Muestra el cuadro de diálogo Abrir.
2 Muestra el cuadro de diálogo Guardar como.
3 Muestra el cuadro de diálogo Color.
4 Muestra el cuadro de diálogo Fuente.
5 Muestra el cuadro de diálogo Impresora.
6 Ejecuta WINHELP.EXE.
NO utilice la propiedad Action. Utilice en su lugar ShowFont, ShowPrinter, ShowSave, ShowOpen , ShowColor y ShowHelp
CancelError
Devuelve o establece un valor que indica si se genera un error cuando el usuario elige el botón Cancelar.
Cuando se establece True en esta propiedad, se producirá el error número 32755 (cdlCancel) cada vez que el usuario elija el botón
Cancelar.
Debe poner esta propiedad a true cuando quiera detectar que se ha pulsado el botón CANCELAR. Luego, debe detectar con la
rutina de detección de errores adecuada, si el error producido ha sido el 32755. De ser así, es que han pulsado ese botón, y Vd.
procederá en consecuencia.
Color
Esta propiedad es de lectura / escritura
De escritura :Establece el color predeterminado con que aparecerá el CD para elegir
color. Puede introducirse como RGB o numéricamente, como se explicó mas atrás. Para que aparezca este color predeterminado,
debe poner la propiedad Flags a 1.
De lectura : Entrega el color elegido, bien en el cuadro de elección de color, bien en el
cuadro de elección de fuente.
Copies
Establece el valor predeterminado para número de copias que aparecerá en el CD cuando se abra para elegir impresora.
DefaultExt
Devuelve o establece la extensión de archivo predeterminada para el cuadro de diálogo.
Puede utilizar esta propiedad para especificar una extensión de archivo predeterminada, como por ejemplo .TXT o .DOC.
Importante para el CommonDialog de Guardar: Cuando se guarde un archivo sin extensión, se le agregará automáticamente la
especificada en esta propiedad.
DialogTitle
Devuelve o establece la cadena mostrada en la barra de título del cuadro de diálogo.
Esta propiedad puede introducirse en la ventana de propiedades, o por programa. Puede utilizar esa propiedad para mostrar el
nombre del cuadro de diálogo en la barra de título.
Nota El control CommonDialog ignora el valor de la propiedad DialogTitle cuando muestra los cuadros de diálogo Color o Fuente.
El título predeterminado para un cuadro de diálogo Abrir es Abrir, y para un cuadro de diálogo Guardar como es Guardar como.
FileName
Devuelve o establece la ruta y el nombre de archivo de un archivo seleccionado. La lectura de esta propiedad devuelve el nombre
del archivo seleccionado actualmente en la lista. Si no hay ningún archivo seleccionado, FileName devuelve una cadena vacía.
Filter
(Explicada mas atrás)
Devuelve o establece los filtros que aparecen en el cuadro de lista Tipo de un cuadro de diálogo.
Utilice el símbolo de canalización ( | , (ASCII 124) ) para separar los valores de descripción y de filtro. No incluya espacios antes ni
después del símbolo de canalización, pues aparecerían en los valores de descripción y valor.
Al especificar más de un filtro en un cuadro de diálogo, utilice la propiedad FilterIndex para especificar el filtro predeterminado.
Nota para los que no tiene teclado de 102 teclas. Para obtener el carácter ASCII 124, pulse la tecla ALT y, sin dejar de pulsarla, teclee 124
en el teclado numérico.
FilterIndex
Devuelve o establece un filtro predeterminado para un cuadro de diálogo Abrir o Guardar Como.
Esta propiedad indica el filtro predeterminado cuando se han especificado varios filtros para un cuadro de diálogo Abrir o Guardar.
El índice del primer filtro definido es 1.
Flags Propiedad que tiene distintos significados para cada tipo de cuadro de diálogo.
Tiene la misma sintaxis para todos los cuadros.
1 &H1& cdlRGBInit
Establece como valor de color inicial para el cuadro de diálogo el indicado en su propiedad Color.
2 &H2& cdlFullOpen
Hace que el cuadro de diálogo se muestre completo al crearlo, incluyendo la sección que permite al usuario crear colores
personalizados. Sin esta opción, el usuario debe elegir el botón de comando Definir colores personalizados para mostrar tal
sección.
4 &H4& cdlPreventFullOpen
Desactiva el botón de comando Definir colores personalizados, evitando que el usuario defina colores.
8 &H8& cdlShowHelp
Hace que el cuadro de diálogo muestre un botón Ayuda.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de cada una de las condiciones a poner.
1 &H1& cdlReadOnly
Hace que la casilla de verificación Sólo lectura aparezca marcada inicialmente al crear el cuadro de diálogo. Este indicador también
señala el estado de la casilla Sólo lectura cuando el cuadro de diálogo está cerrado.
2 &H2& cdlOverwritePrompt
Hace que el cuadro de diálogo Guardar como genere un cuadro de mensaje si el archivo seleccionado ya existe. El usuario deberá
confirmar que desea sobrescribir el archivo.
4 &H4& cdlHideReadOnly
Oculta la casilla de verificación Sólo lectura.
8 &H8& cdlNoChangeDir
Hace que el cuadro de diálogo restablezca como directorio actual el que lo era en el momento de abrirse.
16 &H10& cdlShowHelp
Hace que el cuadro de diálogo muestre el botón Ayuda.
256 &H100& cdlNoValidate
Especifica que el cuadro de diálogo común permita caracteres no válidos en el nombre de archivo devuelto. Funciona tanto con el
cuadro de Abrir como con el de Cerrar. Tenga cuidado a la hora de crear un archivo con nombre no válido !
512 &H200& cdlAllowMultiselect
Especifica que el cuadro de lista Nombre de archivo admita selecciones múltiples. El usuario puede seleccionar más de un archivo
en tiempo de ejecución presionando la tecla MAYÚS y utilizando las teclas FLECHA ARRIBA y FLECHA ABAJO para seleccionar
los archivos deseados. Al hacerlo, la propiedad FileName devolverá una cadena con los nombres de todos los archivos
seleccionados. Los nombres están delimitados en la cadena con espacios.
1024 &H400& cdlExtensionDifferent
Indica que la extensión del nombre de archivo devuelto es distinta de la especificada en la propiedad DefaultExt. Este indicador no
estará activado si la propiedad DefaultExt es Null, si las extensiones coinciden, o si el archivo no tiene extensión. El valor de este
indicador puede comprobarse al cerrar el cuadro de diálogo.
2048 &H800& cdlPathMustExist
Especifica que el usuario sólo pueda introducir una ruta de acceso válida. Si se establece este indicador y el usuario introduce una
ruta no válida, aparecerá un mensaje de advertencia.
4096 &H1000& cdlFileMustExist
Especifica, para el cuadro de Abrir, que el usuario sólo pueda escribir en el cuadro de texto Nombre de archivo nombres de
archivos existentes. Si este indicador está activado y el usuario introduce un nombre de archivo no válido, aparecerá una
advertencia. Este indicador activa automáticamente cdlPathMustExist.
8192 &H2000& cdlCreatePrompt
Especifica, para el cuadro de diálogo de abrir, que si no existe el fichero consulte al usuario antes de crear un archivo que no existe
actualmente. Esta advertencia dice : Este Archivo no existe ¿desea crearlo ? y aparecen los botones de ACEPTAR y CANCELAR.
Si el usuario pulsa aceptar el CommonDialog se cierra normalmente, si se le pulsa CANCELAR desaparece esta advertencia y el
CommonDialog espera a que se le escriba o seleccione otro fichero. Este indicador establece automáticamente los indicadores
cdlPathMustExist y cdlFileMustExist.
16384 &H4000& cdlShareAware
Especifica que se ignoren los errores al compartir archivos.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de cada una de las condiciones a poner.
1 &H1& cdlScreenFonts
Hace que el cuadro de diálogo muestre solamente las fuentes de pantalla que admite el sistema.
2 &H2& cdlPrinterFonts
Hace que el cuadro de diálogo muestre solamente las fuentes que admite la impresora, especificadas por la propiedad hDC.
3 &H3& cdlBoth
Hace que el cuadro de diálogo muestre las fuentes de impresora y de pantalla disponibles. La propiedad hDC identifica el contexto
de dispositivo asociado a la impresora
4 &H4& cdlShowHelp
Hace que el cuadro de diálogo muestre un botón Ayuda.
256 &H100& cdlEffects
Especifica que el cuadro de diálogo permita efectos de tachado, subrayado y color.
1024 &H400& cdlANSIOnly
Especifica que el cuadro de diálogo sólo permita seleccionar las fuentes que utilizan el juego de caracteres de Windows. Si se
establece este indicador, el usuario no podrá seleccionar una fuente que sólo contenga símbolos.
2048 &H800& cdlNoVectorFonts
Especifica que el cuadro de diálogo no permita seleccionar fuentes vectoriales.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los valores de cada una de las condiciones a poner.
(Observará seguramente que lo que se describe a continuación no se cumple siempre. Depende de las impresoras que tenga Vd.
instaladas)
Las opciones para valor son:
0 &H0& cdlAllPages
Devuelve o establece el estado del botón de opción Todas las páginas.
1 &H1& cdlSelection
Devuelve o establece el estado del botón de opción Selección. Si no se especifica cdlPageNums ni cdlSelection, el botón
de opción Todas estará seleccionado.
2 &H2& cdlPageNums
Devuelve o establece el estado del botón de opción Páginas.
4 &H4& cdlNoSelection
Desactiva el botón de opción Selección.
8 &H8& cdlNoPageNums
Desactiva el botón de opción Páginas y el control de edición asociado.
16 &H10& cdlCollate
Devuelve o establece el estado de la casilla de verificación Intercalar.
32 &H20& cdlPrintToFile
Devuelve o establece el estado de la casilla de verificación Imprimir a un archivo.
64 &H40& cdlPrintSetup
Hace que el sistema muestre el cuadro de diálogo Configurar impresora en lugar de Imprimir. Use este Flag cuando lo que
desea es cambiar la impresora predeterminada.
128 &H80& cdlNoWarning
Evita que aparezca una advertencia cuando no hay una impresora predeterminada.
Las seis propiedades siguientes nos dan las características especiales de la fuente elegida (negrita, cursiva, etc.). Una vez seleccionado el
tipo de letra, el valor de estas propiedades contiene la opción elegida para la letra (si FontBold=True es que hemos elegido negrita, etc.)
FontBold
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Negrita.
FontItalic
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Cursiva.
FontStrikethru
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Tachada.
FontName
(Variable toma el valor del nombre de la fuente. Por ejemplo, Variable = “Arial”
En general, deberá modificar FontName antes de establecer los atributos de tamaño y estilo con las propiedades FontSize,
FontBold, FontItalic, FontStrikethru y FontUnderline.
Nota En tiempo de ejecución puede obtener información sobre las fuentes disponibles a través de las propiedades FontCount y
Fonts. Lo verá mas adelante
FontSize
Devuelve de la fuente elegida. Debe ser una variable tipo Integer o Long
donde Variable será una expresión numérica que especifica el tamaño de fuente a utilizar, en puntos.
Nota Las fuentes disponibles en Visual Basic varían dependiendo de la configuración del sistema y de los dispositivos de
presentación e impresión. En las propiedades relacionadas con las fuentes sólo pueden establecerse valores para los que exista
una fuente.
En general, deberá modificar FontName antes de establecer los atributos de tamaño y estilo con las propiedades FontSize,
FontBold, FontItalic, FontStrikethru y FontUnderline. Sin embargo, cuando especifique un tamaño inferior a 8 puntos para una
fuente TrueType, primero deberá establecer el tamaño en puntos con la propiedad FontSize, luego especificar la propiedad
FontName y después establecer de nuevo el tamaño con FontSize. El entorno operativo Microsoft Windows utiliza una fuente
distinta para las fuentes TrueType con un tamaño inferior a 8 puntos.
Index
InitDir
Devuelve o establece el directorio de archivos inicial.
Left y Top
Estas propiedades solamente afectan a la colocación del icono en el formulario. No afectan a la colocación del CommonDialog
durante la ejecución. La posición del CommonDialog en tiempo de ejecución no puede controlarse.
Esta afirmación de que la posición del CommonDialog no es controlable es válida para sistemas a 32 bytes. En VB 4 de 16 bits, el
CommonDialog aparece aproximadamente en la parte superior izquierda del formulario que lo contiene. Algunos programadores
han optado por poner un formulario para contener solamente al CommonDialog, y así, controlando la posición de ese formulario,
poder controlar la posición (aproximada) en la que aparece el CD.
Esto no ocurre para sistemas a 32 bytes, en los que el CD aparece siempre en la parte superior izquierda de la pantalla,
independientemente de donde esté el formulario que lo contiene.
MaxFileSize
Devuelve o establece el tamaño máximo del nombre de archivo abierto con el control CommonDialog.
Name
Nombre que define al CommonDialog
PrinterDefault
Devuelve o establece una opción que determina si la configuración elegida por el usuario en el cuadro de diálogo Imprimir se utiliza
para modificar la configuración predeterminada de impresora del sistema.
True Las opciones que elija el usuario en el apartado Configurar del cuadro de diálogo Imprimir (selección de la impresora,
orientación, etcétera) se utilizan para modificar la configuración de impresora en el archivo WIN.INI del usuario. (En el sistema
operativo Windows NT, esta información se almacena en el Registro).
False Las opciones que elija el usuario no se utilizan para modificar la configuración de impresora predeterminada del sistema.
Utilice esta propiedad, que por defecto está a True, para poner o no poner como impresora predeterminada, la impresora
seleccionada con el CommonDialog. Puede por ejemplo, querer imprimir un texto en una impresora determinada, pero solo ese
texto, y no quiere cambiar la impresora predeterminada por el hecho de haber seleccionado en este momento otra impresora.
Ponga esta propiedad a False (recuerde que por defecto está a True) para que la impresora seleccionada no se quede como
impresora por defecto.
Tag
Lo mismo que se ha explicado para otros controles.
Una imagen representa una figura, bien natural (tipo fotografía) o sintética. Para presentar una imagen es necesario hacerlo sobre un objeto
que la admita. Los objetos que admiten una imagen son:
Formularios
PictureBox
Image
Existen mas controles gráficos que se irán viendo a lo largo del curso. Estos tres son los mas usados y con los que comenzaremos a
trabajar.
Para mostrar una imagen en cualquiera de estos objetos, es necesario especificarlo en su propiedad Picture. La forma de especificarle al
objeto la imagen que debe presentar puede hacerse de dos formas:
Por ejemplo, si tenemos un formulario llamado Form1 y queremos rellenarlo con una imagen contenida en el fichero de Windows metafile
DOLLAR.WMF que se encuentra en el directorio C:\VB\METAFILE\BUSINESS, deberemos ejecutar la instrucción:
Para "descargar" esa imagen de ese formulario, basta con ejecutar la misma instrucción sin fichero alguno:
Form1.Picture = LoadPicture ( )
También pueden tomar la imagen desde otro control de imagen, mediante un procedimiento de Intercambio Dinámico de Datos (DDE)
(Solo el PictureBox)
Puede también meter una imagen en una variable, y luego poner en uno de los controles citados anteriormente la imagen guardada en la
variable. Este método es muy rápido, ya que no necesita acceder al disco para buscar una imagen, pero emplea mucha memoria RAM, ya
que la variable )o variables conteniendo la(s) imágenes están en la RAM.
Para ello debemos declarar una o varias variables tipo Picture, y meter en ellas una imagen mediante el método LoadPicture. Vea en el
capitulo 7 (Métodos Gráficos - Método LoadPicture) un ejemplo muy ilustrativo.
EL FORMULARIO
Ya hemos visto lo que es el Formulario. Simplemente podemos añadir a lo ya dicho, que un formulario tiene la propiedad Picture, con lo que
podemos poner como fondo un bit-map, un fichero de icono ( .ICO) o un Metarchivo (.WMF). Un fondo gráfico sobre el Formulario puede
convertir una aplicación de buena a excelente. No intente nunca mejorar una aplicación mediocre con un fondo artístico en un Formulario.
Este objeto permite presentar todo tipo de ficheros gráficos (.BMP, WMF, .ICO, .CUR)
Las dimensiones del PictureBox se establecen en el diseño o mediante programa, variando las propiedades Height y Width. También
puede cambiarse su posición mediante las propiedades Top y Left. Dispone de una propiedad, Align que permite colocarlo adosado a uno
de los lados del formulario que lo contiene.
El Control PictureBox puede ser destino de los datos de un enlace DDE. (Los datos serán, lógicamente, gráficos. Por ello, tiene las
propiedades LinkMode, LinkItem, LinkTimeout y LinkTopic.
También puede tomar el dato del gráfico de una Base de Datos. (A través de un control Data o un objeto Recordset)
CONTROL IMAGE
Este control permite presentar todo tipo de ficheros gráficos (.BMP, WMF, .ICO, .CUR)
El control Image no puede ser destino de una comunicación DDE. Puede tomar la imagen de una base de datos, bien a través de un control
Data o a través de un objeto Recordset.
El control Image utiliza menos recursos del sistema y repinta con más rapidez que un control PictureBox, pero sólo admite una parte de las
propiedades, los eventos y los métodos de PictureBox. Use la propiedad Stretch para determinar si el gráfico se escala para que se ajuste
al control o viceversa. Poniendo esta propiedad a True el gráfico se adaptará a las dimensiones del control Image. Si se pone a False, el
control Image tomará las medidas del gráfico que contenga. Si el gráfico es un bit-map (Fichero .BMP), con la propiedad Stretch a True
podemos variar el tamaño del bit-map, variando las propiedades Width y Height del control Image, propiedades que se pueden cambiar en
tiempo de ejecución. Si esta propiedad está a False, el tamaño del bit-map no cambiará, presentándose solamente una porción del bit-map,
caso que el control Image sea menor que el tamaño del bit-map, o sobrará espacio en el control, en caso contrario. Aunque puede colocar
un control Image en un contenedor, un control Image no puede actuar como contenedor. Esto se entiende mejor con un ejemplo. Prepare
un formulario con un PictureBox y con un control Image. Introduzca dos OptionButton en cada uno de ellos, y otro en otra parte del
formulario, fuera de ambos. Ejecute la aplicación. Los OptionButton colocados dentro del PictureBox se comportan entre ellos
independientes de los otros tres OptionButton presentes en el formulario, exactamente igual que si se les hubiera introducido en un Frame.
Los controles colocados dentro del control Image cambian formando conjunto con el que se colocó en el formulario, fuera de los dos
controles. El PictureBox funciona como un contenedor de esos dos OptionButton que tiene en su interior, mientras que el control Image,
no. (Vea el ejemplo del capítulo 2, Oficina de cambio de divisas)
Un Image es transparente, es decir, deja ver el fondo del formulario en las partes no ocupadas por su gráfico. Por lo tanto, no tendrían
sentido en este control propiedades como Backcolor, FillColor, o FillStyle.
Permite colocar el control en el borde superior (Align Top), en el inferior (Align Bottom), en el izquierdo (Align Left) o en el
derecho (Align Right) del formulario que lo contiene. Para no alinearlo con ningún borde basta con poner la propiedad Align a
0-None.
Cuando se adosa a uno de los bordes, el tamaño del control se ajusta automáticamente a la anchura o altura del formulario.
Sintaxis
NombrePictureBox.Align [= número]
número Un entero que especifica cómo se presenta el control. Puede tomar los siguientes valores :
0-None (Predeterminado cuando el control se coloca en un formulario no MDI). Con este valor, el
control mantiene el tamaño y la posición asignada en tiempo de diseño.
1-Top (Predeterminado cuando el control se coloca en formularios MDI) El control se coloca en la parte
superior del formulario y su anchura es igual a la anchura del formulario.
2-Bottom El control se coloca en la parte inferior del formulario y su anchura es igual a la anchura del
formulario.
3-Left El control se coloca en la parte izquierda del formulario y su altura es igual a la altura del
formulario.
4-Right El control se coloca en la parte derecha del formulario y su altura es igual a la altura del
formulario.
Se puede usar propiedad Align para crear rápidamente una barra de herramientas o una barra de estado en la parte superior o
inferior de un formulario. Cuando un usuario cambie el tamaño del formulario, un control con la propiedad Align establecida a 1
ó 2 modificará su tamaño de forma automática para ajustarse a la anchura del formulario.
De la misma forma se puede crear barras de herramientas a los lados izquierdo o derecho de un formulario. Si en un formulario
hay dos barras de herramientas, una en la parte superior (o inferior) y otra en un lateral, la de la parte superior o inferior es la
que se extiende hasta la esquina, teniendo preferencia sobre las colocadas verticalmente a la izquierda o a la derecha.
Al ser el PictureBox un contenedor, puede poner un PictureBox en la parte superior de un Formulario, y colocar en este
PictureBox varios controles Image, a los que se les puede poner un icono. De esta forma realizamos una barra de
herramientas.
Establece un valor que determina si se muestra un control que puede alinearse cuando un objeto activo del formulario muestra
una o más barras de herramientas. No está disponible en tiempo de ejecución.
True Si el control se alinea en el formulario (la propiedad Align se establece como un valor no cero), el control
permanecerá visible cuando un objeto activo del formulario muestre una barra de herramientas.
False (Predeterminado) El control no se muestra cuando un objeto activo del formulario muestra una barra de
herramientas. La barra de herramientas del objeto activo se muestra en lugar del control.
Appearance (PictureBox e Image) 3D o Flat, como en otros controles
Permite que el Formulario o PictureBox (El control Image no tiene esta propiedad), mantenga siempre la imagen presente. Si
Autoredraw está a False, el control no presentará las imágenes que no se hayan dibujado realmente (caso por ejemplo de un
formulario minimizado) o que se hayan borrado por haber sido puestas tras otro control.
True Activa el redibujado automático de un control PictureBox. Los gráficos y el texto se escriben en la pantalla y en una
imagen almacenada en memoria. El control no recibe eventos Paint; se vuelve a dibujar cuando es necesario, usando la imagen
almacenada en memoria.
False (Predeterminado) Desactiva el redibujado automático de un control y escribe los gráficos y el texto solamente en la
pantalla. Visual Basic invoca el evento Paint del control cuando se necesita volver a dibujar dicho control.
Devuelve o establece un valor que determina si el tamaño de un control se cambia automáticamente para presentar su
contenido completo.
Devuelve o establece un valor que determina si los métodos gráficos en eventos Paint vuelven a dibujar el objeto entero o
solamente las áreas últimamente expuestas. También determina si el entorno operativo Microsoft Windows crea una zona de
recorte que excluya los controles no gráficos contenidos en el objeto. En tiempo de ejecución es de sólo lectura.
True (Predeterminado) Los métodos gráficos de los eventos Paint vuelven a dibujar completamente el objeto. Antes del
evento Paint se crea una zona de recorte alrededor de los controles no gráficos del formulario.
False Los métodos gráficos de los eventos Paint solamente vuelven a dibujar las partes recién expuestas. Antes del
evento Paint no se crea una zona de recorte alrededor de los controles no gráficos. Los formularios complejos se cargan
normalmente más rápido cuando ClipControls está establecido a False.
Devuelve o establece un valor que indica el nombre del campo de una Base de datos de donde se tomará la imagen a
presentar. (Vea controles enlazados a datos)
Para poder presentar una imagen contenida en una base de datos, el control
PictureBox o Image deben estar enlazados a una base de datos mediante un control
Data.
Establece un valor que especifica el control Data a través del cual el control Picture ó Image se enlaza a una base de datos. No
está disponible en tiempo de ejecución.
Verá esto con mas detalles cuando estudie los Objetos enlazados a Datos.
DragIcon
DragMode (PictureBox e Image) Igual que otros controles
DrawMode (PictureBox solamente)
Devuelve o establece un valor que determina el estilo de línea de la salida de métodos gráficos.
tamaño Expresión numérica comprendida entre 1 y 32.767 que representa la anchura de la línea en pixeles. El valor
predeterminado es 1, es decir, un píxel de ancho.
Propiedades que afectan al comportamiento de este control como DESTINO de una conversación DDE. Se estudiará con mas
detalles al estudiar el Intercambio Dinámico de Datos.
(Una vez que comenzamos a estudiar las propiedades gráficas, se comenta cómo se puede cambiar el icono de la propiedad MouseIcon de
todos los controles)
Sintaxis
objeto.MouseIcon = LoadPicture(ruta) ó
objeto.MouseIcon = imagen
donde :
objeto Nombre del objeto PictureBox o Image
ruta Expresión de cadena que especifica la ruta y el nombre del archivo que contiene el icono personalizado. Así
podemos cargar un icono de los existentes en el disco. Ej. Image1.MouseIcon =
LoadPicture("C:\vb\icons\computer\disk05.ico")
imagen Propiedad Picture de un objeto Form, de un control PictureBox o de un control Image, o nombre de una variable tipo
Picture. De esta forma podemos cargar como un icono el gráfico que tengamos en otro objeto o en una variable tipo Picture.
Ej. Image1.MouseIcon = Picture1.picture
La propiedad MouseIcon proporciona un icono de mouse personalizado que se utiliza cuando el valor de la propiedad
MousePointer es 99.
MousePointer devuelve o establece un valor que indica el tipo de puntero de mouse que aparece cuando se pasa el puntero
del ratón por encima de un objeto en tiempo de ejecución.
Sintaxis objeto.MousePointer [= valor]
Este control no está normalmente en la caja de herramientas. Solamente está disponible en la versión de 32 bits. Hay que introducirlo
mediante los Herramientas | Controles Personalizados y pertenece al grupo Microsoft Windows Common Controls
(COMCTL32.OCX) (Vea Nota 1)
Este control nos permite almacenar varias imágenes. Es, tal como indica su nombre, como un ListBox pero que en vez de contener textos,
contiene imágenes.
La utilidad de este control es para almacenar en él distintas imágenes, y servirlas desde él a otro control, un PictureBox o un control Image,
sin necesidad de tener que acceder a leerlas en el disco, que conllevaría una importante pérdida de tiempo si el cambio de imágenes debe
ser rápido.
Este control es necesario para almacenar las imágenes que se mostrarán en los iconos de la barra de herramientas. Verá mas adelante
como se realiza una barra de herramientas (La barra de herramientas solo está disponible para la versión de 32 Bits)
Un ImageList permite tener varias imágenes dentro de él, pero este control no las presenta. Solamente sirve de “almacén” para pasarlas
rápidamente a otro control (PictureBox, p.e.) que será el que las presenta en pantalla.
En la siguiente figura, pueden verse las propiedades de un ImageList con varias imágenes cargadas.
Nota 1. El grupo de controles Microsoft Windows Common Controls (COMCTL32.OCX) incluye además de este los controles TabStrip,
Toolbar, StatusBar, ProgressBar, TreeView, ListView y Slider.
Para introducir imágenes en el control ImageList deberemos acceder a sus propiedades, bien mediante F4 y luego haciendo click sobre
Personalizado, bien pulsando el botón derecho del ratón sobre el icono del control. Aparecerá un cuadro donde podemos insertar imágenes
El tipo de imágenes pueden ser mapas de bits :BMP o iconos .ICO
El control ImageList tiene una colección llamada ListImages. Esta colección contiene todas las imágenes introducidas en el ImageList y
las propiedades de cada imagen. Como toda colección, será un array donde podemos elegir uno de sus elementos designándolo por su
nombre seguido de su número (Index) encerrado entre paréntesis. Así la imagen número 3 será :
ImageList1.Listimages (3)
Si tenemos un control Picture llamado Picture1 y queremos poner en su propiedad Picture la imagen cargada en el ImageList1, en su
posición 3, usaríamos la expresión :
Observe que tras ListImages ( ) es necesario poner la propiedad Picture, ya que Picture es una propiedad de la colección ListImages
Como cualquier colección, ListImages tiene la propiedad Count, que nos servirá para contar el número de imágenes que guarda.
Numerodeimágenes = ImageList1. ListImages.Count
Dado que al guardar imágenes en un ImageList, estas imágenes están guardadas en la memoria RAM, es fácil realizar una animación.
Para ello necesitamos varias imágenes que poniendo una tras otra, dé la sensación de movimiento. Imaginemos un número indeterminado
de imágenes dentro de un ImageList, y un control Picture llamado Picture1 donde queremos presentar la animación. En el procedimiento
Timer de un Timer pondríamos
Una de las mayores aplicaciones del ImageList es proporcionar imágenes para otros controles. Entre ellos el TOOLBAR
Este control permite realizar una barra de herramientas. La barra de herramientas es, como ya conocerá, una barra donde existen varios
iconos. Estos iconos realizan una determinada función. Normalmente se ponen en la barra de herramientas los iconos que representan las
acciones mas frecuentes de una aplicación. Esto facilita la operación al no tener que desplegar menús para buscar la operación a realizar.
Como el espacio que ocupan los iconos es grande, es también bastante normal que no estén representados en la barra de herramientas
todas las funciones posibles de la aplicación, sino como decíamos, solamente las mas frecuentes. Pero ocurre que la función que para un
usuario es muy frecuente, para otro no lo es, por lo que también es habitual poder programar los iconos que aparecen en la barra de
herramientas.
Para introducir el Toolbar es necesario que esté presente en la caja de herramientas el control personalizado Microsoft Windows Common
Controls (COMCTL32.OCX).
El control Toolbar es un contenedor de un array de iconos. Estos iconos forman botones sobre los que se puede insertar código en sus
procedimientos. A cada botón se le denomina Button y a la colección de botones se le denomina Buttons. Cada Button es un elemento
de la colección Buttons y por lo tanto podemos referirnos a cada uno de ellos por el índice que tiene dentro de la colección.
Los iconos de cada uno de los botones del Toolbar debe introducirse previamente en un control ImageList. Como se recordará, un control
ImageList es un almacén de imágenes, que podemos usar en cualquier parte de la aplicación. Una de esas partes es la confección de la
barra de herramientas. Por lo tanto, es necesario introducir un control ImageList en cualquier aplicación que use un control Toolbar. Todas
las imágenes del Toolbar deben estar en un único ImageList. Y este ImageList debe estar en el mismo formulario que el Toolbar
La barra de herramientas puede realizarse en tiempo de diseño (este sería el caso para cuando no existiese variación ni elección de
botones a lo largo de la ejecución de la aplicación)
o en tiempo de ejecución (caso que correspondería con una aplicación que tuviese una barra de menú programable o que variase esta
barra de menú dependiendo de cada operación que se esté ejecutando en la aplicación).
Para realizar la barra de herramientas en tiempo de diseño, basta con visualizar el cuadro de propiedades que aparece pulsando el botón
derecho del ratón sobre el control Toolbar. Aparecerá un cuadro de diálogo como este :
Puede ver que en el cuadro ImageList aparece el nombre de un ImageList. Al desplegar la lista aparecerán todos los ImageList que existan
en el formulario. El ImageList debe estar en el mismo formulario que el Toolbar. Deberá elegirse el ImageList que contenga las imágenes de
los iconos que queremos introducir en el Toolbar.
Este cuadro nos permite también introducir la forma que adoptará el puntero del ratón cuando entre en el Toolbar (MousePointer), si el
Toolbar aparece por defecto habilitado o deshabilitado (Enabled) y si muestra o no un rótulo programable al pasar el ratón por encima de
cada botón del Toolbar. (ShowTips). (El uso de estos pequeños rótulos pueden hacer una aplicación muy bonita) La propiedad
AllowCustomize permite, si es True, cambiar el orden de los botones e introducir separadores (vea evento DobleClick).
En el cuadro botones podemos introducir los datos deseados para cada uno de los botones que compondrán la colección Buttons.
Para insertar un nuevo botón hay que hacer click sobre Insertar botón e insertará un nuevo botón inmediatamente después del que figura
en la propiedad Index (en la figura del ejemplo, lo insertaría en segundo lugar, no en el último lugar como podría creerse). También
podemos eliminar un botón haciendo click sobre Eliminar botón.
El Caption (opcional) es la palabra que figurará debajo del icono del botón.
La propiedad Key es un nombre que se puede añadir a cada botón. Esta propiedad sirve para identificar el botón que se ha pulsado, pero
no para nombrar al botón.
La propiedad Value es el valor por defecto, con el que aparecerá el botón al comienzo de la aplicación. (Unpressed, no pulsado, Pressed,
pulsado).
ToolTipText es el texto que aparecerá al lado del botón cada vez que se ponga el cursor del ratón sobre el botón. Para que aparezca debe
estar habilitada la propiedad ShowTips.
El control Toolbar también puede realizarse en tiempo de ejecución. Para introducir u botón en el Toolbar hay que crear el botón y añadirlo
a la colección Buttons de Toolbar. Podemos hacerlo en una sola instrucción :
NombreBotón puede ser cualquier nombre (es el nombre del objeto botón)
NombreToolbar es el nombre del Toolbar
Indice es el número de orden de ese botón dentro del Toolbar
Key es el valor de la propiedad Key del botón. Este valor debe ser único para cada botón.
Style es un número del 0 al 4 con el tipo de botón. Vea lista mas arriba
Imagen es el número de la imagen para ese botón, dentro del ImageList que las contiene.
Los botones pueden habilitarse y deshabilitarse usando la propiedad Enabled (True / False). Recuerde que los botones se identifican por su
índice :
Toolbar1.Buttons(Indice).Enabled = False
Con la lectura de la propiedad Key, y la sentencia Case o If ... Then podemos iniciar la parte de la aplicación asociada a cada botón.
ButtonClick
Este evento se produce cada vez que se hace click sobre un botón del Toolbar. Pasa como parámetro el índice del botón pulsado.
Podremos saber que botón se ha pulsado mediante sentencias condicionales :
If Button.Index = 1 Then . . . .
If Button.Index = 2 Then . . . .
Click
Este evento se produce cuando se hace click sobre cualquier botón del Toolbar, pero no pasa parámetros. (No distingue sobre que botón
se ha hecho click) Podemos utilizarlo cuando se quiera realizar una operación común para todos los botones (Que suene un Beep, por
ejemplo)
DobleClick
Este evento solamente se produce cuando se hace doble click en la parte del Toolbar donde no hay botones, y la propiedad
AllowCustomize esté a True. Si se hace doble click sobre un botón se produce solamente el evento click (dos veces). Haciendo doble
click en una zona libre de botones, con la propiedad AllowCustomize = True nos permite cambiar el orden de los botones e introducir
separadores.
Change
Se produce solamente cuando se ha realizado algún cambio del orden por el procedimiento anterior.
DragDrop, DragOver
Igual que el resto de los controles Pasa como parámetro el índice del botón, la tecla de mayúsculas, y las posiciones x e y del ratón.
LA BARRA DE ESTADO
Este control es muy parecido a la barra de herramientas, y suele usarse, colocándolo en la parte inferior de la ventana, para indicar el
proceso que está en curso en la aplicación. La barra de estado, control StatusBar se introduce en la caja de herramientas al mismo tiempo
que el control Toolbar, mediante el control personalizado múltiple Microsoft Windows Common Controls (COMCTL32.OCX).
La barra de estado puede albergar hasta 16 paneles, que pueden contener texto o gráficos. También pueden contener información del
Hardware, tal como el estado de la tecla Bloqueo de Mayúsculas, Bloqueo del teclado numérico, tecla Insert activada, tecla Scroll
Lock activada, o mostrar la fecha y la hora
La barra de estado puede configurarse como de un solo panel o de múltiples paneles. (Propiedad Style. 0=múltiples paneles, 1= panel
único)
Las dimensiones de cada panel pueden configurarse como fijas o ajustadas al tamaño del texto o imagen que presentan.
La barra de estado puede realizarse en tiempo de diseño o en tiempo de ejecución. Para realizarla en tiempo de ejecución basta con
visualizar la ventana de propiedades, muy similar a la del control Toolbar.
Para añadir un panel en tiempo de ejecución basta con añadirlo a la colección Panels del control StatusBar mediante la sentencia :
Donde PanelNuevo es el nombre con el que se va a conocer ese panel que acabamos de crear. PanelNuevo debe declararse como variable
objeto Panel donde sea necesario según el ámbito que le queramos dar. De esta forma, una vez creado, nos podremos referir a ese panel
simplemente citándolo por su nombre (En este caso, PanelNuevo)
Los términos [índice],[key],[Text],[estilo],[gráfico] que entran a formar parte en la sintaxis de creación del panel se explican a
continuación.
Si no se pone alguna de las propiedades opcionales intermedias, deben mantenerse las comas separadoras.
Set PanelNuevo = statusbar1.Panels.Add(pepe, "Contenido del Key " & Str(pepe), "Texto " & Str(pepe), ,
LoadPicture("C:\vb\icons\comm\net09a.ico"))
Estos son los controles gráficos mas importantes. Verá a lo largo del curso que existen otros, y más que podrá encontrar entre diferentes
suministradores de controles, ya que VB ha dejado una puerta abierta para realizar controles a medida. Existen varias empresas de software
dedicadas a la fabricación de controles personalizados, y en el aspecto de controles gráficos, podrá encontrar una amplia gama de
fabricantes y controles. Puede obtener muchos controles en el CD-ROM que acompaña a varias revistas especializadas en programación
VB, y a través de la red Internet.
INTERCAMBO DINAMICO DE DATOS
EL CONTROL PERSONALIZADO MICROSOFT COMM
El intercambio dinámico de datos es una utilidad de Windows que utiliza Visual Basic, y nos permite crear aplicaciones que tomen datos
una de otras.
Para pasar datos de una aplicación a otra se necesitan al menos, dos aplicaciones (lógico), una que se deje leer, y la otra (u otras), que
quieran leer la información en aquella.
Puede darse el caso que una aplicación esté recibiendo datos de otra aplicación, y a su vez envíe datos a una tercera.
A la aplicación que envía la información se le llama aplicación servidor, y a la que la recibe, aplicación cliente.
La aplicación servidor debe estar funcionando antes de que la aplicación cliente le pida la información. Si no es así, se generará un error.
El origen de un intercambio DDE siempre es un formulario. Dentro de este formulario origen estará el Label, TextBox o PictureBox que
contiene la información a enviar.
Para indicar que un formulario es origen de información para un intercambio DDE debemos decírselo en sus propiedades LinkMode y
LinkTopic.
El destino de un texto ha de ser necesariamente un Label, un TextBox, y el destino de un gráfico debe ser un PictureBox.
Cuando queremos que uno de estos controles sea el destino de un intercambio DDE debemos indicarlo en sus propiedades LinkMode,
LinkTopic, LinkItem, e indicarle el tiempo de espera para un intercambio en la propiedad LinkTimeout.
Propiedad LinkMode
Si se establece el valor de esta propiedad a 0 en tiempo de diseño, no podrá cambiarse en tiempo de ejecución. Si se establece a 1 en
tiempo de diseño, se podrá cambiar a 0 y volver a ponerla a 1 en tiempo de ejecución.
Para un control, la propiedad LinkMode le permite que inicie una conversación DDE con una aplicación servidor, (origen), y cómo iniciarla.
Tiene 4 valores posibles :
En tiempo de ejecución, para un control, esta propiedad es de lectura y escritura, es decir, se puede usar para saber que valor tiene esta
propiedad en un determinado control, o para forzar esa propiedad a un determinado valor.
objeto.LinkMode [= número]
donde número es un entero que especifica el tipo de conexión. (0, 1, 2 ó 3 según se ha visto)
y objeto es el nombre del control.
Propiedad LinkTopic
Esta propiedad es de lectura y escritura, tanto para los controles como para los formularios.
Cuando un control destino quiere establecer una comunicación DDE “llama” a la aplicación origen, y dentro de ella, al formulario que
contiene el control cuya información debe ser traspasada. (Nótese que la aplicación origen puede tener varios formularios). Al ese
formulario podría llamarle por su nombre, (por su Name), pero no lo hace así. Le llama por un nombre que le debemos poner al formulario
en su propiedad LinkTopic. A este nombre se le denomina Tema.
La propiedad LinkTopic, para un formulario de origen, devuelve o establece el tema al que el formulario “responde” en una conversación
DDE.
Para un control destino, La propiedad LinkTopic contiene el nombre de la aplicación y el tema, ambos separados mediante el carácter |
(carácter 124)
El nombre de la aplicación origen será el nombre del de proyecto de Visual Basic sin la extensión .VBP (si la aplicación se está ejecutando
en el entorno de desarrollo de Visual Basic), o el nombre de la aplicación de Visual Basic sin la extensión .EXE (si se ejecuta como un
archivo ejecutable independiente).
El tema será el mismo al que “responde” el formulario donde se encuentra el control que contiene la información a traspasar.
( DDE es una utilidad de Windows. Windows establece que el estándar de un vinculo DDE es Aplicación | Tema ! elemento. Véase para
mas detalles el manual de Windows, enlaces DDE)
Propiedad LinkItem
La propiedad LinkItem solamente la tiene el control destino de la información. No la tiene el formulario origen. En esta propiedad deberá
expresarse el nombre del control origen de la información.
Esta propiedad es de lectura y escritura, es decir, tanto sirve para saber el nombre del control origen de los datos, como para establecerlo
en tiempo de ejecución.
donde cadena es el nombre del control origen que tiene los datos y objeto es el nombre del control al que le estamos poniendo la propiedad
LinkItem.
Propiedad LinkTimeout
Devuelve o establece la cantidad de tiempo que un control espera una respuesta a un mensaje DDE.
donde número es una expresión numérica que especifica el tiempo de espera en décimas de segundo.
El tiempo de respuesta DDE desde aplicaciones origen varía. Use esta propiedad para ajustar el tiempo que un control destino espera la
respuesta de una aplicación origen. Si se usa LinkTimeout de forma correcta se puede evitar la generación de un error por Visual Basic si
una aplicación origen tarda mucho en responder.
Nota La plazo mayor de tiempo que un control puede esperar es 65.535 décimas de segundo, es decir, sobre 1 hora y 49 minutos. Al
establecer LinkTimeout a 1 se indica al control que espere la respuesta en una conversación DDE durante el mayor plazo de tiempo. El
usuario puede forzar que el control deje de esperar presionando la tecla ESC..
Evento LinkNotify
Ocurre cuando el origen ha cambiado el dato definido por el vínculo DDE si la propiedad LinkMode del control destino está establecido a 3
(Notificar).
End Sub
En este procedimiento se puede escribir el código necesario para nuestra aplicación, a sabiendas de que este evento se produce cuando
cambia la información en origen. Posiblemente no quiera depositarlo de inmediato en el control destino, puesto que si fuese así habría
puesto la propiedad LinkMode a 1. Cuando quiera colocar el dato en el control destino, puede utilizar el método LinkRequest para obtener el
nuevo dato de la fuente.
Método LinkRequest
Pide a la aplicación origen de una conversación DDE que actualice el contenido de un control Label, PictureBox o TextBox.
Sintaxis objeto.LinkRequest
Siendo objeto el nombre del control destino de la aplicación.
Objeto es el nombre de un control Label, PictureBox o TextBox involucrado en una conversación DDE como destino. LinkRequest provoca
que la aplicación origen envíe los datos actuales al objeto, actualizando la propiedad Caption si objeto es un control Label, la propiedad
Picture si objeto es un control PictureBox o la propiedad Text si objeto es un control TextBox.
Si la propiedad LinkMode del objeto está definida como 1 (Automático), la aplicación origen actualiza objeto automáticamente y
LinkRequest no es necesario. Si la propiedad LinkMode del objeto está definida como 2 (Manual) , la aplicación origen actualiza objeto sólo
cuando se usa LinkRequest.
Si la propiedad LinkMode del objeto está definida como 3 (Notify), el origen notifica al destino que los datos han cambiado invocando el
método LinkNotify. El destino debe entonces usar el método LinkRequest para actualizar los datos.
Método LinkSend
Sintaxis objeto.LinkSend
Objeto debe ser un control PictureBox de un objeto Form que sea origen de una conversación DDE.
Cuando otras aplicaciones establecen vínculos automáticos con un objeto Form de su aplicación, Visual Basic las notifica cuando el
contenido de un control TextBox o Label origen cambia. Sin embargo, Visual Basic no notifica automáticamente a una aplicación destino
DDE cuando el valor de la propiedad Picture de un control PictureBox origen cambia. Como la cantidad de datos de un gráfico pueden ser
muy grande y como no tiene sentido actualizar la aplicación destino por cada cambio de píxel de la imagen, Visual Basic requiere el uso del
método LinkSend para notificar explícitamente a las aplicaciones destino DDE cuándo cambia el contenido de un control PictureBox.
Método LinkPoke
Transfiere el contenido de un control Label, PictureBox o TextBox a la aplicación origen de una conversación DDE.
Sintaxis objeto.LinkPoke
Objeto es el nombre del control Label, PictureBox o TextBox involucrado en la conversación DDE como destino. Si objeto es un control
Label, LinkPoke transfiere el contenido de la propiedad Caption al origen. Si objeto es un control PictureBox, LinkPoke transfiere el
contenido de la propiedad Picture al origen. Si objeto es un control TextBox, LinkPoke transfiere el contenido de la propiedad Text al origen.
Normalmente, en una conversación DDE la información fluye de origen a destino. Sin embargo, LinkPoke permite que un objeto destino
suministre datos al origen. No todas las aplicaciones origen aceptan información de esta forma; si la aplicación origen no acepta los datos,
se produce un error.
A continuación se resumen las ventajas más importantes que proporciona .Net Framework:
Código administrado: El CLR realiza un control automático del código para que este sea seguro, es decir,
controla los recursos del sistema para que la aplicación se ejecute correctamente.
Interoperabilidad multilenguaje: El código puede ser escrito en cualquier lenguaje compatible con .Net ya
que siempre se compila en código intermedio (MSIL).
Compilación just-in-time: El compilador JIT incluido en el Framework compila el código intermedio (MSIL)
generando el código máquina propio de la plataforma. Se aumenta así el rendimiento de la aplicación al ser
específico para cada plataforma.
Garbage collector: El CLR proporciona un sistema automático de administración de memoria denominado
recolector de basura (garbage collector). El CLR detecta cuándo el programa deja de utilizar la memoria y la
libera automáticamente. De esta forma el programador no tiene por que liberar la memoria de forma explícita
aunque también sea posible hacerlo manualmente (mediante el método disponse() liberamos el objeto para
que el recolector de basura lo elimine de memoria).
Seguridad de acceso al código: Se puede especificar que una pieza de código tenga permisos de lectura
de archivos pero no de escritura. Es posible aplicar distintos niveles de seguridad al código, de forma que se
puede ejecutar código procedente del Web sin tener que preocuparse si esto va a estropear el sistema.
Despliegue: Por medio de los ensamblados resulta mucho más fácil el desarrollo de aplicaciones distribuidas
y el mantenimiento de las mismas. El Framework realiza esta tarea de forma automática mejorando el
rendimiento y asegurando el funcionamiento correcto de todas las aplicaciones.
Procesos como la recolección de basura de .Net o la administración de código introducen factores de sobrecarga
que repercuten en la demanda de más requisitos del sistema.
El código administrado proporciona una mayor velocidad de desarrollo y mayor seguridad de que el código sea
bueno. En contrapartida el consumo de recursos durante la ejecución es mucho mayor, aunque con los
procesadores actuales esto cada vez es menos inconveniente.
El nivel de administración del código dependerá en gran medida del lenguaje que utilicemos para programar. Por
ejemplo, mientras que Visual Basic .Net es un lenguaje totalmente administrado, C Sharp permite la administración
de código de forma manual, siendo por defecto también un lenguaje administrado. Mientras que C++ es un lenguaje
no administrado en el que se tiene un control mucho mayor del uso de la memoria que hace la aplicación.
Arquitectura básica de la plataforma .Net. Descripción del Framework y sus principales componentes:
Lenguajes, biblioteca de clases y CLR.
La nueva tecnología de Microsoft ofrece soluciones a los problemas de programación actuales, como son la
administración de código o la programación para Internet. Para aprovechar al máximo las características de .Net es
necesario entender la arquitectura básica en la que esta implementada esta tecnología y así beneficiarse de todas
las características que ofrece esta nueva plataforma.
El Framework de .Net es una infraestructura sobre la que se reúne todo un conjunto de lenguajes y servicios que
simplifican enormemente el desarrollo de aplicaciones. Mediante esta herramienta se ofrece un entorno de ejecución
altamente distribuido, que permite crear aplicaciones robustas y escalables. Los principales componentes de este
entorno son:
Lenguajes de compilación
Biblioteca de clases de .Net
CLR (Common Language Runtime)
Actualmente, el Framework de .Net es una plataforma no incluida en los diferentes sistemas operativos distribuidos
por Microsoft, por lo que es necesaria su instalación previa a la ejecución de programas creados mediante .Net. El
Framework se puede descargar gratuitamente desde la web oficial de Microsoft (ver link de descarga en los
recursos del final).
.Net Framework soporta múltiples lenguajes de programación y aunque cada lenguaje tiene sus características
propias, es posible desarrollar cualquier tipo de aplicación con cualquiera de estos lenguajes. Existen más de 30
lenguajes adaptados a .Net, desde los más conocidos como C# (C Sharp), Visual Basic o C++ hasta otros lenguajes
menos conocidos como Perl o Cobol.
El CLR es el verdadero núcleo del Framework de .Net, ya que es el entorno de ejecución en el que se cargan las
aplicaciones desarrolladas en los distintos lenguajes, ampliando el conjunto de servicios que ofrece el sistema
operativo estándar Win32.
La herramienta de desarrollo compila el código fuente de cualquiera de los lenguajes soportados por .Net en un
mismo código, denominado código intermedio (MSIL, Microsoft Intermediate Lenguaje). Para generar dicho código
el compilador se basa en el Common Language Specification (CLS) que determina las reglas necesarias para crear
código MSIL compatible con el CLR.
De esta forma, indistintamente de la herramienta de desarrollo utilizada y del lenguaje elegido, el código generado
es siempre el mismo, ya que el MSIL es el único lenguaje que entiende directamente el CLR. Este código es
transparente al desarrollo de la aplicación ya que lo genera automáticamente el compilador.
Sin embargo, el código generado en MSIL no es código máquina y por tanto no puede ejecutarse directamente. Se
necesita un segundo paso en el que una herramienta denominada compilador JIT (Just-In-Time) genera el código
máquina real que se ejecuta en la plataforma que tenga la computadora.
De esta forma se consigue con .Net cierta independencia de la plataforma, ya que cada plataforma puede tener su
compilador JIT y crear su propio código máquina a partir del código MSIL.
La compilación JIT la realiza el CLR a medida que se invocan los métodos en el programa y, el código ejecutable
obtenido, se almacena en la memoria caché de la computadora, siendo recompilado sólo cuando se produce algún
cambio en el código fuente.
Cuando se está programando una aplicación muchas veces se necesitan realizar acciones como manipulación de
archivos, acceso a datos, conocer el estado del sistema, implementar seguridad, etc. El Framework organiza toda la
funcionalidad del sistema operativo en un espacio de nombres jerárquico de forma que a la hora de programar
resulta bastante sencillo encontrar lo que se necesita.
Para ello, el Framework posee un sistema de tipos universal, denominado Common Type System (CTS). Este
sistema permite que el programador pueda interactuar los tipos que se incluyen en el propio Framework (biblioteca
de clases de .Net) con los creados por él mismo (clases). De esta forma se aprovechan las ventajas propias de la
programación orientada a objetos, como la herencia de clases predefinidas para crear nuevas clases, o el
polimorfismo de clases para modificar o ampliar funcionalidades de clases ya existentes.
La biblioteca de clases de .Net Framework incluye, entre otros, tres componentes clave:
ASP.NET para construir aplicaciones y servicios Web.
Windows Forms para desarrollar interfaces de usuario.
ADO.NET para conectar las aplicaciones a bases de datos.
La forma de organizar la biblioteca de clases de .Net dentro del código es a través de los espacios de nombres
(namespaces), donde cada clase está organizada en espacios de nombres según su funcionalidad. Por ejemplo,
para manejar ficheros se utiliza el espacio de nombres System.IO y si lo que se quiere es obtener información de
una fuente de datos se utilizará el espacio de nombres System.Data.
La principal ventaja de los espacios de nombres de .Net es que de esta forma se tiene toda la bliblioteca de clases
de .Net centralizada bajo el mismo espacio de nombres (System). Además, desde cualquier lenguaje se usa la
misma sintaxis de invocación, ya que a todos los lenguajes se aplica la misma biblioteca de clases.
Ensamblados
Uno de los mayores problemas de las aplicaciones actuales es que en muchos casos tienen que tratar con
diferentes archivos binarios (DLL´s), elementos de registro, conectividad abierta a bases de datos (ODBC), etc.
Para solucionarlo el Framework de .Net maneja un nuevo concepto denominado ensamblado. Los ensamblados son
ficheros con forma de EXE o DLL que contienen toda la funcionalidad de la aplicación de forma encapsulada. Por
tanto la solución al problema puede ser tan fácil como copiar todos los ensamblados en el directorio de la
aplicación.
Con los ensamblados ya no es necesario registrar los componentes de la aplicación. Esto se debe a que los
ensamblados almacenan dentro de si mismos toda la información necesaria en lo que se denomina el manifiesto del
ensamblado. El manifiesto recoge todos los métodos y propiedades en forma de meta-datos junto con otra
información descriptiva, como permisos, dependencias, etc.
Para gestionar el uso que hacen la aplicaciones de los ensamblados .Net utiliza la llamada caché global de
ensamblados (GAC, Global Assembly Cache). Así, .Net Framework puede albergar en el GAC los ensamblados que
puedan ser usados por varias aplicaciones e incluso distintas versiones de un mismo ensamblado, algo que no era
posible con el anterior modelo COM.
Recursos:
Página oficial de .Net Framework
http://msdn.microsoft.com/netframework/
Un entorno de desarrollo gratuito para tus creaciones ASP.NET, que además ofrece componentes adicionales de
fácil instalación como el .NET Framework o la base de datos SQL Server Express.
http://www.microsoft.com/spanish/msdn/vstudio/express/VWD/default.mspx
Comentamos un programa que ha presentado recientemente Microsoft para facilitar el acceso a su tecnología de
desarrollo ASP.NET. El programa en concreto es Visual Web Developer Express Edition, un IDE (Entorno de
desarrollo) para programar fácilmente en ASP.NET, pero que además proporciona otras herramientas útiles o
imprescindibles para realizar nuestros proyectos.
el programa se encuentra en su versión "Beta 2", que es la que hemos instalado y probado. Se puede descargar
gratuitamente desde la web de Microsoft. La versión publicada gratuitamente se puede utilizar sin limitaciones
durante 30 días. En adelante, si se desea continuar su uso, se debe registrar, también gratis, desde el mismo
ordenador donde se ha instalado y ello nos dará acceso a nuevos beneficios, como documentación adicional.
http://www.microsoft.com/spanish/msdn/vstudio/express/VWD/default.mspx
La primera impresión sobre este programa es muy buena. Muchos de nosotros hemos podido tener problemas para
acceder fácilmente a la nueva tecnología .NET de Microsoft y con esta herramienta finalizan en parte esas
dificultades. Ello es debido a que, no sólo proporciona un programa con el que aumentar la productividad de los
programadores al escribir código ASP.NET, sino que además incluye el .NET Framework, un servidor donde
ejecutar las aplicaciones creadas en .NET. Por tanto, en pocos minutos podremos empezar a realizar nuestras
primeras incursiones en .NET.
Instalación
Durante la instalación se eligen los componentes que se desean poner en nuestro ordenador. El propio programa de
instalación se conectará a Internet para recibir aquellos componentes que deseemos. Entre los componentes
opcionales se encuentran:
El programa comienza mostrando una página de inicio con las acciones típicas que puede necesitar una persona
que acaba de empezar a utilizar Visual Web Developer. Entre otras, podemos realizar acciones como crear un sitio
personal, crear un sitio web, crear un servicio web, nuevas descargas, recursos, tutoriales para manejar el
programa, etc.
Nosotros, para empezar, creamos un sitio web personal, pulsando tan sólo un botón y nos mostró en pocos
segundos una pantalla de bienvenida comentando las características de la página personal. Pulsando CTRL.+F5 se
puso en marcha el sitio web sin problemas. (Eso si, hay que tener instalado el SQL Server Express... y el .NET
Framework, claro. Pero como dijimos, todo lo necesario se puede obtener durante la instalación.)
Trabajar en ASP.NET resulta más complicado que el otros lenguajes para hacer páginas lado del servidor, como
ASP o PHP. Aunque como ventaja hay que remarcar que podrá aumentar sustancialmente nuestra productividad,
dado que ofrece muchas ayudas a los desarrolladores como la programación visual. Por todo ello, sin duda,
necesitaremos cierta experiencia para sacar provecho de este programa. Aunque los programadores de sistemas
Microsoft tendrán mucho de su parte, ya que el entorno y las herramientas son muy similares a los de otros
productos de la compañía.
Para adquirir esos conocimientos sobre .NET, si nos registramos como usuarios de Visual Web Developer Express,
obtendremos acceso, entre otros, a un completo libro para aprender ASP.NET de la editorial Microsoft Press,
Una de las principales desventajas de la programación procedural basada en funciones es su construcción, cuando
una aplicación bajo este tipo de programación crece, la modificación del código se hace muy trabajosa y difícil
debido a que el cambio de una sola línea en una función, puede acarrear la modificación de muchas otras líneas de
código pertenecientes a otras funciones que estén relacionadas.
Con la programación orientada a objetos se pretende agrupar el código encapsulándolo y haciéndolo independiente,
de manera que una modificación debida al crecimiento de la aplicación solo afecte a unas pocas líneas.
La organización de una aplicación en POO se realiza mediante estructuras de código, también llamados objetos.
Estos objetos contienen una serie de procedimientos e información destinados a resolver un grupo de tareas con un
denominador común. Un procedimiento que este situado en un objeto no podrá ser usado por otro procedimiento
perteneciente a otro objeto, si no es bajo una serie de reglas. Los datos que mantenga el objeto, permanecerán
aislados del exterior y sólo se podrá acceder a ellos siguiendo ciertas normas.
El objetivo de POO es catalogar y diferenciar el código, en base a estructuras jerárquicas dependientes, al estilo de
un árbol genealógico.
Los objetos se crean a partir de una serie de especificaciones o normas que definen como va a ser el objeto, esto es
lo que en POO se conoce como una clase.
Las clases definen la estructura que van a tener los objetos que se creen a partir de ella, indicando que propiedades
y métodos tendrán los objetos.
Las propiedades definen los datos o información del objeto, permitiendo modificar o consultar su estado, mientras
que los métodos son las rutinas que definen el comportamiento del objeto. Es necesario tener muy clara cual es la
diferencia entre un objeto y una clase, a este respecto podemos decir que una clase constituye la representación
abstracta de algo mientras que un objeto constituye la representación concreta de lo que la clase define.
Imaginemos los planos de una casa diseñados por un arquitecto, en ellos encontramos el esquema de la casa, las
medidas, los materiales etc... Una vez construida la casa podremos comprobar que cumple todo lo que los planos
determinaban, de esta manera podemos comparar los planos de la casa con las clases en POO, y la casa en si con
un objeto creado a partir de una clase. Se debe destacar también que con los mismos planos se pueden crear
muchas casas iguales, lo mismo ocurre en POO, a partir de una clase se pueden crear muchos objetos iguales.
tipos de datos para la plataforma .NET, con sus correspondencias tanto en VB.NET y C#.
Todos los lenguajes de programación que cumplen las normas de .NET tienen muchas cosas en común, una de
ellas es el conjunto de tipos de datos. Hay que destacar que estos tipos de datos están implementados como clases,
de manera que una variable declarada de un tipo determinado, tendrá la capacidad de usar tanto los métodos como
las propiedades que pertenezcan a la clase del tipo de dato.
VB.NET
Dim Cadena As String
Dim Longitud As Integer
Cadena = "Datos"
Longitud = Cadena.Length()
C#
String Cadena;
Int Longitud;
Cadena = "Datos";
Longitud = Cadena.Length();
En el ejemplo anterior declaramos una variable de tipo String (Cadena de caracteres), y podemos ver como esta
variable posee una serie de propiedades y métodos que pueden ser invocados, en este caso usamos la propiedad
Length() para obtener el numero de caracteres de la variable Cadena y asignarlo a la variable Longitud, que pasaría
a tener el valor 5.
En la siguiente tabla se muestra una relación de los tipos de datos de .NET Framework y su correspondencia en
VB.NET y C#.
Sbyte Sbyte (Nosbyte Entero sin signo de 8bit (Tipo no acorde con el CLS)
nativo)
Uint16 UInt16 (Noushort Entero sin signo de 16 bit. (Tipo no acorde con el CLS)
nativo)
Uint32 Uint32 (Nouint Entero sin signo de 32 bit. (Tipo no acorde con el CLS)
nativo)
Uint64 Uint64 (Noulong Entero sin signo de 64 bit. (Tipo no acorde con el CLS)
nativo)
Single Single float Numero con coma flotante de precisión simple, de 32 bit.
Double Double double Numero con coma flotante de precisión doble, de 64 bit.
IntPtr IntPtr (No-- Entero con signo cuyo tamaño depende de la plataforma: 32 bit en
nativo) plataformas de 32 bit y 64 bit en plataformas de 64 bit. (Tipo no acorde
con el CLS)
UintPtr UintPtr (No-- Entero sin signo cuyo tamaño depende de la plataforma: 32 bit en
nativo) plataformas de 32 bit y 64 bit en plataformas de 64 bit. (Tipo no acorde
con el CLS)
Según el modo en el que se almacenan y manipulan estos tipos de datos se pueden dividir en dos categorías.
Podemos almacenar variables por valor y por referencia. Explicamos lo que significa cada uno y las maneras que
.NET realiza este almacenamiento.
Tipos por valor: los tipos por valor almacenan datos a los que se puede acceder de forma directa, a su vez dentro
de esta categoría encontramos mas subcategorías como los tipos nativos de .NET, los tipos de datos creados por el
programador y los enumerados. Los tipos por valor no pueden tener valores nulos.
Tipos por referencia: Los tipos creados por referencia almacenan la dirección de memoria en la que se encuentra
un dato determinado de manera que usaremos esa dirección de memoria para acceder de forma indirecta al dato.
Los tipos por referencia se dividen en varios subgrupos como son las clases propias de la plataforma, interfaces,
clases creadas por el programador, etc.
Cuando ejecutamos una aplicación es necesario que los datos se sitúen en la memoria del ordenador, la cual esta
divida en dos partes, una llamada Stack, de pequeño tamaño pero de un acceso muy rápido y otra llamada Heap
que cuenta con un mayor tamaño pero con una velocidad de acceso inferior.
Cuando creamos tipos por valor, el valor de la variable de este tipo se almacena en el Stack, si asignamos una
variable de estas características a otra, se crea una copia en el Stack. Al destruir un tipo por valor, se destruye
también el valor que se guardo en el Stack.
Cuando creamos un tipo por referencia, en realidad lo que guardamos en el Heap es una dirección de memoria que
apunta a un valor, pero no al valor en si mismo. Si asignamos una variable que contiene un tipo por referencia a otra
variable, se dice que ambas se refieren al mismo valor. Los tipos por referencia si pueden contener valores nulos.
Explicación de la creación de clases y objetos en los dos principales lenguajes de la plataforma .Net.
Para explicar la creación de clases usaremos un ejemplo sencillo basado en una clase principal "bicicleta".
Para crear una clase debemos definir sus propiedades y sus métodos, en este ejemplo se usan los siguientes
términos como propiedades de la clase bicicleta: Modelo, Precio, NumeroDeVelocidades y Velocidad; como
métodos de la clase se usan: Acelerar(km) , Frenar() y ConsultarVelocidad().
VB.NET
Public Class Bicicleta
Public Modelo as String
Public Precio as Double
Public NumeroDeVelocidades as Integer
Private Velocidad as Integer
Public Sub Acelerar(ByVal km As Integer)
Velocidad = Velocidad + km
End Sub
C#
Class Bicicleta
{
public string Modelo;
public double Precio;
public int NumeroDeVelocidades
private int Velocidad
Nuestra clase bicicleta consta de varias propiedades y métodos, las palabras Private y Public definen la
accesibilidad de las propiedades, funciones o subrutinas. La definición de una propiedad o método de tipo privado
indica que sólo podrá ser usada dentro del código de la misma clase, si creásemos un objeto de tipo bicicleta, las
especificaciones de la clase no nos permitirían acceder a la propiedad velocidad para consultarla o modificarla, ya
que esta definida como privada. En cambio se pueden usar las subrutinas Acelerar() y Frenar() ya que son de tipo
Public, y desde dentro de ellas se interactua con las propiedades privadas, con esto conseguimos encapsular el
código y hacer accesible solo aquello que queramos.
VB.NET
Dim objBicicleta as Bicicleta = New Bicicleta
objBicicleta.Acelerar(5)
objBicicleta.Frenar()
VelocidadActual = objBicicleta.ConsultarVelocidad
C#
Bicicleta objBicicleta = new Bicicleta();
int VelocidadActual;
objBicicleta.Modelo = "Montaña";
objBicicleta.Precio = 200;
objBicicleta.NumeroDeVelocidades = 21;
objBicicleta.Acelerar(5);
objBicicleta.Frenar();
VelocidadActual = objBicicleta.ConsultarVelocidad();
Tras la creación del objeto objBicicleta a partir de la clase, se pueden modificar los valores de las propiedades de
tipo Public, y llamar a los métodos de tipo Public.
En el ejemplo se llama a los métodos Acelerar(5), pasándole el numero de km que queremos acelerar a través del
parámetro "km" que está definido en la subrutina.
Luego se llama al método Frenar() que decrementa en una unidad el valor de la propiedad Velocidad.
Por último se usa la función ConsultarVelocidad(), que retorna el valor de la propiedad Velocidad para introducirlo en
la variable VelocidadActual.
primer programa en .NET, utilizando la consola, que utiliza un formato de salida y entrada de datos en modo
texto.
Se puede definir una aplicación de consola como aquella que se ejecuta en una ventana de MS-DOS, es decir, en
línea de comandos.
Lo más común dentro del desarrollo bajo la plataforma .Net es la creación de aplicaciones Web o aplicaciones
Windows sin embargo la mejor forma de sentar unas bases firmes acerca de la programación orientada a objetos es
comenzar construyendo aplicaciones sencillas de consola.
El primer ejemplo de aplicación de consola es un sencillo programa que pide al usuario 2 números y le pregunta si
desea sumarlos o restarlos.
Antes de comenzar a desarrollar la aplicación se ha de conocer la clase principal que interactúa con la consola de
MS-DOS, la clase Console.
Mediante esta clase se consigue mostrar información en la pantalla así como capturar la información que introduzca
el usuario, cabe destacar que los métodos de la clase Console son de tipo Shared, esto significa que no es
necesario crear un objeto a partir de la clase para invocar a sus métodos, es posible hacerlo indicando el nombre de
la clase seguido de un punto y el nombre del método.
El método WriteLine()
Este método es el que se usa para mostrar texto en la consola, el método escribe en la pantalla el valor que le
pasemos como parámetro.
El parámetro que recibe el método puede ser de varios tipos, ya sea una cadena de caracteres, un número entero,
una línea en blanco, etc...
VB.NET
C#
using System;
namespace ConsoleApplication2
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
//Escribimos una cadena de caracteres.
Console.WriteLine("Escribiendo una línea en la consola");
//Escribimos un numero entero
Console.WriteLine(23);
//Escribimos una comparación lógica
Console.WriteLine(3 > 1);
Console.ReadLine();
}
}
}
Es importante destacar que este método añade automáticamente el salto de carro al final de la línea, esto significa
que la siguiente llamada a Console.WriteLine() escribe en la siguiente línea.
La última línea en la que realizamos una llamada al método ReadLine() se utiliza para evitar que la pantalla se cierre
automáticamente.
Fig1: Ejemplo del método WriteLine()
El método ReadLine()
Este método se usa para recoger la información que el usuario introduce cuando la aplicación así lo requiera.
Cuando invocamos al método Console.ReadLine() el sistema queda en espera hasta que el usuario pulsa la tecla
Intro.
Si se asigna la llamada a Console.ReadLine() a una variable se consigue capturar el dato introducido por el usuario,
para después poder operar con él.
VB.NET
C#
Fig2: WriteLine() y ReadLine()
El método Read()
Este es otro método que permite capturar información que proviene del usuario. La diferencia con el anterior es que
Read() no espera a que el usuario pulse intro para capturar el dato introducido, sino que lo hace tras la pulsación de
cualquier tecla, capturando el valor de la tecla pulsada en código ASCII.
Una vez que hemos aprendido a usar la clase consola, vamos a realizar una aplicación de consola.
Ahora que se conoce un poco mejor la clase Console, se dará comienzo a la aplicación, los lenguajes usados para
este ejemplo son Visual Basic.Net y C#.
Lo primero que se debe hacer después de arrancar Visual Studio.Net, es escoger la opción "Aplicación de consola"
(Fig1), tras este paso Visual Studio genera las siguientes líneas:
Fig3: Creación de una aplicación de consola.
VB.NET
Module Module1
Sub Main()
C#
using System;
namespace ConsoleApplication3
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
}
}
}
Dentro del procedimiento Main(), se introduce el código que se quiere ejecutar. Lo primero que hay que hacer es
declarar las variables que se van a usar, para este ejemplo se usan 2 variables de tipo entero para recoger los
valores de los números que introduzca el usuario:
VB.NET
Module Module1
Sub Main()
Dim Numero1 As Integer
Dim NUmero2 As Integer
End Sub
End Module
C#
using System;
namespace ConsoleApplication3
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int Numero1;
int Numero2;
}
}
}
Una vez están declaradas las variables, se solicitan ambos números al usuario y se introducen sus valores en las
dos variables, a continuación se pide que se seleccione una de las opciones posibles, sumar o restar.
VB.NET
Module Module1
Sub Main()
Dim Numero1 As Integer
Dim Numero2 As Integer
C#
using System;
namespace ConsoleApplication2
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int Numero1;
int Numero2;
int opcion;
Siguiendo el flujo de la aplicación se puede ver que después de que el usuario selecciona una de las 2 opciones, se
muestra el resultado de la operación por pantalla.
Si lo que se desea es encapsular el código en la medida de lo posible se pueden construir 2 funciones que realicen
las operaciones de sumar y restar y que escriben el resultado en la pantalla, el código quedaría de la siguiente
manera:
VB.NET
Module Module1
Sub Main()
Dim Numero1 As Integer
Dim Numero2 As Integer
C#
using System;
namespace ConsoleApplication2
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int Numero1;
int Numero2;
int opcion;
De esta manera se consigue encapsular funcionalidades dentro de la aplicación, asignando las tareas de Sumar y
Restar a dos subrutinas, la principal ventaja es que una vez hayamos asegurado que ambas subrutinas funcionan,
podremos olvidarnos de ellas y continuar con el desarrollo de la aplicación.
Fig4: Resultado del ejemplo.
creación en .NET de aplicaciones en entorno de ventanas, llamadas generalmente aplicaciones Windows.
La creación de aplicaciones Windows ha resultado siempre una tarea compleja debido a la dificultad de tener que
crear una interfaz gráfica que interactúe con el usuario. Los Formularios de Windows (Windows Forms) de .Net
permiten la creación de aplicaciones de interfaz gráfica de forma sencilla. .Net proporciona un amplio conjunto de
controles como botones, cajas de texto, etiquetas, etc. que, unidos a la completa biblioteca de clases de .Net, hace
posible el desarrollo de aplicaciones en poco tiempo.
En los siguientes ejemplos se ha usado Visual Studio.Net, no obstante, es posible crear aplicaciones Windows con
un simple editor de texto y una herramienta de compilación compatible con el CLR de .Net Framework. Visual
Studio.Net admite diseñar la aplicación de forma visual, permitiendo en cada momento acceder al código generado y
sirviendo además como herramienta de compilación y depuración.
Para comenzar una nueva aplicación, se ejecuta Visual Studio y se selecciona Nuevo Proyecto, donde aparecen los
distintos tipos de aplicaciones que se pueden realizar con cada lenguaje, seleccionando en este caso Aplicación
para Windows. Una vez introducido el nombre de la aplicación y la ruta donde se ubicará se pulsa Aceptar.
Fig 1. Ventana de creación de nuevo proyecto.
En los siguientes ejemplos se muestra como crear una aplicación basada en formularios en los dos lenguajes más
comunes, tanto para Visual Basic .Net como para C#, dejando al lector la elección del lenguaje que le resulte más
cercano.
Después de haber creado el proyecto, se dispone de una aplicación completa que puede ser ejecutada. Esto se
puede realizar en el menú Depurar pulsando en el elemento Iniciar (Tecla F5) lo que ejecutará directamente la
aplicación dentro de Visual Studio.Net. Véase el código creado hasta ahora:
VB.NET
Public Class Form1
nbsp; Inherits System.Windows.Forms.Form
End Sub
End Class
Si se ha optado por C# se puede comprobar que el código es muy similar, aunque algo más extenso ya que la
inicialización por defecto esta situada fuera de la región del código que va generando automáticamente el
diseñador.
En el código generado, el formulario 'Form1' es una clase que proviene mediante la palabra clave inherits (heredar)
del espacio de nombres System.Windows.Forms.Form perteneciente a la biblioteca de clases de .Net. Las
aplicaciones desarrolladas con .Net utilizan la biblioteca de clases incluida en el Framework de .Net que
proporcionan un conjunto de funcionalidades prefabricadas que facilitan el desarrollo. Está biblioteca de clases está
organizada en espacios de nombres dependiendo de su funcionalidad.
Todos los lenguajes incluidos en .Net están orientados a objetos, siguiendo esta metodología el formulario 'Form1'
se declara como una clase. Como se verá más adelante esto facilita el acceso a los métodos y propiedades del
formulario y de los controles que se incluyan al tratar a cada elemento como objetos independientes.
proceso de insertar controles en una aplicación Windows. Los controles son elementos que podemos
colocar en una aplicación para interactuar con el usuario o visualizar los resultados del programa.
Los controles simplifican la creación del interfaz facilitando además la interacción ordenada del usuario con la
aplicación y la visualización de los resultados. Dentro de la región denominada "Código generado por el Diseñador
de Windows Forms", el diseñador crea automáticamente el código correspondiente a cada control según se van
añadiendo estos desde la pantalla de diseño visual. Por tanto, para insertar un nuevo control basta con arrastrarlo
desde el cuadro de herramientas al formulario de la aplicación.
Arrastrando un control de tipo botón a nuestro formulario y analizando el código generado se observa lo
siguiente:
VB.NET
Me.Button1 = New System.Windows.Forms.Button()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(184, 64)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
C#
this.button1 = new System.Windows.Forms.Button();
//
// button1
//
this.button1.Location = new System.Drawing.Point(184, 88);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "button1";
Al introducir un control de tipo botón se genera en el código un objeto llamado 'button1' perteneciente a la clase
System.Windows.Forms.Button y se establecen las propiedades por defecto para ese objeto. Estas propiedades se
pueden modificar desde la vista de diseño pulsando sobre el control 'button1' y seleccionado el panel de
propiedades (Tecla F4).
Otra forma de cambiar las propiedades de un control es modificando el código generado automáticamente por el
diseñador. A continuación se muestra un sencillo ejemplo donde se que modifica el literal de texto que aparece
sobre el botón 'button1':
VB.NET
'load de la clase Form1
Button1.Text = "Pulsa aquí"
C#
//load de la clase Form1
button1.Text="Pulsa aquí";
Los eventos son llamadas al código que se producen cuando el usuario realiza una acción. Aprendemos a
utilizarlos en .NET
Los eventos son llamadas al código que se producen cuando el usuario realiza una acción como, por ejemplo,
pulsar un botón o seleccionar un elemento de una lista. Los eventos responden a la acción del usuario sobre un
control ejecutando una función situada en el código.
A continuación se muestra un sencillo ejemplo en el que se introducen una serie de controles en la vista de diseño
modificando las propiedades tal como aparecen en la imagen.
Al pulsar dos veces sobre el botón 'btnBoton' se crea automáticamente en el código del formulario el evento que se
corresponde con la pulsación del botón. La función creada se denomina por defecto 'btnBoton_Click' y responde al
evento btnBoton.Click que se indica por medio de la palabra clave handles (manejador). Seguidamente se muestra
el código en el evento que interactúa con el resto de controles:
VB.NET
Private Sub btnBoton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
btnBoton.Click
End Sub
C#
private void btnBoton_Click(object sender, System.EventArgs e)
{
lblResultado.Text = "Hola " + txtNombre.Text;
}
Cada control tiene su propia colección de eventos. Para crear un nuevo evento se utiliza el menú desplegable de
clases y su correspondiente menú de métodos situados en la parte superior del código.
Las aplicaciones .NET utilizan objetos que podemos programar nosotros mismos. Aprendemos a trabajar
conjuntamente con los controles de las aplicaciones Windows y los objetos que podamos haber
programado.
La programación orientada a objetos proporciona un mejor ordenamiento y claridad del código. La forma de
programar consiste en dividir el código en clases de objetos que posteriormente pueden ser reutilizados. Para más
información se recomienda leer el artículo de 'Programación orientada a objetos, introducción' incluido en esta
sección.
Al arrancar la aplicación, el punto de inicio del código se sitúa por defecto en el evento 'Load' de la clase 'Form1', si
bien se puede cambiar dentro de las propiedades del proyecto desde el explorador de soluciones. El evento 'Load'
es una subrutina que no devuelve ningún valor. En ella se pueden instanciar objetos de otras clases para ser
utilizados posteriormente. El siguiente ejemplo muestra como crear una clase propia y la instanciación de un objeto
de dicha clase:
VB.NET
Public Class MiClaseSumar
End Class
C#
public class MiClaseSumar
{
public int resultado;
VB.NET
'load de la clase Form1
Me.Text = " Mi primera Aplicación con Windows Forms"
lblResultado.Text = objetoSuma.resultado
C#
//load de la clase Form1
this.Text = " Mi primera Aplicación con Windows Forms";
lblResultado.Text = objetoSuma.resultado.ToString();
Se puede observar como en C# es necesario convertir previamente el resultado. Esto se debe a que el resultado de
la suma es de tipo numérico y no se puede asignar directamente al texto de la etiqueta, por lo que se debe convertir
previamente a tipo texto. Esto no es necesario en Visual Basic .Net, donde la conversión de tipos no es obligatoria,
aunque es recomendable para obtener un código más óptimo.
Con la programación orientada a objetos resulta más fácil programar aplicaciones ya que el código está mejor
estructurado y resulta más sencillo de leer y modificar. Además, Visual Studio .Net facilita en gran medida la
creación de aplicaciones con interfaz gráfico al generar automáticamente el código encargado de visualizar
formularios y controles.
Recursos:
Una aplicación de ASP.NET tiene opciones de configuración y administración. Aquí se verá como configurar
y ejecutar una aplicación web de ASP.NET a partir de servidores web como Internet Information Server.
Existen diversos elementos de configuración y administración en una aplicación Web de ASP.Net. Este tipo de
aplicaciones se compone de un conjunto de ficheros almacenados en una carpeta dentro del servidor Web.
Para ejecutar una aplicación Web de ASP.Net se necesita que el servidor Web sea compatible con ASP.Net. En
este caso se va a utilizar IIS 5.0 (Internet Information Server) como servidor Web. El IIS es un componente de
Windows incluido en las versiones profesionales de Windows 2000 y XP. Si no se tiene este componente, se debe
proceder a su instalación mediante el icono de 'Agregar o quitar programas' en el panel de control y seleccionando
'Agregar o quitar componentes de Windows' en donde aparecerá el IIS para su instalación. El acceso al IIS se
realiza mediante el icono de 'Servicios de Internet Information Server' situado en las 'Herramientas administrativas'
dentro del panel de control.
El servidor Web IIS permite administrar las aplicaciones Web y comunicarse con los navegadores cliente mediante
protocolo http (protocolo de transferencia de hipertexto). El IIS también ofrece otros servicios de protocolo, como
transferencia de archivos (FTP), servicio de correo electrónico (SMTP) y servicio de noticias (NNTP).
Con el clásico ASP 3.0 era suficiente con tener el IIS instalado en el servidor Web, ya que era el IIS el que
directamente interpretaba el código ASP y enviaba la respuesta al cliente. Sin embargo, en ASP.Net se necesita que
el servidor Web tenga instalado .Net Framework para poder procesar código de ASP.Net, como ocurre con cualquier
otra aplicación de .Net. Es importante decir que los navegadores cliente que accedan a la aplicación Web no
necesitan tener instalado IIS ni tampoco .Net Framework ya que es el servidor Web el que tiene que saber
interpretar el código de ASP.Net.
Cuando se solicita una página de tipo .aspx (página de ASP.Net) el servidor Web de IIS envía la solicitud a .Net
Framework que es quien realmente procesa la petición de la página. De esta forma, las aplicaciones Web de
ASP.Net se benefician de todas la ventajas de ejecución de código en .Net Framework, ya que el código es
compilado y ejecutado por .Net Framework y devuelto al IIS para que éste a su vez lo envíe al cliente.
Con ASP.Net también es posible tener código de ASP 3.0 dentro de páginas de ASP.Net, con la ventaja de que el
código de ASP 3.0 también se compila junto con el código de ASP.Net aumentando el rendimiento del servidor Web.
A continuación, se muestra un ejemplo de los distintos ficheros que pueden existir en una aplicación Web de
ASP.Net.
Fig. Aplicación Web de ASP.Net
Una vez creada la aplicación, el código de servidor se ensambla en un fichero .dll situado en la carpeta Bin de la
aplicación Web. Por tanto, una vez realizada la compilación, los ficheros de código (.vb ó .cs) ya no son necesarios
para la ejecución de la aplicación ya que están ensamblados en la dll y es aconsejable quitarlos del servidor para
que no se pueda acceder desde el exterior a su contenido.
En resumen, para que funcione una aplicación Web de ASP.Net se debe tener en el Servidor Web lo siguiente:
Tener instalado IIS 5.0 ó superior en el servidor Web y configurar un directorio virtual asociado a la aplicación
Web.
Tener instalado en el servidor Web .Net Framework.
Los archivos .aspx correspondientes a las páginas Web.
Un archivo de ensamblado (DLL) situado en la carpeta Bin de la aplicación Web, que contiene el código de
servidor que necesitan las páginas aspx.
Un archivo llamado Global.asax que sirve para el control general de la aplicación durante su ejecución.
Un archivo llamado Web.config donde se establece la configuración de la aplicación. Aunque este fichero es
opcional se necesita cuando se quieren establecer parámetros de configuración que no sean los de por
defecto.
De manera adicional también puede aparecer en la carpeta Web otro tipo de archivos como:
o Archivos .ascx (controles personalizados de usuario de ASP.Net)
o Archivos .asmx (servicios Web XML de ASP.Net).
o Páginas .htm ó .html (páginas Web estáticas)
o Páginas .asp (páginas activas de servidor)
o Archivos .css (hojas de estilo CSS, Cascade Style Sheet).
o Documentos, imágenes, etc...
Para terminar, se va a crear una aplicación Web de tipo ASP.Net y a instalarla en un servidor Web con IIS. El primer
paso es crear la aplicación Web, para ello se entra en Visual Studio .Net y en el menú 'Archivo' se selecciona 'Nuevo
proyecto'. Aquí se debe elegir uno de los lenguajes disponibles y seleccionar 'Aplicación Web ASP.Net'.
Fig. Creación de una aplicación Web de ASP.Net
De forma automática, al crear un nuevo proyecto Web, Visual Studio .Net crea un directorio virtual en el IIS y lo
asocia con la aplicación Web. Si se ha instalado IIS con la configuración por defecto, el sitio Web predeterminado
(localhost) será 'c:\inetpub\wwwroot'.
En el caso de que se tuviera una aplicación Web de ASP.Net ya creada y se desee instalar en un servidor Web, se
debe copiar la carpeta con la aplicación en el servidor Web y asociarla manualmente a un directorio virtual. Para
ello, dentro de IIS se selecciona el elemento de 'Sitio Web predeterminado' y pulsando con el botón derecho se
selecciona la opción: 'Nuevo' > 'Directorio virtual' donde mediante un asistente se asocia la carpeta de la aplicación
Web a un directorio virtual en el servidor.
Para probar que la aplicación Web funciona correctamente se debe compilar primero en Visual Studio .Net y
posteriormente acceder a la aplicación mediante el navegador:
http://[Nombre_del_servidor]/[directorio_virtual]/[página]
Antes de comenzar con las novedades del lenguaje, queremos mencionar un hecho especialmente destacable: la
evolución paralela de funcionalidades que a partir de Visual Studio 2010 experimentarán y ofrecerán los dos
principales lenguajes de la plataforma: Visual Basic y C#.
Desde la primera versión de .NET Framework, los equipos de desarrollo de estos dos lenguajes han procurado
marcar algunas diferencias entre ambos, siendo su intención la de hacer de Visual Basic un lenguaje más atractivo
al desarrollador de aplicaciones de gestión, mientras que C# se pretendía dirigir a los programadores más
orientados hacia el desarrollo a más “bajo nivel”: componentes, servicios, etc. Scott Wiltamuth, uno de los directores
de la división de lenguajes de Visual Studio, menciona que llevar estos objetivos a la práctica resultó más
complicado de lo esperado, debido a la presencia de lo que él denomina “poderosas fuerzas de unificación” que han
propiciado un cambio de orientación hacia el desarrollo en paralelo de funcionalidades para los dos lenguajes,
como:
La existencia de un entorno de desarrollo integrado y bloques de construcción de aplicaciones comunes a
ambos lenguajes.
La naturaleza orientada a objetos y el sistema de tipos común a los dos lenguajes.
El hecho de que las principales áreas de innovación presente y futura en el desarrollo de los lenguajes se
reflejan en partes “exteriores” de los mismos, como ocurre en el caso de LINQ.
A los elementos anteriores hay que añadir las demandas de las comunidades de desarrolladores, ya que los
programadores de VB querían aquellas funcionalidades disponibles en C# de las que VB carecía, y viceversa.
Todo ello ha propiciado el cambio de estrategia que acabamos de mencionar, que tiene el claro objetivo de que,
independientemente del lenguaje que utilicemos, podamos aprovechar toda la potencia que .NET Framework pone a
nuestra disposición.
Propiedades auto-implementadas
Antes de la llegada de Visual Basic 2010 (o Visual Basic 10, como también se denomina), cada vez que en una
clase se definía una propiedad, estábamos obligados a codificar por completo sus bloques de acceso/asignación
(Get/Set), aún cuando la propiedad no necesitara una lógica especial para dichas operaciones. A partir de esta
nueva versión, es posible crear propiedades auto-implementadas, que se declaran en una simple línea de código sin
necesidad de especificar los bloques Get/Set; con la ventaja adicional de poder asignar al mismo tiempo un valor
predeterminado
Al crear una propiedad de este modo, el compilador genera internamente un campo de respaldo con ámbito de
clase, cuyo nombre se compone de un guión bajo y el nombre de la propiedad. Dicho campo es perfectamente
accesible desde el código de la clase, aunque no es expuesto a través de IntelliSense.
Las propiedades auto implementadas sufren algunas restricciones: no pueden ser declaradas con los
modificadores ReadOnly ni WriteOnly, y en el caso de que la propiedad vaya a contener un array, no
podemos especificar la dimensión del mismo en la declaración, aunque sí es posible inicializarlo, como
vemos en los ejemplos del listado 1.
Inicializadores de colecciones
La manera que hasta ahora teníamos de inicializar una colección con un conjunto de valores consistía en llamar
sucesivamente a su método Add, pero Visual Basic 2010 aporta una nueva sintaxis más sucinta para esta tarea,
consistente en utilizar la palabra clave From en el momento de crear la colección, seguida de una lista con los
valores de inicialización encerrados entre llaves; internamente, el compilador generará una llamada al método Add
de la colección por cada uno de los elementos existentes en la lista. El listado 2 presenta un ejemplo basado en la
clase Libro del listado 1.
As String = "Netalia"
End Sub
End Class
},
}
Listado 3
'------------------------------------------------------
<Extension()>
End Sub
Pero, al inicializar colecciones como la del listado 2, ¿no sería estupendo poder pasar solamente los valores para
las propiedades de cada objeto de la colección, y que ésta se encargara de instanciar los objetos? Esto es
perfectamente posible creando un método de extensión con el nombre Add para la colección List(OfLibro), lo que
hará posible utilizar una sintaxis de inicialización mucho más simple, como muestra el listado 3.
En el caso de que estemos desarrollando una colección propia en la que deseemos que esté disponible esta sintaxis
de inicialización, es preciso implementar la interfaz IEnumerable, o al menos cumplir con el patrón IEnumerable, es
decir, implementar métodos GetEnumeratory Add. Con respecto al método Add, podemos crear una sobrecarga que
facilite la sintaxis de inicialización para nuestra colección, o bien un método de extensión como en el caso anterior.
En el listado 4 vemos un ejemplo.
Listado 4
Dim colBiblioteca1 As New Biblioteca() From {
}
'-----------------------------------
End Sub
End Sub
Return lstLibros.GetEnumerator()
End Function
End Class
Expresiones lambda
Las expresiones lambda fueron introducidas en Visual Basic 2008, pero entonces solo podían constar de una única
línea de código, siendo también obligatorio que la expresión devolviera un valor. Esta restricción ha sido superada
en Visual Basic 2010, donde podemos escribir expresiones lambda compuestas por varias líneas de código. Como
novedad adicional, además de crear expresiones que devuelvan un valor (comportamiento habitual), podemos crear
otras que no devuelvan resultado alguno (al estilo de un procedimiento Sub) utilizando un delegado de tipo Action(Of
T), como se muestra en el listado 5.
Covarianza y contravarianza
Cuando trabajamos con tipos genéricos que mantienen una relación de herencia, debemos tener en cuenta ciertas
restricciones impuestas por la plataforma de las que a priori podemos no ser conscientes, ya que asumimos que
deberían funcionar por una simple cuestión de principios lógicos en los que se basa la OOP. Tomemos como
ejemplo el listado 6.
Listado 5
Dim Lambda01 As Func(Of Integer, String) =
Function(nNumero As Integer)
Dim nNuevoNumero As Integer
Dim sResultado As String
nNuevoNumero = nNumero * 7
sResultado = "El resultado es: " & nNuevoNumero.ToString()
Return sResultado
End Function
Console.WriteLine(Lambda01(123))
Dim Lambda02 =
dtFechaActual.AddDays(nDiasAgregar)
Return dtFechaNueva
End Function
Console.WriteLine(Lambda02(5).ToString("dd-MMMM-yyyy"))
Dim Lambda03 =
Sub(sNombre As String, dtFechaNacimiento As DateTime)
Console.WriteLine(sMensajeCompleto)
End Sub
Lambda03("Ernesto Naranjo", New DateTime(1970, 10, 18))
' Expresión lambda de tipo Sub con declaración estricta
' usando Action(Of T)
End Sub
Lambda04("Hola mundo!")
Listado 6
Public Class Documento
Public Property Texto As String
Public Property Autor As String
End Class
End Class
End Class
'---------------------------------------
Si el intento de asignación de un objeto del tipo IList(Of Carta)a una variable del tipo IList(Of Documento) no
produjera un error en tiempo de ejecución, podríamos reasignar a uno de los elementos de IList(OfDocumento)un
tipo Actae intentar seguidamente extraerlo como un tipo Carta, como vemos en el listado 7, lo que provocaría una
ruptura en el sistema de seguridad de tipos de la plataforma.
Listado 7
ilstDocumentos(1) = New Acta() With {
.DepartamentoEmisor = "Contabilidad",
.Fecha = DateTime.Today }
La versión 4 de .NET Framework levanta en ciertos casos estas restricciones, permitiendo la conversión implícita o
varianza entre ciertos tipos de interfaces en dos modalidades diferentes: covarianza y contravarianza.
La covarianza permite asignar a un tipo como IEnumerable(Of T), en el que T esté situado en un nivel superior de la
jerarquía, un valor de tipo IEnumerable(Of T) cuyo T sea un descendiente, sin que se produzca error. El compilador
acepta esto debido a que dicha interfaz está definida dentro de la plataforma como IEnumerable(Of Out T), lo que
indica que el tipo T solamente podrá ser manipulado en operaciones “de salida”. De esta manera, es posible escribir
el código del listado 8.
Por otra parte, la contravarianza produce, en cierto sentido, un efecto opuesto al anterior, ya que permite, por
ejemplo, que en un tipo derivado T del que hemos creado una colección List(Of T), una operación/ método como
Sort sea llevada a cabo por un tipo superior en la jerarquía de clases de T mediante la interfaz IComparer( Of T).
Ello es posible porque la interfaz está definida dentro de la plataforma como IComparer(Of In T), lo que indica que T
solamente podrá ser manipulado en operaciones “de entrada”. El listado 9 muestra un ejemplo de este caso.
Listado 8
Dim ienumCarta As IEnumerable(Of Carta) = New List(Of Carta) From {
New Carta() With {.Texto = "AAA", .Autor = "Bea", .Destinatario = "Tom"},
New Carta() With {.Texto = "BBB", .Autor = "María", .Destinatario = "Ana"}
}
Dim ienumDocumento As IEnumerable(Of Documento) = ienumCarta
Listado 9
Public Class ComparadorDocumentos
Implements IComparer(Of Documento)
Public Function Compare(ByVal x As Documento, ByVal y As Documento) As Integer
Implements System.Collections.Generic.IComparer(Of Documento).Compare
'....
End Function
End Class
'--------------------------------
}
Dim icompDocumentos As IComparer(Of Documento) = New ComparadorDocumentos()
lstCartas.Sort(icompDocumentos)
Para una descripción en mayor profundidad de esta nueva característica de Visual Basic, también presente en C#,
recomendamos la consulta del artículo sobre este tema que publicó recientemente dotNetManía [2].
Otras novedades adicionales que incorpora Visual Basic 2010 son las siguientes:
La opción /langversion del compilador nos permite especificar la versión del lenguaje con la que se compilará
nuestro código.
Haciendo uso del enlace tardío del que siempre ha gozado Visual Basic, ahora es posible acceder a objetos
creados en lenguajes dinámicos como Iron Python e Iron Ruby.
Al desarrollar aplicaciones que acceden a objetos COM, tales como los componentes de Office, ahora es
posible incrustar directamente en nuestro ensamblado la información de tipos asociada a los objetos COM, en
lugar de tener que importarla desde el ensamblado PIA suministrado por el fabricante.
En el centro de recursos del lenguaje [3], encontrará información ampliada y todo tipo de recursos para sacarle el
mayor partido a todas las nuevas características.
Con toda seguridad, la oferta de funcionalidades del nuevo Visual Basic 2010 será bien recibida por todos los
desarrolladores que utilizan este lenguaje. Esperamos que este rápido repaso sirva para conseguir una mejor toma
de contacto con las novedades aquí presentadas.
Microsoft nos tiene preparadas para la próxima versión de Workflow Foundation, que vendrá de la mano de
la versión 4.0 de .NET Framework y de Visual Studio 2010.
Como todos los desarrolladores de software sabemos, crear programas es una actividad gratificante y que impone
una enorme cantidad de retos. Desde el principio de los tiempos, los programadores siempre andamos buscando y
creando herramientas, librerías, marcos de trabajo, etc. que nos simplifiquen la solución de las tareas y nos faciliten
el desarrollo de las aplicaciones y servicios que nuestros clientes y jefes necesitan.
La mayoría de las complejidades de una aplicación no se ven a simple vista en el software que habitualmente
creamos. Me refiero a cosas como la ejecución en paralelo, la sincronización de procesos, las llamadas a
procedimientos remotos, etc. Detalles que tendríamos que ir resolviendo en cada desarrollo específico si no
contásemos con herramientas como a las que me refería anteriormente.
Workflow Foundation provee al desarrollador de una caja de herramientas que permite abstraernos de muchos de
esos detalles y centrarnos en los aspectos importantes del negocio de la mano que nos da de comer: mejorar
procesos y herramientas para aumentar la productividad y reducir costes; permitiendo que el desarrollador sea más
productivo, que las aplicaciones sean más sencillas de modificar y más fácilmente actualizables.
Si queréis saber más sobre los conceptos que se esconden detrás de Workflow Foundation, os recomiendo que le
echéis un vistazo a "The Workflow Way"
Nuevas características
Para esta nueva versión de .NET Framework, se han introducidos grandes cambios en la versión correspondiente
de Workflow Foundation, que llamaremos WF4, con respecto a las versiones incluidas en .NET 3.0 y 3.5 (a las que
nos referiremos por WF3). El equipo ha revisado el núcleo del modelo de programación, el runtime y las
herramientas, y ha reestructurado cada uno de ellos para mejorar el rendimiento y la productividad, así como para
añadir algunas de las propuestas más importantes recibidas a través del feedback de los usuarios actuales.
La gran mayoría de los cambios que encontrarán los desarrolladores en WF4 con respecto a WF3 han sido
necesarios para mejorar la experiencia de utilización de Workflow Foundation y hacer de él cada vez más una pieza
fundamental en el desarrollo de aplicaciones .NET. Es importante destacar que todos esos cambios se han
realizado manteniendo la compatibilidad hacia atrás. Los nuevos componentes del framework están localizados en
un nuevo ensamblado llamado System. Activities.dll, mientras que los componentes compatibles con versiones
anteriores se encuentran en System.Workflow.dll, de manera que podemos migrar sin tocar nada de código las
aplicaciones que ya tengamos desarrolladas con WF3.
Nota: En esta nueva versión se han revisado el núcleo del modelo de programación, el runtime y las herramientas.
Diseñadores
El diseñador de workflows es la parte más visible de Workflow Foundation, y para el equipo de Visual Studio 2010
los objetivos principales en este sentido han sido la usabilidad y el rendimiento. Los diseñadores de actividades
están basados en Windows Presentation Foundation (WPF), aprovechando todas las capacidades que éste aporta.
A partir de ahora, podremos definir en XAML nuestras actividades, para luego verlas e interactuar con ellas. Una
novedad muy interesante es la posibilidad de alojar (host) el diseñador en nuestras aplicaciones, de forma que
nuestros los usuarios puedan interactuar con los flujos de trabajo de una manera mucho más fácil y natural.
Flujo de datos
En WF3, el flujo de datos dentro de un workflow era algo oscuro. WF4 nos ofrece un modelo de flujo de datos
mucho más claro y conciso en el uso de parámetros y variables. Estos conceptos, que son familiares a los
desarrolladores, simplifican tanto la definición del almacén de datos como su viaje a través de flujos y actividades.
Este nuevo modelo, a la vez, hace más obvias las entradas y salidas esperadas de una actividad, y mejora el
rendimiento del runtime en la medida en que los datos son administrados con más eficiencia.
Diagramas de flujo
En WF4 aparece una nueva actividad de control de flujo llamada Flow- Chart, de manera que los desarrolladores
puedan definir un workflow usando el modelo de diagramas de flujo, algo mucho más similar y cercano a los
conceptos que muchos analistas y desarrolladores manejan habitualmente cuando crean soluciones o diseñan
procesos de negocio, por lo que tenía sentido proveer de una actividad que hiciese más sencillo modelar este
concepto. Este nuevo control permite trabajar con operaciones como volver a pasos anteriores, dividir la lógica en
base a una condición, etc.
Modelo de programación
En WF4, se renueva el modelo de programación de Workflow Foundation para hacerlo más simple y más robusto.
La clase base en este modelo de programación es WorkflowElement, que sirve para representar tanto workflows
como actividades. Además, ya no necesitamos crear un Workflow- Runtime para invocar a un workflow; tan solo
necesitamos crear una instancia del flujo y ejecutarla, lo que simplifica la creación de tests unitarios y elimina la
necesidad de crear un entorno apropiado cada vez que queremos instanciar un flujo.
Flowchart. Es un contenedor de pasos del workflow. Cada paso puede ser una actividad o cualquiera de los
siguientes elementos de esta lista, que para ser ejecutados deberán estar conectados dentro del flowchart.
FlowDecision. Es un bifurcador lógico basado en una condición.
FlowSwitch. Permite varias ramas de ejecución basadas en una expresión.
FlowStep. Representa un paso en el flujo de ejecución, con la posibilidad de estar conectado a otros pasos.
Es importante darse cuenta de que, mientras que hay actividades específicas para este modelo de flowchart,
podemos usar otras actividades en el workflow. Una actividad de tipo flowchart se puede añadir a otra actividad para
que aporte la semántica de ejecución y diseño de un diagrama de flujo. Es decir, podemos tener una secuencia con
muchas actividades y un flowchart justo en el medio.
La actividad Interop
Para aquellos que tenemos workflows y actividades ya definidos en WF3, la actividad Interop puede sernos muy útil
para reusar lo que ya tenemos hecho. Esta actividad nos permite incorporar a un modelo de WF4 las actividades
que ya tengamos definidas bajo un modelo WF3, mapeando las propiedades que tengamos como parámetros en el
modelo de WF4. Al ser estas propiedades parámetros, podremos utilizar expresiones para definir valores. En la
figura 4 se muestra la configuración de una actividad Interop que llama a una actividad de WF3. Los parámetros son
definidos a través de referencias a variables definidas en el workflow.
Actividades de "mensajería"
Uno de los puntos más importantes en WF4 es la mejora en la integración de WF y WCF. Desde el punto de vista de
los workflows, esto se traduce en tener actividades que modelen diferentes operaciones de "mensajería", tales como
enviar o recibir mensajes. Actualmente hay varias actividades para ello, cada una con una funcionalidad y sentido
algo diferentes:
Send/Receive. Actividades de un solo sentido para enviar o recibir mensajes. Estas actividades se componen
de interacciones petición/respuesta.
ReceiveAndSendReply. Modela una operación que recibe un mensaje y devuelve una respuesta.
SendAndReceiveReply. Invoca a un servicio y recibe la respuesta.
SendParameters/ReceiveParameters. Invoca o implementa una operación de servicio usando varios
parámetros.
Para hacer una llamada a un método de un servicio desde un workflow, seguiremos los pasos normales de
añadir una referencia al servicio a nuestro proyecto de Workflow Foundation. Visual Studio creará una actividad
personalizada para cada método que se encuentre en el contrato del servicio. Podéis pensar en esto como algo
similar a un proxy WCF para WF. Por ejemplo, si disponemos de un servicio que busca reservas de hoteles con
el contrato que se muestra en el listado 1, al añadir una referencia a él nos aparecerá una actividad
personalizada como la de la figura 5.
[ServiceContract]
public interface ISearchHotels
{
[OperationContract]
List<HotelSearchResult> SearchHotels( HotelSearchRequest
requestDetails);
}
Todo lo anterior y mucho más nos espera a partir del próximo abril; un sinfín de mejoras en cuanto a rendimiento,
productividad y facilidades a la hora de definir la lógica de negocio. Si quiere tener una visión más detallada de las
características que hemos presentado aquí, así como de algunas otras que se nos han quedado en el tintero, visite
Workflow Foundation 4 Beta 1.
InstallShield es una aplicación que permite generar instaladores de aplicaciones desde hace aproximadamente 20
años.
Hasta la versión 2008 de Visual Studio, existían plantillas propias de Instalador además de la posibilidad de publicar
las aplicaciones a través de ClickOnce.
Con Visual Studio 2010, se introdujo una versión Limitada de InstallShield dando a los desarrolladores nuevas
posibilidades, sin quitar las ya existentes.
Registrarnos en la página propietaria de Installshield . Lo cual lo podremos realizar desde el propio Visual
Studio
Descargar el paquete de InstallShield
Una vez descargado, será necesario reiniciar Visual Studio.
A continuación al agregar un nuevo proyecto de tipo InstallShield nos dará la posibilidad de Activar la Edición
Limitada con el Serial que habrá llegado al email que utilizamos a la hora de realizar el registro.
Para comenzar a utilizar el setup, vamos a definir una solución en Visual Studio con un proyecto simple en el
lenguaje que deseéis, donde vamos a definir un botón, con un MessageBox.
A nuestra solución en Visual Studio, agregaremos un nuevo proyecto de tipo “InstallShield Limited Edition Project”.
Al agregar este nuevo proyecto, vamos a poder observar por un lado un asistente que nos permitirá definir el Setup,
y en el “Explorador de Soluciones”, en el proyecto que acabamos de crear aparecerá la estructura del Setup, la cual
detallaremos más adelante.
El asistente de Installshield
Dentro de esta pantalla podremos encontrarnos con una barra de botones que nos van a permitir, a lo largo de los
distintos pasos del asistente, por cada etapa, así como ir a un paso concreto, o volver a la pantalla de inicio del
asistente.
A continuación vamos a tratar cada uno de los pasos de manera individual:
Nombre de la Empresa.
Nombre de la Aplicación.
Versión de la Aplicación.
Página WEB de la empresa.
Además de lo indicado, podremos indicar el icono que se visualizará en el Panel de Control a la hora de agregar y
quitar programas. También podremos cambiar el directorio de Instalación por defecto.
Podemos especificar si la aplicación necesita algún Sistema Operativo concreto para funcionar, o si necesitamos
algún Software para que funcione.
En el caso de necesitar un Software distinto, podemos especificar el mensaje de error que aparecerá durante la
instalación.
También podremos definir acciones personalizadas como son:
Este paso no se encuentra disponible para la Edición Limitada de Installshield para Visual Studio.
Application Files(Ficheros)
Esta etapa del asistente nos permitirá establecer los ficheros de nuestra aplicación que se van a guardar en cada
directorio:
Directorio de la aplicación.
Carpeta de datos comunes.
Datos de aplicación.
Directorio Temporal.
…
Tendremos la opción de elegir los ficheros de manera manual, añadir carpetas, o elegir que nos copie el resultado
de otro proyecto.
A través de este paso, podremos especificar los accesos directos que queremos que se generen a la hora de
instalar la aplicación.
Para ello, será necesario que indiquemos el fichero Ejecutable al cual se va a acceder. Vamos a disponer de la
posibilidad de agregar un Acceso Directo al Escritorio o al menú inicio de la aplicación. Además de ello, podremos
modificar el Icono del Acceso directo, e incluso asociar una extensión para que por defecto se habrá con nuestra
aplicación.
El asistente nos va a facilitar mucho el trabajo a la hora de definir nuestro instalador pero podemos agregar otras
características que no se observan con el asistente.
Como indicaba al principio, en el explorador de soluciones de Visual Studio, vamos a poder observar el proyecto de
tipo “InstallShield”, con una estructura como la que se puede observar en la imagen:
El proyecto va a constar de los siguientes 6 apartados:
Podremos indicar directorios donde se van a almacenar los ficheros ejecutables, DLL, Base de Datos… Además de
ello, dispondremos de la opción de indicar los ficheros redistribuibles que se van a instalar con el Setup, así como el
orden de instalación de los mismos. 3 Configure Target System (Configuración del equipo de Destino)
En esta sección se van a poder definir las siguientes características con respecto del equipo del usuario:
Nos va a facilitar un poco el trabajo al predefinir estos formatos a la hora de realizar nuestras entregas.
creo que es un acierto por parte de Microsoft la inclusión de este tipo de instalador dentro de Visual Studio.
Es una gran alternativa a los proyectos de instalación que ya brindaba Visual Studio, que podían quedarse algo
cortos para determinadas circunstancias.
El hecho de ser una edición limitada, va a provocar que algunas características que podrían ser de utilidad no estén
disponibles.
http://www.programasprogramacion.com/
.
http://www.programas-gratis.net/descargar-bajar/manuales-tutoriales-programacion
http://www.iworld.com.mx/iw_specialreport_read.asp?iwid=5428&back=1
http://www.monografias.com/trabajos/objetos/objetos.shtml
http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos
C++ y Java como programar, Deitel & Deitel, edición 4.
Programación orientada a objetos, Luis Joyanes Aguilar, edición 1
En este documento se detalla los diferentes herramientas de programación dinámica tales como ASP,PHP,
JAVASCRIPT otros, sus características y funciones primarias. Así mismo ejemplos practicos de asociación e
integridad hompogenea.
http://forum.wordreference.com/showthread.php?t=16428
http://www.itcio.es/desarrollo-personal/analisis/1000598004202/trasfondo-curso-estrategico.2.html
http://www.itcio.es/desarrollo-personal/analisis/1000598004202/trasfondo-curso-estrategico.2.html
http://candadodigital.blogspot.com/2007/10/la-funcin-de-seguridad-informtica-en-la.html
Describe de manera practica la programacon orientada a objetos y la rpgramacion dinámica enfocada a nivel de
servidor y a nivel de cliente.
http://www.mailxmail.com/cursos-programacion
http://www.gratisprogramas.org/descargar/50-libros-de-programacion/
http://www.descargarte.net/search/curso+programacion+en+java/
Realizado lo anterior, debe realizar los talleres que se encuentran en la plataforma, escritos en letra arial 12,
sobre los talleres 1, 2,3,4,5,6.estos deberán ser enviados al tutor a más tardar el último día de la sexta semana
del desarrollo del módulo, a través del correo electrónico.
Actividades previas. Desarrollar las lecturas requeridas, complementarias y observar los videos.
Competencias o indicador de competencias. Conocer el funcionamiento de los diferentes lenguajes de
programación.
Producto a entregar. Taller 1: java; taller 2: C++; taller 3: ASP; taller 4: PHP; taller 5: javascript; taller 6:
VBscript.
El estudiante deberá implementar en cada uno de los programas propuestos, un programa que permita
leer su nombre y apellido; cedula identificación; sueldo básico y descuentos.
Cada taller debe guardarse con el nombre del programa utilizado.
Fecha de inicio y limite.
Fecha inicio: Primer día de la tercera semana
Fecha entrega: Último día de la sexta semana
Porcentaje de valoración. 40%
Una vez resuelto el cuestionario, cada uno de los participantes deberá participar en uno de los grupos
conformados por el tutor. En cada grupo los participantes socializaran el cuestionario anterior, unificaran criterios
y elaboraran un documento con respuestas comunes a cada pregunta la cual se publicará en el foro para ser
socializado.
Actividades previas. Desarrollar las lecturas requeridas, complementarias y observación de los videos.
Competencias o indicador de competencias. Utilizar las herramientas de la programación OO y dinámica para
implementar aplicaciones de entorno empresarial.Utilizar las aplicaciones necesarias para mejorar el rendimiento
de los equipos de cómputo. Compartir el desarrollo del trabajo. Participar activamente y tratar con respeto las
opiniones y posturas de los demás participantes.
Producto a entregar. El documento publicado en la plataforma (foro) con las respuestas.
Fecha de inicio y limite.
Fecha inicio: Primer día de la semana siete
Fecha final: Último día de la semana diez
Porcentaje de valoración. 20%
Identifique
las
necesidade
s de la
empresa
Conozca las Participaci Actividad Consulta Plataforma,
funciones ón de la autónoma y individual chat y blog
de los actividad colaborativa
diferentes en el foro
sistemas
operativos
Desempeño
Expone las
funcionalida
des de
herramienta
s de
escritorio,
aplicaciones
específicas
y utilitarios
Talleres Document Actividad Elaboración Documento
Producto o escrito Colabora del para
Documento tiva y cuestionario participar en
con Acompa en grupo el foro e
respuestas ñamiento plataforma
del del tutor
cuestionario
EVALUACIÓN DE APRENDIZAJES
Lenguajes de programacion
Unidad II
Horas trabajo Horas
Actividad de de trabajo
acompañamiento autónomo
Lectura comprensiva de los
documentos.
Observación de los cuatro videos.
Elaboración de taller 1, taller 2 y 6 8
taller 3.
Trabajo en grupo 3
7. GLOSARIO
En redes locales se entiende como el software que configura un PC como servidor para facilitar el acceso a la red y
sus recursos.
Los Servidores almacenan información en forma de páginas web y a través del protocolo HTTP lo entregan a
petición de los clientes (navegadores web) en formato HTML.
Interacción: Acción que se ejerce recíprocamente entre dos o más objetos, agentes, fuerzas, funciones
Diccionario de la lengua española, (2011). (Vigésima segunda edición). Consultado el 14 de enero de 2011.
Disponible en http://buscon.rae.es/draeI/..
Multiusuario: También llamado multipuesto. Es un tipo de configuración que permite soportar a varios usuarios o
puestos de trabajo al mismo tiempo, de forma que el sistema operativo gestiona la simultaneidad, otorgando a cada
usuario todos los recursos necesarios.
Operador: Se denomina operario a las personas, hombres o mujeres que realizan una tarea determinada,
generalmente de carácter técnico y que es recompensada mediante el pago de un salario.
Enciclopedia libre wikipedia. Consultado el 14 de enero de 2011. Disponible en http://es.wikipedia.org/wiki/Operario.
Se consideran periféricos tanto a las unidades o dispositivos a través de los cuales la computadora se comunica con
el mundo exterior, como a los sistemas que almacenan o archivan la información, sirviendo de memoria auxiliar de
la memoria principal.
Se entenderá por periférico al conjunto de dispositivos que, sin pertenecer al núcleo fundamental de la computadora,
formado por la CPU y la memoria central, permitan realizar operaciones de entrada/salida (E/S) complementarias al
proceso de datos que realiza la CPU. Estas tres unidades básicas en un computador, CPU, memoria central y el
subsistema de E/S, están comunicadas entre sí por tres buses o canales de comunicación.
8. BIBLIOGRAFIA
PARSONS, Jamrich, OJA Dan. (1999).Conceptos Básicos de computación (2da edición). International Thomson
Editores.
Hardware y software sistema informático. Disponible en http://pdf.rincondelvago.com/hardware-y-
software_sistema-informatico.html (Consultado el 28/12/2010).
IES Pedro Espinosa, Antequera. Video sobre la historia del hardware. Disponible en
http://aulasimm.wordpress.com/2008/11/05/video-sobre-la-historia-del-hardware/. (Consultado el 28/12/2010).
Hardware y software sistema informático. Disponible en http://pdf.rincondelvago.com/hardware-y-
software_sistema-informatico.html (Consultado el 28/12/2010).
P., Hernández S,José, Análisis de Desempeño de 3 Sistemas Operativos1 en un computador personal con recursos
de hardware limitados (marzo de 2009). Disponible en http://www.linux-
magazine.es/Readers/white_papers/Comparativa_SOs_Mac_OSX_Ubuntu_Windows_7.pdf . (Consultado el
28/12/2010).
FERRER, Jorge, Fernández Sanguino, Javier, Hispalinux, seguridad informática y software libre. Disponible en
http://lucas.hispalinux.es/Informes/informe-seguridad-SL/informe-seguridad-SL.pdf. (Consultado el 28/12/2010).