Отображение данных приложения

   
На этом шаге мы рассмотрим еще один пример использования архитектуры "документ/вид".

   
На этом шаге мы продолжим работать с приложением 12 шаге.
Мы рассмотрим:

  • пользование класса документа для хранения данных;
  • пользование функции OnDraw() класса представления для отображения данных на экране.

   
Допустим, требуется загрузка данныx из ASCII-файла, в каждой строчке которого имеется название
ценной бумаги, дата и ее стоимость на момент закрытия торгов. Первая Ваша задача - подобрать соответствующую
структуру для моделирования таких данных. В дальнейшем Вы сможете сделать ее частью класса документа.

   
Файл данных - это набор строк, поэтому прежде всего надо выполнить следующее:

  • создать класс, представляющий строку данных;
  • создать набор таких классов.

   
Предлагается использовать класс CStockData, представляющий строку данных, состоящую из следующих
переменных-членов:

  double m_dblPrice; 
  COleDateTime n_date; 
  CString m_strFund;

   
Класс COleDateTime используется для хранения даты и времени. Класс CString работает с
символьными строками переменной длины.

   
Обявление и реализация класса CStockData находятся соответственно в файлах StockData.h и
StackData.cpp. В этих файлах определены
конструкторы, функции доступа к данным и операторы сравнения, а
функция GetAsString() отображает данные в виде строки символов.

   
В файле StockDataList.h хранится объявление класса StockDataList:

  class CStockDataList : public CList< CStockData, CStockData & >  

   
Он основан на шаблонном классе списка CList. Шаблону нужно передать два параметра - тип объекта,
который содержится в списке, и тип ссылки на этот объект.

   
В MFC есть несколько шаблонных классов для создания данных, например САггау и СМар.
Мы выбрали CList из-за того, что он позволяет вставлять данные в любое место списка.

   
Чтобы использовать классы CStockData и CStockDataList Вы должны импортировать их в свой проект.

  • Импорт файлов в проект.
  • Возьмите файлы StockData.h, StockData.cpp, StockDataList.h и StockDataList.cpp
    12 шаге.
  • В окне Workspace щелкните вкладку File View.
  • Щелкните правой кнопкой значок STUpload Files. В контекстном меню выберите пункт Add Files to Project.
    Рис.1. Добавление файлов в проект
  • Перейдите в каталог STUpload. Выбрав файлы StockData.h, StockData.cpp, StockDataList.h и StockDataList.cpp,
    щелкните ОК. Эти файлы будут добавлены в проект.
  • В окне Workspace перейдите на вкладку ClassView. Вы увидите, что в дереве классов появились
    классы StockData и StockDataList. Раскройте их узлы и просмотрите функции-члены и переменные-члены этих классов.


    Рис.2. Добавленные классы

   
Теперь у Вас есть классы для данных - CStockDataList представляет все записи из ASCII-файлов. Следующей Вашей задачей будет
включение класса данных в класс документа. Для этого нужно в классе CSTUploadDoc создать переменную типа CStockDataList.

  • Добавление переменной m_DocList в класс CSTUploadDoc.
  • В окне ClassView щелкните правой кнопкой мыши значок класса CSTUploadDoc.
  • В контекстном меню выберите пункт Add Member Variable.
  • В диалоговом окне Add Member Variable в поле Variable Type введите CStockDataList.
  • В поле Variable Name введите m_DocList.
  • Выберите тип доступа Protected. Щелкните кнопку ОК, чтобы добавить переменную.
    Рис.3. Окно создания переменной m_DocList
  • Чтобы перейти к объявлению класса CSTUploadDoc, щелкните его значок в окне ClassView.
  • Проверьте, есть ли в начале файла CSTUploadDoc.h следуюшая строка:
        #include "StockDataList.h"
    


    Рис.4. Наличие заданной строки
    Так как переменная m_DocList защищенная, то для получения ее значения необходима специальная функция.

  • Добавление функции, имеющей доступ к защищенной переменной m_DocList.   
    Добавьте следующую строку в раздел public в объявлении класса CSTUploadDoc:

      const  CStockDataList &GetDocList() {return m_DocList;}
    


    Рис.5. Добавление строки

       
    Здесь мы не будем создавать функции, загружающие из файла. Вместо этого в конструкторе класса
    CSTUploadDoc мы добавим в переменную CSTUploadDoc::m_DocList несколько элементов типа
    CStockData, чтобы изучить отображение данных в представлении.

  • Добавление записи типа CStockData.
  • Приведем текст конструктора:
    CSTUploadDoc::CSTUploadDoc()
    {
       m_DocList.AddTail( CStockData( _T("ARSC"), 
           COleDateTime( 1999, 4, 1, 0, 0, 0 ),  22.33 ));
       m_DocList.AddTail( CStockData( _T("ARSC"), 
           COleDateTime( 1999, 4, 2, 0, 0, 0 ),  23.44 ));
       m_DocList.AddTail( CStockData( _T("ARSC"), 
           COleDateTime( 1999, 4, 3, 0, 0, 0 ),  24.55 ));
       m_DocList.AddTail( CStockData( _T("ARSC"), 
           COleDateTime( 1999, 4, 4, 0, 0, 0 ),  25.66 ));
       m_DocList.AddTail( CStockData( _T("ARSC"), 
           COleDateTime( 1999, 4, 5, 0, 0, 0 ),  26.77 ));
    }
    

       
    Замечание.
    Макрос _T перекодирует символ или строку в формат Unicode.

       
    В этом коде в переменную CSTUploadDoc::m_DocList добавляются пять объектов типа CStockData.
    Скопируйте этот текст.

  • В окне ClassView дважды щелкните значок конструктора класса CSTUploadDoc,
    чтобы перейти к его реализации. Вы увидите следующий фрагмент:

    CSTUploadDoc::CSTUploadDoc() 
    {
        //TODO:add one-time construction code here 
    }
    
  • Удалите эту функцию и вставьте новый конструктор.
    Рис.6. Реализация нового конструктора

       
    Для иллюстрации работы функции CSTUploadView::OnDraw() мы реализуем ее упрощенную версию.

  • Реализация функции CSTUploadView::OnDraw().
  • Приведем текст функции OnDraw():
    void CSTUploadView::OnDraw(CDC* pDC)
    {
      CSTUploadDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
      // Save the current state of the device context
      int nDC = pDC->SaveDC();
      // Create font for axis labels
      CFont aFont;
      if( aFont.
         CreateFont( 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FF_MODERN, 0 ))   
            pDC->SelectObject( &aFont );
      else
       {
          AfxMessageBox( "Unable to create font" );
          return;
       }
      const CStockDataList & pData = pDoc->GetDocList();
      int yPos = 10;
      int nTextHeight = pDC->GetTextExtent( "A" ).cy;
      POSITION pos = pData.GetHeadPosition();
      while( pos )
        {
          CStockData sd = pData.GetNext( pos );
          pDC->TextOut( 10, yPos, sd.GetAsString() );
          yPos += nTextHeight;
         }
      // Restore the original device context
      pDC->RestoreDC( nDC );
    }
    

       
    Код использует функции класса CList для обхода элементов списка CSTUploadDoc::m_DocList.
    Из них функция CStockData::GetAsString() извлекает информацию, которая потом будет отображаться
    функцией CDC::TextOut(). Обратите внимание на то, что в начале и в конце вызываются функции
    SaveDC() и RestoreDC(), сохраняющие и восстанавливающие контекст устройства.
    Это рекомендуется делать, если Вы вызываете процедуры, которые изменяют контекст устройства.
    В данном случае он корректируется при выборе шрифта функцией CDC::SelectObject().

  • Чтобы перейти к функции CSTUploadView::OnDraw(), щелкните ее значок в окне ClassView.
    Функция, созданная мастером АррWizard, выглядит следующим образом:

    void CSTUploadView::OnDraw(CDC* pDC)
    {
      CSTUploadDoc* pDoc = GetDocument();
      ASSERT_VALID(pDoc);
      // TODO: add draw code for native data here
    }
    
  • Удалите эту функцию, после чего вставьте новую.
    Рис.7. Вставка новой функции CSTUploadView::OnDraw()

   
Собрав и запустив приложение, Вы увидите окно, изображенное на рисунке 8:


Рис.8. Результат работы приложения
Текст этого приложения можно взять здесь (32,2 Кб).

   
На следующем шаге мы начнем знакомиться с вопросами создания пользовательского интерфейса.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий