На этом шаге мы рассмотрим еще один пример использования архитектуры "документ/вид".
На этом шаге мы продолжим работать с приложением STUpload, созданным на 12 шаге. Мы рассмотрим:
Допустим, требуется загрузка данны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 Вы должны импортировать их в свой проект.
Рис.1. Добавление файлов в проект
Рис.2. Добавленные классы
Теперь у Вас есть классы для данных - CStockDataList представляет все записи из ASCII-файлов. Следующей Вашей задачей будет включение класса данных в класс документа. Для этого нужно в классе CSTUploadDoc создать переменную типа CStockDataList.
Рис.3. Окно создания переменной m_DocList
#include "StockDataList.h"
Рис.4. Наличие заданной строки
Добавьте следующую строку в раздел public в объявлении класса CSTUploadDoc:
const CStockDataList &GetDocList() {return m_DocList;}
Рис.5. Добавление строки
Здесь мы не будем создавать функции, загружающие из файла. Вместо этого в конструкторе класса CSTUploadDoc мы добавим в переменную CSTUploadDoc::m_DocList несколько элементов типа 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 )); }
В этом коде в переменную CSTUploadDoc::m_DocList добавляются пять объектов типа CStockData. Скопируйте этот текст.
CSTUploadDoc::CSTUploadDoc()
{
//TODO:add one-time construction code here
}
Рис.6. Реализация нового конструктора
Для иллюстрации работы функции CSTUploadView::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().
void CSTUploadView::OnDraw(CDC* pDC) { CSTUploadDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here }
Рис.7. Вставка новой функции CSTUploadView::OnDraw()
Собрав и запустив приложение, Вы увидите окно, изображенное на рисунке 8:
Рис.8. Результат работы приложения
На следующем шаге мы начнем знакомиться с вопросами создания пользовательского интерфейса.