Egy grafikus markert kezelő program
elkészítése, amely képes
1.
a markert a
képernyőn mozgatni (a kurzormozgató billentyűk segítségével),
2.
a méretét
növelni, illetve csökkenteni (a méret a mozgás lépésköze),
3.
alakját megváltoztatni (amely külső jegye lehet az esetleges
speciális funkciójának).
1.
Mindenekelőtt
próbálja ki: mire lehet gondolni (Marker.exe)!
(„Kezeléséhez”: mozgatás a kurzormozgató billentyűkkel, méretnövelés „+” billentyű, csökkentés „-” billentyű, alakváltoztatás az „0”..„4” billentyűkkel, kilépni
az „Esc” billentyűvel.)
2.
A marker Pascal típusa:
TMarker=Record
typ:TMarkerType;
size,color:Integer;{alaki
jellemzők}
x,y:Integer;{hollét}
End;
TMarkerType=(MT_Pont,MT_Plusz,MT_Rombusz,MT_X,MT_Nyil);
{0Þpont, 1Þ+; 2Þà; 3Þ´; 4Þã (ferde nyíl)}
3.
A markert kezelő
műveletek:
Procedure SetMarker(
Var
mk:TMarker;
Const
typ:TMarkerType; siz,col,x,y: Integer);
{beállítja a marker tulajdonságait}
Procedure SetMarkerType(
Var
mk:TMarker; Const typ:TMarkerType);
{átállítja a marker típusát}
Procedure SetMarkerSize(
Var
mk:TMarker; Const siz:Integer);
{átállítja a marker méretét}
Procedure SetMarkerColor(
Var
mk:TMarker; Const col:Integer);
{átállítja a marker színét}
Procedure Marker(
Var
mk:TMarker; Const x,y:Integer);
{kirajzolja a markert az (x,y) bázisponttól}
… és ezek közül a
legtöbbnek GetOperáció nevű függvénypárja, mint pl. az alábbi.
Function GetMarkerType(Const mk:TMarker):TMarkerType;
{visszadja a marker típusát}
…
4.
A XORPut vonalrajzolási mód beállításával elérhető, hogy könnyen
visszaállíthassuk a marker „alatti” képeket annak elmozdulásakor. Elegendő
ugyanott „újrarajzolni” a markert, és máris előtűnik az a kép, amelyre rákerült
a kirajzoláskor. [1]
A vonalrajzolási mód beállítása a SetWriteMode(XORPut) utasítással történik. A rajzolásmód
figyelembevételével működik a Line, a LineTo, a Rectangle, de nem így
a PutPixel és a Circle… L. a Turbo Grafika
súgóját.
5.
A Free Pascal
esetén két ablakban fut az alkalmazás: egyik a „normál” konzolablak, a másik a
grafikus ablak. Mivel a beavatkozás műveleteit (ReadKey,
KeyPressed) szokásosan a Crt unit
tartalmazza, ezért a beavatkozáshoz a konzolablakot kell aktívvá tenni, ekkor
viszont részben takarva lesz a „főszereplő” ablak. Ezen segíthetünk a WinCrt unittal. Azonban fontos a Crt, WinCrt sorrendje a Uses sorban: előbb legyen a Crt.
Először
megírandó a markert kezelő unit (MarkerUn.pas
néven)! E unitra építve a fent körvonalazott
egyszerű feladatot az alábbi program megoldja. (Letöltheti a Marker.pas-t.)
Program Markerek;
(*
Markerek témához próbaprogram.
Egy marker kezelése.
Egy marker kezelése: mozgatás, nagyítás/kicsinyítés,
típusváltás.
A marker típusa (alakja) és billentyűje:
* "pont" -- 0
* "+" -- 1
* "rombusz" -- 2
* "X" -- 3
* "nyíl" -- 4
*)
Uses
{$IFNDEF FPC -- TurboPascal}
Newdelay, {hogy ne
szálljon el a Crt-ben}
{$ENDIF}
Crt,
{$IFDEF FPC -- FreePascal}
WinCrt, {hogy a
GUI-ban billentyűkkel lehessen vezérelni; Crt után!!!}
{$ENDIF}
Graph, MarkerUn;
Const
path='c:\LANGS\bp\bgi\' ;
ESC=#27;
Le=#80; Fel=#72; Bal=#75; Jobb=#77;
Var
bfx,bfy,jax,jay:Integer; {rajzterület}
mk
:TMarker;
ch
:Char;
x,y :Integer;
meret:Integer;
Procedure Karkezd;
Begin
Window(1,1,80,25);
TextBackGround(Green);
ClrScr;
End;
Procedure Szovegesre;
Begin
CloseGraph;
RestoreCrtMode;
End;
Procedure Grafikusra;
Var
gd,gm:Integer;
Begin
gd:=detect; gm:=0;
InitGraph(gd,gm,path);
SetBkColor(Green);
ClearDevice;
SetLineStyle(SolidLn,0[2],ThickWidth);
Rectangle(2,2,GetMaxX-2,GetMaxY-2);
bfx:=5; bfy:=5; jax:=GetMaxX-5; jay:=GetMaxY-5;
SetWriteMode(XORPut);
End;
Begin
{főprogram}
Karkezd;
Grafikusra;
x:=GetMaxX Div 2; y:=GetMaxY Div 2; meret:=8;
SetMarker(mk,MT_Plusz,meret,Red,x,y);
Marker(mk,x,y); {marker
kirajzolása}
Repeat
ch:=ReadKey;
Marker(mk,x,y); {a régi marker levétele}
Case ch of
'0'..'4':
SetMarkerType(mk,TMarkerType(ord(ch)-ord('0')));
'+': Begin
meret:=meret+1; {alighanem
célszerű lenne korlátozni!!!}
SetMarkerSize(mk,meret);
End;
'-': if
meret>1 then Begin
meret:=meret-1;
SetMarkerSize(mk,meret);
End;
#0: Begin {funkció billentyűk esetén}
ch:=ReadKey;
case ch of
Le: Begin
If (y+meret<=jay) then y:=y+meret;
End;
Fel: Begin
If (y-meret>=bfy) then y:=y-meret;
End;
Bal: Begin
If (x-meret>=bfx) then x:=x-meret;
End;
Jobb: Begin
If (x+meret<=jax) then x:=x+meret;
End;
End;
End;
End;{Case}
Marker(mk,x,y); {a marker újbóli kirajzolása
-- az új állapotában}
Until ch=Esc;
Szovegesre;
End.
A marker unitját felhasználva készítse el a következő
változatokat!
1.
Egyidejűleg két marker
legyen látható és vezérelhető (az egyik „aktív”, másik „inaktív”). A markerek
közötti váltásra a TAB-billentyű legyen használható. A két marker „funkcionális”
(aktív/inaktív) megkülönböztetése történjen színnel. [3] (Kipróbálhatja: Marker2.exe.)
|
1.
ábra. Kezdőállapot. |
2.
Folytassuk a
következővel: a két markert egy „gumiszalag-szerű” vonal állandóan kösse össze,
amelyet ENTER-rel rögzíteni is lehet. Így egyenes szakaszokból ábrát
is lehet rajzolni. A „gumiszalag” és a rögzített vonal színe (esetleg mintázata
is) legyen eltérő. (Kipróbálhatja: Marker3.exe.)
|
2.
ábra. „Vonalazás” közben. |
3.
Bővítsük azzal,
hogy további
fajta alakzatokat is lehessen rajzolni. Pl. „K”-val kört, „D”-vel
„dobozt”, és természetesen „V”-vel egyenes vonalat. Az
aktuális alakzatot ENTER-rel lehet „rögzíteni”. A körív-rajzolás csak a Line-ra visszavezetve megy, ui. a CIRCLE-re a XORPut nem hat! Ezért az egyik
korábbi gyakorlaton készített
körív-rajzoló eljárást itt be kell építeni a programba. (Kipróbálhatja: Marker4.exe.)
|
3.
ábra. Rajzolás közben. |
4.
További bővítés
lehetne a tartományszínezés.
A lényeg, hogy a megrajzolt alakzatok vonalszínnel határolt tartományait
kitöltő színnel lehessen színezni. Ehhez fel lehet használni a Turbo Grafika FloodFill(x,y,vonalSzin) eljárását.[4] Természetesen nincs
akadálya annak sem, hogy a korábbi gyakorlat
tartományfestő eljárásainak valamelyikét itt felhasználhassuk.
Problémák a tartományszínezéskor:
· a markerek ne látsszanak, mert a színezést megzavarják, pl.:
o
eltűnik a
tartományba eső részük (és az újrarajzolásnál csonkulnak),
o
miattuk nem lesz
zárt a tartomány (és „kifolyik” a szín a tartományból)
· egyetlen aktív marker, ezért nincs „gumi alakzat”
· a végleges ábrát a tényleges vonalszínnel rögzíteni
kell,
o
azaz ne XORPut módon, hanem NormalPut módon kerüljön kirajzolásra, de
· a markerek e közben se látsszanak, mert a marker-újrarajzolás
nem kívánt nyomot hagy.
A háttérszínt célszerű a legsemlegesebb
színre (feketére) változtatni.
Kipróbálhatja: Marker5.exe.
|
4.
ábra. Rajzolás közben. |
[1] Kitalálható, hogy e rajzolási mód hátterében a pixelek színbitjeinek XOR („kizáró-vagy”) művelete húzódik, amely –mint köztudomású– saját maga inverz művelete.
[2] Ez a paraméter a „vonalmintázat”, amelynek szerepe csak az első paraméter „UserBitLn” esetében van.
[3] Megoldásnál a próbaprogramot úgy kell módosítani, hogy mindig az éppen „aktív” marker paraméterei legyenek kéznél (azaz az „alapmegoldáshoz” képest sok Get-es műveletre lesz szükség.)
[4] L. még a következő Turbo Grafika fogalmakat:
Type FillPatternType;
Procedure GetFillPattern(pattern), SetFillPattern(pattern,rajzSzin).