- •Отчет по учебной практике
- •Оглавление
- •Html. Web – презентация с использованием css.
- •Лабораторная работа № 1. Простейшее приложение
- •Лабораторная работа № 2. Клиентская область
- •Лабораторная работа № 4. Работа с таймером
- •Индивидуальное задание. Создание анимации
- •Лабораторная работа №1. Простейшее приложение Windows Forms
- •Лабораторная работа №2. Перекодировка текстового файла
- •Список литературы:
Лабораторная работа № 4. Работа с таймером
Цель:Изучить способы обработки событий в WinAPI. Рассмотреть функции KillTimer, SetTimer, InvalidateRectдля создания анимации.
Краткие теоретические сведения:
Функция InvalidateRect добавляет прямоугольник области обновления определяемого окна. Область модификации представляет собой часть клиентской области окна, что переписывается заново. Функция InvalidateRect добавляет прямоугольник области обновления определяемого окна. Область модификации представляет собой часть клиентской области окна, что переписывается заново.
SetTimer создает таймер с заданным значением времени ожидания.
KillTimer уничтожает заданный таймер.
ReleaseCapture освобождает мышь из окна в текущем потоке и восстанавливает нормальную обработку ввода мыши. Окно, которое захватило мышь получает весь ввод мыши, независимо от положения курсора, кроме случаев, когда нажатие кнопки мыши, когда курсор горячая точка находится в окне другого потока.
Задание:
4.1. Машинка движется по клиентской области слева направо, когда уходит за область, то вновь появляется слева или разворачивается и возвращается.
Дополнительные эффекты для учебной практики:
движение с ускорением/замедлением;
изменение цвета при приближении к стенке;
движение по наклонной;
видно вращение колес;
выезд за область постепенный, по частям машины.
Сообщения:
WM_CREATE – создать таймер;
WM_PAINT – нарисовать машинку в текущей позиции;
WM_TIMER – изменить текущую позицию машинки и сообщить о необходимости обновить клиентскую область.
4.2. Светофор. Обеспечить переключение цветов.
4.3. В клиентской области расположены три круга разных цветов. Щелчок левой кнопкой мыши по кругу приводит к его «миганию» (увеличение/уменьшение диаметра). Щелчок правой кнопкой мыши по кругу останавливает мигание.
Сообщения:
WM_CREATE – создать таймер;
WM_PAINT – нарисовать три круга в соответствующем состоянии;
WM_TIMER – изменить состояния кругов и сообщить о необходимости обновить клиентскую область;
WM_LBUTTONDOWN – добавить соответствующий круг к «мигающим» (функция GetPixel() позволит определить цвет пикселя, на который попал курсор мыши, и, следовательно, узнать, в область какого круга попал курсор мыши);
WM_RBUTTONDOWN – удалить соответствующий круг из «мигающих».
4.4. График функции
Нарисовать график функции y=f(x) на отрезке [a,b]. График масштабируется в зависимости от размеров клиентской области. Щелчок по графику приводит к отображению значений (x,y). Проверить для различных функций.
4.5. Шарик катится по синусоиде туда и обратно.
Анализ реализации алгоритма
В первом задании для обеспечения движения автомобиля по наклонной плоскости используем объект класса XFORM, позволяющий изменить систему координат. Чтобы показать вращение колес, применяю соответствующие тригонометрические функции. Используя специальные переменные при обработке сообщения WM_TIMER, придадим машине ускорение.
Исходный код:
lpXform.eM11 = sin(t);
lpXform.eM21 = cos(t);
lpXform.eM22 = -sin(t);
lpXform.eM12 = cos(t);
Rectangle(hdc, x - 120, -70, x - 20, -10);
Rectangle(hdc, x - 20, -70, x + 10, 10);
DeleteObject(hbrush1);
hbrush1 = CreateSolidBrush(RGB(255, 255, 0));
SelectObject(hdc, hbrush1);
Ellipse(hdc, x - 100, -80, x - 80, -60);
Ellipse(hdc, x - 30, -80, x - 10, -60);
DeleteObject(hbrush1);
Line(hdc, (x - 90) + 10 * sin(-x / 10), -80 + (10 - 10 * cos(-x / 10)), (x - 90) - 10 * sin(-x / 10), -(10 - 10 * cos(-x / 10)) - 60);
Line(hdc, (x - 20) + 10 * sin(-x / 10), (-80) + (10 - 10 * cos(-x / 10)), (x - 20) - 10 * sin(-x / 10), -(10 - 10 * cos(-x / 10)) - 60);
Скриншоты реализации можно просмотреть в приложении 2.
В третьем задании я изобразила несколько возможных состояний светофора. Переключение между ними происходит посредством счетчика, обработываемого в WM_TIMER.
Исходный код:
case WM_TIMER:
{
A[0]->red = A[1]->red = A[1]->green = A[2]->green = 100;
switch (Color)
{
case Red:
A[0]->red += 150;
Color = Yellow;
break;
case Yellow:
A[1]->red += 150;
A[1]->green += 150;
Color = Green;
break;
case Green:
A[2]->green += 150;
Color = Red;
break;
}
InvalidateRect (hWnd, NULL, true);
break;
}
Скриншоты реализации можно просмотреть в приложении 2.
В третьем задании, используя специально описанную структуру Circle, по нажатию соответствующей клавиши мыши изменяю значения ее полей. Для работы с неколькими кругами использую вектор заданного типа Circle. Нажатие левой клавиши мыши обрабатывается посредтсвом WM_LBUTTONDOWN, правой клавиши - WM_RBUTTONDOWN.
Исходный код:
case WM_LBUTTONDOWN:
{
hdc = GetDC(hWnd);
xMs = GET_X_LPARAM(lParam);
yMs = GET_Y_LPARAM(lParam);
COLORREF MsClick = GetPixel(hdc, xMs, yMs);
for (int i = 0; i < 3; ++i)
{
if ( MsClick == RGB(A[i]->red, A[i]->green, A[i]->blue) && condition[i] == NoBlink)
condition[i] = BlinkStandart;
}
InvalidateRect (hWnd, NULL, true);
break;
}
WM_RBUTTONDOWN работает аналогично.
Скриншоты реализации можно просмотреть в приложении 2.
В четвертом задании изобразили график и оси. Для того, чтобы определить, в какую часть клиентской области указал мышью пользователь, рассмотривается цвет соответствующего пикселя. Если он совпадает с цветом графика, то, можно пересчитать координаты графика и вывести их на экран с помощью текстового сообщения.
Исходный код:
case WM_CREATE:
{
GetClientRect(hwnd, &R);
T = new Table(R, marg,a,b);
F = new Function (T->GetCell(), T->GetMarg(), a, b);
}
case WM_PAINT:
{
hDC = GetDC(hwnd);
hDC = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &R);//
T = new Table(R, marg,a,b);//
F = new Function (T->GetCell(), T->GetMarg(), a, b);//
Point = T->DrawingTable(hDC);
F->Drawing(hDC, Point, Func);
EndPaint(hwnd, &ps);
break;
}
case WM_LBUTTONDOWN:
{
hDC = GetDC(hwnd);
xMs = GET_X_LPARAM(lParam);
yMs = GET_Y_LPARAM(lParam);
GetClientRect(hwnd, &R);//
T = new Table(R, marg,a,b);//
F = new Function (T->GetCell(), T->GetMarg(), a, b);//
Point = T->DrawingTable(hDC);//
if( F->HitTheTarget(xMs, yMs, Point, Func))
{
P = F->GetCoordinates(xMs, yMs, Point, Func);
F->DrawCoordinates(hDC, xMs, yMs, P);
}
break;
}
Скриншоты реализации можно просмотреть в приложении 2.
В пятом задании, произвольно определяя координату x, буду рассчитывать координату y с помощью функции синуса. Рассчитанные координаты считаю центром нашего круга. Радиус-вектор перемещаю, используя тригонометрические функции.
Исходный код:
void SetXC (double x0, int PixToCM)
{
double r = (double)R/PixToCM;
double cosin = cos(x0);
double xCG = x0 - r*cosin/sqrt(cosin*cosin+1);
double yCG = sin(x0) + sqrt(r*r - (x0-xCG)*(x0-xCG));
xC = xCG*PixToCM;
yC = rect.bottom/2 - (int)(yCG*PixToCM);
double xNEW = r*cos(alpha)+xCG, yNEW = r*sin(alpha)+yCG;
xN = xNEW*PixToCM;
yN = rect.bottom/2 - (int)(yNEW*PixToCM);
}
case WM_PAINT:
{
hdc = BeginPaint(hWnd,&ps);
int PixToCM = rect.right/15;
C.SetXC((double)x0/PixToCM, PixToCM);
HBRUSH hbro, hbr = CreateSolidBrush(C.Color);
hbro = (HBRUSH)SelectObject(hdc,hbr);
Ellipse (hdc, C.xC-C.R, C.yC-C.R, C.xC+C.R, C.yC+C.R);
DeleteObject(SelectObject(hdc,hbro));
HPEN oldpen, pen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
oldpen = (HPEN)SelectObject (hdc, pen);
MoveToEx(hdc, C.xC, C.yC, 0);
LineTo(hdc, C.xN, C.yN);
DeleteObject(SelectObject(hdc,oldpen));
for (int i=0; i<=rect.right; i++)
{
double xG, yG;
int yP;
xG = (double)i/PixToCM;
yG = sin(xG);
yP = yG*PixToCM;
SetPixel(hdc, i, rect.bottom/2 - yP, RGB(200,0,0));
}
EndPaint(hWnd,&ps);
break;
}
Скриншоты реализации можно просмотреть в приложении 2.
Выводы: Использовав функцииInvalidateRect, SetTimer, KillTimer, ReleaseCapture, описанные в кратких теоретических сведениях, а также функции BeginPaint, EndPaint, MessageBox, Ellipse и другие, изученные ранее, научилась обрабатывать события.
