En el capítulo del
mes pasado
vimos los pasos
necesarios
a la hora de abrir
una pantalla,
sin embargo
todavía se puede
sacar un mayor
provecho de
la estructura
de pantalla. |
Los cuadernos del
Ensamblador
Por F. Javier Rodríguez |
|
CAPÍTULO X |
Una vez vista la estructura que devuelve el sistema cada vez que se abre una pantalla de usuario, nos damos cuenta de la flexibilidad con la que cuenta el Amiga para su programación. Pudieron comprobar en la tabal publicada de la estructura la existencia de unas cuantas direcciones que sin lugar a dudas pueden sernos de gran ayuda. En este capítulo nos detendremos a ver que es todo lo que podemos realizar con dicha información, y quizás podamos llegar a realizar un programa similar a 'Melt (1)' e incluso también podríamos llegar a realizar nuestro propio capturador de pantallas.
(1) Melt es un programa de dominio público que simula el derretimiento de la pantalla WorkBench, en alguna de las versiones de este programa puede considerarse como un Virus residente en memoria algo molesto.
Para ello lo primero que deberemos conocer es para qué sirve la primera palabra de la estructura de pantalla. En concreto esta contiene un puntero a la estructura de la siguiente pantalla abierta, en caso de que no se encuentre ninguna del tipo Custom esta será pantalla WorkBench. Otras direcciones de gran utilidad dentro de esta estructura es la que nos indica la resolución y dimensiones de la pantalla en cuestión, así como el offset de desplazamiento sobre el cual se encuentra abierta. Como podrán deducir, también es la primera palabra de la siguiente estructura la que apunte a la siguiente; así hasta que en dicha posición de la estructura se encuentre el valor cero.
Ahora es el momento para pasar a ver la forma de 'interceptar' una pantalla, para ello tendremos que utilizar la estructura de pantalla. El primer paso que debemos realizar es cargar en un registro el puntero a la siguiente estructura de pantalla; las dos líneas siguientes de programa se encargan de realizar esta tarea:
 |
move.l screenhd,a0 ;Cargamos puntero de estructura.
move.l $0(a0),a0 ;Cargamos puntero a siguiente
;estructura de pantalla en el mismo
;registro (ubicado en la estructura
;con el offset = 0).
|
 |
A partir de esta operación tendremos en el registro A0 el puntero a la nueva estructura de pantalla; generalmente la primera siempre es WorkBench, a no ser que se encuentren otras pantallas abiertas por encima del WorkBench.
A continuación podremos acceder a los datos que nos interesan, tales como ancho y alto de la pantalla, número de bitplanes, offset de desplazamiento con respecto a la esquina superior izquierda y lo que es más importante; ubicación de los bitplanes de dicha pantalla.
En el caso concreto del programa 'Melt' se puede prescindir de unos cuantos parámetros, ya que se saben datos fijos a cerca de la pantalla WorkBench; tales como ancho y alto, modo de representación, número de bitplanes (a no ser que se utilicen los programas que circulan en el dominio público encargados de aumentar el número de colores de la pantalla WorkBench), y offset de desplazamiento. De esta forma sólo es necesario leer las direcciones que apuntan a los dos BitPLanes que la componen, para ello al igual que en el caso anterior leeremos los correspondientes offsets de su estructura:
move.l $c0(a0),bitplane1 move.l $c4(a0),bitplane2 |
Mediante estas dos líneas se cargan los vectores que apuntan a los dos BitPlanes que componen la pantalla del WorkBench. El siguiente paso que se debe realizar es calcular el algoritmo mediante el cual se 'derretirán' los planos de la pantalla. En esta ocasión lo realizaremos de una forma sencilla, aunque el usuario podrá complicarlo para dar una mayor sensación de que la pantalla efectivamente se está derritiendo.
En nuestro caso primeramente copiaremos el contenido de la pantalla WorkBench a la nuestra propia, para realizar las posteriores operaciones en esta. Para ello debemos calcular el número de Bytes que deben ser leídos:
 |
Ancho = 640
Altura = 256
n� BitPlanes = 2
640/8 = 80
80*256 = 20480
20480 * 2 = 40960
|
 |
Una vez realizada esta operación sabemos que necesitamos copiar un total de 40960 Bytes. Para agilizar el proceso, copiaremos los datos con una longitud de palabra, con lo cual debemos dividir este valor entre cuatro;
Ahora ya tenemos el valor real de datos con el cual deberemos trabajar. Para copiar la pantalla del WorkBench es necesario leer los datos de la misma hacia la nuestra propia, por lo que debemos conocer los vectores que apuntan a nuestros BitPLanes. Para ello realizaremos la siguiente operación:
 |
move.l screenhd,a0
move.l $c0(a0),BP1C
move.l $c4(a0),BP2C
BP1C = BitPlane 1 Custom
BP2C = BitPlane 2 Custom
|
 |
Ahora debemos cargar los primeros vectores de cada pantalla en sendos registros; no es necesario cargar los cuatro puesto que los segundos BitPlanes de cada pantalla son correlativos a los primeros. La siguiente rutina es la encargada de copiar la pantalal WorkBench en la nuestra (CUstom):
 |
move.l bitplane1,a0
move.l BP1C,a1
move.l #10240-1,d0
loop: move.l (a0)+.(a1)+
dbra d0,loop
|
 |
Cuando esta rutina se haya ejecutado, nuestra pantalla contendrá la misma imagen que la pantalla WorkBench, ahora es cuando podrá realizar la rutina encargada de grabar esta a disco (con lo cual se habrá hecho un minicapturador) o bien realizar un programa tipo Melt; en definitiva podrá realizar con los datos de la misma todo lo que quiera.
Sin embargo con las pantallas Custom no sólo podemos realizar este tipo de operaciones, sino que con las funciones contenidas en las librerías, varias vistas en 'Las Librerías del Amiga', podremos realizar operaciones tales como pasar la pantalla al fondo, a primer plano, mover con respecto a su eje X, etc.
En concreto varias de las funciones de la librería Intuition, relacionadas con operaciones de pantalla son las siguientes: OpenScreen(), CloseScreen(), DisplayBeep(), GetScreenData, MakeScreen(), MoveScreen(), OpenWorkBench(), CloseWorkBench(), ScreenToBack(), ScreenToFront(), ShowTitle(), WBenchToBack() y WBenchToFront().
Ventanas: una 'zona' de trabajo
Un elemento muy importante y al cual ya estamos acostumbrados, por su continuado uso en el Amiga, son las ventanas. Podemos decir que estas sirven para 'separar' varias zonas de trabajo en un mismo programa o para separar programas entre si. Al igual que las pantallas Custom, las ventanas resultan muy flexibles, siendo estas las que a su vez pueden contener diversos elementos del Intuition como es el caso de los Gadgets, Requesters o lo que es más importante: los menús (en este mismo número se incluye un interesante artículo explicando la estructura de los mismos).
Una característica de las ventanas es que estas pueden abrirse o visualizarse en cualquier tipo de pantalla (incluida la pantalla WorkBench), además de poder redimensionarse o desplazar la misma a lo largo de la pantalla.
Al igual que las pantallas Custom, hay que informar al Intuition de diversos parámetros mediante la correspondiente estructura. Esta tiene algunos parámetros que también son necesarios en las pantallas Custom, tales como ancho y alto de la ventana, offset de desplazamiento, etc.
A continuación podrá ver la estructura necesaria para definir la ventana en cuestión, así como informar al Intuition de dónde se abrirá la misma:
 |
| Número |
Tamaño |
Definición |
| 0 |
W |
Esquina superior izquierda relativa a la posición de la pantalla. |
| 2 |
W |
- |
| 4 |
W |
Ancho y alto de la ventana (en Pixels). |
| 6 |
W |
- |
| 8 |
B |
Color para el primer plano. |
| 9 |
B |
Color de fondo. |
| 10 |
L |
Flags IDCMP. Tratamiento del Intuition (VER CUADRO 1). |
| 14 |
L |
Flags para definición de la ventana (VER CUADRO 2). |
| 18 |
L |
Puntero a primer Gadget de ventana. |
| 22 |
L |
Puntero al gráfico de Selección. |
| 26 |
L |
Puntero al texto para título de la ventana. |
| 30 |
L |
Puntero a la pantalla sobre la cual se abre la ventana. |
| 34 |
L |
Puntero al BitMap de ventana. |
| 38 |
W |
Ancho mínimo de la ventana. |
| 40 |
W |
Altura mínima de la ventana. |
| 42 |
W |
Ancho máximo de la ventana. |
| 44 |
W |
Altura máxima de la ventana. |
| 46 |
W |
Tipo de ventana. |
|
 |
| CUADRO 1. |
Flags de Control IDCMP. |
| Bit |
Valor |
Descripción |
| 0 |
$000001 |
Comprueba tamaño. |
| 1 |
$000002 |
Nuevo tamaño. El Intuition envía mensaje si se altera tamaño. |
| 2 |
$000004 |
Refresco de Ventana. |
| 3 |
$000008 |
Pulsación del ratón. El Intuition envía mensaje si se pulsa cualquier botón del ratón. |
| 4 |
$000010 |
Movimiento del ratón. El Intuition envía mensaje si se mueve el ratón. |
| 5 |
$000020 |
Gadget activado. El Intuition envía mensaje si se ha pulsado un Gadget especial. |
| 6 |
$000040 |
Gadget desactivado. Lo mismo que el caso anterior. |
| 7 |
$000080 |
Activación del Requester. |
| 8 |
$000100 |
Elección de una opción del menú. El Intuition devuelve mensaje si se ha seleccionado alguna opción del menú. |
| 9 |
$000200 |
Cerrar ventana. El Intuition envía un mensaje si se cierra la ventana. |
| 10 |
$000400 |
Comprobación del teclado. El Intuition envía mensaje si se pulsa una tecla. |
| 11 |
$000800 |
Verificar Requester. |
| 12 |
$001000 |
Borrar Requester. |
| 13 |
$002000 |
Verificación del menú. |
| 14 |
$004000 |
Modificación en las opciones del Preferences. |
| 15 |
$008000 |
Comprobación de disco insertado. El Intuition envía un mensaje si se ha insertado un disco en cualquier unidad. |
| 16 |
$010000 |
Comprueba si se ha sacado un disco de cualquier disquetera. El Intuition envía mensaje si el disco ha sido sacado de cualquier disquetera. |
| 17 |
$020000 |
La ventana muestra los mensajes en la pantalla WorkBench. |
| 18 |
$040000 |
Comprueba la activación de una ventana. El Intuition envía un mensaje si la ventana ha sido activada. |
| 19 |
$080000 |
Comprueba si una ventana está desactivada. El Intuition envía un mensaje si la ventana ha sido desactivada. |
| 20 |
$100000 |
Movimiento relativo del ratón. El Intuition envía un mensaje en caso de que se haya movido el ratón. |
|
Al igual que en el caso de definición y apertura de la pantalla, necesitamos acceder a una función de Intuition para abrir la ventana. Dicha función es OpenWindow(), a la cual se accede mediante el offset -204. Es necesario saber que antes de abrir una ventana deberá abrirse una pantalla, en el caso de que se desee situar sobre una pantalla Custom, o que se encuentre abierto (activo) el WorkBench. Una vez esta se encuentra abierta mediante la correspondiente rutina (sirva la del mes pasado), podremos abrir la ventana. Como ejemplo, a continuación, les mostraré la rutina que se encarga de abrir la ventana propipamente dicha:
 |
; Abrir Ventana sobre la pantalla Custom.
OpenWindow = -204
lea windefs,a0
jsr OpenWindow(a6)
beq error
move.l D0,winhd
.
.
.
windefs: dc.w 0
dc.w 0
dc.w 320
dc.w 256
dc.b 0
dc.b 1
dc.w 0
dc.l $1008
dc.l 0
dc.l 0
dc.l wintitle
screenhd: dc.l 0
dc.l 0
dc.w 0
dc.w 0
dc.w 320
dc.w 256
dc.w 15
winhd: dc.l 0
wintitle: dc.b 'Mi ventana',0
|
 |
Una vez ejecutada esta rutina se nos devolverá en D0 el vector que apunta a un bloque de datos sobre la ventana abierta (usualmente llamada Handler), como podrán recordar esta misma operación era resultado de abrir una pantalla, en el caso de que esta no haya podido abrirse por cualquier motivo, el registro D0 devolverá el valor cero; con lo cual se saltará a la rutina encargada de tratar el error. Hay que tomar una precaución muy especial, ya que si las dimensiones de la ventana son mayores que la de la pantalla sobre la cual se dese abrir, o el offset de desplazamiento sobrepasa las dimensiones de la pantalla, o las definidas como máximo en la ventana, se producirá un error al abrir la misma.
En concreto los datos de control para la ventana, resultante de la operación OpenWindow(), son muy útiles. A continuación se muestran los mismos en forma de offset con respecto a la dirección base del Handler:
 |
| Offset |
Tamaño |
Descripción |
| 0 |
L |
Puntero a la siguiente ventana de la pantalla. |
| 4 |
W |
Posición del margen superior e izquierdo de la ventana. |
| 6 |
W |
- |
| 8 |
W |
Ancho y altura de la ventana el Pixels. |
| 10 |
W |
- |
| 12 |
W |
Posición del ratón relativa a la ventana (Y/X). |
| 14 |
W |
- |
| 16 |
W |
Ancho mínimo de la ventana. |
| 18 |
W |
Altura mínima de la misma. |
| 20 |
W |
Ancho máximo de la ventana. |
| 22 |
W |
Altura máxima de la misma. |
| 24 |
L |
Flags de la ventana. |
| 28 |
L |
Puntero a la estructura de menú de esta ventana. |
| 32 |
L |
Puntero al texto de título en la ventana. |
| 36 |
L |
Puntero al primer Requester de la ventana. |
| 40 |
L |
Puntero al doble menú Requester de la ventana. |
| 44 |
W |
Número de Requester abiertos sobre la ventana. |
| 46 |
W |
Vector que apunta a la pantalla WorkBench. |
| 50 |
L |
Puntero a RastPort de la ventana. |
| 62 |
L |
Puntero al primer Gadget en la ventana. |
| 66 |
L |
Puntero a ventana previa. |
| 70 |
L |
Puntero a ventana siguiente. |
| 74 |
L |
Puntero al gráfico del puntero. |
| 98 |
B |
Color para primer plano. |
| 99 |
B |
Color de fondo. |
| 100 |
L |
Puntero a gráfico para marca deseleccionado. |
| 104 |
L |
Puntero a texto de título de pantalla. |
|
 |
| CUADRO 2. |
Flags para definición de Ventana. |
| Bit |
Valor |
Descripción |
| 0 |
$000001 |
El tamaño de la ventana podrá alterarse. |
| 1 |
$000002 |
La ventana podrá desplazarse por la pantalla. |
| 2 |
$000004 |
La ventana dispondrá de Gadgets de profundidad. |
| 3 |
$000008 |
La ventana dispondrá del Gadget para cerrar la misma. |
| 4 |
$0000010 |
La ventana dispondrá de barra de Slider horizontal. |
| 5 |
$0000020 |
La ventana dispondrá de barra de Slider vertical. |
| 6 |
$0000040 |
Refresco de la ventana simple. |
| 7 |
$0000080 |
Super_Bitmap. Salvará el contenido de la ventana al ser 'pisada' por otra. |
| 8 |
$0000100 |
La ventana aparecerá detrás de las demás. |
| 9 |
$0000200 |
Devuelve las coordenadas del ratón. |
| 10 |
$0000400 |
Ventana Gimmezerozero. |
| 11 |
$0000800 |
Ventana sin bordes. |
| 12 |
$0001000 |
Ventana activada. |
| 25 |
$2000000 |
Ventana WorkBench. |
|
Como puede observar, la información contenida en este Handler es mucho más amplia que en el caso de la pantalla. Obviamente se pueden realizar muchas más operaciones actuando en base a estos datos. En el próximo capítulo mostraremos varios ejemplos, además de explicar diversos conceptos que aparecen contenidos en la estructura de ventana. En el cuadro 'LISTADO 1' se encuentra el programa completo, encargado de abrir una ventana (sin Gadgets ni marco) sobre una pantalla Custom.
Como puede observar, la información contenida en este Handler es mucho más amplia que en el caso de la pantalla. Obviamente se pueden realizar muchas más operaciones actuando en base a estos datos. En el próximo capítulo mostraremos varios ejemplos, además de explicar diversos conceptos que aparecen contenidos en la estructura de ventana. En el cuadro 'LISTADO 1' se encuentra el programa completo, encargado de abrir una ventana (sin Gadgets ni marco) sobre una pantalla Custom. |
Una características
de las ventanas
es que estas
pueden abrirse
o visualizarse
en cualquier tipo
de pantalla
(incluida la pantalla
WorkBench). |
 |
LISTADO. 1
; ABRIR VENTANA USUARIO
;
; 7/6/91, Window V1.0
;
; (C) 1991, F. Javier Rodr�guez
;
; Esta rutina se encarga de abrir una pantalla y una ventana
; (Esta �ltima sin marco ni Gadgets).
;
execbase = 4
openlibrary = -408
closelibrary = -414
openscreen = -198
closescreen = -66
openwindow = -204
closewindow = -72
PANTA: move.l execbase,a6
lea intname,a1
jsr openlibrary(a6)
move.l d0,intbase
move.l intbase,a6
lea screendefs,a0
jsr openscreen(a6)
move.l d0,screenhd
WINDOW: lea windefs,a0
jsr openwindow(a6)
move.l d0,windowhd
beq error
loop: btst #6,$bfe001
bne.s loop
move.l windowhd,a0
jsr closewindow(a6)
error: move.l intbase,a6
move.l screenhd,a0
jsr closescreen(a6)
move.l intbase,a1
move.l execbase,a6
jsr closelibrary(a6)
rts
screendefs: dc.w 0
dc.w 0
dc.w 320
dc.w 256
dc.w 2
dc.b 0
dc.b 1
dc.w 2
dc.w 15
dc.l 0
dc.l sname
dc.l 0
dc.l 0
sname: dc.b 'Mi Pantalla',0
even
intname: dc.b 'intuition.library',0
even
windowhd: dc.l 0
intbase: dc.l 0
windefs: dc.w 120
dc.w 0
dc.w 160
dc.w 256
dc.b 1
dc.b 0
dc.l $0
dc.l $1800
dc.l 0
dc.l 0
dc.l windowname
screenhd: dc.l 0
dc.l 0
dc.w 320
dc.w 200
dc.w 320
dc.w 200
dc.w 15
windowname: dc.b 'Mi Ventana'
end
|
 |
|