Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
Динамически загружаемые библиотеки MFC
Установка параметров области рисования
Перед тем, как начать рисование, нужно узнать размеры области рисования, куда будет помещен рисунок. Для этого в новый класс MyModArt нужно добавить функцию, которая скопирует информацию в переменную-член m_rDrawArea.
- Во вкладке Class View выделите класс MyModArt и через контекстное меню вызовите мастер добавления функций, который заполните так
-
Щелкните по кнопке Add, затем по кнопке Finish
Мастер добавит следующий код в файлы объявления и реализации
Код, добавленный мастером в файл MyModArt.h #pragma once #include "afx.h" #include "afxcoll.h" #include "atltypes.h" class MyModArt : public CObject { public: MyModArt(void); ~MyModArt(void); private: // Для хранения массива объектов линий CObArray m_oaLines; // Для хранения размеров области рисования CRect m_rDrawArea; public: // Установить прямоугольник области рисования Drawing Area void SetRect(CRect rDrawArea); };
Код, добавленный мастером в файл MyModArt.cpp #include "StdAfx.h" #include ".\mymodart.h" MyModArt::MyModArt(void) { } MyModArt::~MyModArt(void) { } // Установить прямоугольник области рисования Drawing Area void MyModArt::SetRect(CRect rDrawArea) { }
-
Наполните код функции так
Код функции SetRect() в файле MyModArt.cpp // Установить прямоугольник области рисования Drawing Area void MyModArt::SetRect(CRect rDrawArea) { m_rDrawArea = rDrawArea; }
Создание одной линии-зигзага
Основная особенность этого модуля - его способность создавать в области рисования случайные волнистые линии разной толщины и цвета. Сначала необходимо создать одну функцию рисования случайных линий, затем многократно ее вызывать. Для этой функции требуется задать количество линий, цвет и толщину пера, а также начальную точку рисования. Добавим эту функцию к классу рисования.
- Во вкладке Class View выделите класс MyModArt и через контекстное меню вызовите мастер добавления функций, который заполните так
-
Наполните новую функцию необходимым кодом, как показано ниже
Код функции NewLine() в файле MyModArt.cpp // Функция рисования одной случайной волны void MyModArt::NewLine() { int iNumLines; int iCurLine; int iCurColor; unsigned int iCurWidth; CPoint ptBegin; CPoint ptEnd; static COLORREF crColors[8] = { // Таблица цветов RGB( 0, 0, 0), // Black - Черный RGB( 0, 0, 255), // Blue - Синий RGB( 0, 255, 0), // Green - Зеленый RGB( 0, 255, 255), // Cyan - Голубой RGB( 255, 0, 0), // Red - Красный RGB( 255, 0, 255), // Magenta - Сиреневый RGB( 255, 255, 0), // Yellow - Желтый RGB( 255, 255, 255) // White - Белый }; // Упорядочить (Normalize) координаты прямоугольника // перед определением ширины и высоты m_rDrawArea.NormalizeRect(); // Получить ширину и высоту области рисования int iWidth = m_rDrawArea.Width(); int iHeight = m_rDrawArea.Height(); // Сгенерировать случайное ненулевое число частей волны while(!(iNumLines = rand() % 100)); iCurColor = rand() % 8; // Случайный цвет iCurWidth = (rand() % 8) + 1; // Случайная толщина // Случайная начальная точка рисования в области рисования ptBegin.x = (rand() % iWidth) + m_rDrawArea.left; ptBegin.y = (rand() % iHeight) + m_rDrawArea.top; // Рисование волны посегментно for(iCurLine = 0; iCurLine < iNumLines; iCurLine++){ // Определить конечную точку сегмента ptEnd.x = ((rand() % 20) - 10) + ptBegin.x; ptEnd.y = ((rand() % 20) - 10) + ptBegin.y; MyLine *pLine = NULL; try // Попытка { // Создать и инициализировать новый объект MyLine pLine = new MyLine(ptBegin, ptEnd); pLine->Set(crColors[iCurColor], iCurWidth); // Добавить новую линию к массиву объектов m_oaLines.Add(pLine); } catch(CMemoryException *perr) // Исключение по памяти { AfxMessageBox("Не хватило памяти", MB_ICONSTOP | MB_OK); if(pLine){ delete pLine; pLine = NULL; } perr->Delete(); // Удалить объект-исключение } // Переместить начало рисования для продолжения ptBegin = ptEnd; } // End of for }
Таким образом мы создали функцию, которая рисует одну волнистую линию со случайными характеристиками.
Генерация набора линий-зигзагов
Теперь нужно разработать функцию, которая будет генерировать последовательность таких линий. Для этого добавим новый метод к классу рисования.
- Выделите во вкладке Class View класс MyModArt и через контекстное меню вызовите мастер добавления функций, который заполните так
-
Мастер сгенерирует заготовку функции, которую заполните следующим кодом
Код функции NewDrawing() в файле MyModArt.cpp // Генерация полного рисунка void MyModArt::NewDrawing(void) { int iNumLines; // Определить количество создаваемых линий while(!(iNumLines = rand() % 10)); // Рисуем линии for(int iCurLine = 0; iCurLine < iNumLines; iCurLine++) NewLine(); }
Функция NewDrawing() заполнит массив объектов, на который указывает переменная-член m_oaLines.
Добавление функциональности по отображению рисунка
После того, как массив линий всего рисунка будет заполнен, его нужно отобразить в классе представления SDI -приложения. Каждый элемент массива линий представляет собой объект-экземпляр класса MyLine, члены-данные которого содержат начальную и конечную координаты прямолинейного отрезка, а также его цвет и толщину. Кроме того, каждый объект MyLine способен нарисовать себя в переданном ему контексте устройства. Добавим к классу MyModArt метод, который в цикле будет перебирать все объекты массива отрезков прямых и рисовать каждый из них в указанном контексте устройства.
-
Во вкладке Class View выделите класс MyModArt и через контекстное меню вызовите мастер добавления функций, который заполните так
Не забудьте нажать кнопку Add!
-
Сгенерированную мастером заготовку новой функции рисования наполните следующим кодом
Код функции Draw() в файле MyModArt.cpp // Рисование всех линий void MyModArt::Draw(CDC* pDC) { // Получить количество элементов массива линий int iCount = m_oaLines.GetSize(); if(!iCount) // Если нечего рисовать return; // Рисование каждой линии for(int iPos = 0; iPos < iCount; iPos++) ((MyLine*)m_oaLines.GetAt(iPos))->Draw(pDC); }
Преобразование массива линий в последовательную форму
Для преобразования в последовательную форму воспользуемся функцией Serialize массива объектов, которую мы уже применяли ранее в классе MyLine. Упакуем ее в функцию с таким же именем класса MyModArt.
-
Вызовите для класса MyModArt мастер добавления функций и заполните его так
Не забудьте нажать кнопку Add!
-
Сгенерированную мастером заготовку новой функции рисования наполните следующим кодом
Код функции Serialize() в файле MyModArt.cpp // Преобразование в последовательную форму void MyModArt::Serialize(CArchive& ar) { // Передать архивный объект массиву объектов m_oaLines.Serialize(ar); }
Очистка массива объектов линий
Для полноценного набора функциональных возможностей нужно предусмотреть и возможность удаления рисунка из класса рисования. Это нужно для того, чтобы можно было создать новый рисунок или загрузить существующий. Для этого достаточно перебрать все элементы массива объектов линий и удалить каждый из них. При этом нужно учесть, что в массиве объектов находятся не сами объекты, а указатели на неименованную область, где хранятся экземпляры. Поэтому после удаления каждого неименованного объекта по его указателю необходимо очистить сам массив указателей.
- Добавьте новый метод к классу рисования MeModArt через мастер добавления функций, заполнив его так
-
Сгенерированную мастером заготовку новой функции рисования наполните следующим кодом
Код функции ClearDrawing() в файле MyModArt.cpp // Очистка рисунка void MyModArt::ClearDrawing(void) { // Получить количество элементов массива линий int iCount = m_oaLines.GetSize(); // Удаление каждой линии for(int iPos = 0; iPos < iCount; iPos++) delete m_oaLines.GetAt(iPos); m_oaLines.RemoveAll(); }