Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Последовательность выполнения. Задание для самостоятельной работы




Задание для самостоятельной работы

Цель. Создание окон произвольной формы. Обработка сообщений «мыши», системного таймера.

Задание. Разработать MFC приложение, реализующее построение графических окон двух типов:

 

 

а) б)

Каждое окно должно иметь единую базовую функциональность и обеспечивать: задание цвета окна, перемещение окна при помощи указателя мыши, анимацию окна изменением цвета от 0 до 360 в цветовом пространстве HSV

 

 

  1. Создать проект MFC Application
    1. Выполнить: File – New – Project – Other Languages – Visual C++ – MFC – MFC Application
    2. На вкладке Overview Нажать Next
    3. На вкладке Application Type установить Application Type = Dialog Based и нажать Finish
    4. Запустить проект и убедиться в отсутствии ошибок
  2. Подключить GDI+
    1. Произвести стандартное подлкючение в stdafx.h, stdafx.cpp
    2. Запуск GDI+ произвести в файле Lab4.cpp, в методе CLab4App::InitInstance() после вызова функции AfxEnableControlContainer
    3. Останов GDI+ произвести в том же файле Lab4.cpp, в том же методе CLab4App::InitInstance() перед командой return
    4. Запустить проект и убедиться в отсутствии ошибок
  3. Добавить в проект новый класс, который будет обладать свойством перемещения и анимации
    1. Project – Add Class – MFC Class
    2. Задать Class name: Widget, тип наследуемого окна оставить CWnd и нажать Finish.
    3. Запустить проект и убедиться в отсутствии ошибок
  4. Создать обработчки метода OnPaint для нового класса Widget
    1. В окне Class View выделить класс Widget
    2. В окне Properties выбрать группу Messages
    3. Добавить обработчик для сообщения WM_PAINT

CPaintDC dc(this);

Graphics graphics(dc.GetSafeHdc());

RECT rect;

// Получение прямоугольной области окна

GetClientRect(&rect);

// Формирование изображения в памяти

Bitmap bmp(rect.right, rect.bottom);

// Контекст рисования в памяти

Graphics g(&bmp);

 

g.FillRectangle(&SolidBrush(Color(0, 0, 255)), Rect(0, 0, rect.right, rect.bottom));

// Вывод построенного изображения на экран

graphics.DrawImage(&bmp, 0, 0);

    1. Запустить проект и убедиться в отсутствии ошибок

 

  1. Создать и отобразить объекты
    1. В файле Lab4Dlg.cpp в методе CLab4Dlg::OnInitDialog() перед командой return добавить команды создания объекта (не забыть подключить необходимый заголовочный файл)

Widget *widget = new Widget();

widget->Create(NULL, L"MyWidget", WS_CHILD|WS_VISIBLE, CRect(0, 0, 100, 100), this, 1234);

 

    1. В файле Lab4Dlg.h объявить объект для хранения списка указателей, который будет содержать общий перечень объектов Widget.

CPtrList widgets;

 

    1. В файле Lab4Dlg.cpp в методе CLab4Dlg::OnInitDialog() после создания объекта Widget поместить его в общий перечень объектов.

widgets.AddTail(widget);

 

    1. Запустить проект и убедиться в отсутствии ошибок

 

  1. Реализовать удаление объектов widgets, определив обработчик метода OnClose для CLab4Dlg
    1. В окне Class View выделить класс CLab4Dlg
    2. В окне Properties выбрать группу Messages
    3. Добавить обработчик для сообщения WM_CLOSE

while (widgets.IsEmpty() == false)

delete (Widget *)widgets.RemoveHead();

CDialog::OnClose();

 

    1. Запустить проект и убедиться в отсутствии ошибок

 

  1. Расширить интерфейс объекта Widget возможностями: удобного создания объекта, задания цвета объекта, изменения расположения объекта
    1. Определить более удобный метод создания объекта

int Widget::Create(CWnd *parent)

{

return CWnd::Create(NULL, L"MyWidget", WS_CHILD|WS_VISIBLE, CRect(0, 0, 100, 100), parent, 1234);

}

 

    1. Определить переменную для хранения цвета объекта

Color bkColor;

 

    1. Назначить цвет объекта по умолчанию в конструкторе класса Widget

bkColor.SetValue(Color::MakeARGB(255, 0, 0, 0));

 

    1. Поправить метод Widget::OnPaint таким образом, чтобы цвет кисти для закрашивания объекта соответствовал переменной bkColor
    2. Определить метод перемещения объекта в заданную точку с координатами x, y

void Widget::Move(int x, int y)

{

RECT rect;

GetWindowRect(&rect);

MoveWindow(x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);

}

    1. После проделанных манипуляций процедура создания и назначения свойств объекту widget может иметь следующий вид:

widget->Create(this);

widget->Move(150, 0);

widget->SetColor(Color(255, 0, 0));

    1. Запустить проект и убедиться в отсутствии ошибок
    2. Можно воспользоваться более интересным вариантом закрашивания прямоугольной области при помощи градиентной кисти

LinearGradientBrush linGrBrush(

PointF(0.0f, 0.0f),

PointF(rect.right*1.5, rect.bottom*1.5),

bkColor, Color(255, 255, 255));

 

  1. Реализовать возможность перемещения объекта Widget посредством указателя мыши
    1. Изменить метод Widget::OnPaint и добавить вывод текущих координат окна относительно родительского объекта
    2. Добавить объявление переменных в класс Widget

bool shouldMove;

CPoint clickPoint;

 

    1. Назначить значение параметра по умолчанию конструкторе класса Widget

shouldMove = false;

 

    1. Создать обработчик нажатия левой клавиши мыши

i. В окне Class View выделить класс Widget

ii. В окне Properties выбрать группу Messages

iii. Добавить обработчик для сообщения WM_LBUTTONDOWN

clickPoint = point;

// Включает отслеживание перемещений мыши данным объектом

SetCapture();

// Установить флаг "необходимо переместить"

shouldMove = true;

 

CWnd::OnLButtonDown(nFlags, point);

 

    1. Создать обработчик отжатия левой клавиши мыши

i. В окне Class View выделить класс Widget

ii. В окне Properties выбрать группу Messages

iii. Добавить обработчик для сообщения WM_LBUTTONUP

// Отключает отслеживание перемещений мыши

ReleaseCapture();

// Сбросить флаг "необходимо переместить"

shouldMove = false;

 

CWnd::OnLButtonUp(nFlags, point);

 

    1. Создать обработчик «отжатия» левой клавиши мыши

i. В окне Class View выделить класс Widget

ii. В окне Properties выбрать группу Messages

iii. Добавить обработчик для сообщения WM_MOUSEMOVE

if (shouldMove)

{

// Включает отслеживание перемещений мыши данным объектом

SetCapture();

 

RECT space;

// Получает параметры клиентской области родительского окна

GetParent()->GetClientRect(&space);

 

RECT rect;

// Получает параметры текущего окна в глобальных координатах

GetWindowRect(&rect);

// Переводит глобальные координаты текущего окна в координаты родительского окна

GetParent()->ScreenToClient(&rect);

 

int deltaX = point.x - clickPoint.x;

int deltaY = point.y - clickPoint.y;

 

// ограничивает перемещение объекта по Х внутри родительской области

if (rect.left + deltaX < space.top)

deltaX = space.left - rect.left;

else if (rect.right + deltaX > space.right)

deltaX = space.right - rect.right;

// ограничивает перемещение объекта по Y внутри родительской области

if (rect.top + deltaY < space.top)

deltaY = space.top - rect.top;

else if (rect.bottom + deltaY > space.bottom)

deltaY = space.bottom - rect.bottom;

 

// Перемещение окна в новую точку

Move(rect.left + deltaX, rect.top + deltaY);

// Перерисовка окна

Invalidate();

}

 

CWnd::OnMouseMove(nFlags, point);

 

    1. Запустить проект и убедиться в отсутствии ошибок

 

  1. Добавить возможность анимирования объекта. В качестве эффекта анимации применить изменение параметра цвет объекта от 0 до 360 в цветовом пространстве HSV
    1. Добавить объявление переменных в класс Widget

bool animationEnabled;

UINT_PTR timerId;

 

    1. Назначить значения параметров по умолчанию в конструкторе класса Widget

animationenabled = false;

timerId = 0;

 

    1. Поправить метод Widget::OnPaint таким образом, чтобы цвет кисти для закрашивания объекта соответствовал переменной bkColor
    2. Определить метод включения/отключения анимирования объекта

void Widget::SetAnimationEnabled(bool enable)

{

if (animationEnabled == enable)

return;

 

if (enable == false && timerId!= 0)

{

KillTimer(timerId);

timerId = 0;

}

if (enable == true && timerId == 0)

{

Hue = 0;

timerId = SetTimer(1, 100, NULL);

}

animationEnabled = enable;

}

    1. Запустить проект и убедиться в отсутствии ошибок

 

    1. Создать обработчик события срабатывания таймера

i. В окне Class View выделить класс Widget

ii. В окне Properties выбрать группу Messages

iii. Добавить обработчик для сообщения WM_TIMER

void Widget::OnTimer(UINT_PTR nIDEvent)

{

if (timerId)

{

// Команды, реализующие анимацию

...

// Произвести перерисовку объекта

Invalidate();

}

 

CWnd::OnTimer(nIDEvent);

}

    1. После проделанных манипуляций процедура включения анимирования объекта widget может иметь следующий вид:

widget->SetAnimationEnabled(true);

 

    1. Запустить проект и убедиться в отсутствии ошибок

 

  1. Создание графических окон произвольной формы

Для создания графического окна произвольной формы необходимо сформировать область при помощи класса Region из состава библиотек GDI+, а затем назначить методом SetWindowRgn форме очертание в соответствие с построенной областью.

    1. Добавить объявление переменных в класс Widget

GraphicsPath Path;

 

    1. Создать графическое окно следующего вида

 

i. В окне Class View выделить класс Widget

ii. В окне Properties выбрать группу Messages

iii. Добавить обработчик для сообщения WM_CREATE

 

if (CWnd::OnCreate(lpCreateStruct) == -1)

return -1;

 

// Создание объекта Graphics

Graphics g(this->m_hWnd);

 

const int edge = 70;

const int penWidth = 16;

 

// Выводит линию длиной = 2*edge - penWidth, толщиной = penWidth с началом в точке (penWidth/2, edge)

Path.AddLine(penWidth/2, edge, 2*edge - penWidth/2, edge);

// Объявление объекта матрицы преобразования

Matrix rotate;

// Создание матрицы поворота на -60 градусов относительно точки (edge, edge)

rotate.RotateAt(-60.0, PointF(edge, edge));

// Применение матрицы преобразования к объекту Path (то есть поворот линии на -60 градусов)

Path.Transform(&rotate);

// Окружность с радиусом = edge и координатой верхнего левого угла в точке (penWidth/2, penWidth/2)

Path.AddEllipse(penWidth/2, penWidth/2, 2*edge - penWidth, 2*edge - penWidth);

 

// Перо для отрисовки контура

Pen pen(Color(255, 0, 0, 0), penWidth);

 

// Расширение рисунка на толщину пера = penWidth

Path.Widen(&pen);

// Выделение из графического пути общего контура

Path.Outline();

 

// Объявление областей

Region rgn(&Path);

 

// Определение параметров области, занимаемой построенным объектом

Rect perfectRect;

rgn.GetBounds(&perfectRect, &g);

// Смешение области в точку с координатами (0, 0)

rgn.Translate(-perfectRect.X, -perfectRect.Y);

 

HRGN hrgn = rgn.GetHRGN(&g);

// Устанавливает контур окна на основе сформированной области hrgn

SetWindowRgn(hrgn, TRUE);

// Изменяет размеры объекта таким образом, чтобы они соответствовали области rgn

MoveWindow(lpCreateStruct->x, lpCreateStruct->y, perfectRect.Width, perfectRect.Height, FALSE);

return 0;

 

    1. Запустить проект и убедиться в отсутствии ошибок
    2. Самостоятельно создать графическое окно следующего вида




Поделиться с друзьями:


Дата добавления: 2014-12-07; Просмотров: 349; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.007 сек.