Загрузка данных


#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define KEY_UP    72
#define KEY_DOWN  80
#define KEY_LEFT  75
#define KEY_RIGHT 77
#define KEY_ENTER 13
#define KEY_ESC   27

HDC     hDC = NULL;
HWND    hWnd = NULL;
RECT    Rect;
HPEN    hPen, hOldPen;
HBRUSH  hBrush, hOldBrush;
HFONT   hFont, hOldFont;
LOGFONT g_lf = { 0 };

typedef struct {
    int         x, y, w, h;
    int         active;
    const char* text;
} Knopka;

typedef struct {
    Knopka* P;
    Knopka* H_P;
    int     n, m;
    int     is_minimized;
} Menu;

static void clear_screen(void)
{
    hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 180));
    hBrush = CreateSolidBrush(RGB(0, 0, 180));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Rectangle(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);
}

static void draw_triangle(int x, int y, int w, int h, int active)
{
    POINT shadow[3] = { {x + w / 2 + 4,y + 4}, {x + 4,y + h + 4}, {x + w + 4,y + h + 4} };
    hPen = CreatePen(PS_SOLID, 1, RGB(20, 20, 20));
    hBrush = CreateSolidBrush(RGB(40, 40, 40));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, shadow, 3);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT light[3] = { {x + w / 2,y}, {x,y + h}, {x + w / 2,y + h} };
    hPen = CreatePen(PS_SOLID, 1, RGB(220, 220, 220));
    hBrush = CreateSolidBrush(RGB(200, 200, 200));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, light, 3);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT dark[3] = { {x + w / 2,y}, {x + w,y + h}, {x + w / 2,y + h} };
    hPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));
    hBrush = CreateSolidBrush(RGB(120, 120, 120));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, dark, 3);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT pts[3] = { {x + w / 2,y}, {x,y + h}, {x + w,y + h} };
    if (active) {
        LOGBRUSH lb = { BS_SOLID, RGB(255, 0, 0), 0 };
        hPen = ExtCreatePen(PS_GEOMETRIC | PS_DASH, 2, &lb, 0, NULL);
    }
    else {
        hPen = CreatePen(PS_SOLID, 1, RGB(80, 80, 80));
    }
    hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, pts, 3);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush);
}

static void draw_diamond(int x, int y, int w, int h, int active)
{
    int cx = x + w / 2, cy = y + h / 2;

    POINT shadow[4] = { {cx + 4,y + 4}, {x + w + 4,cy + 4}, {cx + 4,y + h + 4}, {x + 4,cy + 4} };
    hPen = CreatePen(PS_SOLID, 1, RGB(20, 20, 20));
    hBrush = CreateSolidBrush(RGB(40, 40, 40));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, shadow, 4);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT top_half[4] = { {cx,y}, {x + w,cy}, {cx,cy}, {x,cy} };
    hPen = CreatePen(PS_SOLID, 1, RGB(220, 220, 220));
    hBrush = CreateSolidBrush(RGB(200, 200, 200));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, top_half, 4);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT bot_half[4] = { {cx,cy}, {x + w,cy}, {cx,y + h}, {x,cy} };
    hPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));
    hBrush = CreateSolidBrush(RGB(120, 120, 120));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, bot_half, 4);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    POINT pts[4] = { {cx,y}, {x + w,cy}, {cx,y + h}, {x,cy} };
    if (active) {
        LOGBRUSH lb = { BS_SOLID, RGB(255, 0, 0), 0 };
        hPen = ExtCreatePen(PS_GEOMETRIC | PS_DASH, 2, &lb, 0, NULL);
    }
    else {
        hPen = CreatePen(PS_SOLID, 1, RGB(80, 80, 80));
    }
    hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Polygon(hDC, pts, 4);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush);
}

static void draw_button(Knopka* p, int idx)
{
    if (idx % 2 == 0)
        draw_triangle(p->x, p->y, p->w, p->h, p->active);
    else
        draw_diamond(p->x, p->y, p->w, p->h, p->active);

    LOGFONT lf = g_lf;
    lf.lfHeight = 13;
    hFont = CreateFontIndirect(&lf);
    hOldFont = (HFONT)SelectObject(hDC, hFont);
    SetTextColor(hDC, RGB(255, 255, 255));
    SetBkMode(hDC, TRANSPARENT);
    int tx = p->x + p->w / 2 - (int)(strlen(p->text) * 3);
    int ty = p->y + p->h + 3;
    TextOutA(hDC, tx, ty, p->text, (int)strlen(p->text));
    SelectObject(hDC, hOldFont); DeleteObject(hFont);
}

static void draw_panel(Menu* M)
{
    if (M->is_minimized) {
        int p_top = Rect.bottom - 70 - 5;
        int p_bottom = Rect.bottom - 5;
        int p_left = 12;
        int p_right = Rect.right - 12;

        for (int i = 0; i < M->n; i++)
            M->H_P[i].y = p_top + 8;

        hPen = CreatePen(PS_SOLID, 1, RGB(20, 20, 20));
        hBrush = CreateSolidBrush(RGB(30, 30, 30));
        hOldPen = (HPEN)SelectObject(hDC, hPen);
        hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
        Rectangle(hDC, p_left + 2, p_top + 2, p_right + 2, p_bottom + 2);
        SelectObject(hDC, hOldPen); DeleteObject(hPen);
        SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

        hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
        hBrush = CreateSolidBrush(RGB(140, 140, 140));
        hOldPen = (HPEN)SelectObject(hDC, hPen);
        hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
        Rectangle(hDC, p_left, p_top, p_right, p_bottom);
        SelectObject(hDC, hOldPen); DeleteObject(hPen);
        SelectObject(hDC, hOldBrush); DeleteObject(hBrush);
        return;
    }

    int px = 14, py = 14;
    int pw = M->P[0].w + 40;
    int ph = M->n * (M->P[0].h + M->P[0].h / 2 + 20) + 20;

    hPen = CreatePen(PS_SOLID, 1, RGB(20, 20, 20));
    hBrush = CreateSolidBrush(RGB(30, 30, 30));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Rectangle(hDC, px + 6, py + 6, px + pw + 6, py + ph + 6);
    SelectObject(hDC, hOldPen); DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
    hBrush = CreateSolidBrush(RGB(140, 140, 140));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Rectangle(hDC, px, py, px + pw, py + ph);
    SelectObject(hDC, hOldPen); DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);
}

static Menu menu_init(const char** texts, int n, int bw, int bh)
{
    Menu M;
    M.n = n; M.m = 0; M.is_minimized = 0;
    M.P = (Knopka*)malloc(n * sizeof(Knopka));
    M.H_P = (Knopka*)malloc(n * sizeof(Knopka));

    int sv = bh + bh / 2 + 20;
    for (int i = 0; i < n; i++) {
        M.P[i].x = 25; M.P[i].y = 25 + i * sv;
        M.P[i].w = bw; M.P[i].h = bh;
        M.P[i].active = (i == 0) ? 1 : 0;
        M.P[i].text = texts[i];

        M.H_P[i].x = 22 + i * (50 + 15); M.H_P[i].y = 0;
        M.H_P[i].w = 50;             M.H_P[i].h = 30;
        M.H_P[i].active = (i == 0) ? 1 : 0;
        M.H_P[i].text = texts[i];
    }
    return M;
}

static void menu_del(Menu* M)
{
    free(M->P);
    free(M->H_P);
}

static void update_hbutton_y(Menu* M)
{
    GetClientRect(hWnd, &Rect);
    int p_top = Rect.bottom - 70 - 5;
    for (int i = 0; i < M->n; i++)
        M->H_P[i].y = p_top + 8;
}

static void render_menu(Menu* M)
{
    GetClientRect(hWnd, &Rect);
    clear_screen();
    draw_panel(M);

    if (!M->is_minimized) {
        for (int i = 0; i < M->n; i++) {
            M->P[i].active = (M->m == i) ? 1 : 0;
            draw_button(&M->P[i], i);
        }
    }
    else {
        update_hbutton_y(M);
        for (int i = 0; i < M->n; i++) {
            M->H_P[i].active = (M->m == i) ? 1 : 0;
            draw_button(&M->H_P[i], i);
        }
    }
}

static int menu_run(Menu* M)
{
    int ch;
    render_menu(M);
    do {
        ch = _getch();
        if (ch == 0 || ch == 224) {
            ch = _getch();
            if (!M->is_minimized) {
                if (ch == KEY_UP)   M->m = (M->m == 0) ? M->n - 1 : M->m - 1;
                else if (ch == KEY_DOWN) M->m = (M->m == M->n - 1) ? 0 : M->m + 1;
            }
            else {
                if (ch == KEY_LEFT)  M->m = (M->m == 0) ? M->n - 1 : M->m - 1;
                else if (ch == KEY_RIGHT) M->m = (M->m == M->n - 1) ? 0 : M->m + 1;
            }
            render_menu(M);
        }
        else if (ch == KEY_ESC) {
            return -1;
        }
    } while (ch != KEY_ENTER);
    return M->m;
}

static void action_move_down(Menu* M)
{
    GetClientRect(hWnd, &Rect);
    int ph = M->n * (M->P[0].h + M->P[0].h / 2 + 20) + 20;
    int new_y = Rect.bottom - ph - 20;
    if (new_y < 0) new_y = 0;
    int dy = new_y - M->P[0].y;
    for (int i = 0; i < M->n; i++)
        M->P[i].y += dy;
}

static void action_minimize(Menu* M)
{
    M->is_minimized = 1;
    update_hbutton_y(M);
}

static void action_restore(Menu* M)
{
    M->is_minimized = 0;
    int sv = M->P[0].h + M->P[0].h / 2 + 20;
    for (int i = 0; i < M->n; i++) {
        M->P[i].x = 25;
        M->P[i].y = 25 + i * sv;
    }
}

static void show_hatching(void)
{
    GetClientRect(hWnd, &Rect);
    int cx = (Rect.right + Rect.left) / 2;
    int cy = (Rect.bottom + Rect.top) / 2;
    int pw = 420, ph = 240;
    int px = cx - pw / 2, py = cy - ph / 2;

    hPen = CreatePen(PS_SOLID, 1, RGB(10, 10, 10));
    hBrush = CreateSolidBrush(RGB(20, 20, 20));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Rectangle(hDC, px + 6, py + 6, px + pw + 6, py + ph + 6);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
    hBrush = CreateSolidBrush(RGB(240, 240, 240));
    hOldPen = (HPEN)SelectObject(hDC, hPen);
    hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
    Rectangle(hDC, px, py, px + pw, py + ph);
    SelectObject(hDC, hOldPen);   DeleteObject(hPen);
    SelectObject(hDC, hOldBrush); DeleteObject(hBrush);

    LOGFONT tlf = g_lf; tlf.lfHeight = 18;
    hFont = CreateFontIndirect(&tlf);
    hOldFont = (HFONT)SelectObject(hDC, hFont);
    SetTextColor(hDC, RGB(0, 0, 100));
    SetBkMode(hDC, TRANSPARENT);
    TextOutA(hDC, px + 20, py + 15, "VARIANT 18 - Hatching / No Hatching", 35);
    SelectObject(hDC, hOldFont); DeleteObject(hFont);

    {
        POINT tri[3] = { {px + 80,py + 60}, {px + 20,py + 170}, {px + 140,py + 170} };
        hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 150));
        hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 150));
        hOldPen = (HPEN)SelectObject(hDC, hPen);
        hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
        Polygon(hDC, tri, 3);
        SelectObject(hDC, hOldPen);   DeleteObject(hPen);
        SelectObject(hDC, hOldBrush); DeleteObject(hBrush);
    }
    {
        POINT tri[3] = { {px + 210,py + 60}, {px + 150,py + 170}, {px + 270,py + 170} };
        hPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 150));
        hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
        hOldPen = (HPEN)SelectObject(hDC, hPen);
        hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
        Polygon(hDC, tri, 3);
        SelectObject(hDC, hOldPen);   DeleteObject(hPen);
        SelectObject(hDC, hOldBrush);
    }
    {
        POINT dia[4] = { {px + 340,py + 60}, {px + 400,py + 115}, {px + 340,py + 170}, {px + 280,py + 115} };
        hPen = CreatePen(PS_SOLID, 2, RGB(150, 0, 0));
        hBrush = CreateHatchBrush(HS_CROSS, RGB(150, 0, 0));
        hOldPen = (HPEN)SelectObject(hDC, hPen);
        hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
        Polygon(hDC, dia, 4);
        SelectObject(hDC, hOldPen);   DeleteObject(hPen);
        SelectObject(hDC, hOldBrush); DeleteObject(hBrush);
    }

    hFont = CreateFontIndirect(&g_lf);
    hOldFont = (HFONT)SelectObject(hDC, hFont);
    SetTextColor(hDC, RGB(30, 30, 30));
    TextOutA(hDC, px + 45, py + 180, "Hatching", 8);
    TextOutA(hDC, px + 160, py + 180, "No Hatching", 11);
    TextOutA(hDC, px + 290, py + 180, "Rhombus+Hatch", 13);
    SelectObject(hDC, hOldFont); DeleteObject(hFont);

    _getch();
}

int main(void)
{
    g_lf.lfHeight = 16;
    g_lf.lfWidth = 0;
    g_lf.lfWeight = FW_BOLD;
    g_lf.lfCharSet = DEFAULT_CHARSET;
    wcscpy(g_lf.lfFaceName, L"Arial");

    hWnd = GetConsoleWindow();
    if (!hWnd) { printf("Cant get hWnd\n"); (void)_getch(); return -1; }

    ShowScrollBar(hWnd, SB_BOTH, FALSE);

    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode = 0;
    GetConsoleMode(hIn, &mode);
    mode &= ~ENABLE_QUICK_EDIT_MODE;
    mode &= ~ENABLE_MOUSE_INPUT;
    mode |= ENABLE_EXTENDED_FLAGS;
    SetConsoleMode(hIn, mode);

    MoveWindow(hWnd, 30, 30, 860, 640, TRUE);

    hDC = GetDC(hWnd);
    if (!hDC) { printf("Cant get DC\n"); (void)_getch(); return -2; }

    GetClientRect(hWnd, &Rect);

    const char* texts[] = { "5.Down", "12.Min", "13.Max", "Exit" };
    int n = 4;

    Menu M = menu_init(texts, n, 160, 35);

    int sel;
    do {
        sel = menu_run(&M);
        if (sel < 0) break;
        switch (sel) {
        case 0: action_move_down(&M); break;
        case 1: action_minimize(&M);  break;
        case 2: action_restore(&M);   break;
        case 3: break;
        }
    } while (sel != 3);

    if (sel == 3) show_hatching();

    menu_del(&M);
    ReleaseDC(hWnd, hDC);
    return 0;
}