Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 999 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Самостоятельная работа 16:

Динамически загружаемые библиотеки 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();
    }
Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .