Добавил:
nyan
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
// lab2_IGS.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "lab2_IGS.h"
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
//название программы
WCHAR const szClassName[] = TEXT("Movement");
//заголовок окна
WCHAR const szWindowTitle[] = TEXT("Korneev V. Move, drawing in memory ");
//прототимы функций
BOOL RegisterApp(HINSTANCE hInst);
HWND CreateApp(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Move_OnCreate();
void Move_OnDestroy(HWND hwnd);
void Move_OnTimer(HWND hwnd);
void Move_OnKeydown(HWND hwnd);
void Move_OnPaint(HWND);
const int NN = 20;
//главная функция
//#pragma argsused
int PASCAL WinMain(HINSTANCE hInst, //дескриптор(идентификатор) программы
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
MSG msg; //структура для работы с сообщениями
if (!RegisterApp(hInst)) //регистрация окна
return FALSE;
if (!CreateApp(hInst, nCmdShow)) //создание окна
return FALSE;
while (GetMessage(&msg, NULL, 0, 0)) //цикл обработка сообщений
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//регистрация окна
BOOL RegisterApp(HINSTANCE hInst)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; //стиль окна
wc.lpfnWndProc = WndProc; //имя оконной процедуры
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst; //дескриптор программы
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //иконка
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //форма курсора
wc.hbrBackground = GetStockBrush(GRAY_BRUSH); //цвет окна
wc.lpszMenuName = TEXT("APP_MENU"); //имя меню окна
wc.lpszClassName = szClassName; //название программы
return RegisterClass(&wc); //регистрация окна
}
//создание окна
HWND CreateApp(HINSTANCE hInstance, int nCmdShow)
{
HWND hwnd; //дескриптор окна
hwnd = CreateWindow(szClassName, //название программы
szWindowTitle, //заголовок окна
WS_OVERLAPPEDWINDOW, //вид окна
CW_USEDEFAULT, //x - координата окна
CW_USEDEFAULT, //y - координата окна
CW_USEDEFAULT, //ширина окна
CW_USEDEFAULT, //высота окна
NULL,
NULL,
hInstance,
NULL);
if (hwnd == NULL)
return hwnd;
ShowWindow(hwnd, nCmdShow); //показать окно
UpdateWindow(hwnd); //обновить окно
return hwnd;
}
//оконная процедура обрабатывающая сообщения
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
Move_OnCreate();
break;
case WM_PAINT:
Move_OnPaint(hwnd);
break;
case WM_TIMER:
Move_OnTimer(hwnd);
break;
case WM_KEYDOWN:
Move_OnKeydown(hwnd);
break;
case WM_DESTROY:
Move_OnDestroy(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0L;
}
//размеры окна вывода в мировой системе координат
double xLeft, xRight, yBottom, yTop;
//размеры окна вывода в пикселах в окне программы
int nLeft, nRight, mBottom, mTop;
//переход от x к пикселу n
inline int xn(double x)
{
return (int)((x - xLeft) / (xRight - xLeft)*(nRight - nLeft)) + nLeft;
}
//переход от y к пикселу m
inline int ym(double y)
{
return (int)((y - yBottom) / (yTop - yBottom)*(mTop - mBottom)) + mBottom;
}
//класс для работы с матрицами аффинных преобразований
//используются однородные координаты
class Matrix2D
{
public:
double x[3][3];
Matrix2D(); //матрица единичная
void rotate(double fi); //матрица поворота
void displa(double kx, double ky); //матрица растяжения
void transl(double tx, double ty); //матрица трансляции
//перемножение матриц
friend Matrix2D operator * (const Matrix2D&, const Matrix2D&);
};
Matrix2D::Matrix2D()
{
x[0][0] = 1; x[0][1] = 0; x[0][2] = 0;
x[1][0] = 0; x[1][1] = 1; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::rotate(double fi)
{
double cosfi = cos(fi), sinfi = sin(fi);
x[0][0] = cosfi; x[0][1] = -sinfi; x[0][2] = 0;
x[1][0] = sinfi; x[1][1] = cosfi; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::displa(double kx, double ky)
{
x[0][0] = kx; x[0][1] = 0; x[0][2] = 0;
x[1][0] = 0; x[1][1] = ky; x[1][2] = 0;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
void Matrix2D::transl(double tx, double ty)
{
x[0][0] = 1; x[0][1] = 0; x[0][2] = tx;
x[1][0] = 0; x[1][1] = 1; x[1][2] = ty;
x[2][0] = 0; x[2][1] = 0; x[2][2] = 1;
}
Matrix2D operator * (const Matrix2D& a, const Matrix2D& b)
{
Matrix2D c;
double s;
for (int i = 0; i<3; i++)
for (int j = 0; j<3; j++)
{
s = 0;
for (int n = 0; n<3; n++)
s += a.x[i][n] * b.x[n][j];
c.x[i][j] = s;
}
return c;
}
struct Point
{
double x;
double y;
};
//аффинное преобразование координат точки P с помощью
//матрицы A
Point affine(Matrix2D A, Point P)
{
Point Pp;
Pp.x = A.x[0][0] * P.x + A.x[0][1] * P.y + A.x[0][2] * 1;
Pp.y = A.x[1][0] * P.x + A.x[1][1] * P.y + A.x[1][2] * 1;
return Pp;
}
//создаем 6 матриц аффинный преобразований
Matrix2D R, R1, T, D, A, T1, T2;
//флаг остановки и запуска таймера
int MoveStop;
//время задержки таймера
UINT uElapse;
//функция обрабатывающая сообщение WM_KEYDOWN
void Move_OnKeydown(HWND hwnd)
{
if (MoveStop == 0)
{
KillTimer(hwnd, 1);
MoveStop = 1;
}
else
{
SetTimer(hwnd, 1, uElapse, NULL);
MoveStop = 0;
}
}
//функция обрабатывает сообщение WM_DESTROY
void Move_OnDestroy(HWND hwnd)
{
KillTimer(hwnd, 1);
PostQuitMessage(0); //закрывает окно
}
class Ball
{
public:
Ball(){};
POINT pt[2];
//началтные и текущие точки цента стрелки
double xA0, yA0, xA2, yA2, xA1, yA1;
double l, m;
double tA, dtA, dtA0;
//координты вершин стрелки текущие и начальные
Point PtA[2];
Point PtA0[2];
COLORREF color = RGB(0,255, 0);
Point TrajA(double t)
{
Point P;
P.x = this->l * t - 5;
P.y = this->m * t - 4.2;
return P;
}
void Arrow(HDC hdc, Point *Pts, int N, double x1, double y1,
double x2, double y2, POINT *pts)
{
//создаем матрицы аффинного преобразования
T1.transl(-x1, -y1);
T.transl(x2 - x1, y2 - y1);
T2.transl(x1, y1);
A = T2*T*T1;
//совершаем аффинное преобразование точек фигуры
for (int n = 0; n<2; n++)
Pts[n] = affine(A, Pts[n]);
//b.PtA = Pt;
for (int i = 0; i < 2; i++)
{
pts[i].x = xn(Pts[i].x); pts[i].y = ym(Pts[i].y);
}
HBRUSH hbrush, hbrushOld;
HPEN hpen, hpenOld;
hbrush = CreateSolidBrush(this->color);
hbrushOld = (HBRUSH)SelectObject(hdc, hbrush); //выбираем кисть hbrush
hpen = CreatePen(PS_SOLID, 2, this->color);
hpenOld = (HPEN)SelectObject(hdc, hpen); // выбираем перо hpen
Ellipse(hdc, pts[0].x, pts[0].y, pts[1].x, pts[1].y);
SelectObject(hdc, hpenOld);
DeleteObject(hpen); //убираем перо hpen
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush); //убираем перо hpen
}
};
Ball b1[NN];
void Move_OnCreate()
{
//размеры поля вывода в мировых и экранных координатах
xLeft = -10; xRight = 10; yBottom = -6.0; yTop = 6.0;
nLeft = 50; nRight = 550; mTop = 50; mBottom = 350;
//начальные координты вершин стрелки
for (int i = 0; i < NN; i++){
b1[i].PtA0[0].x = 1.0; b1[i].PtA0[0].y = 0.0;
b1[i].PtA0[1].x = 0.0; b1[i].PtA0[1].y = 1.0;
b1[i].dtA0 = 0.04;
}
//время задержки таймера
uElapse = 25;
//флаг запуска таймера
MoveStop = 1;
}
//траектория стрелки
void Land(HDC hdc)
{
HBRUSH hbrush, hbrushOld;
HPEN hpen, hpenOld;
hbrush = CreateSolidBrush(RGB(0, 200, 0));
hbrushOld = (HBRUSH)SelectObject(hdc, hbrush); //выбираем кисть hbrush
hpen = CreatePen(PS_SOLID, 7, RGB(139, 69, 19));
hpenOld = (HPEN)SelectObject(hdc, hpen); // выбираем перо hpen
Rectangle(hdc, nLeft, mBottom, nRight, mTop);
SelectObject(hdc, hpenOld);
DeleteObject(hpen); //убираем перо hpen
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush); //убираем перо hpen
}
//рисует стрелку по координатам вершин Pt в точке x2, y2
//след от стрелки
/*void TracA(HDC hdc, double te, double dt)
{
double x, y, t;
t = 0;
x = TrajA(t,l,m).x;
y = TrajA(t, l, m).y;
HPEN hpen, hpenOld;
hpen = CreatePen(PS_SOLID, 2, RGB(255, 255, 0));
hpenOld = (HPEN)SelectObject(hdc, hpen); // выбираем перо hpen
MoveToEx(hdc, xn(x), ym(y), 0);
do{
t += dt;
x = TrajA(t, l, m).x;
y = TrajA(t, l, m).y;
LineTo(hdc, xn(x), ym(y));
} while (t < te);
SelectObject(hdc, hpenOld);
DeleteObject(hpen); //убираем перо hpen
}*/
//функция обрабатывает сообщение WM_PAINT
void Move_OnPaint(HWND hwnd)
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps); //получаем контекст устройства
HBRUSH hbrush, hbrushOld;
HPEN hpen, hpenOld;
hbrush = CreateSolidBrush(RGB(0, 200, 0));
hbrushOld = (HBRUSH)SelectObject(hdc, hbrush); //выбираем кисть hbrush
hpen = CreatePen(PS_SOLID, 7, RGB(139, 69, 19));
hpenOld = (HPEN)SelectObject(hdc, hpen); // выбираем перо hpen
Rectangle(hdc, nLeft, mBottom, nRight, mTop);
SelectObject(hdc, hpenOld);
DeleteObject(hpen); //убираем перо hpen
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush); //убираем перо hpen
//Land(hdc);
SetTextColor(hdc, RGB(230, 230, 220));
SetBkColor(hdc, RGB(0, 0, 0));
TextOut(hdc, 225, 100, TEXT(" P r e s s a n y k e y "), 27);
//начальный момент времени для стрелки
for (int i = 0; i < NN; i++)
{
b1[i].tA = 0; b1[i].dtA = b1[i].dtA0;
}
for (int i = 0; i < NN; i++)
{
b1[i].l = i + 1;
b1[i].m = i - 6;
b1[i].xA0 = b1[i].TrajA(b1[i].tA).x;
b1[i].yA0 = b1[i].TrajA(b1[i].tA).y;
for (int n = 0; n<2; n++)
b1[i].PtA[n] = b1[i].PtA0[n];
b1[i].Arrow(hdc, b1[i].PtA, 2, 0, 0, b1[i].xA0, b1[i].yA0, b1[i].pt);
b1[i].xA1 = b1[i].xA0; b1[i].yA1 = b1[i].yA0;
}
EndPaint(hwnd, &ps); //освобождаем контекст устройства
}
//функция обрабатывает сообщение WM_TIMER
void Move_OnTimer(HWND hwnd)
{
HDC hdcMem, hdcWin;
HBITMAP hBitmap, hBitmapOld;
hdcWin = GetDC(hwnd); //получаем контекст экрана
hdcMem = CreateCompatibleDC(hdcWin); //создаем контекст
//памяти связаный с контекстом экрана
//памяти надо придать вид экрана - подходт битовая карта с форматом
// как у экрана. В памяти будем рисовать на битовой карте
hBitmap = CreateCompatibleBitmap(hdcWin, nRight, mBottom); //создаем
//битовую карту совместмую с контекстом экрана
hBitmapOld = (HBITMAP)SelectObject(hdcMem, hBitmap); //помещаем
// битовую карту в контекст памяти
Land(hdcMem);
for (int i = 0; i < NN; i++){
b1[i].tA += b1[i].dtA;
b1[i].yA2 = b1[i].TrajA(b1[i].tA).y;
b1[i].xA2 = b1[i].TrajA(b1[i].tA).x;
if (b1[i].xA2 >= xRight - 1)
{
b1[i].xA2 = xRight - 1;
b1[i].color = RGB(200 - i*i, i*i*i, i+100);
b1[i].dtA = b1[i].dtA *(-1);
}else
if (b1[i].xA2 <= xLeft){
b1[i].yA2 = xLeft;
b1[i].color = RGB(90+i, 5*i*i*i, i);
b1[i].dtA = b1[i].dtA * (-1);
}else
if (b1[i].yA2 >= yTop - 1)
{
b1[i].yA2 = yTop - 1;
b1[i].color = RGB(10+2*i, 50 + i* 20, 250+i);
b1[i].dtA = b1[i].dtA*(-1);
}else
if(b1[i].yA2 <= yBottom){
b1[i].yA2 = yBottom;
b1[i].color = RGB(i*50, 90+i, 40+i);
b1[i].dtA = b1[i].dtA*(-1);
}
else{
b1[i].Arrow(hdcMem, b1[i].PtA, 2, b1[i].xA1, b1[i].yA1, b1[i].xA2, b1[i].yA2, b1[i].pt);
//TracA(hdcMem, tA, dtA);
b1[i].xA1 = b1[i].xA2; b1[i].yA1 = b1[i].yA2;
}
};
BitBlt(hdcWin, nLeft, mTop, nRight, mBottom, hdcMem, nLeft, mTop, SRCCOPY); //копи-
//руем контекст памяти в контекст экрана
SelectObject(hdcMem, hBitmapOld); //востанавливаем контекст памяти
DeleteObject(hBitmap); //убираем битовую карту
DeleteDC(hdcMem); // освобождаем контекст памяти
ReleaseDC(hwnd, hdcWin); //освобождаем контекст экрана
}