Esta versión está basada en la segunda de la agenda.
La apariencia que tendrá esta versión será ésta:
Y el fuente podría ser así:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Agenda: versión para }
{ Turbo Vision }
{ AGENDATV.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Turbo Pascal 7.0 }
{--------------------------}
{ ========================================================
Ejemplito de Agenda, adaptado a Turbo Vision.
Basado en el segundo ejemplo (MiniAgenda2)
Nacho Cabanes, Junio 96, para CUPAS (Curso de Pascal)
======================================================== }
program MiniAgendaTV;
uses App, { Para objeto TApplication }
Drivers, { TEvent, por ejemplo }
Objects, { TRect, etc }
Menus, { Pues eso ;-) }
Views, { Vistas y hcXX }
MsgBox; { MessageBox, InputBox, etc }
{$V-}
{ Directiva de compilación: tamaño de strings no estricto (ver
ampliación 6). Para poder usar LeeValor con Strings de cualquier
tamaño }
const
nombref: string[12]='agenda.dat'; { Nombre del fichero }
longNOM = 20;
longDIR = 30;
longCIU = 15;
longCP = 5;
longTLF = 12;
longOBS = 40;
cmSaludo = 1001; { Las ordenes que podremos dar }
cmSalir = 1002;
cmNumero = 1005;
cmNuevo = 1006;
cmModifica = 1007;
cmBusca = 1008;
cmAnterior = 101; { Estas se podrán deshabilitar }
cmPosterior = 102;
type { Nuestro tipo de datos }
tipoagenda = record
nombre: string[ longNOM ];
direccion: string[ longDIR ];
ciudad: string[ longCIU ];
cp: string[ longCP ];
telef: string[ longTLF ];
observ: string[ longOBS ]
end;
programa = object (TApplication) { Nuestro programa }
{ Heredados }
procedure HandleEvent(var Event: TEvent); virtual; { Manj eventos }
procedure InitMenuBar; virtual; { Barra de menú }
procedure InitStatusLine; virtual; { Línea de estado }
{ Creados }
procedure Saludo; { Saludo al entrar }
procedure CreaInterior; { Ventana con el texto }
procedure Anterior; { Retrocede una ficha }
procedure Posterior; { Avanza una ficha }
procedure Numero; { Salta a una ficha }
procedure Modifica; { Modifica la actual }
procedure Nuevo; { Ficha nueva }
procedure Busca; { Busca un texto }
end;
PITexto = ^TITexto; { Texto con los datos: interior }
TITexto = object(TView)
constructor Init(var Limite: TRect);
procedure Draw; virtual;
end;
PVTexto = ^TVTexto; { Texto con los datos: ventana }
TVTexto = object(TWindow)
constructor Init(Limite: TRect; Titulo: String);
procedure MakeInterior(Limite: TRect);
{ Podría tener su propio HandleEvent y demás, pero dejo que la }
{ maneje el programa principal }
end;
var
prog: programa; { El programa en sí }
FichAgenda: file of tipoagenda; { Fichero }
ficha: TipoAgenda; { Guarda la ficha actual }
NumFicha: word; { El número de ficha actual }
Ultima: word; { Número de la última ficha }
VTexto: PVTexto; { La ventana de texto }
constructor TITexto.Init(var Limite: TRect);
begin
TView.Init(Limite);
GrowMode := gfGrowHiX + gfGrowHiY; { Para evitar problemas al redimensionar }
{ aunque dejaré la ventana fija }
Options := Options or ofFramed; { Con borde }
end;
procedure TITexto.Draw;
var
color1,color2: Byte;
temp1, temp2:string; { Para escribir el número de ficha y el total }
result: word;
procedure EscribeTexto(x,y:longint; cadena:string; color:byte);
var b: TDrawBuffer;
begin
MoveStr(b,cadena,color);
WriteLine(x,y,length(cadena),1,b);
end;
begin
{$I-}
reset( FichAgenda );
{$I+}
if ioresult<>0 then
begin { Si no hay fichero, lo creo }
rewrite(FichAgenda);
ficha.nombre:='Nacho Cabanes';
ficha.direccion:='Apartado 5234';
ficha.ciudad:='Alicante';
ficha.cp:='03080';
ficha.observ:='Creador de esto...';
write(FichAgenda,ficha);
NumFicha := 1;
end;
seek(FichAgenda, NumFicha -1);
read(FichAgenda,ficha);
ultima:=filesize(FichAgenda);
close(FichAgenda);
{ Habilito o deshabilito órdenes según donde me encuentre }
If NumFicha = 1 then DisableCommands([cmAnterior])
else EnableCommands([cmAnterior]);
If NumFicha = ultima then DisableCommands([cmPosterior])
else EnableCommands([cmPosterior]);
TView.Draw;
str(numFicha,temp1);
str(ultima,temp2);
with ficha do
begin
color1 := getcolor(1); color2 := getcolor(2);
EscribeTexto(60,1,'Ficha '+temp1+' de '+temp2,color1);
EscribeTexto(2,1,'Nombre:',color1);
EscribeTexto(4,2,Nombre,color2);
EscribeTexto(2,5,'Calle',color1);
EscribeTexto(4,6,direccion,color2);
EscribeTexto(2,8,'Ciudad',color1);
EscribeTexto(4,9,ciudad,color2);
EscribeTexto(36,8,'C.P.',color1);
EscribeTexto(38,9,cp,color2);
EscribeTexto(2,11,'Teléfono',color1);
EscribeTexto(4,12,telef,color2);
EscribeTexto(2,15,'Observaciones',color1);
EscribeTexto(4,16,observ,color2);
end;
end;
constructor TVTexto.Init(Limite: TRect; Titulo: String);
begin
TWindow.Init(Limite, Titulo, wnNoNumber);
Flags:= flags and not wfClose and not wfGrow
and not wfMove and not wfZoom; { Ventana fija, no redimensionable }
MakeInterior(Limite);
end;
procedure TVTexto.MakeInterior(Limite: TRect);
var
Interior: PITexto;
begin
GetExtent(Limite); { Leemos el tamaño disponible }
Limite.Grow(-1,-1); { Sera un poco más pequeño }
Interior := New(PITexto, Init(Limite)); { Y lo creamos }
Insert(Interior);
end;
procedure Programa.Saludo; { ----- Cartelito de presentación }
begin
MessageBox(
' MiniAgenda Turbo Vision'#13#13+
' ¡Bienvenido!'
, nil, mfOkButton+mfInformation);
end;
function LeeValor(rotulo, texto: string; { Auxiliar para leer datos }
var valor: string; longitud: byte): word;
var total:word;
r:trect;
Maximo: byte;
begin
Maximo:=longitud; { Hago la entrada más flexible }
if longitud>60 then longitud:=60; { que en InputBox: el tamaño }
total:=longitud+length(texto)+10; { de la línea de entrada (Input }
if total<30 then total:=30; { Line) y el de la ventana varían }
r.assign(0,0,total,9); { en cada caso. }
r.move(40-total div 2,7);
LeeValor:=InputBoxRect(R,rotulo,texto,
valor,maximo);
end;
procedure Programa.Modifica;
var
rotulo: string;
result: word;
begin
rotulo:='Modificar';
with ficha do begin
result:=LeeValor(rotulo,'Nombre',nombre,longNOM);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Dirección',direccion,longDIR);
if result=cmCancel then exit;
result:=Leevalor(rotulo,'Ciudad',ciudad,longCIU);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Código postal',cp,longCP);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Teléfono',telef,longTLF);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Observaciones',observ,longOBS);
if result=cmCancel then exit;
end;
reset(FichAgenda);
seek( FichAgenda, NumFicha-1 ); { Como siempre... :-) }
write( FichAgenda, ficha );
close(FichAgenda);
VTexto^.redraw;
end;
procedure Programa.Nuevo;
var
rotulo: string;
result: word;
ficha: TipoAgenda;
begin
rotulo:='Añadir datos';
fillchar(ficha, sizeof(Ficha), 0);
with ficha do begin
result:=LeeValor(rotulo,'Nombre',nombre,longNOM);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Dirección',direccion,longDIR);
if result=cmCancel then exit;
result:=Leevalor(rotulo,'Ciudad',ciudad,longCIU);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Código postal',cp,longCP);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Teléfono',telef,longTLF);
if result=cmCancel then exit;
result:=LeeValor(rotulo,'Observaciones',observ,longOBS);
if result=cmCancel then exit;
end;
NumFicha := Ultima + 1; { Hay que escribir al final }
reset(FichAgenda);
seek( FichAgenda, NumFicha-1 ); { Se sitúa }
write( FichAgenda,ficha ); { y escribe la ficha }
Ultima := Ultima + 1; { Ahora hay una más }
VTexto^.redraw;
end;
procedure Programa.Anterior;
begin
Dec(NumFicha);
VTexto^.redraw;
end;
procedure Programa.Posterior;
begin
Inc(NumFicha);
VTexto^.redraw;
end;
procedure Programa.Numero;
var
numeroStr: string[4]; { Numero como string }
numeroW: word; { Numero como word }
result: word; { Por si se cancela }
r: trect; { Rectángulo para la ventana }
cod: integer; { Para "val" }
begin
r.assign(0,0,68,9);
r.move(4,12);
NumeroStr:='';
result:=InputBoxRect(R,'Agenda: Número de Ficha',
'¿ Cual es el número de la ficha a la que quiere saltar ?',
NumeroStr,4);
if result=cmCancel then exit;
val (numeroStr, numeroW, cod);
if not (numeroW in [1..ultima]) then exit else NumFicha:=numeroW;
VTexto^.redraw;
end;
procedure Programa.CreaInterior;
var
R: TRect;
begin
GetExtent(r);
R.B.Y:=R.B.Y-2;
VTexto := New(PVTexto, Init(R, 'Agenda Turbo Vision'));
DeskTop^.Insert(VTexto);
end;
procedure Programa.Busca;
var
posAnterior: word; { Por si se cancela, volver a la anterior }
result: word; { Para comprobar si se cancela }
texto: string; { Texto a buscar }
i: word; { Bucles }
begin
posAnterior := numFicha;
texto := ''; { Posible mejora: conservar el texto buscado }
result := InputBox('Agenda: Buscar',
'¿ Qué texto quiere buscar ?',
Texto,15);
if result = cmCancel then exit;
reset(fichAgenda);
for i := numFicha to ultima do { Busca desde la actual }
begin
seek(FichAgenda, i-1);
read(FichAgenda, ficha);
with ficha do { Miro en todos los campos }
if (pos(texto, nombre) > 0) or (pos(texto, direccion) > 0) or
(pos(texto, ciudad) > 0) or (pos(texto, cp) > 0) or
(pos(texto, telef) > 0) or (pos(texto, observ) > 0)
then
begin
MessageBox(
#3'Encontrado'
, nil, mfOkButton+mfInformation);
numFicha := i;
vTexto^.redraw;
{close(fichAgenda);}
{ No hace falta cerrar el fichero: lo hago al redibujar }
exit;
end;
end;
MessageBox(
#3'No encontrado'
, nil, mfOkButton+mfInformation);
close(fichAgenda);
numFicha := posAnterior;
end;
procedure Programa.InitMenuBar;
var R: TRect;
begin
GetExtent(R);
R.B.Y := R.A.Y + 1;
MenuBar := New(PMenuBar, Init(R, NewMenu(
NewSubMenu('AGENDA', hcNoContext, NewMenu(
NewItem('~A~cerca de...', '', kbNoKey, cmSaludo, hcNoContext,
NewLine(
NewItem('~T~erminar', 'Alt-T', kbAltT, cmQuit, hcNoContext,
nil)))),
NewSubMenu('~O~rdenes', hcNoContext, NewMenu(
NewItem('Anterior', 'Re.Pag.', kbPgUp, cmAnterior, hcNoContext,
NewItem('Posterior', 'Av.Pag.', kbPgDn, cmPosterior, hcNoContext,
NewItem('Número de ~f~icha', 'Alt-F', kbAltF, cmNumero, hcNoContext,
NewItem('Añadir ficha ~n~ueva', 'Alt-A', kbAltA, cmNuevo, hcNoContext,
NewItem('~M~odificar', 'Alt-M', kbAltM, cmModifica, hcNoContext,
NewItem('~B~uscar texto', 'Alt-B', kbAltB, cmBusca, hcNoContext,
nil))))))),
nil)))));
end;
procedure Programa.InitStatusLine;
var R: TRect;
begin
GetExtent(R);
R.A.Y := R.B.Y - 1;
StatusLine := New(PStatusLine, Init(R,
NewStatusDef(0, $FFFF,
NewStatusKey('', kbF10, cmMenu,
NewStatusKey('~T~erminar', kbAltT, cmQuit,
NewStatusKey('', kbAltX, cmQuit, { Salir con Alt+T ó Alt+X }
NewStatusKey('~Re.Pag.~', kbPgUp, cmAnterior,
NewStatusKey('~Av.Pag.~', kbPgDn, cmPosterior,
NewStatusKey('~F~icha', kbAltF, cmNumero,
NewStatusKey('~N~uevo', kbAltN, cmNuevo,
NewStatusKey('~M~odificar', kbAltM, cmModifica,
NewStatusKey('~B~uscar', kbAltB, cmBusca,
NewStatusKey('', kbEsc, cmClose,
nil)))))))))),
nil)));
end;
procedure Programa.HandleEvent(var Event: TEvent);
begin
Inherited HandleEvent(Event);
if Event.What = evCommand then
begin
case Event.Command of
cmSaludo: Saludo;
cmAnterior: Anterior;
cmPosterior:Posterior;
cmNumero: Numero;
cmModifica: Modifica;
cmNuevo: Nuevo;
cmBusca: Busca;
else
Exit;
end;
ClearEvent(Event);
end;
end;
begin { ----- Cuerpo del programa ----- }
assign( FichAgenda, nombref );
NumFicha := 1;
Prog.Init;
Prog.Saludo;
Prog.CreaInterior;
Prog.Run;
Prog.Done;
writeln('Se acabó...');
end.