· перемещение окна при помощи «мыши»
· простейший приём анимации изображения
Приложение «Анимация»
5.1 Иерархия классов MFC


5.2 Отправка оконных сообщений
Центральной функцией приложения Windows является WindowProc, которая обрабатывает сообщения uMsg, предназначенные для окна hWnd.


5.3 Задание для самостоятельной работы
Цель. Создание окон произвольной формы. Обработка сообщений «мыши», системного таймера.
Задание. Разработать MFC приложение, реализующее построение графических окон двух типов:


а) б)
Каждое окно должно иметь единую базовую функциональность и обеспечивать: задание цвета окна, перемещение окна при помощи указателя мыши, анимацию окна изменением цвета от 0 до 360 в цветовом пространстве HSV
Последовательность выполнения
Создать проект MFC Application Выполнить: File – New – Project – Other Languages – Visual C++ – MFC – MFC Application На вкладке Overview Нажать Next На вкладке Application Type установить Application Type = Dialog Based и нажать Finish Запустить проект и убедиться в отсутствии ошибок Подключить GDI+ Произвести стандартное подлкючение в stdafx. h, stdafx. cpp Запуск GDI+ произвести в файле Lab4.cpp, в методе CLab4App::InitInstance()после вызова функции AfxEnableControlContainer Останов GDI+ произвести в том же файле Lab4.cpp, в том же методе CLab4App::InitInstance() перед командой return Запустить проект и убедиться в отсутствии ошибок Добавить в проект новый класс, который будет обладать свойством перемещения и анимации Project – Add Class – MFC Class Задать Class name: Widget, тип наследуемого окна оставить CWnd и нажать Finish. Запустить проект и убедиться в отсутствии ошибок Создать обработчки метода OnPaint для нового класса Widget В окне Class View выделить класс Widget В окне Properties выбрать группу Messages Добавить обработчик для сообщения WM_PAINTCPaintDC 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);
Запустить проект и убедиться в отсутствии ошибок Создать и отобразить объекты В файле 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);
В файле Lab4Dlg. h объявить объект для хранения списка указателей, который будет содержать общий перечень объектов Widget.CPtrList widgets;
В файле Lab4Dlg. cpp в методе CLab4Dlg::OnInitDialog() после создания объекта Widget поместить его в общий перечень объектов.widgets. AddTail(widget);
Запустить проект и убедиться в отсутствии ошибок Реализовать удаление объектов widgets, определив обработчик метода OnClose для CLab4Dlg В окне Class View выделить класс CLab4Dlg В окне Properties выбрать группу Messages Добавить обработчик для сообщения WM_CLOSEwhile (widgets.IsEmpty() == false)
delete (Widget *)widgets.RemoveHead();
CDialog::OnClose();
Запустить проект и убедиться в отсутствии ошибок Расширить интерфейс объекта Widget возможностями: удобного создания объекта, задания цвета объекта, изменения расположения объекта Определить более удобный метод создания объектаint Widget::Create(CWnd *parent)
{
return CWnd::Create(NULL, L"MyWidget", WS_CHILD|WS_VISIBLE, CRect(0, 0, 100, 100), parent, 1234);
}
Определить переменную для хранения цвета объектаColor bkColor;
Назначить цвет объекта по умолчанию в конструкторе класса WidgetbkColor.SetValue(Color::MakeARGB(255, 0, 0, 0));
Поправить метод Widget::OnPaint таким образом, чтобы цвет кисти для закрашивания объекта соответствовал переменной bkColor Определить метод перемещения объекта в заданную точку с координатами x, yvoid Widget::Move(int x, int y)
{
RECT rect;
GetWindowRect(&rect);
MoveWindow(x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}
После проделанных манипуляций процедура создания и назначения свойств объекту widget может иметь следующий вид:widget->Create(this);
widget->Move(150, 0);
widget->SetColor(Color(255, 0, 0));
Запустить проект и убедиться в отсутствии ошибок Можно воспользоваться более интересным вариантом закрашивания прямоугольной области при помощи градиентной кистиLinearGradientBrush linGrBrush(
PointF(0.0f, 0.0f),
PointF(rect.right*1.5, rect.bottom*1.5),
bkColor, Color(255, 255, 255));
Реализовать возможность перемещения объекта Widget посредством указателя мыши Изменить метод Widget::OnPaint и добавить вывод текущих координат окна относительно родительского объекта Добавить объявление переменных в класс Widgetbool shouldMove;
CPoint clickPoint;
Назначить значение параметра по умолчанию конструкторе класса WidgetshouldMove = false;
i. В окне Class View выделить класс Widget
ii. В окне Properties выбрать группу Messages
iii. Добавить обработчик для сообщения WM_LBUTTONDOWN
clickPoint = point;
// Включает отслеживание перемещений мыши данным объектом
SetCapture();
// Установить флаг "необходимо переместить"
shouldMove = true;
CWnd::OnLButtonDown(nFlags, point);
Создать обработчик отжатия левой клавиши мышиi. В окне Class View выделить класс Widget
ii. В окне Properties выбрать группу Messages
iii. Добавить обработчик для сообщения WM_LBUTTONUP
// Отключает отслеживание перемещений мыши
ReleaseCapture();
// Сбросить флаг "необходимо переместить"
shouldMove = false;
CWnd::OnLButtonUp(nFlags, point);
Создать обработчик «отжатия» левой клавиши мыши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);
Запустить проект и убедиться в отсутствии ошибок Добавить возможность анимирования объекта. В качестве эффекта анимации применить изменение параметра цвет объекта от 0 до 360 в цветовом пространстве HSV Добавить объявление переменных в класс Widgetbool animationEnabled;
UINT_PTR timerId;
Назначить значения параметров по умолчанию в конструкторе класса Widgetanimationenabled = false;
timerId = 0;
Поправить метод Widget::OnPaint таким образом, чтобы цвет кисти для закрашивания объекта соответствовал переменной bkColor Определить метод включения/отключения анимирования объекта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;
}
Запустить проект и убедиться в отсутствии ошибок Создать обработчик события срабатывания таймераi. В окне Class View выделить класс Widget
ii. В окне Properties выбрать группу Messages
iii. Добавить обработчик для сообщения WM_TIMER
void Widget::OnTimer(UINT_PTR nIDEvent)
{
if (timerId)
{
// Команды, реализующие анимацию
...
// Произвести перерисовку объекта
Invalidate();
}
CWnd::OnTimer(nIDEvent);
}
После проделанных манипуляций процедура включения анимирования объекта widget может иметь следующий вид:widget->SetAnimationEnabled(true);
Запустить проект и убедиться в отсутствии ошибок Создание графических окон произвольной формыДля создания графического окна произвольной формы необходимо сформировать область при помощи класса Region из состава библиотек GDI+, а затем назначить методом SetWindowRgn форме очертание в соответствие с построенной областью.
Добавить объявление переменных в класс WidgetGraphicsPath Path;
Создать графическое окно следующего вида
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;
Запустить проект и убедиться в отсутствии ошибок Самостоятельно создать графическое окно следующего вида
6 Создание пользовательской библиотеки графических объектов
· создание приложения MFC
· добавление в приложение кнопок, надписей, контейнеров
· проектирование иерархии классов библиотеки графических объектов
· задание свойств графического объекта
· чтение и сохранение свойств графического объекта в файлы
6.1 Иерархия классов библиотеки графических объектов


6.2 Задание для самостоятельной работы
Цель. Создание редактора блок-схем. Построение библиотеки графических объектов. Чтение и сохранение блок-схем
Задание. Разработать MFC приложение, удовлетворяющее следующим функциональным требованиям:
• обеспечить добавление, изменение, удаление элементов блок-схемы следующих типов: терминатор (пуск - остановка), процесс, решение, данные (ввод - вывод), линии, стрелки
• обеспечить перемещение элементов-блок схемы при помощи указателя мыши
• элементы блок-схемы терминатор, процесс, решение и данные должны иметь следующие настраиваемые свойства: ширина, высота, цвет1 фона, цвет2 фона (для создания градиентной заливки), текст, цвет текста
• элементы блок-схемы линия и стрелка должны иметь следующие настраиваемые свойства: длина, толщина, цвет фона, угол поворота
• обеспечить возможность чтения и сохранения блок-схем в файл в определённом формате
• построить блок-схему алгоритма работы собственной программы и сохранить в файл
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 |


