Ahogy azt megszokhattuk először is az új
control karaktereit kell megrajzolnunk. A szokásos CHAREDIT programmal
ezt megtehetjük, s az alábbi nyilakat kell megrajzolni:
Felfelé nyíl két
karakterből: #212 és #183:
|
Felfelé nyíl a második karakter invertálása
után:
|
Lefelé nyíl két karakterből: #213 és #184: |
Lefelé nyíl a második karakter invertálása után: |
Bal nyíl két karakterből: #217 és #21: |
Bal nyíl a második karakter invertálása után: |
Jobb nyíl két karakterből: #218 és #185: |
Jobb nyíl a második karakter invertálása után: |
Nézzük meg, hogyan kell módosítanunk a VIEWS unit forráskódját ahhoz, hogy szép saját scrollbar-jainkat használhassuk.
A Turbo Vision írói ötletes módon egy tömbbe rakták azokat a karaktereket melyekkel a scrollbar-t kiírják. Így a jobb nyíl ASCII kódját, majd a bal nyílét, stb. Persze ezek a sima DOS-os karakterek nem valami szépek, nem csoda, hisz nem erre lettek kitalálva. Épp ezért írjuk át. Mi is az eredetihez hasonlóan egy tömbbe rakjuk a karaktereket amikkel majd kiírjuk a scrollbar-t. A bökkenő az, hogy a TV által definiált ilyen tömb típus (TScrollChars) csak 5 karakteres nekünk meg 6 karakteres tömb kell lévén, hogy a fel és le nyilunk nem egy hanem két karakter széles. Így definiálhatunk egy új, saját típust legyen a változatosság kedvéért: TPCXScrollChars.
Majd ezt a tömböt saját scrollbar objektumunk Init-jében ahogy az eredeti TScrollBar-ban initializáljuk. Persze nem csak grafikus kinézetű karakterekkel töltünk fel egy tömböt, hanem meghagyjuk a sima text karakterekkel is mert lehet, hogy sima nem grafikus kinézetű módban akarjuk elindítani az applikációt. Így elkerülhetjük azt, hogy két külön scrollbar objektumot kelljen használni attól függően, hogy sima text, vagy grafikus látszatú text módban fut –e a programunk. Így a text módtól függően egy objektum fogja lekezelni a scrollbar-t.
Lássuk a saját scrollbar objektumunk init-jét:
constructor TPCXScrollBar.Init(var Bounds: TRect);
const
{ felb felj leb lej }
GVChars: TPCXScrollChars = (#212, #183, #213, #184, GFrameEdgeL,
GFrameEdgeR);
GHChars: TPCXScrollChars = (#217, #21, #218, #185, #215,
#215);
VChars : TPCXScrollChars = (#30, #31, #177, #254, #178,
#32); {Text, it's }
HChars : TPCXScrollChars = (#17, #16, #177, #254, #178,
#32); {the original}
begin
TView.Init(Bounds);
if IsPCXGraphCharsOn then TempB:=2 else
TempB:=1;
Value := 0;
Min := 0;
Max := 0;
PgStep := 1;
ArStep := 1;
if Size.X = TempB then
begin
GrowMode := gfGrowLoX + gfGrowHiX + gfGrowHiY;
if IsPCXGraphCharsOn then Chars
:= GVChars
else Chars := VChars;
IsHorizontal:=False;
end else
begin
GrowMode := gfGrowLoY + gfGrowHiX + gfGrowHiY;
if IsPCXGraphCharsOn then Chars
:= GHChars
else Chars := HChars;
IsHorizontal:=True;
end;
end;
Konstans | Jelentése ha bekapcsolt: |
gfGrowLoX | A view bal oldala konstans távolságra marad az owner-ének (tulajdonosának) jobb oldalától. |
gfGrowLoY | A view tetejének koordinátái nem változnak az owner aljának koordinátáihoz képest. A távolság a view teteje és az owner alja között konstans marad. |
gfGrowHiX | A view jobb oldala konstans távolságra marad az owner jobb oldalától. |
gfGrowHiY | A view alja konstans távolságban marad az owner aljától. |
gfGrowAll | A view az owner átméretezésekor csak mozog, s az owner jobb alsó sarkához képest távolsága nem változik. |
gfGrowRel | TWindow-nak a spec. méretváltozása 25-sorról 43/50-re való váltáskor. Ekkor az eredeti arányok megmaradnak. |
Nyílván való, hogy ahol az eredeti TScrollbar megvizsgálja, hogy horizontális, vagy vertikális –e a scrollbar ott módosítani kell, mert a régi feltétel ez volt: Size.X = 1. Ez ugye megváltozott hisz lehet kettő széles scrollbar s még akkor is vertikális, csak grafikus kinézetű. (hisz az eredeti objektumban minden ami nem egy széles volt az horizontális volt.) Így a Size.X = 1 -eket Size.X = TempB-re kell átállítani. (Persze bizonyos helyeken fel lehetne használni az IsHorizontal: Boolean logikai változót, de nem tesszük mert inkább megőrizzük a régivel a látszat szerinti kompatibilitást.) Nos lássuk, mit kell átalakítani. Első sorban a HandleEvent()-öt ami jelentős számban használja ezen vizsgálatot. Így az új objektumunk HandleEvent()-je így néz ki:
procedure TPCXScrollBar.HandleEvent(var Event: TEvent);
{...}
function GetPartCode: Integer;
var
Mark, Part: Integer;
begin
Part := -1;
if Extent.Contains(Mouse) then
begin
if Size.X = TempB then
Mark := Mouse.Y else Mark := Mouse.X;
if Mark = P then Part := sbIndicator
else
begin
if Mark < TempB
then Part := sbLeftArrow else
if Mark < P then
Part := sbPageLeft else
if Mark < S then
Part := sbPageRight else
Part := sbRightArrow;
if Size.X = TempB then
Inc(Part, 4);
end;
end;
GetPartCode := Part;
end;
{ ... }
begin
TView.HandleEvent(Event);
case Event.What of
evMouseDown:
begin
{ ... }
if ClickPart <> sbIndicator then
begin
{ ... }
end else
begin
repeat
MakeLocal(Event.Where,
Mouse);
Tracking
:= Extent.Contains(Mouse);
if
Tracking then
begin
if Size.X = TempB then I := Mouse.Y else I := Mouse.X;
end;
{ ... ...
... ... ... ...}
end;
end;
Hasonlóan ki kell cserélni a GetSize() függvényben is:
function TPCXScrollBar.GetSize: Integer;
var
S: Integer;
begin
if Size.X = TempB then S := Size.Y
else S := Size.X;
if S < 2+TempB then GetSize := 2+TempB
else GetSize := S;
end;
Nos jöjjön az objektum lelke a Draw() és DrawPos() metódus, melyet nem véletlenül hagytam a végére. A Draw() metódust ugyanúgy kell az objektumban implementálni ahogy elődjében. (Azért kell deklarálni, mert a DrawPos() rutin privát, s nem virtuális. Így az általunk írt DrawPos() metódus nem tud visszahatni ősének Draw() metódusára.) Lássuk a DrawPos()-t:
procedure TPCXScrollBar.DrawPos(Pos: Integer);
var
S: Integer;
B: TDrawBuffer;
i: Word;
begin
if IsPCXGraphCharsOn then
begin
if Not IsHorizontal then
begin
S := GetSize - 1;
MoveCStr(B[0], Chars[0], GetColor(2));
MoveCStr(B[1], Chars[1], SwapHighAndLowAreaOfByte(GetColor(2)));
if Max = Min then
begin
i:=0;
while i<(S*2)-1
do
begin
Inc(I,2);
MoveCStr(B[i],
''+Chars[4]+Chars[5]+'', GetColor(1));
end;
end
else
begin
i:=0;
while
i<(S*2)-1 do
begin
Inc(i,2);
MoveCStr(B[i], ''+Chars[4]+Chars[5]+'', GetColor(3));
MoveCStr(B[Pos*2], ''+Chars[4]+Chars[5]+'', GetColor(4));
end;
end;
MoveCStr(B[S*2], Chars[2], GetColor(2));
MoveCStr(B[(S*2)+1], Chars[3], SwapHighAndLowAreaOfByte(GetColor(2)));
WriteBuf(0, 0, Size.X, Size.Y, B);
end
else
begin
S := GetSize - 1;
if Pos=1 then Inc(Pos);
if Pos+1=S then Pos:=S-3;
MoveCStr(B[0], Chars[0], GetColor(2));
MoveCStr(B[1], Chars[1], SwapHighAndLowAreaOfByte(GetColor(2)));
if Max = Min then
MoveChar(B[2], Chars[4],
GetColor(1), S - 2)
else
begin
MoveChar(B[2], Chars[4],
GetColor(3), S - 2);
MoveCStr(B[Pos], Chars[5]+Chars[5],
GetColor(4));
end;
MoveCStr(B[S-1], Chars[2], GetColor(2));
MoveCStr(B[S], Chars[3], SwapHighAndLowAreaOfByte(GetColor(2)));
WriteBuf(0, 0, Size.X, Size.Y, B);
end;
end
else
begin
S := GetSize - 1;
MoveChar(B[0], Chars[0], GetColor(2), 1);
if Max = Min then
MoveChar(B[1], Chars[4], GetColor(1),
S - 1)
else
begin
MoveChar(B[1], Chars[2], GetColor(1),
S - 1);
MoveChar(B[Pos], Chars[3], GetColor(3),
1);
end;
MoveChar(B[S], Chars[1], GetColor(2), 1);
WriteBuf(0, 0, Size.X, Size.Y, B);
end;
Message(Application, evCommand, cmMouseChanged, @Self);
end;
Hogyan is működik ?
while i<(S*2)-1 do
begin
Inc(i,2);
MoveCStr(B[i], ''+Chars[4]+Chars[5]+'', GetColor(3));
MoveCStr(B[Pos*2], ''+Chars[4]+Chars[5]+'', GetColor(4));
end;
MoveCStr(B[S*2], Chars[2], GetColor(2));
MoveCStr(B[(S*2)+1], Chars[3], SwapHighAndLowAreaOfByte(GetColor(2)));
WriteBuf(0, 0, Size.X, Size.Y, B);
MoveCStr(B[0], Chars[0], GetColor(2));
MoveCStr(B[1], Chars[1], SwapHighAndLowAreaOfByte(GetColor(2)));
if Max = Min then
MoveChar(B[2], Chars[4], GetColor(1), S - 2)
else
begin
MoveChar(B[2], Chars[4], GetColor(3), S - 2);
MoveCStr(B[Pos], Chars[5]+Chars[5], GetColor(4));
end;
MoveCStr(B[S-1], Chars[2], GetColor(2));
MoveCStr(B[S], Chars[3], SwapHighAndLowAreaOfByte(GetColor(2)));
WriteBuf(0, 0, Size.X, Size.Y, B);
Egy kérdés érdekel valakit a C++ objektum orientáltsága? Mert ha igen
akkor arról beszélhetünk a TV-átírás után. Akit érdekel, eresszen el egy
egysoros levelecskét a PC-XUser@FREEMAIL.C3.HU-ra.