Egyszerű rajzolás Windowson

A 2017-es fizikus évfolyam hallgatói hívták fel a figyelmemet arra, hogy a konzolablakba viszonylag egyszerűen rajzolhatunk. A sok, rendelkezésre álló funkció közül néhányat összegyűjtöttem egy példaprogramba, ez a 2. példa. Azért, hogy ne ijesszek el vele senkit, az egyik függvényrajzolást külön kiemeltem, ez lett az első példa.

A Google segítségével megtalálható a függvények leírása, ill. további függvények is, meg persze tőlem is lehet kérdezni.

1. Egyszerű példaprogram
#include <windows.h>
#include <math.h>

int main() {
    int i;

    // inicializálás
    HWND console = GetConsoleWindow();
    HDC hdc = GetDC(console);
    SelectObject(hdc, GetStockObject(DC_PEN));
    SelectObject(hdc, GetStockObject(DC_BRUSH));

    // R=red, G=green, B=blue, mindhárom 0...255-ig lehet
    // A rajzoló szín fehér legyen
    SetDCPenColor(hdc, RGB(255, 255, 255));

    // Felrajzoljuk a koordinátatengelyeket
    // Az ablak bal felső sarka a 0,0, az y tengely lefelé nő
    MoveToEx(hdc, 20, 20, (LPPOINT)NULL); // a vonal innen indul
    LineTo(hdc, 20, 200); // ebbe a pontba húzza a vonalat
    LineTo(hdc, 500, 200);

    // Vonalakból rajzolunk egy szinusz függvényt.
    SetDCPenColor(hdc, RGB(127, 255, 63));
    MoveToEx(hdc, 20, 200, (LPPOINT)NULL);
    for (i = 21; i < 500; i++)
        LineTo(hdc, i, 200 - (int)(90 * sin(4 * 3.1415*(i - 20.0) / (500 - 20))));

    // Ezt ne felejtsük!
    ReleaseDC(console, hdc);
    return 0;
}

 

2. További dolgokkal kiegészített példaprogram
#include <windows.h>
#include <math.h>
#include <conio.h>

int main() {
    int i;

    // inicializálás
    HWND console = GetConsoleWindow();
    HDC hdc = GetDC(console);
    SelectObject(hdc, GetStockObject(DC_PEN));
    SelectObject(hdc, GetStockObject(DC_BRUSH));

    // ha akarunk, változóban is tárolhatunk színt
    // R=red, G=green, B=blue, mindhárom 0...255-ig lehet
    COLORREF white = RGB(255, 255, 255);
   
    // A rajzoló szín fehér legyen
    SetDCPenColor(hdc, white);
    
    // Felrajzoljuk a koordinátatengelyeket
    // Az ablak bal felső sarka a 0,0, az y tengely lefelé nő
    MoveToEx(hdc, 20, 20, (LPPOINT)NULL); // a vonal innen indul
    LineTo(hdc, 20, 200); // ebbe a pontba húzza a vonalat
    LineTo(hdc, 500, 200);
    
    // Rajzolunk egy négyzetgyök függvényt pixelekből
    for (i = 25; i < 500; i++)
        SetPixelV(hdc, i, 195-(int)sqrt(40.0*(i-25)), RGB(0, 255, 255));

    // Most vonalakból rajzolunk egy szinusz függvényt. Ha vonalakból
    // rajzoljuk, akkor folytonos lesz, ha pixelekből, akkor lyukak
    // lehetnek a görbében a pixelek között
    SetDCPenColor(hdc, RGB(127, 255, 63));
    MoveToEx(hdc, 20, 200, (LPPOINT)NULL);
    for (i = 21; i < 500; i++)
        LineTo(hdc, i, 200-(int)(90*sin(4*3.1415*(i-20.0)/(500-20))));

    // A kitöltő szín (pl. téglalap vagy ellipszis belseje) piros
    SetDCBrushColor(hdc, RGB(255, 0, 0));
    SetDCPenColor(hdc, white);
    Rectangle(hdc, 100, 300, 200, 400);

    SetDCPenColor(hdc, RGB(0, 0, 255));
    SetDCBrushColor(hdc, RGB(255, 255, 0));

    // Kört rajzoluk kék kerettel és sárga kitöltéssel
    Ellipse(hdc, 300, 300, 400, 400);

    // Írjunk ki valamit!
    SetTextColor(hdc, white); // fehér szöveg
    SetBkMode(hdc, TRANSPARENT); // nincs háttérszín
    RECT rect; // Egy téglalap alakú területet adunk meg: ide íródik a szöveg
    rect.left = 20;
    rect.top = 201;
    rect.right = 500;
    rect.bottom = 250;
    LPCWSTR message = L"Ékezetes betűket is lehet használni";
    DrawText(hdc, message, -1, &rect, DT_SINGLELINE | DT_NOCLIP); // egy sorba, kilóghat a téglalapból
    SetPixelV(hdc, i, 1, 1); // Valamit rajzolunk a szöveg után, mert a szöveg csak 
                             // így jelenik meg. Van erre jobb megoldás?

    // A tevékenységünktől függő tartalom.
    SetDCPenColor(hdc, white);
    SetTextColor(hdc, RGB(0, 0, 0));
    COLORREF szintomb[6] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255),
        RGB(255, 255, 0), RGB(0, 255, 255), RGB(255, 255, 255) };
    const int kozep_x = 150, kozep_y = 150;
    char s[2] = "X"; // Egy karakternyi szöveget fogunk kiírni.
    wchar_t ws[2]; // De nem ASCII, hanem UNICODE formában.
    LPCWSTR ptr = ws; // A kiírandó szövegre mutató pointer.
    rect.left = kozep_x - 10;
    rect.top = kozep_y - 10;
    rect.right = kozep_x + 10;
    rect.bottom = kozep_y + 10;
    int ch = getch(); // Egy karakter beolvasása a billentyűzetről a conio.h függvényével.
                      // A leütött karakter nem jelenik meg a képernyőn (lásd getche())
    for (i = 1; ch!='q' && i <= 10; i++) { // max 10 billenytűleütés, de q-ra rögtön kilép
        // egyre nagyobb kört rajzolunk
        SetDCBrushColor(hdc, szintomb[ch % 6]); // A kör belsejének színe a leütött karaktertől függ
        Ellipse(hdc, kozep_x - i * 15, kozep_y - i * 15, kozep_x + i * 15, kozep_y + i * 15);

        s[0] = (ch>32 && ch<127) ? (char)ch : 'á'; // Ha nem látható ASCII karakter, 'á'-t írunk.
        mbstowcs(ws, s, strlen(s) + 1); // A C sztring UNICOD sztringgé konvertálása.
        DrawText(hdc, ptr, -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
        SetPixelV(hdc, i, 1, 1);

        ch = getch();
    }

    // Ezt ne felejtsük!
    ReleaseDC(console, hdc);
    return 0;
}