Újra itt vagyunk néhány rövidke mondanivalóval. Elôzô számunkban 'csodálatos' adatnyilvántaró Turbo Vision-ös programunkban szépen megnézhettük a már létezô személyek adatait, sôt újakat is hozhattunk létre, s mindezt kollekciókkat tároltuk a közönség bámulatba ejtése végett. (Persze nem mintha ez olyan nagy dolog lenne, csak így elegánsabb !) De a t. Olvasó joggal hiányolhat egy dolgot: "az jól van, hogy az Alma Józsi a legelsô személy a nyílvántartásban és az is, hogy a Xerox Marox meg az utolsó, de Piripócs Ödömér hányadik kliens. És egyáltalán hány személyt tartunk nyílván összesen ?" Ennek megmutatása a legszembetűnôbb helyen kell, hogy megtörténjen, pl. az ablak bal alsó sarkában a kereten !

De a bökkenô csak ott van, hogy a Turbo Vision-nek nincs ilyen alap objektuma ... Ciki ... Hát egye-fene akkor csináljunk magunk ! Ennek megoldására segítségül hívjuk a Turbo Vision példatárának Count.PAS forráskódját (Copyright (c) 1992 Borland International.), melyet itt-ott megtoldunk egy kicsivel, hogy magyarosabb legyen. Nem kívánom hasonló analógia alapján újra megírni a Count.PAS file-t, hisz hasonlóan nézne ki. (Ugyanis ezt a problémát nem lehet sok féle képen megoldani. Csak a metódus nevek, ill. a változók publicitása lenne ill. lehetne más.) Milyen lépésekbôl áll egy új view objektum létrehozása ?

Elsô nagy nagy nagy nagy lépés: (huhhh milyen bonyolult ... )

  • Nos azt akarjuk kiírni, hogy a hányadik nyilvántartott adat látszik a képernyôn, ehhez a kollekcióból az aktuálisat kell lekérdezni.
  • Ezt az aktuális értéket kell átadni a TCountView objektumnak (nevezzük így a számláló objektumot.) pl. legyen a SetCurrent() metódussal
  • Másodszor: Meg kell adni, pontosabban kell, hogy meglehessen adni az aktuális értékhez hasonlóan többször az éppen maximális nyilvántartott elemek számát, pl. a SetCount() metódussal. Logikus, hogy a max-ot is töbször kell | lehet megadni, hisz az adtaok közül törölhetünk vagy újat vihetünk be.

Második elrettentô lépés:

  • Ha már megvannak a mindig aktuális (ez nem az a TV műsor ...) számok akkor azokat ki is lehetne írni ... Elôször is ez a fent már megnevezett TCountView megkreálásával lehetséges. Hozzunk létre valami emberi konstruktor Init-et, sôt egy Draw; virtuális metódus se ártana ha már annyira ki akarjuk iratni.
  • A fent nevezett SetCurrent() és SetCount() metódusokat is ide az objektumba böködjük (magyarosan insert-eljük) be.
  • Ha már van két metódusunk ami tudja az aktuális értéket, s maximásik elem szám értékét növelni, akkor ugyanmá' legyen két változó mit növelhetünk ... Current és Count Borland-ék szerint publikus változó - ill. akarom mondani mezô.

Utolsó szívfacsaró lépés:

  • Mondjuk meg a TAdatnyilvDialog-nak, hogy boccsi öreg, de rád szeretnénk rajzolni egy Count view-ot, ha nem haragszol. Sôt még arra is meg szeretnénk kérni, hogy a HandleEvent()-ödben legyél szíves meghívni a TCountView SetCurrent() és SetCount() metódusát ha valamilyen érték megváltozna. Kösssz ...

Aki tudta idáig tartani a lépést, és nem dôlt ki a lökött - esetleg besült poénoktól annak meghálálom az alábbiakkal: (sorry guys, de két napja gép elôtt ülök, s a vacsorám is csak mezei objektumok voltak, s gülübe állt a szemem ...)

Szóval (erôt veszek ...). Lássuk az objektum felépítését:

type

PCountView = ^TCountView;

TCountView = Object(TView)

Current: Longint;

Count : Longint;

constructor Init(var Bounds: Trect);

constructor Load(var S: TStream);

procedure Draw; virtual;

function GetPalette: PPalette; virtual;

procedure SetCount(NewCount: Longint);

procedure IncCount;

procedure DecCount;

procedure SetCurrent(NewCurrent: Longint);

procedure IncCurrent;

procedure DecCurrent;

procedure Store(var S: TStream); virtual;

end;

Hát igen:

  • Init-et, minden tisztességes programozó használ, csak a mazoisták nem:

constructor TCountView.Init(var Bounds:TRect);

begin

Inherited Init(Bounds);

SetCount(0);

SetCurrent(1);

end;

Hát igen ez egy diplomatikus megoldás volt, csak az elôd (az örökölt) Init()-et hívtuk, meg, s beállítottuk kezdôértékre a Count és Current változókat:

  • Lássuk a SetCount() és SetCurrent() metódusokat hátha többet látunk:

procedure TCountView.SetCount(NewCount:Longint);

begin

Count := NewCount;

DrawView;

end;

procedure TCountView.SetCurrent(NewCurrent:Longint);

begin

Current := NewCurrent;

DrawView;

end;

Csak a változókat módosítjuk, de alattomos módon a modosítás után ki akarjuk írni a képernyôre az új információ(ka)t s emiatt kell meghívni a DrawView; metódust. Ehhez annyit kell tudni, hogy a DrawView; metódus a TView-tól kezdôdôen abban, s utódaiban létezik. A DrawView; a virtuális Draw; metódust hívja meg, így nekünk csak a TView Draw-ját kell átírni, hogy szépen kiírhassuk a képernyôre amit akarunk. Lássuk a lényeget:

  • Hogyan működik a Draw; metódus:

procedure TCountView.Draw;

function GetRag(ForRag: Longint): String;

begin

case ForRag mod 10 of

0, 3, 6, 8: GetRag:='ból';

1, 2, 4, 5, 7, 9, 10: GetRag:='bôl';

else GetRag:='bôl';

end;

end;

function ConvertLongintToString(d: Longint): String;

var S: String;

begin

Str(d,s);

ConvertLongintToString:=S;

end;

function GetNevelo(ANevelo: Longint): String;

var

S: String;

B, i: Byte;

L: Longint;

begin

S:=ConvertLongintToString(ANevelo);

B:=Byte(Length(S));

L:=10;

for i:=1 to B-1 do L:=L*10;

B:=ANevelo mod L;

case B of

0, 2, 3, 4, 6, 7, 8, 9: GetNevelo:='A';

1, 5, 10: GetNevelo:='Az';

else GetNevelo:='A';

end;

end;

function GetHanyadik(ADik: Longint): String;

begin

if ADik = 1 then GetHanyadik:='elsô'

else GetHanyadik:=ConvertLongintToString(ADik)+'.';

end;

var

B: TDrawBuffer;

C: Word;

{Params : Array[0..1] of Longint;} {Remarked By R4s}

Start : Word;

First : String[10];

Display: String[20];

begin

C := GetColor(2); { Uses same color as frame }

MoveChar(B, '=', C, Size.X);

{Params[0] := Current;

Params[1] := Count;

FormatStr(Display, ' ~%d~ of %d ', Params);} {Remarked By R4s}

FormatStr(Display, ' '+GetNevelo(Current)+' '+GetHanyadik(Current)+ ' a %d-'+GetRag(Count), Count);

{ If Current is greater than Count, display Current as highlighted }

if Current > Count then C := GetColor($0504)

else C := GetColor($0202);

MoveCStr(B, Display, C);

WriteLine(0, 0, Size.X, Length(Display), B);

end;

Kezdjük az eljén, pontosabban a TCountView.Draw; begin-jénél.

  • C:=GetColor(2); A TCountView owner-ának szín palettájából a 2. elem lesz a keretre kiírt szöveg színe. Ez mivel az owner egy TView, pontosabban a TWindow -TDialog lesz, az aktív keret színével egyezik meg.
  • A MoveChar() rutinról a Turbo Vision elején még beszéltünk olyan 3. - 4. szám felé. Ez röviden annyit csinál, hogy a TDrawBuffer a kirajzolandó hosszon (Size.X) feltölti a keret karakterével a = jellel. Ezt azért teszi, hogy ne |====== 3. a 9-ból ======= | látszódjon, tehát nem Size.X hosszon space legyen s erre középre helyezve a a számláló, hanem a számláló a kerettel egybe olvadva látszódjon.
  • A FormatStr() az adott módon formázott string-et állít elô. A GetNevelo() az adott számhoz a vagy az névelôt rendel. A -dik ragot állítja elô, pl. ha elsô hát elsô, ha második akkor 2. . A GetRag() pedig a maximális elem számhoz készít ragot. Pl.: a 123-ból vagy 129-bôl. (ból | bôl).
  • Ha nagyobb az aktuális elem szám, mint a maximális akkor más színnel dolgozunk.
  • A MoveCStr()annyit csinál, hogy a B: TDrawBuffer-be (ez a kiírási buffer egy karakter utána egy szín byte) másolja itt: a Display string-en C színnel.
  • A WriteLine()-ról is a fent elmondottak szerint már szólottunk, de röviden ennyit csinál:
    procedure TView.WriteLine(X, Y, W, H: Integer; var Buf);
    Az X, Y koordinátára W szélességben (ha ennél hosszabb string van a Bufferban akkor nem írja ki) H-szor írja ki a szinnel együtt tárolt szöveget a Buf bufferbôl.

Persze vannak Load() és Store() metódusok meg RegisterView()-ot használunk, de azok az elôzô számok alapján nyílván egyértelműek.

Nos a TCountView így, s ilyen egyszerűen működik, de ahhoz hogy látszódjon még a TAdatnyilvDialog-ot is módosítani kell:

type

PAdatnyilvDialog = ^TAdatnyilvDialog;

TAdatnyilvDialog = Object(TDialog)

Szamlalo : PCountView;

{ ... a többi a régi}

end;

    Nyílván a TAdatnyilvDialog Init-jét modosítani kell, hogy be legyen insert-elve a számlaló view:

constructor TAdatnyilvDialog.Init;

begin

{... a többi a régi }

R.Assign(4, 19, 25, 20);

New(Szamlalo, Init(R));

Szamlalo^.SetCount(AdatColl^.Count);

Insert(Szamlalo);

end;

Áha, így jó ! Most már minden látszik, csak az értékeket kell frissíteni a TAdatnyilvDialog.HandleEvent()-tel. Legalább is az okosak szerint kell ott, szerintem most röptében megfelel nekünk a ShowAdatRec() metódusban is:

procedure TAdatnyilvDialog.ShowAdatRec(AAdatNum: Integer);

begin

CurrentAdat := AAdatNum;

TempAdatok := PAdatokObj(AdatColl^.At(CurrentAdat))^.AdatRec;

SetData(TempAdatok);

Szamlalo^.SetCurrent(AAdatNum + 1);

{ ... a többi a régi}

end;

Hát ennyi, nézzétek meg a példa programot, úgy könnyebb megérteni. Ha végképp nem megy akkor eMail-ezzetek. Következô számunkban ha minden igaz saját Turbo Vision átírásunkkal kezdünk foglalkozni (Lásd a TVDEMO.exe-t !). Persze lehet, hogy szót ejtünk pár apróságról ami kimaradhatott: TCheckBox(), TRadioButton(), stb..

 

Felhasznált forráskód: Count.PAS, Copyright (c) 1992 Borland International.

PS: Sorry, hogy kicsit rövidebb lett, de a vizsgák, a leadási határidô is közelebb lett hozva ...

Majd a következôben !