Ya hemos visto cómo crear ventanas de diálogo, que "paralizan" al resto de la aplicación mientras estén activas.
Ahora veremos cómo crear ventanas más generales, no modales (podremos hacer otras cosas mientras estén visibles), que usaremos para mostrar textos en pantalla.
Tomando la base de "Dlg1", la aplicación con la que creamos la
primera ventana de diálogo, podemos hacer otra muy parecida, pero
que ahora use ventanas "normales":
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de texto }
{ en Turbo Vision - 1 }
{ VENT1.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Vent1;
uses App, Objects, Menus, Drivers, Views;
const
cmVentana = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Ventana;
end;
procedure Programa.InitStatusLine;
var
R: TRect; { Rectángulo de pantalla }
begin
GetExtent(R); { Miramos cuando ocupa }
R.A.Y := R.B.Y - 1; { Nos quedamos la línea inferior }
New(StatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('~Alt-S~ Salir', kbAltS, cmQuit,
NewStatusKey('~Alt-V~ Ventana', kbAltV, cmVentana,
nil)),
nil)));
end;
procedure Programa.HandleEvent(var Suceso: TEvent);
var
R: TRect;
begin
inherited HandleEvent(Suceso); { Primero que mire el "padre" }
if Suceso.What = evCommand then { Si es una orden }
case Suceso.Command of { Miramos qué orden es }
cmVentana: Ventana;
end;
end;
procedure Programa.Ventana;
var
R: TRect; { El "rectángulo" que ocupará }
W: PWindow; { La ventana en si }
begin
R.Assign(10,10,40,20); { Definimos el tamaño }
W := New(PWindow, { Inicializamos: nueva ventana }
Init(R, 'Prueba', { en la zona R, título Prueba }
wnNoNumber)); { y sin número de ventana }
InsertWindow(W); { La insertamos en nuestro programa }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Esta vez hemos creado una ventana de texto, que recuerda a las que usa
el entorno de Turbo Pascal cuando editamos nuestros programas. Como
hicimos en el apartado anterior, hemos empezado por una ventana vacía,
pero antes de añadir algo en su interior quiero remarcar un par
de cosas:
Así que antes de "llenar" la ventana, vamos a ver cómo
darle un número. Lo haré de una forma más o
menos estricta: podemos llevar cuenta del número de ventanas abiertas
en cualquier parte de nuestro programa, pero lo más correcto es
que sea nuestro objeto "Programa" quien lo gestione, así que le
voy a añadir un campo y voy a redefinir el constructor Init.
También haré que las ventanas aparezcan en posiciones aleatorias
de la pantalla, para que se vean mejor:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de texto }
{ en Turbo Vision - 2 }
{ VENT2.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Vent2;
uses App, Objects, Menus, Drivers, Views;
const
cmVentana = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
NumeroVent: byte; { Número de ventana }
constructor Init; { Vamos a ampliar el Init }
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Ventana;
end;
constructor Programa.Init; { Nuestra propia versión del Init }
begin
Inherited Init; { Que hará lo mismo que la inicial }
NumeroVent := 0; { Pero además prepara la variable }
end;
procedure Programa.InitStatusLine;
var
R: TRect; { Rectángulo de pantalla }
begin
GetExtent(R); { Miramos cuando ocupa }
R.A.Y := R.B.Y - 1; { Nos quedamos la línea inferior }
New(StatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('~Alt-S~ Salir', kbAltS, cmQuit,
NewStatusKey('~Alt-V~ Ventana', kbAltV, cmVentana,
nil)),
nil)));
end;
procedure Programa.HandleEvent(var Suceso: TEvent);
var
R: TRect;
begin
inherited HandleEvent(Suceso); { Primero que mire el "padre" }
if Suceso.What = evCommand then { Si es una orden }
case Suceso.Command of { Miramos qué orden es }
cmVentana: Ventana;
end;
end;
procedure Programa.Ventana;
var
R: TRect; { El "rectángulo" que ocupará }
W: PWindow; { La ventana en si }
begin
Inc(NumeroVent); { Una ventana más }
R.Assign(0,0,30,10); { Definimos el tamaño }
R.Move(random(50), random(13));
W := New(PWindow, { Inicializamos: nuevo diálogo }
Init(R, 'Prueba',NumeroVent)); { en la zona R, y título Prueba }
InsertWindow(W); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Ahora sí, ya vamos a escribir algo dentro de la ventana. Lo haremos exactamente igual que vimos para los diálogos, creando un rectángulo interior, que rellenaremos con "Static Text".
Como el tipo TStaticText está definido en la unidad Dialogs,
tendremos que añadirla en nuestra sección de "uses".
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de texto }
{ en Turbo Vision - 3 }
{ VENT3.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Vent3;
uses App, Objects, Menus, Drivers, Views, Dialogs;
const
cmVentana = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
NumeroVent: byte; { Número de ventana }
constructor Init; { Vamos a ampliar el Init }
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Ventana;
end;
constructor Programa.Init; { Nuestra propia versión del Init }
begin
Inherited Init; { Que hará lo mismo que la inicial }
NumeroVent := 0; { Pero además prepara la variable }
end;
procedure Programa.InitStatusLine;
var
R: TRect; { Rectángulo de pantalla }
begin
GetExtent(R); { Miramos cuando ocupa }
R.A.Y := R.B.Y - 1; { Nos quedamos la línea inferior }
New(StatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('~Alt-S~ Salir', kbAltS, cmQuit,
NewStatusKey('~Alt-V~ Ventana', kbAltV, cmVentana,
nil)),
nil)));
end;
procedure Programa.HandleEvent(var Suceso: TEvent);
var
R: TRect;
begin
inherited HandleEvent(Suceso); { Primero que mire el "padre" }
if Suceso.What = evCommand then { Si es una orden }
case Suceso.Command of { Miramos qué orden es }
cmVentana: Ventana;
end;
end;
procedure Programa.Ventana;
var
R: TRect; { El "rectángulo" que ocupará }
W: PWindow; { La ventana en si }
begin
Inc(NumeroVent); { Una ventana más }
R.Assign(0,0,30,10); { Definimos el tamaño }
R.Move(random(50), random(13));
W := New(PWindow, { Inicializamos: nuevo diálogo }
Init(R, 'Prueba',NumeroVent)); { en la zona R, y título Prueba }
R.Assign(2,2,10,5); { Definimos una zona interior }
W^.Insert(New(PStaticText, { e insertamos texto en ella }
Init(R, 'Prueba de texto estático')));
InsertWindow(W); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
También podremos insertar botones, líneas de estado, etc. en una ventana de texto como ésta, pero el manejo se complica mucho comparado con los diálogos que vimos en el apartado anterior.
Finalmente, vamos a ver cómo cambiar la apariencia y propiedades de una ventana de texto.
Las ventanas tienen una serie de "flags", cuyo nombre empieza por "wf" y que nos permiten modificar su comportamiento:
Recordemos que las ventanas tenían "botones" para hacer muchas
de estas cosas. Pero Turbo Vision ya lo tiene en cuenta: si
decimos que no se pueda cerrar una ventana, el botón de cierre no
aparecerá siquiera.
Un último detalle antes de pasar al ejemplo: estos flags se almacenan como bits de un byte, que es el campo "flags". Por ello, deberemos modificarlos con "and" u "or". Por ejemplo, para fijar el bit wfClose asegurarnos de que una se podrá cerrar, podemos usar
flags := flags or wfClose;
y para que no se pueda cerrar sería
flags := flags and not wfClose;
Ahora ya, vamos a ver cómo quedaría el programita:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de texto }
{ en Turbo Vision - 4 }
{ VENT4.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Vent4;
uses App, Objects, Menus, Drivers, Views, Dialogs;
const
cmVentana = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
NumeroVent: byte; { Número de ventana }
constructor Init; { Vamos a ampliar el Init }
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Ventana;
end;
constructor Programa.Init; { Nuestra propia versión del Init }
begin
Inherited Init; { Que hará lo mismo que la inicial }
NumeroVent := 0; { Pero además prepara la variable }
end;
procedure Programa.InitStatusLine;
var
R: TRect; { Rectángulo de pantalla }
begin
GetExtent(R); { Miramos cuando ocupa }
R.A.Y := R.B.Y - 1; { Nos quedamos la línea inferior }
New(StatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('~Alt-S~ Salir', kbAltS, cmQuit,
NewStatusKey('~Alt-V~ Ventana', kbAltV, cmVentana,
nil)),
nil)));
end;
procedure Programa.HandleEvent(var Suceso: TEvent);
var
R: TRect;
begin
inherited HandleEvent(Suceso); { Primero que mire el "padre" }
if Suceso.What = evCommand then { Si es una orden }
case Suceso.Command of { Miramos qué orden es }
cmVentana: Ventana;
end;
end;
procedure Programa.Ventana;
var
R: TRect; { El "rectángulo" que ocupará }
W: PWindow; { La ventana en si }
begin
Inc(NumeroVent); { Una ventana más }
R.Assign(0,0,30,10); { Definimos el tamaño }
R.Move(random(50), random(13));
W := New(PWindow, { Inicializamos: nuevo diálogo }
Init(R, 'Prueba',NumeroVent)); { en la zona R, y título Prueba }
R.Assign(2,2,10,5); { Definimos una zona interior }
W^.Insert(New(PStaticText, { e insertamos texto en ella }
Init(R, 'Prueba de texto estático')));
W^.flags := W^.flags and not (wfClose or WfGrow);
InsertWindow(W); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Como se ve, la ventana ya no tiene botón de cierre ni la esquina
inferior de redimensionado, pero sí que se la puede mover o ampliar
totalmente.
Pues con esto doy por finalizada la introducción a Turbo Vision. Con lo que hemos visto, uno ya puede hacer con una cierta facilidad que sus programas queden más "bonitos"... como mínimo.
El avanzar a partir de aquí, ya lo dejo a quien quiera. Con esta base confío en que asuste menos acercarse a fuentes que empleen Turbo Vision, o al manual de TP, o incluso a la ayuda en línea.
Incluyo un ejemplo, que sería nuestra super Agenda ;-), pasada a Turbo Vision. En ella se puede observar que he dibujado la ventana de texto de otra forma menos rígida que la que acabo de comentar: en vez de "insertar" texto estático, defino su interior como View y luego ya lo incluyo en la ventana. Esto es más versátil porque nos permite usar barras de desplazamiento, por ejemplo, pero también es bastante más complicado, y no sé si alguien lo llegará a usar, así que quien quiera trastear con ello, no tiene más que basarse en el ejemplo.
Si alguien quiere avanzar más y saber cómo poner también barras de desplazamiento y demás, le doy la pista clave: VIEWTEXT.PAS es un visor de texto, en el que me he basado yo para el lector de las primeras versiones del curso. Es uno de los ejemplos que trae Turbo Pascal 7, dentro del directorio
TP\EXAMPLES\TVFM
(o algo similar, según donde lo hayais instalado). Venga,
a jugar... :-)