Simplificando un poco el asunto, podemos distinguir dos tipos de
ventanas en un entorno gráfico (a los que intenta imitar Turbo Vision):
modales y no modales.
¿Suena raro? Con un par de ejemplos seguro que se verá
claro del todo. Vamos a fijarnos en el lector del curso. podemos tener
abiertas a la vez varias ventanas con textos de distintas lecciones, y
saltar de una o otra, pasearnos por el menú, etc. Son ventanas
no
modales. En cambio, accedemos a alguna de las opciones de ayuda,
pulsando F1 por ejemplo, no podemos acceder al menú ni a las demás
ventanas que hayamos abierto, a no ser que cerremos la actual. Es
una ventana modal.
Insisto en que todo esto está simplificado. Y ahora voy a hacer una simplificación más: esas ventanas no modales es lo que llamaré "ventanas de texto", y las veremos en el siguiente apartado; las ventanas modales como las de ayuda son las que llamaré "ventanas de diálogo".
Esto no es del todo cierto: podemos hacer que ventanas como los InputBox y MessageBox que hemos visto no sean modales, y que una ventana de texto sí lo sea, pero eso me lo salto... al menos de momento.
Volvamos a lo práctico. Hemos visto cómo usar algunas ventanas predefinidas de Turbo Vision, que casi "se creaban solas". Ahora vamos a ver cómo crearlas nosotros.
Deberemos crear una ventana de diálogo y ejecutarla. Primer
ejemplillo, directamente:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de diálogo }
{ en Turbo Vision - 1 }
{ DLG1.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Dlg1;
uses App, Objects, Menus, Drivers, Views, Dialogs;
{ ^ Incluimos esta Unit }
const
cmDialogo = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Dialogo;
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-D~ Diálogo', kbAltD, cmDialogo,
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 }
cmDialogo: Dialogo;
end;
end;
procedure Programa.Dialogo;
var
R: TRect; { El "rectángulo" que ocupará }
D: PDialog; { La ventana en sí }
begin
R.Assign(10,10,30,20); { Definimos la zona de pantalla }
D := New(PDialog, { Inicializamos: nuevo diálogo }
Init(R, 'Prueba')); { en la zona R, y título Prueba }
ExecuteDialog(D,nil); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Hemos creado una ventana de diálogo, pero estaba vacía. Ahora vamos a hacer que tenga algo en su interior.
Para hacer que tenga algo en su interior, bastará con
crear un nuevo rectángulo y añadirlo antes de ejecutar el
diálogo:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de diálogo }
{ en Turbo Vision - 2 }
{ DLG2.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Dlg2;
uses App, Objects, Menus, Drivers, Views, Dialogs;
const
cmDialogo = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Dialogo;
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-D~ Diálogo', kbAltD, cmDialogo,
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 }
cmDialogo: Dialogo;
end;
end;
procedure Programa.Dialogo;
var
R: TRect; { El "rectángulo" que ocupará }
D: PDialog; { La ventana en sí }
begin
R.Assign(10,10,30,20); { Definimos la zona de pantalla }
D := New(PDialog, { Inicializamos: nuevo diálogo }
Init(R, 'Prueba')); { en la zona R, y título Prueba }
R.Assign(2,2,10,5); { Definimos una zona interior }
D^.Insert(New(PStaticText, { e insertamos texto en ella }
Init(R, 'Prueba de texto estático')));
ExecuteDialog(D,nil); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Se va complicando, ¿verdad? }:-)
Ahora que ya sabemos cómo "tener cosas" en un diálogo,
vamos ver cómo poner varias cosas de interés ;-) , por ejemplo
botones y líneas de introducción de texto:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de diálogo }
{ en Turbo Vision - 3 }
{ DLG3.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Dlg3;
uses App, Objects, Menus, Drivers, Views, Dialogs;
const
cmDialogo = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Dialogo;
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-D~ Diálogo', kbAltD, cmDialogo,
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 }
cmDialogo: Dialogo;
end;
end;
procedure Programa.Dialogo;
var
R: TRect; { El "rectángulo" que ocupará }
D: PDialog; { La ventana en sí }
begin
R.Assign(0,0,50,15); { Definimos el tamaño }
R.Move(15,5); { y la posición }
D := New(PDialog, { Inicializamos: nuevo diálogo }
Init(R, 'Más vistoso')); { en la zona R, y título Prueba }
R.Assign(2,2,20,3); { Definimos una zona interior }
D^.Insert(New(PStaticText, { e insertamos texto en ella }
Init(R, 'Esto es un texto estático')));
R.Assign(5,11,20,13); { Igual para el botón }
D^.Insert(New(PButton,
Init(R, '~A~dios', cmQuit, bfNormal)));
R.Assign(10,7,40,8); { Y para la línea de entrada }
D^.Insert(New(PInputLine,
Init(R, 50))); { de longitud 50 }
ExecuteDialog(D,nil); { Ejecutamos, sin parámetros }
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
Comentarios sobre este programa:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Ventanas de diálogo }
{ en Turbo Vision - 4 }
{ DLG4.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Free Pascal 2.2.0w }
{ - Turbo Pascal 7.0 }
{--------------------------}
program Dlg4;
uses App, Objects, Menus, Drivers, Views, Dialogs, MsgBox;
const
cmDialogo = 100; { La orden que vamos a crear }
type Programa = object (TApplication)
texto: string;
procedure InitStatusLine; virtual;
procedure HandleEvent(var Suceso: TEvent); virtual;
procedure Dialogo;
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-D~ Diálogo', kbAltD, cmDialogo,
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 }
cmDialogo: Dialogo;
end;
end;
procedure Programa.Dialogo;
var
R: TRect; { El "rectángulo" que ocupará }
D: PDialog; { La ventana en sí }
Enlace: PView; { Para la enlazar la etiqueta
con la InputLine }
begin
Texto := 'Texto por defecto'; { Texto inicial }
R.Assign(0,0,50,15); { Definimos el tamaño }
R.Move(15,5); { y la posición }
D := New(PDialog, { Inicializamos: nuevo diálogo }
Init(R, 'Más vistoso')); { en la zona R, y título Prueba }
R.Assign(2,2,20,3); { Definimos una zona interior }
D^.Insert(New(PStaticText, { e insertamos texto en ella }
Init(R, 'Esto es un texto estático')));
R.Assign(5,11,20,13); { Igual para el primer botón }
D^.Insert(New(PButton,
Init(R, '~C~ancelar', cmCancel, bfNormal)));
R.Assign(25,11,40,13); { Y para el segundo }
D^.Insert(New(PButton,
Init(R, '~A~ceptar', cmOK, bfDefault)));
R.Assign(10,7,40,8); { Y para la línea de entrada }
Enlace := New(PInputLine, Init(R, 50));
D^.Insert(Enlace);
R.Assign(9,6,30,7); { Y la etiqueta asociada }
D^.Insert(New(PLabel,
Init(R, 'Texto:', Enlace)));
ExecuteDialog(D,@Texto); { Ejecutamos, CON parámetros }
MessageBox('Ha tecleado: '+ Texto, { Y mostramos el resultado }
nil, mfInformation or mfOKButton);
end;
var Prog: Programa;
begin
Prog.Init;
Prog.Run;
Prog.Done;
end.
En un diálogo también podemos poner casillas de verificación de opciones, visores de listas, etc., pero eso lo dejo para que lo investigue quien tenga muchas inquietudes.
Diseñar diálogos "a pelo" puede ser algo muy pesado. En muchas BBS y en Internet podremos encontrar utilidades que nos permiten hacerlo de forma "visual", como DLGDSN (Dialog Design, de L. David Baldwin)
(Nota: todo esto está realizado con TP7; no lo he probado en TP6).