Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This is a personal academic project. Dear PVS-Studio, please check it.
- // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdio.h>
- #include "graphical_output.h"
- int N_gl = 0;
- float *x_gl = NULL;
- float *A_gl = NULL;
- float *phi_gl = NULL;
- float *Re_gl = NULL;
- float *Im_gl = NULL;
- void draw_and_save_chart(int N, float *x, float *A, float *phi, float *Re, float *Im)
- {
- N_gl = N;
- x_gl = x;
- A_gl = A;
- phi_gl = phi;
- Re_gl = Re;
- Im_gl = Im;
- max_x = 1250;
- max_y = 700;
- initWindow();
- }
- void initWindow()
- {
- //Получаем хендл приложения, потребуется при создании класса окна и самого окна.
- HINSTANCE histance = GetModuleHandleW(NULL);
- //Создаем класс окна.
- WNDCLASSEX wclass = { 0 }; //Заполнять будем не все поля, остальные будут равны 0
- wclass.cbSize = sizeof(WNDCLASSEX); //По размеру структуры Windows определит, какая версия API была использована
- wclass.style = CS_HREDRAW | CS_VREDRAW; //Перерисовываться при изменении размеров окна
- wclass.lpfnWndProc = WndProc; //Указываем функцию обработки сообщений.
- wclass.hInstance = histance; //Указываем хендл приложения.
- wclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //GetStockObject возвращает хендл на белую кисточку, для фона окна
- wclass.lpszClassName = (LPCSTR)"CHARTS"; //Имя данного класса, должно быть уникальным, иначе, если класс с таким именем уже зарегестрирован, то в регистрации будет отказано.
- //Регистрируем класс окна.
- RegisterClassEx(&wclass);
- //Создаем окно.
- HWND window = CreateWindowExW(
- 0,
- L"CHARTS", //Имя класса.
- L"Charts", //Заголовок окна.
- WS_OVERLAPPEDWINDOW, //Тип окна, влияет на отображение системного меню, кнопок в верхнем правом углу и т.п.
- 0, 0, //Координаты окна.
- 1250, 750, //Ширина окна.
- 0, //Ссылка на родительское окно.
- 0, //Хендл меню.
- histance, //Хендл приложения, получаем его функцией GetModuleHandleW.
- 0
- );
- //Показываем окно, если этого не сделать окно не будет отображено.
- ShowWindow(window, SW_SHOW);
- //Обновляем окно.
- UpdateWindow(window);
- //Запускаем цикл обработки сообщений окна.
- MSG msg = { 0 };
- while (GetMessage(&msg, 0, 0, 0)) {
- TranslateMessage(&msg); //Преобразуем виртуальную клавишу в ASCII-код и посылаем сообщение WM_CHAR (тут не нужно.Необходимо, если надо работать с текстом, вводимым с клавиатуры)
- DispatchMessage(&msg); //Передаем сообщения для обработки в "главную функцию обработки сообщений"
- }
- return;
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps;
- RECT Rect;
- HDC hCmpDC;
- HBITMAP hBmp;
- switch (messg)
- {
- case WM_PAINT:
- GetClientRect(hWnd, &Rect);
- hdc = BeginPaint(hWnd, &ps);
- // Создание теневого контекста для двойной буферизации
- hCmpDC = CreateCompatibleDC(hdc);
- hBmp = CreateCompatibleBitmap(hdc, Rect.right - Rect.left,
- Rect.bottom - Rect.top);
- SelectObject(hCmpDC, hBmp);
- // Закраска фоновым цветом
- LOGBRUSH br;
- br.lbStyle = BS_SOLID;
- br.lbColor = 0xFFFFFF;
- HBRUSH brush;
- brush = CreateBrushIndirect(&br);
- FillRect(hCmpDC, &Rect, brush);
- DeleteObject(brush);
- draw_charts(hCmpDC, 30, 30);
- // Здесь рисуем на контексте hCmpDC
- SaveBMPFile("C:\\test\\chart.bmp", hBmp, hCmpDC, max_x - 20, max_y);
- // Копируем изображение из теневого контекста на экран
- SetStretchBltMode(hdc, COLORONCOLOR);
- BitBlt(hdc, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top,
- hCmpDC, 0, 0, SRCCOPY);
- // Удаляем ненужные системные объекты
- DeleteDC(hCmpDC);
- DeleteObject(hBmp);
- hCmpDC = NULL;
- EndPaint(hWnd, &ps);
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- default:
- return (DefWindowProc(hWnd, messg, wParam, lParam));
- }
- return (0);
- }
- void draw_charts(HDC hdc, int offset_x, int offset_y) {
- int cur_x, cur_y;
- int length_x, length_y;
- int i;
- char str[10];
- draw_X(hdc, offset_x, offset_y);
- //Четыре графика друг под другим
- length_x = max_x / 2 - 2 * offset_x;
- length_y = (max_y - 8 * offset_y) / 4;
- cur_x = max_x / 2 + offset_x;
- cur_y = offset_y;
- draw_point_chart(hdc, offset_x, offset_y, length_x, length_y, max_x/2 + offset_x, offset_y + length_y / 2, Re_gl, "u", "Re(F(u))");
- draw_point_chart(hdc, offset_x, offset_y, length_x, length_y, max_x/2 + offset_x, 3 * offset_y + length_y + length_y / 2, Im_gl, "u", "Im(F(u))");
- draw_point_chart(hdc, offset_x, offset_y, length_x, length_y, max_x/2 + offset_x, 5 * offset_y + 2 * length_y + length_y / 2, A_gl, "u", "A(u)");
- draw_point_chart(hdc, offset_x, offset_y, length_x, length_y, max_x/2 + offset_x, 7 * offset_y + 3 * length_y + length_y / 2, phi_gl, "u", "phi");
- }
- void draw_X(HDC hdc, int offset_x, int offset_y)
- {
- char str[10];
- int length_x, length_y;
- int cur_x, cur_y, prev_x, prev_y;
- int del_x, del_y;
- int i;
- float y_max = 0, y;
- length_x = max_x / 2 - 2 * offset_x;
- length_y = max_y - 4 * offset_y;
- MoveToEx(hdc, offset_x, 2 * offset_y, NULL); //Ось y
- LineTo(hdc, offset_x, 2 * offset_y + length_y);
- TextOut(hdc, offset_x - 20, 2 * offset_y - 10, L"X[k]", 1);
- MoveToEx(hdc, offset_x, length_y / 2 + 2 * offset_y, NULL); //Ось x
- LineTo(hdc, offset_x + length_x, length_y / 2 + 2 * offset_y);
- TextOut(hdc, offset_x + length_x, length_y / 2 + 2 * offset_y, L"k", 1);
- MoveToEx(hdc, offset_x - 3, 2 * offset_y + 5, NULL); //Стрелка на оси y
- LineTo(hdc, offset_x, 2 * offset_y);
- LineTo(hdc, offset_x + 3, 2 * offset_y + 5);
- MoveToEx(hdc, offset_x + length_x - 5, length_y / 2 + 2 * offset_y - 3, NULL); //Стрелка на оси x
- LineTo(hdc, offset_x + length_x, length_y / 2 + 2 * offset_y);
- LineTo(hdc, offset_x + length_x - 5, length_y / 2 + 2 * offset_y + 3);
- length_x -= 20;
- //length_y -= 20;
- cur_x = offset_x;
- cur_y = length_y / 2 + 2 * offset_y;
- del_x = length_x / (N_gl - 1);
- for (i = 0; i < N_gl; i++) //Подписи по оси x
- {
- MoveToEx(hdc, cur_x, cur_y - 3, NULL);
- LineTo(hdc, cur_x, cur_y + 3);
- sprintf(str, "%d", i);
- TextOut(hdc, cur_x + 1, cur_y + 3, str, strlen(str));
- cur_x += del_x;
- }
- for (i = 0; i < N_gl; i++) //Поиск максимального значения y
- {
- if (fabs(*(x_gl + i)) > fabs(y_max))
- {
- y_max = *(x_gl + i);
- }
- }
- del_y = fabs((length_y/2) / y_max);
- i = 0;
- y = *(x_gl + i);
- prev_x = offset_x + del_x * i;
- prev_y = length_y/2 + 2 * offset_y - del_y * y;
- MoveToEx(hdc, offset_x - 3, prev_y, NULL);
- LineTo(hdc, offset_x + 3, prev_y);
- sprintf(str, "%.1f", y);
- TextOut(hdc, 0, prev_y, str, strlen(str));
- for (i = 1; i < N_gl; i++)
- {
- y = *(x_gl + i);
- cur_x = offset_x + del_x * i;
- cur_y = length_y / 2 + 2 * offset_y - del_y * y;
- MoveToEx(hdc, prev_x, prev_y, NULL);
- LineTo(hdc, cur_x, cur_y);
- MoveToEx(hdc, offset_x - 3, cur_y, NULL);
- LineTo(hdc, offset_x + 3, cur_y);
- sprintf(str, "%.1f", y);
- TextOut(hdc, 0, cur_y, str, strlen(str));
- prev_x = cur_x;
- prev_y = cur_y;
- }
- }
- void draw_point_chart(HDC hdc, int offset_x, int offset_y, int length_x, int length_y, int zero_x, int zero_y, float *arr, char *x, char *y)
- {
- char str[10];
- int cur_x, cur_y;
- int del_x, del_y;
- int i;
- float y_max = 0, tmp;
- MoveToEx(hdc, zero_x, zero_y, NULL); //Горизонтальная ось
- LineTo(hdc, zero_x + length_x, zero_y);
- MoveToEx(hdc, zero_x, zero_y + length_y / 2, NULL); //Вертикальная ось
- LineTo(hdc, zero_x, zero_y - length_y / 2);
- MoveToEx(hdc, zero_x - 3, zero_y - length_y/2 + 3, NULL); //Стрелка на вертикальной оси
- LineTo(hdc, zero_x, zero_y - length_y / 2);
- LineTo(hdc, zero_x + 3, zero_y - length_y/2 + 3);
- MoveToEx(hdc, zero_x + length_x - 3, zero_y - 3, NULL); //Стрелка на горизонтальной оси
- LineTo(hdc, zero_x + length_x, zero_y);
- LineTo(hdc, zero_x + length_x - 3, zero_y + 3);
- length_x -= 20;
- for (i = 0; i < N_gl; i++) //Находим максимальное значение в массиве
- {
- tmp = *(arr + i);
- if (fabs(tmp) > fabs(y_max))
- {
- y_max = tmp;
- }
- }
- del_x = length_x / (N_gl - 1);
- del_y = fabs((length_y / 2) / y_max);
- cur_y = zero_y;
- cur_x = zero_x;
- for (i = 0; i < N_gl; i++) //Разметка по оси x
- {
- MoveToEx(hdc, cur_x, cur_y - 3, NULL);
- LineTo(hdc, cur_x, cur_y + 3);
- sprintf(str, "%d", i);
- TextOut(hdc, cur_x + 2, cur_y + 10, str, strlen(str));
- cur_x += del_x;
- }
- cur_x = zero_x;
- for (i = 0; i < N_gl; i++)
- {
- MoveToEx(hdc, cur_x, zero_y, NULL);
- cur_y = zero_y - *(arr + i) * del_y;
- LineTo(hdc, cur_x, cur_y);
- Ellipse(hdc, cur_x - 3, cur_y - 3, cur_x + 3, cur_y + 3);
- cur_x += del_x;
- }
- //TextOut(hdc, cur_x + length_x, cur_y, L"x", 1); //TODO
- TextOut(hdc, zero_x + length_x + 15, zero_y + 3, x, strlen(x)); //Подпись по горизонтальной оси
- TextOut(hdc, zero_x - 20, zero_y - length_y / 2 - 20, y, strlen(y)); //Подпись по вертикальной оси
- }
- /*void save_bmp_file(char *file_name)
- {
- }*/
- int SaveBMPFile(char *filename, HBITMAP bitmap, HDC bitmapDC, int width, int height) {
- HBITMAP OffscrBmp = NULL;
- HDC OffscrDC = NULL;
- LPBITMAPINFO lpbi = NULL;
- LPVOID lpvBits = NULL;
- HANDLE BmpFile = INVALID_HANDLE_VALUE;
- BITMAPFILEHEADER bmfh;
- if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, width, height)) == NULL)
- return 0;
- if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL)
- return 0;
- HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
- BitBlt(OffscrDC, 0, 0, width, height, bitmapDC, 0, 0, SRCCOPY);
- if ((lpbi = (LPBITMAPINFO)(malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)))) == NULL)
- return 0;
- ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
- lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- SelectObject(OffscrDC, OldBmp);
- if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, NULL, lpbi, DIB_RGB_COLORS))
- return 0;
- if ((lpvBits = malloc(lpbi->bmiHeader.biSizeImage)) == NULL)
- return 0;
- if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, lpvBits, lpbi, DIB_RGB_COLORS))
- return 0;
- if ((BmpFile = CreateFile(filename,
- GENERIC_WRITE,
- 0, NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL)) == INVALID_HANDLE_VALUE)
- return 0;
- DWORD Written;
- bmfh.bfType = 19778;
- bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
- if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
- return 0;
- if (Written < sizeof(bmfh))
- return 0;
- if (!WriteFile(BmpFile, &lpbi->bmiHeader, sizeof(BITMAPINFOHEADER), &Written, NULL))
- return 0;
- if (Written < sizeof(BITMAPINFOHEADER))
- return 0;
- int PalEntries;
- if (lpbi->bmiHeader.biCompression == BI_BITFIELDS)
- PalEntries = 3;
- else PalEntries = (lpbi->bmiHeader.biBitCount <= 8) ?
- (int)(1 << lpbi->bmiHeader.biBitCount) : 0;
- if (lpbi->bmiHeader.biClrUsed)
- PalEntries = lpbi->bmiHeader.biClrUsed;
- if (PalEntries) {
- if (!WriteFile(BmpFile, &lpbi->bmiColors, PalEntries * sizeof(RGBQUAD), &Written, NULL))
- return 0;
- if (Written < PalEntries * sizeof(RGBQUAD))
- return 0;
- }
- bmfh.bfOffBits = SetFilePointer(BmpFile, 0, 0, FILE_CURRENT);;
- if (!WriteFile(BmpFile, lpvBits, lpbi->bmiHeader.biSizeImage, &Written, NULL))
- return 0;
- if (Written < lpbi->bmiHeader.biSizeImage)
- return 0;
- bmfh.bfSize = SetFilePointer(BmpFile, 0, 0, FILE_CURRENT);
- SetFilePointer(BmpFile, 0, 0, FILE_BEGIN);
- if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
- return 0;
- if (Written < sizeof(bmfh))
- return 0;
- CloseHandle(BmpFile);
- free(lpvBits);
- free(lpbi);
- DeleteDC(OffscrDC);
- DeleteObject(OffscrBmp);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement