Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów
szkół średnich

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek
Konsultacje: Wojciech Grodowski, mgr inż. Janusz Wałaszek
Uaktualniono 08.02.2024

©2024 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Obsługa konsoli znakowej w Windows

SPIS TREŚCI
Podrozdziały

Opis

Biblioteka newconio powstała kilka lat temu na kole informatycznym w I LO w Tarnowie. Jej głównym zastosowaniem jest umożliwienie programiście sterowanie wszystkimi funkcjami dostępnymi w trybie konsoli znakowej Windows bez zbędnego grzebania się w Win32 API:

  • kolorowy tekst
  • polskie litery
  • pozycjonowanie tekstu
  • wypełnianie obszarów
  • tworzenie ramek
  • zapamiętywanie obszarów i odtwarzanie ich
  • przesuwanie obszarów w różnych kierunkach

Funkcje te pozwalają na wygodne pisanie dowolnych gier konsolowych, na których młodzi adepci szlifują swoje umiejętności programowania w języku C++. Na kole informatycznym I LO powstało wiele programów, które wykorzystują bibliotekę newconio.


Na początek:  podrozdziału   strony 

Instalacja

Instalacja biblioteki jest bardzo prosta:

Przekopiuj do swojego katalogu projektowego poniższe dwa pliki:

newconio.cpp  -  plik źródłowy biblioteki
newconio.h  - plik nagłówkowy dla biblioteki

Dołącz do projektu plik newconio.cpp.

W każdym programie wykorzystującym funkcje biblioteczne wpisz polecenie preprocesora:

#include "newconio.h"

Na początku funkcji main() umieść wywołanie:

 _cinit();

Dokonuje ono inicjalizacji biblioteki. Od tego momentu możesz w swoim programie korzystać ze wszystkich funkcji biblioteki. W Code::Blocks możesz zapisać szablon projektu użytkownika, który znakomicie przyspiesza wszystkie te czynności.


Na początek:  podrozdziału   strony 

Funkcje biblioteki newconio

_cinit()

Funkcja inicjuje bibliotekę newconio oraz ustawia odpowiednio konsolę znakową do pracy z programem. Funkcję tą wywołujemy tylko jeden raz w programie użytkownika - na samym początku funkcji main():

main()
{
    _cinit();
    ...
}

_pl(tekst)

Konsola znakowa pracuje w innym standardzie znaków niż środowisko graficzne Windows, w którym przygotowujemy teksty programów C++. Konsekwencją tego faktu jest to, iż teksty zawierające polskie literki będą nieprawidłowo wyświetlone przez konsolę. Problem rozwiązuje funkcja _pl(). Zamienia ona kody znaków reprezentujących polskie literki w standardzie Windows na odpowiednie kody tych znaków w konsoli znakowej. Użycie jest następujące:

...
cout << _pl("Zażółć gęślą jaźń\n");
...

center(nr wiersza, tekst)

Procedura wyświetla podany tekst na środku zadanego wiersza ekranu. Nadaje się głównie do tytułów.

clrscr()

Funkcja czyści ekran konsoli znakowej. Ustawia pozycję kursora na początku pierwszego wiersza. Na całym ekranie ustawiane są bieżące atrybuty kolorów.

cursoroff()

Jeśli tworzymy na ekranie konsoli jakąś animację, to często denerwuje nas kursor tekstowy. Za pomocą tej funkcji możemy go wyłączyć - tzn. kursor tekstowy stanie się niewidoczny.

cursoron()

Po wykonaniu tej funkcji kursor staje się znów widoczny.

delay(czas w milisekundach)

Funkcja wstrzymuje wykonanie programu na zadaną liczbę milisekund. Jest przydatna, gdy chcemy zsynchronizować czasowo wykonanie programu. Odmierzanie czasu jest przybliżone i nie należy raczej tworzyć np. zegara na podstawie tej funkcji. Ale w pozostałych przypadkach jest bardzo pożyteczna.

delay(1000); // czeka około 1 sekundę
delay(500);   // czeka około 1/2 sekundy, itd.

fillrectattr(atrybut, xb, yb, xe, ye)

Funkcja wypełnia zadany obszar okna konsoli (od pozycji (xb,yb) w lewym górnym narożniku, do pozycji (xe,ye) w prawym dolnym narożniku) podanym atrybutem. Znaki zawarte w tym obszarze nie są zmieniane. Również nie zmienia się pozycja kursora tekstowego.

fillrectattr(0x2f,1,1,78,23); // prostokąt z ciemnozielonym tłem i białymi znakami

fillrectch(znak xb, yb, xe, ye)

Funkcja wypełnia zadany obszar okna konsoli (od pozycji (xb,yb) w lewym górnym narożniku, do pozycji (xe,ye) w prawym dolnym narożniku) podanym znakiem. Kolory zawarte w tym obszarze nie są zmieniane. Również nie zmienia się pozycja kursora tekstowego.

fillrectch('X',1,1,78,23); // prostokąt wypełniony literkami X

fillrect(znak, atrybut, xb, yb, xe, ye)

Funkcja wypełnia zadany obszar okna konsoli (od pozycji (xb,yb) w lewym górnym narożniku, do pozycji (xe,ye) w prawym dolnym narożniku) podanym znakiem i atrybutem. Nie zmienia się pozycja kursora tekstowego.

fillrect('X',0x2f,1,1,78,23); // prostokąt wypełniony literkami białymi X na ciemnozielonym tle.

frame(rodzaj, atrybut, xb, yb, xe, ye)

Na obrzeżach zadanego obszaru okna konsoli (od pozycji (xb,yb) w lewym górnym narożniku, do pozycji (xe,ye) w prawym dolnym narożniku) rysowana jest ramka. Nie zmienia się pozycja kursora tekstowego. Rodzaje ramek są następujące:

FRAME_EMPTY - ramka wypełniona spacjami
FRAME_SINGLE - ramka zbudowana z pojedynczej linii
FRAME_DOUBLE - ramka zbudowana z linii podwójnej
FRAME_SOLID - ramka wypełniona znakiem pełnym
FRAME_SHADED - ramka wypełniona znakiem cieniowanym

fillframe(rodzaj, atrybut, xb, yb, xe, ye)

Na obrzeżach zadanego obszaru okna konsoli (od pozycji (xb,yb) w lewym górnym narożniku, do pozycji (xe,ye) w prawym dolnym narożniku) rysowana jest ramka. Dodatkowo wnętrze obszaru zostaje wypełnione spacjami i atrybutem koloru. Nie zmienia się pozycja kursora tekstowego. Rodzaje ramek są takie same jak dla funkcji frame().

fullscreen(tryb)

Funkcja włącza tryb pełnoekranowy dla parametru tryb = true lub tryb pracy w oknie dla tryb = false. W trybie pełnoekranowym okno konsoli posiada 50 wierszy po 80 kolumn w każdym. Ekran nie może być przewijany. W trybie okienkowym liczba kolumn wynosi 80, lecz liczba wierszy może zależeć od ustawionego rozmiaru okna. Treść okna konsoli może być przewijana.

...
fullscreen(true); // włączenie trybu pełnoekranowego
...
fulscreen(false); // powrót do trybu okienkowego
...

Uwaga: Funkcja ta nie działa w systemie Windows 10/11. Aby Przejść w konsoli do trybu pełnoekranowego, należy nacisnąć kombinację klawiszy [lewy Alt + Enter].

getattrxy(x, y)

Funkcja odczytuje atrybut koloru z pozycji x,y ekranu konsoli.

getch()

Funkcja odczytuje klawisz naciśnięty na klawiaturze. Jeśli klawisz nie został naciśnięty, funkcja oczekuje na niego. Nadaje się zatem np. do wstrzymywania pracy programu aż do reakcji użytkownika.

Jeśli naciśnięto klawisz sterujący (np. klawisze kursora, F1..F12, PgUp, PgDn), to pierwsze wywołanie tej funkcji zwraca 0. Dopiero drugie wywołanie zwraca tzw. kod matrycowy klawisza sterującego. Kody matrycowe znajdziemy w kodzie programu przy definicji tablicy kbdtab[].

...
while(!getch()) ;  // oczekiwanie na dowolny klawisz.
...

getchxy(x, y)

Funkcja odczytuje kod ASCII znaku umieszczonego na pozycji x,y ekranu konsoli.

getrect(xb, yb, xe, ye)

Funkcja rezerwuje bufor dla zdefiniowanego w parametrach obszaru okna konsoli i umieszcza w tym buforze zawartość obszaru, po czym adres (wskaźnik) bufora jest zwracany jako wynik (jeśli wynikiem jest NULL, to obszar został błędnie zdefiniowany lub jest poza oknem konsoli). Funkcja ta została zaprojektowana do chwilowego przechowania fragmentu ekranu konsoli, na którym wyświetlono coś innego (np. komunikat). Funkcja współpracuje z funkcją putrect(), która odtwarza z bufora poprzednio zapamiętany obszar.

WORD * bufor;
...
if(!(bufor = getrect(10,10,69,14))
{
  ...             // robimy coś na obszarze 10,10 \ 69,14, np, wyświetlamy ostrzeżenie
  putrect(bufor); // odtwarzamy obszar i zwalniamy pamięć bufora
}

gotoxy(x,y)

Funkcja umieszcza kursor na pozycji x,y okna konsoli. Pierwszy zapis do okna rozpocznie się od tej pozycji.

...
gotoxy(37,12); cout << "HELLO";
...

highvideo()

Funkcja rozjaśnia kolor tekstu (o ile nie jest rozjaśniony), który zostanie po niej wypisany w oknie konsoli.

...
cout << _pl("Naciśnij klawisz ");
highvideo(); cout << "ENTER"; lowvideo();
cout << _pl(", aby zakończyć działanie programu...");
...

kbhit()

Funkcja sprawdza, czy na klawiaturze został naciśnięty jakiś klawisz. Jeśli tak, zwraca true. Inaczej zwraca false.

...
while(!kbhit())
{
    ...
}
...

lowvideo()

Funkcja przyciemnia kolor tekstu (o ile nie jest przyciemniony), który zostanie po niej wypisany w oknie konsoli.

...
cout << _pl("Naciśnij klawisz ");
highvideo(); cout << "ENTER"; lowvideo();
cout << _pl(", aby zakończyć działanie programu...");
...

putattrxy(atrybut, x, y)

Funkcja wprowadza atrybut koloru na pozycję x,y ekranu konsoli. Kolor znaku na tej pozycji oraz jego tła zostaną odpowiednio zmienione.

putchxy(znak, x, y)

Funkcja umieszcza znak na pozycji x,y ekranu konsoli. Atrybut tej pozycji nie jest zmieniany.

putrect(bufor)

Funkcja odtwarza obszar konsoli zapamiętany wcześniej za pomocą funkcji getrect(). Użyty do tego celu bufor jest po wykonaniu operacji zwalniany.

putxy(znak, atrybut, x, y)

Funkcja umieszcza podany znak oraz atrybut koloru na pozycji x,y ekranu konsoli.

scrollrect(kierunek, odległość, xb, yb, xe, ye)

Funkcja przesuwa treść obszaru zawartego w prostokącie od (xb,yb) do (xe,ye) w podanym kierunku i na zadaną odległość. Treść okna konsoli poza zdefiniowanym obszarem nie ulega zmianie. Po przesunięciu treści obszaru powstaje puste miejsce. Zostanie ono wypełnione spacjami w bieżącym kolorze tła i tekstu. Dozwolone kierunki przesuwu są następujące:

SCROLL_UP - przesuw w górę
SCROLL_RIGHT - przesuw w prawo
SCROLL_DOWN - przesuw w dół
SCROLL_LEFT - przesuw w lewo

textattr(atrybut)

Funkcja ustawia bieżący atrybut koloru. Po jej wywołaniu znaki wypisywane na konsoli będą posiadały kolory tekstu i tła zgodne z podanym atrybutem.

textbackground(kolor)

Funkcja ustawia kolor tła znaków. Kody kolorów (0...16) podaliśmy w tabelce na początku rozdziału. Zamiast wartości liczbowych można również stosować odpowiednie stałe, np. BLACK, YELLOW, WHITE itp. Po wywołaniu tej funkcji znaki zapisywane do konsoli będą posiadały zadany kolor tła.

textcolor(kolor)

Funkcja ustawia kolor znaków. Kody kolorów (0...16) podaliśmy w tabelce na początku rozdziału. Zamiast wartości liczbowych można również stosować odpowiednie stałe, np. BLACK, YELLOW, WHITE itp. Po wywołaniu tej funkcji znaki zapisywane do konsoli będą posiadały zadany kolor.

wherex()

Funkcja odczytuje numer kolumny ekranu konsoli zawierającej kursor.

wherey()

Funkcja odczytuje numer wiersza ekranu konsoli zawierającego kursor.


STAŁE KOLORÓW DLA KONSOLI
binarnie szesnastkowo dziesiętnie nazwa stałej kolor
0000 0 0 BLACK                 
0001 1 1 BLUE  
0010 2 2 GREEN  
0011 3 3 CYAN  
0100 4 4 RED  
0101 5 5 MAGENTA  
0110 6 6 BROWN  
0111 7 7 LIGHTGRAY  
1000 8 8 DARKGRAY  
1001 9 9 LIGHTBLUE  
1010 A 10 LIGHTGREEN  
1011 B 11 LIGHTCYAN  
1100 C 12 LIGHTRED  
1101 D 13 LIGHTMAGENTA  
1110 E 14 YELLOW  
1111 F 15 WHITE  

Na początek:  podrozdziału   strony 

Przykłady

W wybranych miejscach ekranu program wyświetla przypadkowe znaki.

// (C)2010 Koło Informatyczne I LO
//
// -------------------------------

#include "newconio.h"
#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;

int main()
{
    int key;
  
    _cinit();

    srand((unsigned)time(NULL)); 
  
    gotoxy(11,0);
    cout << _pl("Aby zakończyć działanie programu, naciśnij klawisz ");
    highvideo(); cout << "[ESC]"; lowvideo(); cout << ".";

    do
    {
      putchxy(rand() % 256, 1 + rand() % 78, 2 + rand() % 22);
      if(kbhit()) while(!(key = getch())) ;
    } while(key != 27); // powtarzamy aż do naciśnięcia ESC

    return 0;
}

obrazek


W wybranych miejscach ekranu program ustawia przypadkowe atrybuty.

// (C)2010 Koło Informatyczne I LO
//
// -------------------------------

#include "newconio.h"
#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;

int main()
{
    int key;
  
    _cinit();

    srand((unsigned)time(NULL)); 
  
    gotoxy(11,0);
    cout << _pl("Aby zakończyć działanie programu, naciśnij klawisz ");
    highvideo(); cout << "[ESC]"; lowvideo(); cout << ".";

    do
    {
      putattrxy(rand() % 256, 1 + rand() % 78, 2 + rand() % 22);
      if(kbhit()) while(!(key = getch())) ;
    } while(key != 27); // powtarzamy aż do naciśnięcia ESC

    return 0;
}

obrazek


Na ekranie konsoli przedstawione zostają wszystkie możliwe kombinacje kolorów tła i znaków (w sumie 256 możliwości).

// (C)2010 Koło Informatyczne I LO
//
// -------------------------------

#include "newconio.h"
#include <iostream>

using namespace std;

int main()
{
    int i,j;
  
    _cinit();

    gotoxy(11,0);
    cout << _pl("Aby zakończyć działanie programu, naciśnij klawisz ");
    highvideo(); cout << "[ESC]"; lowvideo(); cout << ".\n\n\n";
    for(i = 0; i < 16; i++)
    {
      gotoxy(8,wherey());
      for(j = 0; j < 16; j++)
      {
        textattr(i << 4 | j);
        cout << (char) 176 << (char) 177 << (char) 178 << (char) 219;
      }
      cout << endl;
    }

    while(getch() != 27); // Czekamy na klawisz ESC

    textattr(7);

    return 0;
}

obrazek


Na początek:  podrozdziału   strony 

Pliki

Plik newconio.h zawiera prototypy funkcji bibliotecznych oraz definicje stałych.

Zawartość pliku newconio.h
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//----------------------------------------------------------------
// plik nagłówkowy dla procedur obsługi konsoli znakowej w Windows
//                 (C)2006 mgr Jerzy Wałaszek
//----------------------------------------------------------------

#if !defined(__NEW_CON_FUNCT__)
#define __NEW_CON_FUNCT__

#include <windows.h>
#include <string>

using namespace std;

#if !defined(__COLORS)
#define __COLORS

enum COLORS
{
  BLACK,          // ciemne kolory
  BLUE,
  GREEN,
  CYAN,
  RED,
  MAGENTA,
  BROWN,
  LIGHTGRAY,
  DARKGRAY,       // jasne kolory
  LIGHTBLUE,
  LIGHTGREEN,
  LIGHTCYAN,
  LIGHTRED,
  LIGHTMAGENTA,
  YELLOW,
  WHITE
};

#endif

#if !defined(__FRAMES_TYPES__)
#define __FRAMES_TYPES__

enum FRAMES
{
  FRAME_EMPTY,
  FRAME_SINGLE,
  FRAME_DOUBLE,
  FRAME_SOLID,
  FRAME_SHADED
};

#endif

#if !defined(__SCROLL_DIRECTION__)
#define __SCROLL_DIRECTION__

enum SCROLLS
{
  SCROLL_UP,
  SCROLL_RIGHT,
  SCROLL_DOWN,
  SCROLL_LEFT
};

#endif

void _cinit(void);
string _pl(string);
void center(int,string);
void clrscr(void);
void cursoroff(void);
void cursoron(void);
void delay(int);
void fillrectattr(WORD,int,int,int,int);
void fillrectch(TCHAR,int,int,int,int);
void fillrect(TCHAR,WORD,int,int,int,int);
void frame(int,int,int,int,int,int);
void fillframe(int,int,int,int,int,int);
void fullscreen(bool);
int  getattrxy(int,int);
int  getch(void);
char getchxy(int,int);
WORD * getrect(int,int,int,int);
void gotoxy(int,int);
void highvideo(void);
bool kbhit(void);
void lowvideo(void);
void putattrxy(WORD,int,int);
void putchxy(TCHAR,int,int);
void putrect(WORD *);
void putxy(TCHAR,WORD,int,int);
void scrollrect(int,unsigned,int,int,int,int);
void textattr(int);
void textbackground(int);
void textcolor(int);
int  wherex(void);
int  wherey(void);

#endif //__NEW_CON_FUNCT__

Plik newconio.cpp zawiera definicje funkcji bibliotecznych.

Zawartość pliku newconio.cpp
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------
// Zbiór procedur obsługi konsoli znakowej w Windows
//          (C)2006 mgr Jerzy Wałaszek
//--------------------------------------------------

#include <iostream>
#include <windows.h>
#include <string>
#include "newconio.h"

using namespace std;

__declspec(dllimport) BOOL WINAPI SetConsoleDisplayMode(HANDLE,DWORD,PCOORD);

static WORD   _txattr;
static HANDLE _hcout,_hcin;
static int    _cextend = -1;

//----------------------------------------------------------------------
// Poniższa tablica odwzorowuje wirtualne kody klawiszy Windows na kody
// BIOS dla klawiatury IBM PC. Dla każdego wirtualnego kodu klawisza
// dostępne są cztery wartości BIOS: zwykła, z shift, z Ctrl i z Alt.
// Kombinacje klawiszy nie posiadające odpowiednika BIOS mają wartość
// -1 i są ignorowane. Rozszerzone klawisze (nie ze zbioru ASCII)
// mają ustawiony na 1 bit 8 przy pomocy makra EXT.
//----------------------------------------------------------------------

#define EXT(key)    ((key)+0x100)
#define ISEXT(val)  ((val)&0x100)
#define EXTVAL(val) ((val)&0xff)

struct kbd
{
    short keycode; // kod wirtualny
    short normal;  // normalny kod BIOS
    short shift;   // kod BIOS z shift
    short ctrl;    // kod BIOS z Ctrl
    short alt;     // kod BIOS z Alt
} kbdtab [] =
{
//  wirtualny     normalny   shift       ctrl         alt

  { VK_BACK,      0x08,       0x08,       0x7f,       EXT(14)  },
  { VK_TAB,       0x09,       EXT(15),    EXT(148),   EXT(165) },
  { VK_RETURN,    0x0d,       0x0d,       0x0a,       EXT(166) },
  { VK_ESCAPE,    0x1b,       0x1b,       0x1b,       EXT(1)   },
  { VK_SPACE,     0x20,       0x20,       EXT(3),     0x20,    },
  { '0',          '0',        ')',        -1,         EXT(129) },
  { '1',          '1',        '!',        -1,         EXT(120) },
  { '2',          '2',        '@',        EXT(3),     EXT(121) },
  { '3',          '3',        '#',        -1,         EXT(122) },
  { '4',          '4',        '$',        -1,         EXT(123) },
  { '5',          '5',        '%',        -1,         EXT(124) },
  { '6',          '6',        '^',        0x1e,       EXT(125) },
  { '7',          '7',        '&',        -1,         EXT(126) },
  { '8',          '8',        '*',        -1,         EXT(127) },
  { '9',          '9',        '(',        -1,         EXT(128) },

  { 'A',          'a',        'A',        0x01,       EXT(30)  },
  { 'B',          'b',        'B',        0x02,       EXT(48)  },
  { 'C',          'c',        'C',        0x03,       EXT(46)  },
  { 'D',          'd',        'D',        0x04,       EXT(32)  },
  { 'E',          'e',        'E',        0x05,       EXT(18)  },
  { 'F',          'f',        'F',        0x06,       EXT(33)  },
  { 'G',          'g',        'G',        0x07,       EXT(34)  },
  { 'H',          'h',        'H',        0x08,       EXT(35)  },
  { 'I',          'i',        'I',        0x09,       EXT(23)  },
  { 'J',          'j',        'J',        0x0a,       EXT(36)  },
  { 'K',          'k',        'K',        0x0b,       EXT(37)  },
  { 'L',          'l',        'L',        0x0c,       EXT(38)  },
  { 'M',          'm',        'M',        0x0d,       EXT(50)  },
  { 'N',          'n',        'N',        0x0e,       EXT(49)  },
  { 'O',          'o',        'O',        0x0f,       EXT(24)  },
  { 'P',          'p',        'P',        0x10,       EXT(25)  },
  { 'Q',          'q',        'Q',        0x11,       EXT(16)  },
  { 'R',          'r',        'R',        0x12,       EXT(19)  },
  { 'S',          's',        'S',        0x13,       EXT(31)  },
  { 'T',          't',        'T',        0x14,       EXT(20)  },
  { 'U',          'u',        'U',        0x15,       EXT(22)  },
  { 'V',          'v',        'V',        0x16,       EXT(47)  },
  { 'W',          'w',        'W',        0x17,       EXT(17)  },
  { 'X',          'x',        'X',        0x18,       EXT(45)  },
  { 'Y',          'y',        'Y',        0x19,       EXT(21)  },
  { 'Z',          'z',        'Z',        0x1a,       EXT(44)  },

  { VK_PRIOR,     EXT(73),    EXT(73),    EXT(132),   EXT(153) },
  { VK_NEXT,      EXT(81),    EXT(81),    EXT(118),   EXT(161) },
  { VK_END,       EXT(79),    EXT(79),    EXT(117),   EXT(159) },
  { VK_HOME,      EXT(71),    EXT(71),    EXT(119),   EXT(151) },
  { VK_LEFT,      EXT(75),    EXT(75),    EXT(115),   EXT(155) },
  { VK_UP,        EXT(72),    EXT(72),    EXT(141),   EXT(152) },
  { VK_RIGHT,     EXT(77),    EXT(77),    EXT(116),   EXT(157) },
  { VK_DOWN,      EXT(80),    EXT(80),    EXT(145),   EXT(160) },
  { VK_INSERT,    EXT(82),    EXT(82),    EXT(146),   EXT(162) },
  { VK_DELETE,    EXT(83),    EXT(83),    EXT(147),   EXT(163) },
  { VK_NUMPAD0,   '0',        EXT(82),    EXT(146),   -1       },
  { VK_NUMPAD1,   '1',        EXT(79),    EXT(117),   -1       },
  { VK_NUMPAD2,   '2',        EXT(80),    EXT(145),   -1       },
  { VK_NUMPAD3,   '3',        EXT(81),    EXT(118),   -1       },
  { VK_NUMPAD4,   '4',        EXT(75),    EXT(115),   -1       },
  { VK_NUMPAD5,   '5',        EXT(76),    EXT(143),   -1       },
  { VK_NUMPAD6,   '6',        EXT(77),    EXT(116),   -1       },
  { VK_NUMPAD7,   '7',        EXT(71),    EXT(119),   -1       },
  { VK_NUMPAD8,   '8',        EXT(72),    EXT(141),   -1       },
  { VK_NUMPAD9,   '9',        EXT(73),    EXT(132),   -1       },
  { VK_MULTIPLY,  '*',        '*',        EXT(150),   EXT(55)  },
  { VK_ADD,       '+',        '+',        EXT(144),   EXT(78)  },
  { VK_SUBTRACT,  '-',        '-',        EXT(142),   EXT(74)  },
  { VK_DECIMAL,   '.',        '.',        EXT(83),    EXT(147) },
  { VK_DIVIDE,    '/',        '/',        EXT(149),   EXT(164) },
  { VK_F1,        EXT(59),    EXT(84),    EXT(94),    EXT(104) },
  { VK_F2,        EXT(60),    EXT(85),    EXT(95),    EXT(105) },
  { VK_F3,        EXT(61),    EXT(86),    EXT(96),    EXT(106) },
  { VK_F4,        EXT(62),    EXT(87),    EXT(97),    EXT(107) },
  { VK_F5,        EXT(63),    EXT(88),    EXT(98),    EXT(108) },
  { VK_F6,        EXT(64),    EXT(89),    EXT(99),    EXT(109) },
  { VK_F7,        EXT(65),    EXT(90),    EXT(100),   EXT(110) },
  { VK_F8,        EXT(66),    EXT(91),    EXT(101),   EXT(111) },
  { VK_F9,        EXT(67),    EXT(92),    EXT(102),   EXT(112) },
  { VK_F10,       EXT(68),    EXT(93),    EXT(103),   EXT(113) },
  { VK_F11,       EXT(133),   EXT(135),   EXT(137),   EXT(139) },
  { VK_F12,       EXT(134),   EXT(136),   EXT(138),   EXT(140) },
  { 0xdc,         '\\',       '|',        0x1c,       EXT(43)  },
  { 0xbf,         '/',        '?',        -1,         EXT(53)  },
  { 0xbd,         '-',        '_',        0x1f,       EXT(130) },
  { 0xbb,         '=',        '+',        -1,         EXT(131) },
  { 0xdb,         '[',        '{',        0x1b,       EXT(26)  },
  { 0xdd,         ']',        '}',        0x1d,       EXT(27)  },
  { 0xba,         ';',        ':',        -1,         EXT(39)  },
  { 0xde,         '\'',       '"',        -1,         EXT(40)  },
  { 0xbc,         ',',        '<',        -1,         EXT(51)  },
  { 0xbe,         '.',        '>',        -1,         EXT(52)  },
  { 0xc0,         '`',        '~',        -1,         EXT(41)  },

  { -1,           -1,         -1,         -1,         -1       }  // KONIEC
};

// Funkcja inicjuje parametry konsoli - należy
// ją wywołać na samym początku programu
//--------------------------------------------

void _cinit()
{
  _hcout = GetStdHandle(STD_OUTPUT_HANDLE);
  _hcin  = GetStdHandle(STD_INPUT_HANDLE);
  _txattr = 7; // Czarne tło i białe znaki
  clrscr();
}

// Funkcja konwertuje tekst ze standardu Windows 1250
// na standard konsoli znakowej Latin II.
//---------------------------------------------------
// s - tekst kodowany wg Windows 1250
//---------------------------------------------------
string _pl(string s)
{
    for(unsigned i = 0; i < s.length(); i++)
        switch(s[i])
        {
            case 'ą' : s[i] = 165; break;
            case 'ć' : s[i] = 134; break;
            case 'ę' : s[i] = 169; break;
            case 'ł' : s[i] = 136; break;
            case 'ń' : s[i] = 228; break;
            case 'ó' : s[i] = 162; break;
            case 'ś' : s[i] = 152; break;
            case 'ż' : s[i] = 190; break;
            case 'ź' : s[i] = 171; break;
            case 'Ą' : s[i] = 164; break;
            case 'Ć' : s[i] = 143; break;
            case 'Ę' : s[i] = 168; break;
            case 'Ł' : s[i] = 157; break;
            case 'Ń' : s[i] = 227; break;
            case 'Ó' : s[i] = 224; break;
            case 'Ś' : s[i] = 151; break;
            case 'Ż' : s[i] = 189; break;
            case 'Ź' : s[i] = 141; break;
        }
    return s;
}

// Funkcja wyświetla zadany parametrem tekst
// na środku podanego wiersza konsoli
//------------------------------------------
void center(int y, string s)
{
  gotoxy((80 - s.length()) / 2, y);
  cout << s;
}

// Funkcja czyści ekran konsoli.
//------------------------------
void clrscr()
{
   COORD cpos = { 0, 0 };
   DWORD cwrt;
   CONSOLE_SCREEN_BUFFER_INFO cinf;
   DWORD csize;

   if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return;
   csize = cinf.dwSize.X * cinf.dwSize.Y;
   if(!FillConsoleOutputCharacter(_hcout,' ',csize,cpos,&cwrt)) return;
   if(!FillConsoleOutputAttribute(_hcout,_txattr,csize,cpos,&cwrt)) return;
   SetConsoleCursorPosition(_hcout, cpos);
   SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja wyłącza kursor
//-----------------------
void cursoroff()
{
  CONSOLE_CURSOR_INFO ccinf;

  GetConsoleCursorInfo(_hcout,&ccinf);
  ccinf.bVisible = false;
  SetConsoleCursorInfo(_hcout,&ccinf);
}

// Funkcja włącza kursor
//-----------------------
void cursoron()
{
  CONSOLE_CURSOR_INFO ccinf;

  GetConsoleCursorInfo(_hcout,&ccinf);
  ccinf.bVisible = true;
  SetConsoleCursorInfo(_hcout,&ccinf);
}

// Funkcja wstrzymuje wykonanie na zadaną
// liczbę milisekund
//---------------------------------------
// msec - liczba milisekund
//---------------------------------------
void delay(int msec)
{
  unsigned t1 = GetTickCount();
  while((GetTickCount() - t1) < (unsigned)msec) ;
}

// Funkcja wypełnia zadany obszar okna konsoli
// podanym atrybutem. Pozycja kursora oraz znaki
// zawarte w obszarze nie są zmieniane.
//----------------------------------------------
// attr - atrybut do wypełnienia obszaru
// xb,yb - współrzędne lewego górnego narożnika
// xe,ye - współrzędne prawego dolnego narożnika
//----------------------------------------------
void fillrectattr(WORD attr, int xb, int yb, int xe, int ye)
{
  CONSOLE_SCREEN_BUFFER_INFO cinf;
  COORD pos;
  DWORD crd;

  if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return;
  if((xb >= cinf.dwSize.X) || (yb >= cinf.dwSize.Y) ||
     (xe < xb) || (ye < yb) || (xe < 0) || (ye < 0)) return; // poza oknem
  if(xb < 0) xb = 0;
  if(yb < 0) yb = 0;
  if(xe >= cinf.dwSize.X) xe = cinf.dwSize.X - 1;
  if(ye >= cinf.dwSize.Y) ye = cinf.dwSize.Y - 1;
  DWORD len = xe - xb + 1;
  pos.X = xb;
  for(int i = yb; i <= ye; i++)
  {
    pos.Y = i;
    FillConsoleOutputAttribute(_hcout,attr,len,pos,&crd);
  }
}

// Funkcja wypełnia zadany obszar okna konsoli
// podanym znakiem. Pozycja kursora oraz atrybuty
// zawarte w obszarze nie są zmieniane.
//-----------------------------------------------
// c - znak do wypełnienia obszaru
// xb,yb - współrzędne lewego górnego narożnika
// xe,ye - współrzędne prawego dolnego narożnika
//-----------------------------------------------
void fillrectch(TCHAR c, int xb, int yb, int xe, int ye)
{
  CONSOLE_SCREEN_BUFFER_INFO cinf;
  COORD pos;
  DWORD crd;

  if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return;
  if((xb >= cinf.dwSize.X) || (yb >= cinf.dwSize.Y) ||
     (xe < xb) || (ye < yb) || (xe < 0) || (ye < 0)) return; // poza oknem
  if(xb < 0) xb = 0;
  if(yb < 0) yb = 0;
  if(xe >= cinf.dwSize.X) xe = cinf.dwSize.X - 1;
  if(ye >= cinf.dwSize.Y) ye = cinf.dwSize.Y - 1;
  DWORD len = xe - xb + 1;
  pos.X = xb;
  for(int i = yb; i <= ye; i++)
  {
    pos.Y = i;
    FillConsoleOutputCharacter(_hcout,c,len,pos,&crd);
  }
}

// Funkcja wypełnia zadany obszar okna konsoli
// podanym znakiem i atrybutem. Pozycja kursora
// nie jest zmieniana.
//----------------------------------------------
// c - znak do wypełnienia
// attr - atrybut do wypełnienia obszaru
// xb,yb - współrzędne lewego górnego narożnika
// xe,ye - współrzędne prawego dolnego narożnika
//----------------------------------------------
void fillrect(TCHAR c, WORD attr, int xb, int yb, int xe, int ye)
{
  CONSOLE_SCREEN_BUFFER_INFO cinf;
  COORD pos;
  DWORD crd;

  if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return;
  if((xb >= cinf.dwSize.X) || (yb >= cinf.dwSize.Y) ||
     (xe < xb) || (ye < yb) || (xe < 0) || (ye < 0)) return; // poza oknem
  if(xb < 0) xb = 0;
  if(yb < 0) yb = 0;
  if(xe >= cinf.dwSize.X) xe = cinf.dwSize.X - 1;
  if(ye >= cinf.dwSize.Y) ye = cinf.dwSize.Y - 1;
  DWORD len = xe - xb + 1;
  pos.X = xb;
  for(int i = yb; i <= ye; i++)
  {
    pos.Y = i;
    FillConsoleOutputCharacter(_hcout,c,len,pos,&crd);
    FillConsoleOutputAttribute(_hcout,attr,len,pos,&crd);
  }
}

// Funkcja rysuje prostokątną ramkę
// type - określa typ ramki. Dozwolone typy, to:
//        FRAME_EMPTY,FRAME_SINGLE,FRAME_DOUBLE,
//        FRAME_SOLID, FRAME_SHADED
// attr - określa atrybut koloru dla ramki
// xb,yb - współrzędne lewego górnego wierzchołka
// xe,ye - współrzędne dolnego prawego wierzchołka
//------------------------------------------------
void frame(int type,int attr,int xb,int yb,int xe,int ye)
{
  TCHAR c;

  if((xb >= xe) || (yb >= ye)) return;
  switch(type) // lewy górny róg
  {
    case FRAME_EMPTY : c =  32; break;
    case FRAME_SINGLE: c = 218; break;
    case FRAME_DOUBLE: c = 201; break;
    case FRAME_SOLID : c = 219; break;
    case FRAME_SHADED: c = 177; break;
  }
  fillrect(c,attr,xb,yb,xb,yb);
  switch(type) // lewy dolny róg
  {
    case FRAME_SINGLE: c = 192; break;
    case FRAME_DOUBLE: c = 200; break;
  }
  fillrect(c,attr,xb,ye,xb,ye);
  switch(type) // prawy górny róg
  {
    case FRAME_SINGLE: c = 191; break;
    case FRAME_DOUBLE: c = 187; break;
  }
  fillrect(c,attr,xe,yb,xe,yb);
  switch(type) // prawy dolny róg
  {
    case FRAME_SINGLE: c = 217; break;
    case FRAME_DOUBLE: c = 188; break;
  }
  fillrect(c,attr,xe,ye,xe,ye);
  switch(type) // góra i dół
  {
    case FRAME_SINGLE: c = 196; break;
    case FRAME_DOUBLE: c = 205; break;
  }
  fillrect(c,attr,xb + 1,yb,xe - 1,yb);
  fillrect(c,attr,xb + 1,ye,xe - 1,ye);
  switch(type) // lewy i prawy
  {
    case FRAME_SINGLE: c = 179; break;
    case FRAME_DOUBLE: c = 186; break;
  }
  fillrect(c,attr,xb,yb + 1,xb,ye - 1);
  fillrect(c,attr,xe,yb + 1,xe,ye - 1);
}

// Funkcja rysuje prostokątną ramkę z wypełnieniem
// type - określa typ ramki. Dozwolone typy, to:
//   FRAME_EMPTY  - ramka zbudowana ze spacji
//   FRAME_SINGLE - ramka pojedyncza
//   FRAME_DOUBLE - ramka podwójna
//   FRAME_SOLID  - ramka wypełniona znakiem pełnym
//   FRAME_SHADED - ramka wypełniona znakiem cieniowanym
// attr - określa atrybut koloru dla ramki i tła
// xb,yb - współrzędne lewego górnego wierzchołka
// xe,ye - współrzędne dolnego prawego wierzchołka
//------------------------------------------------
void fillframe(int type,int attr,int xb,int yb,int xe,int ye)
{
  frame(type,attr,xb,yb,xe,ye);
  fillrect(' ',attr,xb+1,yb+1,xe-1,ye-1);
}

// Funkcja przełącza okno konsoli w tryb pełnoekranowy
// lub okienkowy. Pełny ekran ma 80 kolumn x 50 wierszy
// mode = true  - pełny ekran
// mode = false - okno
//-----------------------------------------------------
void fullscreen(bool mode)
{
  COORD dim;
  SetConsoleDisplayMode(_hcout, mode ? 1 : 2, &dim);
}

// Funkcja odczytuje atrybut z pozycji x,y ekranu konsoli
//-------------------------------------------------------
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//-------------------------------------------------------
int getattrxy(int x, int y)
{
  COORD pos = {(short)x,(short)y};
  WORD attr;
  DWORD crd;

  ReadConsoleOutputAttribute(_hcout,&attr,1,pos,&crd);
  return attr;
}

// Funkcja odczytuje kod klawisza z bufora konsoli. Jeśli bufor jest pusty, czeka na klawisz.
// Odczytany znak nie pojawia się na ekranie. Jeśli naciśnięto klawisz sterujący, to pierwsze
// wywołanie funkcji zawsze zwraca kod 0. Drugie wywołanie zwraca kod klawiaturowy danego
// klawisza sterującego.
//-------------------------------------------------------------------------------------------
int getch()
{
  INPUT_RECORD inp;
  DWORD nread;
  DWORD kbdmode;
  struct kbd *k;
  int keycode, state, c;

// Jeśli poprzednie wywołanie zwróciło rozszerzony kod 0,
// zwracamy kod klawiaturowy tego klawisza.

  if(_cextend != -1)
  {
    c = _cextend;
    _cextend = -1; // Resetujemy znacznik
    return c;      // Zwracamy rozszerzony kod klawiaturowy
  }

// Pobieramy tryb pracy konsoli, a następnie ustawiamy go w tryb binarny.
// Robimy to, aby zapobiec przetwarzaniu przez Windows klawiszy sterujących
// np. Ctrl-C lub Ctrl-S.

  if(!GetConsoleMode(_hcin,&kbdmode)) return -1;
  if(!SetConsoleMode(_hcin,0))        return -1;

// Pobieramy zdarzenia klawiatury, aż napotkamy właściwe

  for (;;)
  {
    if(!ReadConsoleInput(_hcin, &inp, 1, &nread))
    {
      c = -1; break;
    }
    else if((inp.EventType == KEY_EVENT) && inp.Event.KeyEvent.bKeyDown)
    {
      keycode = inp.Event.KeyEvent.wVirtualKeyCode;
      state   = inp.Event.KeyEvent.dwControlKeyState;
      if((state & NUMLOCK_ON) && (keycode == VK_DELETE)) keycode = VK_DECIMAL;

// Poszukujemy wirtualnego kodu klawisza w tablicy. Ignorujemy
// nierozpoznane klawisze

      for(k = &kbdtab[0]; keycode != k->keycode && k->keycode != -1; k++) ;
      if(k->keycode == -1) continue; // wartość nieobecna w tablicy

// Sprawdzamy stan klawiszy sterujących. ALT posiada najwyższy priorytet
// następnie Ctrl i Shift. W zależności od stanu tych klawiszy
// wybieramy odpowiednią pozycję w tablicy

      if(state & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))        c = k->alt;
      else if(state & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) c = k->ctrl;
      else if(state & SHIFT_PRESSED)                            c = k->shift;
      else
      {

// Jeśli jest to klawisz znakowy, wykorzystujemy kod ASCII dostarczony
// przez Windows i uwzględniamy stan CapsLock.

        if(keycode >= 'A' && keycode <= 'Z')
          c = inp.Event.KeyEvent.uChar.AsciiChar;
        else
          c = k->normal;
      }
      if(c == -1) continue; // brak odpowiednika BIOS

// Jeśli jest to klawisz rozszerzony, zapamiętujemy jego kod
// i zwracamy 0.  Przy następnym wywołaniu zostanie zwrócona
// wartość klawisza.

      if(ISEXT(c))
      {
        _cextend = EXTVAL(c);
        c = 0;
      }
      break;
   }
  }

// Przywracamy normalny tryb pracy konsoli

  if(!SetConsoleMode(_hcin,kbdmode)) return -1;
  return c;
}

// Funkcja odczytuje znak z pozycji x,y ekranu konsoli
//----------------------------------------------------
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//----------------------------------------------------
char getchxy(int x, int y)
{
  COORD pos = {(short)x,(short)y};
  TCHAR c;
  DWORD crd;

  ReadConsoleOutputCharacter(_hcout,&c,1,pos,&crd);
  return c;
}

// Funkcja tworzy bufor na treść okna konsoli.
// Następnie umieszcza w tym buforze zawartość
// prostokątnego obszaru konsoli i zwraca
// wskazanie do bufora.
// xb,yb - współrzędne lewego górnego rogu
// xe,ye - współrzędna prawego dolnego rogu
//--------------------------------------------
WORD * getrect(int xb, int yb, int xe, int ye)
{
  CONSOLE_SCREEN_BUFFER_INFO cinf;
  COORD pos;
  DWORD crd;

  if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return NULL;
  if((xb >= cinf.dwSize.X) || (yb >= cinf.dwSize.Y) ||
     (xe < xb) || (ye < yb) || (xe < 0) || (ye < 0)) return NULL; // poza oknem
  if(xb < 0) xb = 0;
  if(yb < 0) yb = 0;
  if(xe >= cinf.dwSize.X) xe = cinf.dwSize.X - 1;
  if(ye >= cinf.dwSize.Y) ye = cinf.dwSize.Y - 1;
  DWORD len_x = xe - xb + 1;
  WORD * buf = new WORD[4 + 2 * len_x * (ye - yb + 1)];
  if(buf)
  {
    buf[0] = xb; buf[1] = yb; buf[2] = xe; buf[3] = ye; // współrzędne obszaru
    int j = 0;
    for(int i = yb; i <= ye; i++)
    {
      pos.X = xb; pos.Y = i;
      ReadConsoleOutputCharacter(_hcout,(CHAR *)(buf+4+(j++)*len_x),len_x,pos,&crd);
      ReadConsoleOutputAttribute(_hcout,buf+4+(j++)*len_x,len_x,pos,&crd);
    }
  }
  return buf;
}

// Funkcja umieszcza kursor na zadanej pozycji
//--------------------------------------------
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//--------------------------------------------
void gotoxy(int x, int y)
{
  COORD cpos = {(short)x,(short)y};
  SetConsoleCursorPosition(_hcout, cpos);
}

// Funkcja rozjaśnia kolor znaków
//-------------------------------
void highvideo()
{
  _txattr = _txattr | 0x8;
  SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja sprawdza, czy użytkownik nacisnął jakiś
// klawisz na klawiaturze. Jeśli tak, zwraca true.
//------------------------------------------------
bool kbhit()
{
  DWORD en, enr; // liczba zdarzeń oraz liczba odczytanych zdarzeń

  GetNumberOfConsoleInputEvents(_hcin, &en);
  INPUT_RECORD * ir = new INPUT_RECORD[en];  // przydzielamy pamięć
  PeekConsoleInput(_hcin, ir, en, &enr);     // odczytujemy zdarzenia

  for(DWORD i = 0; i < enr; i++)               // przeglądamy zdarzenia
  {
    if(ir[i].EventType & KEY_EVENT &&
       ir[i].Event.KeyEvent.bKeyDown)        // jeśli zdarzenie klawisza!
    {                                        // ale nie kontrolnego!
      if(ir[i].Event.KeyEvent.wVirtualKeyCode != VK_CONTROL &&
         ir[i].Event.KeyEvent.wVirtualKeyCode != VK_MENU &&
         ir[i].Event.KeyEvent.wVirtualKeyCode != VK_SHIFT)
      {
        delete ir; return true;              // klawisz w buforze konsoli
      }
    }
  }
  delete ir; return false;                   // bufor konsoli jest pusty
}

// Funkcja przyciemnia kolor znaków
//---------------------------------
void lowvideo()
{
  _txattr = _txattr & 0xf7;
  SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja zapisuje podany atrybut na pozycji x,y.
// Pozycja kursora i znak na tej pozycji nie są zmieniane
//-------------------------------------------------------
// attr - atrybut koloru
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//-------------------------------------------------------
void putattrxy(WORD attr, int x, int y)
{
  COORD pos = {(short)x,(short)y};
  DWORD cwrt;

  WriteConsoleOutputAttribute(_hcout,&attr,1,pos,&cwrt);
}

// Funkcja zapisuje podany znak na pozycji x,y.
// Pozycja kursora i atrybut pozycji nie są zmieniane.
//----------------------------------------------------
// c - znak ASCII do zapisu
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//----------------------------------------------------
void putchxy(TCHAR c, int x, int y)
{
  COORD pos = {(short)x,(short)y};
  DWORD cwrt;

  WriteConsoleOutputCharacter(_hcout,&c,1,pos,&cwrt);
}

// Funkcja odtwarza prostokątny obszar ekranu
// zapamiętany w buforze przez getrect(). Bufor
// jest zwalniany do puli pamięci systemu.
// buf - wskaźnik bufora z treścią obszaru
//---------------------------------------------
void putrect(WORD * buf)
{
  COORD pos;
  DWORD crd;

  if(!buf) return; // na wypadek, gdy bufor jest pusty!
  DWORD len_x = buf[2] - buf[0] + 1;
  int j = 0;
  for(int i = buf[1]; i <= buf[3]; i++)
  {
    pos.X = buf[0]; pos.Y = i;
    WriteConsoleOutputCharacter(_hcout,(CHAR *)(buf+4+(j++)*len_x),len_x,pos,&crd);
    WriteConsoleOutputAttribute(_hcout,buf+4+(j++)*len_x,len_x,pos,&crd);
  }
  delete buf;
}

// Funkcja zapisuje podany znak i atrybut na pozycji x,y.
// Pozycja kursora pozycji nie jest zmieniana.
//-------------------------------------------------------
// c - znak ASCII do zapisu
// attr - atrybut koloru
// x - pozycja w poziomie (0..79)
// y - pozycja w pionie   (0..49)
//-------------------------------------------------------
void putxy(TCHAR c, WORD attr, int x, int y)
{
  COORD pos = {(short)x,(short)y};
  DWORD cwrt;

  WriteConsoleOutputCharacter(_hcout,&c,1,pos,&cwrt);
  WriteConsoleOutputAttribute(_hcout,&attr,1,pos,&cwrt);
}

// Funkcja przesuwa zawartość prostokątnego obszaru
// w wyznaczonym kierunku o zadaną liczbę pozycji.
// Powstały pusty obszar wypełniony zostaje spacjami
// w aktualnym kolorze tła.
//------------------------------------------------------------------------
// dir - kierunek przesuwu okna. Dozwolone są następujące kierunki:
//   SCROLL_UP    - przesuw w górę
//   SCROLL_RIGHT - przesuw w prawo
//   SCROLL_DOWN  - przesuw w dół
//   SCROLL_LEFT  - przesuw w lewo
// howfar - określa liczbę kolumn lub wierszy, o które będzie przesunięcie
// xb,yb - współrzędna lewego górnego wierzchołka
// xe,ye - współrzędna prawego dolnego wierzchołka
//------------------------------------------------------------------------
void scrollrect(int dir, unsigned howfar, int xb, int yb, int xe, int ye)
{
  SMALL_RECT r,cr;
  COORD dest;
  CONSOLE_SCREEN_BUFFER_INFO cinf;

  if(!GetConsoleScreenBufferInfo(_hcout, &cinf)) return;
  if((xb >= cinf.dwSize.X) || (yb >= cinf.dwSize.Y) || (dir > 3) || !howfar ||
     (xe < xb) || (ye < yb) || (xe < 0) || (ye < 0)) return; // poza oknem
  if(xb < 0) xb = 0;
  if(yb < 0) yb = 0;
  if(xe >= cinf.dwSize.X) xe = cinf.dwSize.X - 1;
  if(ye >= cinf.dwSize.Y) ye = cinf.dwSize.Y - 1;
  dest.X = r.Left = cr.Left  = xb;
  dest.Y = r.Top  = cr.Top   = yb;
  r.Right  = cr.Right  = xe;
  r.Bottom = cr.Bottom = ye;
  switch(dir)
  {
    case SCROLL_UP    : r.Top    += howfar; break;
    case SCROLL_RIGHT : r.Right  -= howfar; dest.X += howfar; break;
    case SCROLL_DOWN  : r.Bottom -= howfar; dest.Y += howfar; break;
    case SCROLL_LEFT  : r.Left   += howfar; break;
  }
  CHAR_INFO chinf = {{' '},_txattr};
  ScrollConsoleScreenBuffer(_hcout,&r,&cr,dest,&chinf);
}

// Funkcja ustawia atrybut koloru
//-------------------------------
// attr - nowy atrybut
//-------------------------------
void textattr(int attr)
{
  _txattr = attr & 0xff;
  SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja ustawia kolor tła tekstu
//---------------------------------
// attr - kod koloru tekstu
//---------------------------------
void textbackground(int attr)
{
  _txattr = (_txattr & 0xf) | ((attr & 0xf) << 4);
  SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja ustawia kolor tekstu i tła
//--------------------------------------------
// attr - kod atrybutu dla koloru tekstu i tła
//--------------------------------------------
void textcolor(int attr)
{
  _txattr = (_txattr & 0xf0) | (attr & 0xf);
  SetConsoleTextAttribute(_hcout,_txattr);
}

// Funkcja odczytuje bieżącą pozycję x kursora
//--------------------------------------------
int wherex()
{
  CONSOLE_SCREEN_BUFFER_INFO sinf;

  GetConsoleScreenBufferInfo(_hcout,&sinf);
  return sinf.dwCursorPosition.X;
}

// Funkcja odczytuje bieżącą pozycję y kursora
//--------------------------------------------
int wherey()
{
  CONSOLE_SCREEN_BUFFER_INFO sinf;

  GetConsoleScreenBufferInfo(_hcout,&sinf);
  return sinf.dwCursorPosition.Y;
}

Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2024 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.