Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Технологии программирования. Программирование графических интерфейс

.pdf
Скачиваний:
3
Добавлен:
15.11.2022
Размер:
2.24 Mб
Скачать

IDR_MAINFRAME – идентификатор ресурсов, используемых совместно с типом документов, управляемых шаблоном. К таким ресурсам относятся меню, пиктограмма, строковый ресурс, таблица акселератов.

С помощью макросов RUNTIME_CLASS приложение получает указатели на объекты класса CRuntimeClass. Эти указатели получаются из классов CMyAppDoc, CMainFrame, CMyAppView.

Таким образом, при создании шаблона документа класс документа связывается с ресурсами, окном-рамкой и представлением (видом).

Шаблон добавляется к приложению функцией CWinApp :: AddDocTemplate().

7.4. Вид на базе класса CListView

Класс CListView используется для отображения, содержащего объект CListCtrl, который может показывать элементы списка различными способами.

Класс CListView имеет две функции:

CListView::CListView() – конструктор,

CListCtrl& CListView::GetListCtrl() – возвращает объект

CListCtrl, ассоциированный с окном отображения.

Класс CListCtrl

class CListCtrl : public CWnd

Для поддержки класса CListCtrl должен быть подключен заголовочный файл afxcmn.h

#include <afxcmn.h>

Класс CListView позволяет упростить использование элемента управления Windows LIST VIEW и инкапсулировавшего его функциональные возможности класса CListCtrl в архитектуре «документ–представление».

Объект класса CListCtrl создается или в блоке диалога добавлением в шаблон блока диалога соответствующего элемента,

111

или в обычном окне при помощи вызова функции Create() в функциях окна OnInitDialog() (для диалогов) или OnCreate().

При использовании в качестве базового класса для вида класса CListView необходимо:

1. Добавитьвклассотображения ссылку наобъектCListCtrl class CPrView : public CListView

{

….

protected:

CListCtrl& cList; // СсылканавстроенныйсписокCListCtrl CPrDoc *pDoc; // Указатель на “Документ”

};

2. CList инициализировать в конструкторе

CPrView::CPrView():cList(GetListCtrl())

{

// TODO: add construction code here

}

3. Реализовать поддержку режима отображения содержимого списка в виде таблицы. Для этого следует в обязательном порядке, независимо от количества полей представления записей списка, создать столбцы.

Создавать столбцы можно в обработчике OnCreate

Int CListView::OnCreate(LPCREATESTRUCT lpCreateStruct);

Для добавления (вставки) нового столбца служит функция

CListCtrl::InsertColumn().

Например,

cList.InsertColumn (0,"Имя",LVCFMT_LEFT,210);

Иногда полезно для создания столбцов написать метод void InitList() и добавить его в класс отображения. Вызов метода InitList() следует организовать в методе класса отображения OnInitialUpdate(). Однако в этом случае необходимо создавать столбцы только при первом вызове OnInitialUpdate(). Для этого в методе InitList() нужно сделать проверку вроде следующей:

112

LV_COLUMN lvc;

if (!cList.GetColumn (0,&lvc)

{

/*

Создание столбцов

*/

}

4. Для того чтобы окно отображения показывало таблицу, изменитьстильсозданногоокна, добавивпараметрLVS_REPORT.

Стили, используемые для отображения списка, заданы константами с префиксом LVS_

Изменить стиль окна списка можно в функции

CListView::PreCreateWindow().

5. Для добавления записи (строки таблицы) в список слу-

жит функция CListCtrl::InsertItem().

После добавления можно изменить текст элемента или подэлементасписка. ДляэтогослужитфункцияCListCtrl::SetItemText().

Пример

Пусть в объекте «документ» в коллекции типа «массив» хранятся объекты с четырьмя полями. Необходимо показать эти поля в списке CListCtrl.

Вставить значения этих полей в список можно следующим образом:

for (int i=0; i<iNum; i++)

{

// Выбор из коллекции очередного объекта

p = pDoc->m_Array.GetAt(i);

// Вставка строки и значения первого поля в список

cList.InsertItem (LVIF_TEXT,i,p->GetName(),0,0,0,0L); // Вставка значений следующих полейв список

cList.SetItemText(i,1,p->GetAddress()); cList.SetItemText(i,2,p->GetPhone()); cList.SetItemText(i,3,p->GetPassport());

}

113

Здесь

iNum – количество объектов в коллекции;

p – указатель на объект, хранящийся в коллекции; m_Array – коллекция, хранящаяся в «документе»; GetName() ит.д. – методыдоступакзакрытымполямобъекта.

7.5. Сериализация

Сериализация служит для сохранения объектной структуры данных приложения при их записи или восстановления из архива постоянного хранения.

Идея состоит в том, что существуют устойчивые (persistent) объекты, которые можно сохранять на диске при завершении программы и восстанавливать при следующем запуске. Этот процесс сохранения и восстановления объектов и называется сериализацией. Поддерживающие ее классы MFC содержат функцию Serialize().

Встроенная в MFC сериализация обеспечивается классом CObject. Необходимо, чтобы все другие классы, поддерживающие сериализацию, были производными от CObject и перегружали функцию CObject :: Serialize(). Задача Serialize() заключается в архивировании отдельных данных класса и сохранении и восстановлении из объекта MFC – класса CArchive.

В MFC дисковые файлы представлены oбъектами CFile. Если программа не выполняет прямые операции ввода/вывода на диск, а полагается на сериализацию, явного применения объектов CFile можно избежать. Между функцией Serialize() и объектом CFile располагается объект CArchive. Он буферизует данные для CFile и поддерживает внутренний флажок, указывающий, записывается ли архив на диск или считывается с него. За создание объектов CFile и CArchive, открытие файла и связывание архива с файлом отвечает каркас приложения.

Все, что вам остается сделать в своей функции Serialize(), – загрузить данные из объекта-архива или сохранить их в нем.

114

Каркас приложения вызывает функции Serialize() класса «документ» при обработке команд Open и Save из меню File.

Отдельно взятый объект CArchive можно применять либо для сохранения данных, либо для их загрузки. Время жизни CArchive ограничено одним проходом записи в файл или чтения объектов из файла.

Вклассе CArchive определены операторы помещения

впоток (<<) и извлечения из потока (>>).

Сериализация в приложениях MFC осуществляется следующим образом.

Данные приложения сохраняются в объекте документа. Они сериализуются в дисковый файл, а затем восстанавливаются в этот объект. Тип файла вы связываете с приложением, задав расширение в диалоговом окне Advanced Options мастера App-

Wizard (Step 4) (рис. 7.2).

Рис. 7.2

115

Объект документа начинает сериализацию данных приложения в ответ на выбор соответствующего пункта меню. Каркас создает объект CArchive соответствующего типа (для сохранения или восстановления) и передает его в функцию Serialize().

Пример 1

Допустим, что CMyObj – класс, поддерживающий сериализацию.

class CMytAppDoc //класс “документ” { CString m_string;

DWORD m_dwVar; CMyObj m_obj; public:

}

void CMyAppDoc :: Serialize(CArchive &ar) { if (ar.IsStoring())

{

ar<<m_string; ar<<m_dwVar;

}

else

{

ar>>m_string; ar>>m_dwVar;

}

m_obj.Serialize(ar);

}

Процедуры сериализации гарантируют корректную «реконструкцию» структуры объекта при ее восстановлении из дискового файла. Это обеспечивается сохранением сведений не только о типе объекта, но и о его текущем состоянии (значе-

116

нием членов-данных). Вам надо гарантировать корректность создания объекта, предоставив для своего сериализуемого класса конструктор по умолчанию (без параметров).

Функции CDocument :: UpdateAllViews() информирует каждое представление, присоединенное к документу, о том, что документ был изменен. Это приводит к вызову функции CView :: OnUpdate для каждого представления, передавая им информацию об изменениях в документе.

Пример 2

void CMyAppDoc :: OnEdit() //Диалог редактирования данных объекта

{

CEditDialog dlg;

dlg. m_dwVar = m_dwVar; dlg.m_ m_string =m_string; if (IDOK==dlg.DoModal())

{ m_dwVar s=dlg. m_dwVar ; m_string=dlg.m_string; UpdateAllViews(NULL); SetModifiedFlag();

}

}

Функция CDocument :: SteModifiedFlag() позволяет пометить документ как измененный, что позволяет библиотеке MFC гарантировать вывод окна запроса пользователю на сохранение документа перед его закрытием.

Функция CDocument :: DeleteContents() удаляет данные до-

кумента без разрушения самого объекта. Она вызывается библиотекой MFC непосредственно перед разрушением документа, а также гарантирует, что документ пустой, если есть необходимость в его многократном использовании. Разрабатывая SDI-приложение, вы обязаны переопределить эту функцию, обнуляющую все членыданные. Иначе в текущем документе вы увидите данные, оставшиеся отпредыдущих сеансов работыприложения.

117

Пример 3

void CMyAppDoc :: DeleteContents()

{m_dwVar =0; m_string=””;

CDocument :: DeleteContents();

}

Для того чтобы класс был сериализуемым, необходимо:

1)наследовать класс от CObject;

2)определить для класса конструктор по умолчанию (без параметров);

3)вставить MFC-макрос DECLARE_SERIAL в объявление класса в заголовочном файле.

Этот макрос, а также его парный макрос IMPLEMENT_SERIAL предоставляют сериализуемому классу информацию о MFC-классе времени выполнения. Кроме того, они предоставляют глобальный оператор «извлечь из потока» (>>), который использует информацию о классе времени выполнения для восстановления объектов создаваемого времени класса. Последний передаетсяв DECLARE_SERIAL вкачествепараметра.

Пример 4

class CMyClass : public CObject

{

DECLARE_SERIAL(CMyClass) public:

CMyClass() {}

virtual void Serialize(CArchive &ar);

};

4) добавить макрос IMPLEMENT_SERIAL в файл с реализацией класса:

IMPLEMENT_SERIAL(CMyClass, CObject, 1); 5) переопределить в классе функцию Serialize().

118

Сериализация классов – наборов MFC

В каждом из шаблонных классов – наборов MFC (CArray, CList, CMap) реализована своя версия функции Serialize(), отвечающая за сериализацию любых элементов этого набора.

Предположим, что ваш класс документа содержит целый набор целочисленных значений CList<int, int>m_intList;

Его можно сериализовать, добавив в Serialize() следующую

строку: m_intList.Serialize(ar);

CList : Serialize() обращается к шаблону глобальной вспо-

могательной функции SerializeElements();

Компилятор генерирует реализацию этого шаблона, соответствующую типу шаблона. По умолчанию эта функция переносит побитовую копию данных шаблона или из места его хранения. Такое поведение вполне годится для простых типов, но не подходит для манипуляций с более сложными объектами. Например, ваш класс-документ содержит такой член:

CList<CMyClass, CMyClass&> m_ObjList;

А CMyClass определен так: class CMyClass

{

DECLARE_SERIAL(CMyClass) public:

CMyClass() {}; int m_int; DWORD m_clw; CString m_string;

virtual void Serialize(CArchive &ar);

};

Попытка сериализации набора m_ObjList путем добавле-

ния строки m_ObjList.Serialize(ar); вызовет сбой.

Ошибка заключается в том, что объекты класса CMyClass содержат строки CString, представляющие собой сложные объекты с нестандартными методами выделения памяти и отсчета ссылок.

119

Функция SerializeElements() для набора m_ObjList, соз-

данная по умолчанию, попытается считать или записать побитовую копию элементов набора в обход специальных процедур, встроенных в операторы >> и << класса CString. В этом случае вам придется создавать собственную версию функции Serial-

izeElements().

Для простого набора CString-объектов создавать отдельную версию SerializeElements() не нужно: MFC автоматически сделает это висходном тексте CArchive.

7.6. Работа с документами

Пусть мастер приложения (MFC AppWizard(exe)) создаст каркас приложения с четырьмя классами:

CMyPrApp: public CWinApp – класс приложения; CMainFrame: public CFrameWnd – класс главного окна –

рамки;

CMyPrDoc: public CDocument – класс документа;

CMyPrView: public CView – класс вида.

На 6-м шаге мастера AppWizard предоставляет возможность выбрать базовый класс для класса вида(поумолчанию CView).

Библиотека MFC представляет следующий набор производных классов от CView:

CScrollView – для автоматической прокрутки и масштабирования отображения;

CFormView – для отображения форм, содержащих элементы управления;

CCtrlView – базовый класс для классов CEditView,

CTreeView, CListView, CRichEditView;

CEditView – для отображения реализующего свойства окна редактирования. Объект CEditView реализут работу простого текстового редактора;

CRichEditView – реализует свойства окна редактирования и позволяет управлять форматированием текста.

120