#include #include #include #include #include "prog_res.h" #include "conf.h" #define SECTORS_MAX 6 #define WIN_TITLE L"Khalansky D. V., P3415, 11th variation" #define MAIN_WIN_CLASS L"Main window" #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define REDRAW RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW) struct diagram { BOOL present [SECTORS_MAX]; size_t sectors; }; void InitDiagram(struct diagram *diagram, size_t sectors) { diagram->sectors = sectors; for (size_t i = 0; i < SECTORS_MAX; ++i) { diagram->present[i] = i < sectors; } } void RemoveDiagramSlice(struct diagram *diagram, size_t slice) { if ((slice >= SECTORS_MAX) || (diagram->sectors == 1) || !diagram->present[slice]) return; diagram->present[slice] = FALSE; --diagram->sectors; } void DisplayAbout(HWND hWnd) { MessageBoxW(hWnd, L"This is a course task on Programming Technologies.", L"About", MB_ICONINFORMATION | MB_OK); } int GetSectorNumber(HWND hWnd, int x, int y, const struct diagram *d) { RECT rect; GetClientRect(hWnd,&rect); const int xc = (rect.right - rect.left) / 2, yc = (rect.bottom - rect.top) / 2, r = MIN(MIN(xc, yc), 300); if ((x - xc) * (x - xc) + (y - yc) * (y - yc) >= r * r) { return -1; } float ack = acos((yc - y) / (sqrt((x - xc) * (x - xc) + (y - yc) * (y - yc)))) * 180 / M_PI; if (x > xc) { ack = 360 - ack; } size_t k = (size_t)(ack * d->sectors / 360); size_t j = 0; for (size_t i = 0; i < k; ++i) { while (!d->present[j]) ++j; ++j; } return j; } void PaintDiagram(HWND hWnd, const struct diagram *d) { PAINTSTRUCT ps; RECT rect; HDC hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd,&rect); const LONG xc = (rect.right - rect.left) / 2, yc = (rect.bottom - rect.top) / 2, r = MIN(MIN(xc, yc), 300); FillRect(hdc, &rect, (HBRUSH) (COLOR_WINDOW)); size_t j = 0; for (size_t i = 0; i < d->sectors; ++i) { const float coeff = 360 / d->sectors; const float ang_st = 90 + i * coeff; const float ang_sw = coeff; WCHAR node[] = L"0"; while (!d->present[j]) ++j; node[0] += j; COLORREF bgcolor = RGB((2777 * j) % 256, (15353 * j) % 256, (23153 * j) % 256); COLORREF fgcolor = RGB(255 - GetRValue(bgcolor), 255 - GetGValue(bgcolor), 255 - GetBValue(bgcolor)); LONG ym = yc - r * sin((2 * ang_st + ang_sw) * M_PI / 360) / 2; LONG xm = xc + r * cos((2 * ang_st + ang_sw) * M_PI / 360) / 2; RECT nodeRect = { .top = ym - 15, .bottom = ym + 15, .left = xm - 15, .right = xm + 15 }; BeginPath(hdc); SetDCBrushColor(hdc, bgcolor); SelectObject(hdc, GetStockObject(DC_BRUSH)); MoveToEx(hdc, xc, yc, NULL); AngleArc(hdc, xc, yc, r, ang_st, ang_sw); LineTo(hdc, xc, yc); EndPath(hdc); StrokeAndFillPath(hdc); SetTextColor(hdc, fgcolor); SetBkMode(hdc, TRANSPARENT); DrawTextW(hdc, node, 1, &nodeRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); ++j; } EndPaint(hWnd, &ps); } LRESULT CALLBACK MainWindowProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { int sectors; static struct diagram diagram = { .sectors = 0 }; int sector_num; switch(msg) { case WM_SIZE: REDRAW; break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_ABOUT: DisplayAbout(hWnd); break; case IDM_CHOOSE: sectors = GetUserChoice(hWnd); if (sectors > 0) { InitDiagram(&diagram, sectors); REDRAW; } break; case IDM_EXIT: SendMessage(hWnd, WM_CLOSE, 0, 0); break; } break; case WM_LBUTTONDBLCLK: sector_num = GetSectorNumber(hWnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), &diagram); if (sector_num != -1) { RemoveDiagramSlice(&diagram, sector_num); REDRAW; } break; case WM_SYSKEYDOWN: if (wParam >= 0x30 && wParam <= 0x39 && GetAsyncKeyState(VK_MENU)) { sector_num = wParam & 0xF; RemoveDiagramSlice(&diagram, sector_num); REDRAW; } break; case WM_PAINT: PaintDiagram(hWnd, &diagram); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProcW(hWnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSW mainWc = {0}; mainWc.lpszClassName = MAIN_WIN_CLASS; mainWc.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU); mainWc.hInstance = hInstance; mainWc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); mainWc.lpfnWndProc = MainWindowProc; mainWc.hCursor = LoadCursor(0, IDC_ARROW); mainWc.style = CS_DBLCLKS; RegisterClassW(&mainWc); CreateWindowW(MAIN_WIN_CLASS, WIN_TITLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 250, NULL, NULL, hInstance, NULL); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }