Lekcja 7 - Własne Biblioteki i obsługa Myszki
Źródła programów zamieszczonych w tej lekcji

Na lekcji tej dowiesz się jak zamienić liczbę na tekst (np. WORD => STRING), jak zbudować własne biblioteki oraz utworzymy parę procedur i funkcji do obsługi myszki.


Procedura Str

Składnia: Str(liczba,tekst:string);            LICZBA może być typu BYTE, INTEGER, WORD itd.

Procedura zamienia liczbę "LICZBA" na zmienną typu "STRING" np.

Var
 X:Byte;
 S:String;

Begin
  X:=48;
  Str(x,s);
  WriteLn(s);
End.

Tworzenie Bibliotek

Przy nauce tworzenia bibliotek zrobimy sobie procedurę, która czasami może się nam przydać, mianowicie procedurę rysującą ramkę w trybie tekstowym. Wykorzystamy również dodatkowo procedurę WriteXY, którą utworzyliśmy w lekcji 3.

USES CRT;

PROCEDURE WriteXY(x,y:byte; s:string);
Begin
  GotoXY(x,y);
  Write(s);
End;

PROCEDURE Ramka(x1,y1,x2,y2:byte);
Var                                                   {1}
 t:byte;

Begin
  WriteXY(x1,y1,chr(201));                            {2}
  WriteXY(x1,y2,chr(200));                            {3}
  WriteXY(x2,y1,chr(187));                            {4}
  WriteXY(x2,y2,chr(188));                            {5}
  For t:=x1+1 To x2-1 Do WriteXY(t,y1,chr(205));      {6}
  For t:=x1+1 To x2-1 Do WriteXY(t,y2,chr(205));      {7}
  For t:=y1+1 To y2-1 Do WriteXY(x1,t,chr(186));      {8}
  For t:=y1+1 To y2-1 Do WriteXY(x2,t,chr(186));      {9}
End;

Begin
  Clrscr;
  Ramka(5,5,12,9);
End.
Zmienne:
X1 - współrzędna X lewego górnego rogu ramki
Y1 - współrzędna Y lewego górnego rogu ramki
X2 - współrzędna X prawego dolnego rogu ramki
Y2 - współrzędna Y prawego dolnego rogu ramki

{1} Tego wcześniej nie było: definicja zmiennej LOKALNEJ. W przeciwieństwie do zmiennych GLOBALNYCH, które do tej pory stosowaliśmy (Globalne to te umieszczone jeszcze przed głównym programem, procedurami i funkcjami), zmienna Lokalna jest "znana" TYLKO przez procedurę w której została użyta (tzn. że każda procedura może mieć własne zmienne, mogą się tak samo nazywać, ale ani główny program, ani też żadna inna procedura nie może z nich korzystać ponieważ ich nie zna, dlatego też mogą istnieć zmienne Lokalne i Globalne o tej samej nazwie).
{2} Wyświetl lewy górny róg ramki
{3} Wyświetl lewy dolny róg ramki
{4} Wyświetl prawy górny róg ramki
{5} Wyświetl prawy dolny róg ramki
{6} Wyświetl linię górną
{7} Wyświetl linię dolną
{8} Wyświetl linię lewą
{9} Wyświetl linię prawą

Teraz przeanalizuj dokładnie linie {2}-{9} na jakiej zasadzie było wykonane wyświetlanie tej ramki.

Oki czas zabrać się za główny temat tej lekcji "własnych bibliotek". Najważniejszą rzeczą jest to aby NAZWA PLIKU W KTÓREJ UMIESZCZONE JEST ŹRÓDŁO BIBLIOTEKI MIAŁO TAKĄ SAMĄ NAZWĘ JAK BIBLIOTEKA ! Czyli jeżeli bibliotekę nazwiemy GIGIKURS to jej źródło powinno się znajdować się w pliku GIGIKURS.PAS a po skompilowaniu otrzymamy GIGIKURS.TPU (oczywiście ze względów na to że nazwa pliku nie może mieć więcej niż 8 znaków nie można utworzyć biblioteki "Moja_Fajna_Super_Biblioteka" :)))))

Dobra dosyć marudzenia zabierzmy się za konkrety, będzie to poprzedni program zamieniony na bibliotekę:
UNIT GIGIKURS;                                  {1}

INTERFACE                                       {2}

USES CRT,DOS,GRAPH;    { GRAPH i DOS są wstawione od razu gdyż później będą nam potrzebne }

PROCEDURE WriteXY(x,y:byte; s:string);          {3}
PROCEDURE Ramka(x1,y1,x2,y2:byte);              {4}

IMPLEMENTATION                                  {5}


PROCEDURE WriteXY(x,y:byte; s:string);          {6}
Begin
  GotoXY(x,y);
  Write(s);
End;

PROCEDURE Ramka(x1,y1,x2,y2:byte);              {7}
Var
 t:byte;

Begin
  WriteXY(x1,y1,chr(201));
  WriteXY(x1,y2,chr(200));
  WriteXY(x2,y1,chr(187));
  WriteXY(x2,y2,chr(188));
  For t:=x1+1 To x2-1 Do WriteXY(t,y1,chr(205));
  For t:=x1+1 To x2-1 Do WriteXY(t,y2,chr(205));
  For t:=y1+1 To y2-1 Do WriteXY(x1,t,chr(186));
  For t:=y1+1 To y2-1 Do WriteXY(x2,t,chr(186));
End;

Begin                                           {8}
End.                                            {8}
{1} Definicja "oto nowa biblioteka o nazwie GIGIKURS". Linia ta powinna znajdować się w źródle jako PIERWSZA.
{2} Definicja "teraz będą się znajdować opisy funkcji i bibliotek które chcemy udostępniać w innych programach". Zwróć uwagę że nie ma tutaj postawionego na końcu średnika.
{3,4} Informujemy kompilator, że w bibliotece tej znajdują się procedury "WriteXY" oraz "Ramka". Są to linie TAKIE SAME jak linie {6} i {7}
{5} Koniec definicji, teraz zaczynają się główne procedurki.
{8} Zobacz na to ! Pomiędzy "Begin" i "End." nic nie ma ! A to dlatego że to jest biblioteka, a nie program do uruchomienia. Po skompilowaniu pascal utworzy plik GIGIKURS.TPU i w nim będą się znajdować nasze dwie nowe procedury, a ponieważ jest to biblioteka to definiuje się jej użycie tak jak i innych bibliotek w linii z USES :
USES CRT,GIGIKURS;

Begin
  Clrscr;
  Ramka(5,5,12,9);
End.
Przyznasz chyba że tak program wygląda bardziej czytelnie :)


Procedury do obsługi Myszki

Teraz utworzę procedury do obsługi myszki, nie musisz znać ich działania na poziomie na którym teraz jesteś, gdyż będę operował na przerwaniach więc lepiej tego nie ruszaj :) , a ty mam nadzieję że sam dorzucisz je do naszej biblioteki GIGIKURS.

PROCEDURE PokazMyche;
Var r:registers;
Begin
  r.ax:=$0001;
  Intr($33,r);
End;

PROCEDURE SchowajMyche;
Var r:registers;
Begin
  r.ax:=$0002;
  Intr($33,r);
End;

PROCEDURE UstawMyche(x1,y1,x2,y2:word);
Var r:registers;
Begin
  r.ax:=$0007;
  r.cx:=x1;
  r.dx:=x2;
  Intr($33,r);
  r.ax:=$0008;
  r.cx:=y1;
  r.dx:=y2;
  Intr($33,r);
End;


PROCEDURE PobierzMyche(var x,y,butt:word);
Var r:registers;
Begin
  r.ax:=$0003;
  Intr($33,r);
  x:=r.cx;
  y:=r.dx;
  butt:=r.bx;
End;

PROCEDURE VgaOn;
Var
  driver,mode:integer;
Begin
  driver:=vga; mode:=vgahi;
  InitGraph(driver,mode,'c:\bp\bgi');           { Tutaj wprowadz swoja sciezke do plikow BGI }
End;
Poszczególne procedury służą do:
PokazMyche - wyświetlenie myszki na ekranie
SchowajMyche - schowanie kursora myszki
UstawMyche - ustawienie minimalnych i maksymalnych wychyleń, w których porusza się kursor myszki:
    X1 - współrzędna X lewego górnego rogu
    Y1 - współrzędna Y lewego górnego rogu
    X2 - współrzędna X prawego dolnego rogu
    Y2 - współrzędna Y prawego dolnego rogu
PobierzMyche - pobranie informacji o położeniu i stanie przycisków myszki, zmienne:
    X - współrzędna pozioma położenia myszki
    Y - współrzędna pionowa położenia myszki
    BUTT - informacja o wciśniętych klawiszach w myszce:
        1=lewy klawisz myszki
        2=środkowy klawisz myszki
        3=lewy+środkowy klawisz myszki
        4=prawy klawisz myszki
        5=lewy+prawy klawisz myszki
        6=środkowy+prawy klawisz myszki
        7=lewy+środkowy+prawy klawisz myszki
VgaOn - to nie jest związane z mychą ale jest dość przydatne, po prostu włącza tryb graficzny jedną linijką.

Teraz dwie żelazne zasady obsługi mychy:
Zasada 1. Jeżeli wykonasz po sobie N razy procedurę SchowajMyche, to aby ukazał się kursor myszki należy wykonać również N razy PokazMyche np.
[...]
PokazMyche;        { myszka widoczna }
SchowajMyche;      { myszka niewidoczna }
SchowajMyche;      { myszka niewidoczna }
PokazMyche;        { myszka NADAL NIEWIDOCZNA gdyż zostało użyte 2 razy ukrycie ! }
PokazMyche;        { i dopiero teraz myszka widoczna }
[...]
Zasada 2. Jeżeli myszka znajduje się na ekranie i np. narysujemy linię akurat przechodzącą przez kursor myszki, to część linii, na której znajdował się wyświetlony kursor zostanie skasowana tak więc sposobem na to jest wykonanie zawsze czegoś takiego:
[...]
SchowajMyche;                   { Ukryj mychę aby kursor nie przeszkadzał }
Line(1,1,100,100);              { Narysuj już teraz linię bez obaw że się coś skasuje }
PokazMyche;                     { Pokaż spowrotem myszkę }
[...]

Myszka w praktyce

Teraz będzie program ukazujący możliwości nowych procedur, na początek prymitywny do włączenia trybu graficznego i wyświetlenia kursora myszki :)

Uses CRT,GRAPH,GIGIKURS;

Begin
  VgaOn;
  UstawMyche(1,1,635,475);        { aby lepiej to poznac poeksperymentuj z tymi wartosciami }
  PokazMyche;
  Repeat Until Keypressed;
  CloseGraph;
End.
Extra ! Mycha jest ! Nawet się rusza :) Ale co dalej ? Rozbudujemy na początek ten program tak abyśmy widzieli na jakich współrzędnych znajduje się aktualnie kursor myszki:
Uses CRT,GRAPH,GIGIKURS;
Var
  x,y,przyciski:word;
  tekstx,teksty:string;

Begin
  VgaOn;
  UstawMyche(1,1,635,475);
  PokazMyche;
    Repeat
      PobierzMyche(X,Y,PRZYCISKI);      {1}
      SchowajMyche;
      Str(X,tekstx);                    {2}
      Str(Y,teksty);                    {3}
      OutTextXY(10,10,tekstx);          {4}
      OutTextXY(10,30,teksty);          {5}
      PokazMyche;
    Until Keypressed;
  CloseGraph;
End.
{1} Pobranie współrzędnych położenia kursora mychy ( Działa nawet wtedy gdy nie widać kursora !)
{2-5} Zamiana wartości liczbowych współrzędnych X i Y na tekst gdyż OutTextXY nie potrafi wyświetlać liczb i wyświetlenie tych współrzędnych na ekranie.

No niby wyświetla tylko że jest jedna liczba na drugiej i całkiem wszystko jest przez to zamazane, kolejnym krokiem będzie czyszczenie miejsca pod liczbami:
Uses CRT,GRAPH,GIGIKURS;
Var
  x,y,przyciski:word;
  tekstx,teksty:string;

Begin
  VgaOn;
  UstawMyche(1,1,635,475);
  PokazMyche;
  SetFillStyle(SolidFill,Black);                {1}
    Repeat
      PobierzMyche(X,Y,PRZYCISKI);
      SchowajMyche;
      Str(X,tekstx);
      Str(Y,teksty);
      Bar(10,10,40,40);                         {2}
      OutTextXY(10,10,tekstx);
      OutTextXY(10,30,teksty);
      PokazMyche;
    Until Keypressed;
  CloseGraph;
End.
{1} Ustawienie koloru wyświetlania wypełnionego prostokąta na czarny
{2} Narysowanie prostokąta i zamazanie przez to liczb "pod nim" się znajdujących

Coraz lepiej :) Tylko to migotanie wszystkiego :( Rozwiązać to można tak:
Uses CRT,GRAPH,GIGIKURS;
Var
  x,y,przyciski:word;
  staryx,staryy:word;                           {1}
  tekstx,teksty:string;

Begin
  VgaOn;
  UstawMyche(1,1,635,475);
  PokazMyche;
  SetFillStyle(SolidFill,Black);
  staryx:=1000;                                 {2}
    Repeat
      PobierzMyche(X,Y,PRZYCISKI);
      If (staryx<>x) OR (staryy<>y) Then        {3}
      Begin
        SchowajMyche;
        Str(X,tekstx);
        Str(Y,teksty);
        Bar(10,10,40,40);
        OutTextXY(10,10,tekstx);
        OutTextXY(10,30,teksty);
        Staryx:=x;                              {4}
        Staryy:=y;                              {5}
        PokazMyche;
      End;
    Until Keypressed;
  CloseGraph;
End.
{1} nowe zmienne będące informacją "w jakim położeniu znajdował się poprzednio kursor"
{2} wstawiam liczbę 1000 do zmiennej STARYX, aby już na samym początku wywołać wyświetlenie współrzędnych myszki, a dokonuję tego w ten sposób: ponieważ początkowo X=0 a gdy STARYX=1000 to w linii {3} zostanie spełniony warunek wyświetlania.
{3} jeżeli zmieniło się położenie kursora ( zmienił się X lub Y ) to wyczyść miejsce pod tekst i wyświetl aktualne współrzędne.
{4,5} utrwal aktualne położenie kursora w zmiennych

No popatrz ! Już jest wszystko oki ! Nic nie mruga :) Teraz dla wprawy wstaw jedną linijkę z
PutPixel tak, aby można było "rysować" pixelkami na ekranie ( nie będzie to porażająca prędkość, rzekłbym nawet że tragiczna więc się zbytnio nie przejmuj :)


Wybieranie Myszką Obiektów

Powinieneś już co nieco rozumieć z obsługi mychy, zajmiemy się jeszcze na tej lekcji wybieraniem obiektów np. przycisków. Narysujmy więc na początek trzy proste ikonki:

USES CRT,GRAPH,GIGIKURS;

Begin
  VgaOn;
  SetFillStyle(SolidFill,Green);
  Bar(215,220,275,250);
  Bar(285,220,345,250);
  Bar(355,220,415,250);
  OuttextXY(218,232,'Opcja 1');
  OuttextXY(288,232,'Opcja 2');
  OuttextXY(358,232,'Opcja 3');
  Repeat Until Keypressed;
  CloseGraph;
End.
Dorzućmy do tego obsługę myszki z poprzedniego programu wycinając niepotrzebne już linie wyświetlające współrzędne:
Uses CRT,GRAPH,GIGIKURS;
Var
  x,y,przyciski:word;

Procedure OPCJA1;
Begin
  Sound(50);
End;

Procedure OPCJA2;
Begin
  Sound(100);
End;

Procedure OPCJA3;
Begin
  Sound(150);
End;

Begin
  VgaOn;
  SetFillStyle(SolidFill,Green);
  Bar(215,220,275,250);                   {1}
  Bar(285,220,345,250);                   {2}
  Bar(355,220,415,250);                   {3}
  OuttextXY(218,232,'Opcja 1');
  OuttextXY(288,232,'Opcja 2');
  OuttextXY(358,232,'Opcja 3');
  UstawMyche(1,1,635,475);
  PokazMyche;
    Repeat
      PobierzMyche(X,Y,PRZYCISKI);
        If (PRZYCISKI=1) Then             {4}
          Begin
            If (X>215) AND (y>220) AND (x<275) AND (y<250) Then OPCJA1;    {5}
            If (X>285) AND (y>220) AND (x<345) AND (y<250) Then OPCJA2;    {6}
            If (X>355) AND (y>220) AND (x<415) AND (y<250) Then OPCJA3;    {7}
          End;
    Until Keypressed;
  Nosound;                                {8}
  CloseGraph;
End.
Doszły nam 3 procedury: OPCJA1, OPCJA2, OPCJA3 to one właśnie będą wywoływane i będą wydawały dźwięki o różnej częstotliwości. Teraz interesuje nas tylko czy został wciśnięty klawisz myszy i czy znajduje się w tym momencie nad jakąś ikonką.

{1-3} Wyświetlenie trzech "ikonek"
{4} sprawdź czy wciśnięty jest lewy klawisz myszki jeśli tak to:
{5-7} Sprawdź kolejno czy kursor znajduje się nad jakąś ikonką, jeśli tak to wywołaj odpowiednią procedurę
{8} Wyłącz dźwięk przy wychodzeniu

Porównaj teraz wartości liczb w liniach {1, 5} {2, 6} {3, 7} wnioski "kiedy kursor znajduje się na ikonce" powinne się same nasuwać.

Jako zadanie domowe (feeeee... jak to brzydko brzmi :) utwórz 4-5 ikonek o RÓŻNYCH WIELKOŚCIACH i RÓŻNYM POŁOŻENIU (rozsiane po całym ekranie) i zrób ich obsługę. Jak będziesz się bardzo nudził to może pokusisz się nawet na zrobienie małego "syntezatorka" tak aby można było na nim "grać" :)

Powrot na Strone Glowna