Функции отрисовки механизма
1) Введем функцию, для закрашивания всей области экрана фоном. Фон сделаем желтым и в клеточку (это удобный для восприятия глаз фон). Откроем MotorView.h, и впишем туда еще одну функцию:
class CMotorView : public CView
{
.
.
.
// Implementation
public:
int round(double z0);
void FindPointC();
void FindPointD();
void FindPointE();
void LeadOutParameters();
à void Background();
.
.
.
}
2) Далее опишем эту функцию в MotorView.cpp:
à void CMotorView::Background()
à {
à CClientDC dc(this);
à CPen newpen;
à CPen* oldpen;
à CBrush newbrush;
à CBrush* oldbrush;
à newbrush.CreateHatchBrush(PS_DASHDOTDOT,RGB(255,255,0));
à newpen.CreatePen(PS_SOLID,0,RGB(255,255,255));
à oldpen = dc.SelectObject(&newpen);
à oldbrush = dc.SelectObject(&newbrush);
à dc.Rectangle(0, 0, 3000, 2000);
à }
3) Теперь введем функцию для отрисовки механизма. Впишем ее в MotorView.h:
class CMotorView : public CView
{
.
.
.
// Implementation
public:
int round(double z0);
void FindPointC();
void FindPointD();
void FindPointE();
void LeadOutParameters();
void Background();
à void DRAW();
.
.
.
}
4) И разберемся в ее программном коде, который мы впишем в MotorView.cpp. Для начала запишем функции по нахождению координат точек механизма. После того, как эти функции все посчитают по нашим исходным данным, мы будем знать, откуда и куда нам чертить:
à void CMotorView::DRAW()
à {
à Bx = Ox + round(cos(a)*AB);
à By = Oy - round(sin(a)*AB);
à FindPointC();
à FindPointD();
à FindPointE();
à }
5) Теперь объявим контекст устройства для рисования, а также необходимый набор типов пера и кисти:
void CMotorView::DRAW()
{
Bx = Ox + round(cos(a)*AB);
By = Oy - round(sin(a)*AB);
FindPointC();
FindPointD();
FindPointE();
à CClientDC dc(this); // контекст устройства для рисования
à CPen newpen1, newpen2, newpen3; // объявление пера
à CPen* oldpen; // указатель на перо
à CBrush newbrush; // объявление кисти
à CBrush* oldbrush; // указатель на кисть
à newpen1.CreatePen(PS_SOLID,2,RGB(0,0,0));
à newpen2.CreatePen(PS_SOLID,0,RGB(255,255,255));
à newpen3.CreatePen(PS_SOLID,0,RGB(0,0,0));
à newbrush.CreateHatchBrush(PS_DASHDOT, RGB(0,0,0));
{
6) Мы задали типы пера:
newpen1 – чертит сплошную толстую линию черного цвета,
newpen2 – чертит сплошную тонкую линию белого цвета,
newpen3 – чертит сплошную тонкую линию черного цвета.
Тин кисти:
newbrush – закрашивает область штриховкой черного цвета.
Теперь установим кисть newpen3, и начертим две кулисы. Кулиса начнет чертиться от стойки до некоторой координаты, которая оптимизирована так, что камень не уйдет за ее пределы:
void CMotorView::DRAW()
{
Bx = Ox + round(cos(a)*AB);
By = Oy - round(sin(a)*AB);
FindPointC();
FindPointD();
FindPointE();
CClientDC dc(this);
CPen newpen1, newpen2, newpen3;
CPen* oldpen;
CBrush newbrush;
CBrush* oldbrush;
newpen1.CreatePen(PS_SOLID,2,RGB(0,0,0));
newpen2.CreatePen(PS_SOLID,0,RGB(255,255,255));
newpen3.CreatePen(PS_SOLID,0,RGB(0,0,0));
newbrush.CreateHatchBrush(PS_DASHDOT, RGB(0,0,0));
oldpen = dc.SelectObject(&newpen3);
à // Кулиса
à ACx = Ox + round(cos(a01)*(AB+BC+50));
à ACy = Oy - round(sin(a01)*(AB+BC+50));
à AEx = Ox + round(cos(a02)*(AB+BD+DE+50));
à AEy = Oy - round(sin(a02)*(AB+BD+DE+50));
à dc.MoveTo(Ox, Oy);
à dc.LineTo(ACx, ACy);
à dc.MoveTo(Ox, Oy);
à dc.LineTo(AEx, AEy);
}
7) Теперь нарисуем стойку. Она будет состоять из трех черных линий и прямоугольника, у которого будут белые границы, и который будет закрашен черной штриховкой. Дополним код функции DRAW():
void CMotorView::DRAW()
{
.
.
.
à //Стойка
à oldbrush = dc.SelectObject(&newbrush);
à oldpen = dc.SelectObject(&newpen2);
à dc.Rectangle(Ox-14, Oy+12, Ox+14, Oy+23);
à oldpen = dc.SelectObject(&newpen1);
à dc.MoveTo(Ox, Oy);
à dc.LineTo(Ox-7, Oy+12);
à dc.MoveTo(Ox, Oy);
à dc.LineTo(Ox+7, Oy+12);
à dc.MoveTo(Ox-12, Oy+12);
à dc.LineTo(Ox+12, Oy+12);
}
Рис. 3.6.1. Схема камня |
8) Камень рисуется по четырем точкам, координаты которых я связал с его центральной точкой следующим образом:
Глядя на схему, видно что координаты точек P, Q, R, и S, можно найти по формулам:
Дополним код функции DRAW():
void CMotorView::DRAW()
{
.
.
.
à // Камень
à oldpen = dc.SelectObject(&newpen1);
à dc.SelectStockObject(PS_SOLID);
à KC[0].x=Cx+round(cos(a01+aK)*dK);
à KC[0].y=Cy-round(sin(a01+aK)*dK);
à KC[1].x=Cx+round(cos(a01+PI-aK)*dK);
à KC[1].y=Cy-round(sin(a01+PI-aK)*dK);
à KC[2].x=Cx+round(cos(a01+PI+aK)*dK);
à KC[2].y=Cy-round(sin(a01+PI+aK)*dK);
à KC[3].x=Cx+round(cos(a01-aK)*dK);
à KC[3].y=Cy-round(sin(a01-aK)*dK);
à KE[0].x=Ex+round(cos(a02+aK)*dK);
à KE[0].y=Ey-round(sin(a02+aK)*dK);
à KE[1].x=Ex+round(cos(a02+PI-aK)*dK);
à KE[1].y=Ey-round(sin(a02+PI-aK)*dK);
à KE[2].x=Ex+round(cos(a02+PI+aK)*dK);
à KE[2].y=Ey-round(sin(a02+PI+aK)*dK);
à KE[3].x=Ex+round(cos(a02-aK)*dK);
à KE[3].y=Ey-round(sin(a02-aK)*dK);
à dc.Polygon(KC,4);
à dc.Polygon(KE,4);
}
9) Осталось только нарисовать звенья и шарниры. Дополним код функции DRAW():
void CMotorView::DRAW()
{
.
.
.
//Звенья
à dc.MoveTo(Bx, By);
à dc.LineTo(Ox, Oy);
à dc.MoveTo(Bx, By);
à dc.LineTo(Cx, Cy);
à dc.MoveTo(Bx, By);
à dc.LineTo(Dx, Dy);
à dc.MoveTo(Dx, Dy);
à dc.LineTo(Cx, Cy);
à dc.MoveTo(Dx, Dy);
à dc.LineTo(Ex, Ey);
à //Шарниры
à dc.Ellipse(Ox-3, Oy-3, Ox+3, Oy+3);
à dc.Ellipse(Bx-3, By-3, Bx+3, By+3);
à dc.Ellipse(Cx-3, Cy-3, Cx+3, Cy+3);
à dc.Ellipse(Dx-3, Dy-3, Dx+3, Dy+3);
à dc.Ellipse(Ex-3, Ey-3, Ex+3, Ey+3);
}
10) Теперь у нас есть все необходимые функции, чтобы мы могли нарисовать механизм. Впишем их в стандартную функцию OnDraw(CDC* pDC), для того чтобы увидеть механизм сразу после запуска приложения. Также функция OnDraw(CDC* pDC) постоянно обновляет клиентскую область окна. Откроем файл MotorView.cpp:
void CMotorView::OnDraw(CDC* pDC)
{
CMotorDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
à Background();
à LeadOutParameters();
à DRAW();
}
Рис. 3.6.2. Первый запуск программы |
На данном этапе уже можно откомпилировать программу и запустить приложение: