Иллюстрированный самоучитель по Visual Studio .NET

Взаимодействие представлений документа

Перейдем к разработке следующего метода класса CTreeDoc. При переводе фокуса с одного узла дерева на другой мы должны освободить память, занимаемую контейнером полигонов m_Shapes и другими временными данными, которые соответствуют документам, обнаруженным в текущей папке. Эти действия выполняет метод FreeDocs. При освобождении контейнера методом clear он вызывает для каждого из своих объектов деструктор. Так.как класс CPolygon мы снабдили деструктором, освобождающим свой вложенный контейнер точек (CDPoint), то вызов m_Shapes .clear (); порождает целую цепочку действий, которую вы можете проследить. Для этого установите точку останова (F9) в теле деструктора класса CPolygon, запустите приложение в режиме отладки (F5) и откройте окно Call Stack, которое позволяет увидеть всю цепочку вызовов функций. Открыть окно Call Stack вы сможете, дав команду Debug › Windows › Call Stack. Команда доступна только в режиме отладки (F5):

void CTreeDoc::FreeDocs()
{
m_sFiles.clear(); m_Shapes.clear();
//====== Выясняем адрес правого окна
CRightView *pView = dynamic_cast<CRightView*>
(GetView(RUNTIME_CLASS(CRightView)));
//====== Освобождаем окна-картинки
if (pView) pView › Clear();
}

При обращении к функции Getview мы должны подать на вход адрес структуры CRuntimeClass, которая характеризует искомый класс. Это можно сделать двумя способами: используя макроподстановку RUNTIME_CLASS(), как и сделано выше, или подставив более длинное, но разъясняющее суть макроса, выражение:

Getview(SCRightView::classCRightView)

Выражения:

RUNTIME_CLASS(CRightView)

И:

&CRightView::classCRightView

Эквивалентны. Вторая форма записи подсказывает вам, что в классе CRightView определена статическая переменная classCRightview типа CRuntimeClass, которая помогает по адресу объекта определить его тип на этапе выполнения.

Рассмотрим метод ProcessDocs класса CTreeDoc, который обрабатывает информацию о файлах документов, обнаруженных в текущей папке. Здесь демонстрируется, как связать архив (объект класса CArchive) с файлом (объектом класса CFile) и заставить объект прочесть данные из файла. Для этой цели используется всего" один временный объект poly класса с Polygon. Данные очередного документа сначала читаются из файла в этот объект – poly.Serialize (ar); а затем весь объект помещается в контейнер – m_Shapes.push_back (poly). Контейнеры устроены таким образом, что они создают свою собственную копию объекта и именно ее и хранят. Благодаря этому мы можем многократно использовать временный объект poly:

void CTreeDoc::ProcessDocs()
{
UINT nFiles = m_sFiles.size();
//====== Если документы не обнаружены
if (!nFiles)
return;
for (UINT i=0; i < nFiles; i++)
{
//====== Читаем все документы
GFile file; // Класс, управляющий файлами
CFileException e; // Класс для обработки сбоев
CString fn = m_sFiles[i); // Имя файла
if (Ifile.Open (fn, CFile::modeRead |
CFile::shareDenyWrite, &e))
{
//=== В случае сбоя в зависимости от причины
//=== выдаем то или иное сообщение
CString rasg =
e.m_cause == CFileException::fileNotFound? "Файл: " + fn + " не найден"
: "Невозможно открыть " + fn; AfxMessageBox(msg);
return;
}
//====== Связываем архив с файлом
CArchive ar (sfile, CArchive::load);
CPolygon poly; // Временный полигон poly.Set(this);
// Обратный указатель poly.Serialize (ar);
// Читаем данные m_Shapes.push_back(poly);
// Запоминаем в массиве
}
//====== Отображаем результат в правом окне
CRightView *pView – dynamic_cast<CRightView*>
(GetView(RUNTIME_CLASS(CRightView)));
pView › Show();
}
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.