Spinner
#include <windows.h>
#include <math.h>
#define Pi 3.14159265
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void DrawSpinner(HWND hwnd, HDC hdc, double offset);
void DrowSotelit(HDC hdc, double alpha, double rcenter, double rsotelit);
TCHAR szTitle[] = L"Spinner";
TCHAR szWindowClass[] = L"spinner";
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX); //размер структуры
wcex.style = CS_HREDRAW | CS_VREDRAW; //задаем стиль окна, подробнее смотрите в MSDN
wcex.lpfnWndProc = (WNDPROC)WindowProcedure; //указываем оконную процедуру
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; //указываем дескриптор приложениея
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); //устанавливаем иконку приложения по умолчанию
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //устанавливаем курсор по умолчанию
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); //задаем цвет окна
wcex.lpszMenuName = 0; //меню окна - нет меню
wcex.lpszClassName = szWindowClass; //указываем класс окна
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //загружаем иконку окна
if (!RegisterClassEx(&wcex))
{
MessageBox(hWnd, L"Ошибка регистрации класса окна", L"Ошибка", IDI_ERROR || MB_OK);
return 1;
}
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(hWnd, L"Ошибка создания окна", L"Ошибка", IDI_ERROR || MB_OK); //в случае чего - говорим об ошибке
return 1;
}
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps; //структура для рисования
HDC hdc; //дескриптор устройства (монитор)
RECT rect; //область, где рисовать
static double offset = 0; //смещение для спиннера
SetTimer(hWnd, 1, 200, NULL); //устанавливаем таймер обновления рисунка
switch (message) //обрабатываем сообщения ос
{
case WM_TIMER: // если сообщение - сработал таймер, то...
GetClientRect(hWnd, &rect); //получаем рабочую область
InvalidateRect(hWnd, &rect, true); //объявляем ее недействительной
UpdateWindow(hWnd); //перерисовываем окно
offset+=0.3; //меняем значение смещения синусоиды
break;
case WM_PAINT: // если сообщение - перерисовать окно, то...
hdc = BeginPaint(hWnd, &ps); //получаем дескриптор устройства
DrawSpinner(hWnd, hdc, offset); //рисуем синусоиду
EndPaint(hWnd, &ps); //заканчиваем рисование
break;
case WM_DESTROY: // если сообщение - уничтожить окно, то...
PostQuitMessage(0); //посылаем "прощальное" сообщение операционке
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam); //обработка всех других сообщений
}
return 0;
}
void DrawSpinner(HWND hwnd, HDC hdc, double offset)
{
RECT rect;
GetClientRect(hwnd, &rect);
const int width = rect.right - rect.left;
const int height = rect.bottom - rect.top;
const double r = height / 10;
SetWindowExtEx(hdc, 500, 500, NULL);
SetViewportOrgEx(hdc, width / 2, height / 2, NULL);
//HPEN hPen1 = CreatePen(PS_SOLID, 3, RGB(144, 0, 32));
//SelectObject(hdc, hPen1);
//Ellipse(hdc, -r, r, r, -r); //центральный круг
//DrowSotelit(hdc, 0 + offset, r, r);
//DrowSotelit(hdc, 2*Pi/3 + offset, r, r);
//DrowSotelit(hdc, 4*Pi/3 + offset, r, r);
HPEN hPen2 = CreatePen(PS_SOLID, 3, RGB(144, 0, 32));
SelectObject(hdc, hPen2);
Ellipse(hdc, -r / 2 * 3, r / 2 * 3, r / 2 * 3, -r / 2 * 3); //центральный круг
Ellipse(hdc, -r / 2, r / 2, r / 2, -r / 2);
DrowSotelit(hdc, 0 + offset, r, r);
DrowSotelit(hdc, 2 * Pi / 3 + offset, r, r);
DrowSotelit(hdc, 4 * Pi / 3 + offset, r, r);
}
void DrowSotelit(HDC hdc, double alpha, double rcenter, double rsotelit)
{
double rvector = rcenter + rsotelit;
double a = sin(alpha)*rvector; //проекция радиус-вектора на OX
double b = cos(alpha)*rvector; //проекция радиус-вектора на OY
Ellipse(hdc, b - rsotelit, a + rsotelit, b + rsotelit, a - rsotelit);
}