Технологии программирования. Программирование графических интерфейс
.pdfПосле создания каркаса приложения мы должны выполнить следующую работу:
1. Cоздать класс объектов, с которыми будет работать приложение:
class CMyClass : public CObject
{
protected:
DECLARE_SERIAL(CMyClass) <данные – члены класса> public: <методы – члены класса>
virtual void Serialize(CArchive &ar);
}; 2. Определить в классе документа контейнер (коллекцию)
для хранения объектов, например :
class CMyPrDoc: public CDocument() {…
CTypePtrMap<CMapStringToOb, CString, CMyClass *>CMap;
}; 3. Переопределить в классе документа методы (в случае
необходимости)
virtual BOOL OnNewDocument();
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); virtual void DeleteContents();
virtual void Serialize(CArchive &ar);
Метод OnNewDocument() вызывается средой выполнения при создании нового документа как часть выполнения команды File/New. По умолчанию реализация этого метода вызывает метод DeleteContens() для удаления данных документа, а затем помечает документ как «чистый».
При переопределении метода следует вызывать метод OnNewDocument() базового класса для выполнения стандартный действий. Как правило, переопределение метода заключается в инициализации нового документа: для SDI-приложения – это
121
переинициализация уже существующего документа, а для MDIприложений – инициализация нового документа.
Пример 5
BOOL CMyPrDoc :: OnNewDocument() { if (!CDocument :: OnNewDocument())
return FALSE; CFile file;
CFileException except;
CString fn=AfxGetApp()->GetProfileString(“Recent File
List”, “File1”);
/* эта функция возвращает значение строки с именем File1 из секции с именем Recent File List реестра. Таким образом, получаем имя последнего открывавшегося файла.
if (!file.Open(fn, CFile :: modeReadWrite, &except)) if (except.m_cause==CFileException :: fileNotFound) AfxMessageBox(“файл”+fn+”не найден”);
else
AfxMessageBox(“ошибка открытия файла”+fn); return FALSE;
}
//связываем архив с файлами
CArchive ar(&file, CArchive : load); Serialize(ar); //чтение файла
UpdateAllViews(NULL); return TRUE;
}
Метод UpdateAllViews() вызывается видом после изменения документа. Этот метод инициирует для каждого отображение вызов методов CView :: OnUpdate(). В свою очередь, метод OnUpdate() по умолчанию отмечает всю клиентскую область как поврежденную и инициирует сообщение WM_PAINT.
Метод OnOpenDocument() вызывается средой выполнения при открытии нового документа, например, как часть вы-
122
полнения команды File/Open. По умолчанию реализация этого метода открывает указанный файл, вызывает метод DeleteContents(), затем вызывает метод Serialize() для чтения файла и помечает документ как «чистый».
Этот метод может быть переопределен для реализации других механизмов управления данными, без использования архива, а также для определения дополнительного кода инициализации.
Метод OnSaveDocument() вызывается средой выполнения при сохранении документа, например, как часть выполнения команд File/Save или File/Save As. По умолчанию реализация открывает указанный файл, вызывает метод Serialize() для записи данных из документа в файл и помечает документ как «чистый».
Этот метод может быть переопределен для реализации других механизмов управления данными, а также определения дополнительного кода для сохранения данных.
Метод DeleteContents() вызывается средой выполнения для удаления данных объекта без разрушения самого объекта. Метод может также вызываться для очистки содержимого документа с целью повторного использования или для реализации команды Edit/Clear All.
Реализация этого метода по умолчанию не выполняет никаких действий.
Пример 6
void CMyPrDoc :: DeleteContents()
{
cMap.RemoveAll()
CDocument :: DeleteContents();
}
4. Реализовать класс отображения.
Как уже указывалось, класс отображения может быть создан на основе различных базовых классов. В зависимости от этого могут быть предложены различные методики реализации отображения документа. Рассмотрим некоторые из них.
123
♦ Класс отображения создан на основе класса CView class CMyPrView : public CFormView
Класс CFormView является базовым классом, используемым для отображений, содержащих элементы управления. Он поддерживает работу с оконными формами с их прокруткой (используя возможности класса CScrollView).
Создание отображения CFormView аналогично созданию диалогового окна. Надо сделать следующее:
1)Разработать в редакторе диалога шаблон диалогового окна и установить для него следующие атрибуты:
– на панели Style выбрать Child (WS_CHILD вкл.);
– на панели Border выбрать None (WS_BORDER откл.);
– снять флажок Visible (WS_VISIBLE откл.);
– снять флажок Titebar (WS_CAPTION откл.).
2)Используя ClassWizard, добавить в класс отображения переменные для обмена данными с элементами управления диалоговых окон (формой).
ClassWizard формирует функцию DoDataExchange(), добавив в нее соответствующие DDX_ и DDV_ функции.
3)Переопределить метод OnUpdate(). Этот метод определен
вклассе CView и вызывается для обновления отображения окнаформы. При использовании DDX_ функций (методов) можно вызвать метод CWnd :: UpdateData(FALSE). При первичной инициализации отображения вызывается метод OnInitialUpdate(). В классе CFormView этот метод переопределен таким образом, что он выполняет вызов DDX_ методов, устанавливающих первоначальное значение элементов управления.
4)Реализовать методы, выполняющие внесение изменений из отображения в документ. При использовании DDX_ методов следует вызвать метод CWnd :: UpdateData(TRUE) для занесения изменений в переменные класса отображения, а затем, используя значения этих переменных, вносить изменения в документ.
При изменении документа следует вызвать метод
void CDocument :: SetModifiedFlag(BOOL bModified=TRUE);
124
При вызове этого метода с параметром TRUE документ помечается как измененный. Это гарантирует, что перед закрытием документа среда выполнения выдаст пользователю запрос о сохранении сделанных изменений.
Вызов метода с параметром FALSE помечает документ как «чистый» (без изменений).
♦ Класс отображениясоздан на основеклассаCListView.
Если в предыдущем случае для ввода и отображения данных использовались элементы управления окна-формы, то в этом случае для ввода и отображения данных необходимо создавать специальные диалоговые окна. Впрочем, и в предыдущем случае можно создавать эти окна, которые будут активизироваться кнопками в окне-форме (окне вида).
Как в этом случае реализуется диалог? Надо сделать следующее:
1)Разработать в редакторе диалога шаблоны диалоговых окон, например, окна для создания объекта, просмотра объектов, редактирования и т.д.
2)Создать классы диалогов. Для этого, находясь в редакторе ресурсов с открытым шаблоном диалогового окна, вызвать ClassWizard, а затем вызвать команду Add Class.
3)Используя ClassWizard, добавить в классы диалогов переменные для обмена информацией с элементами управления диалоговых окон.
4)В классы отображения добавить переменные – члены класса для хранения объектов, например, ссылку на встроенный список, отображающий наши объекты, хранящиеся в документе (в контейнере map):
CListCtrl &cList;
CMyPrDoc *pDoc; //указатель на документ – для удобства.
5)Определить обработчики событий команд меню для работы сдокументом (добавитьобъект, редактировать объект ит.д.).
6)При необходимости определить обработчики событий от кнопок диалоговых окон.
125
Как получить доступ к документу в объекте диалого-
вого окна? Это можно сделать следующим образом:
1) В классе диалогового окна ввести переменные CMyPr-
View *pView; CMyPrDoc *pDoc.
2) В этом же классе определить конструктор CViewDia-
log(CMyPrView *).
3) Реализовать этот конструктор: CViewDialog :: CViewDialog(CMyPrView *p) :
CDialog(CViewDialog :: IDD, P)
{ pView=p; pDoc=p->GetDocument();
}
4) Вызвать диалог:
void CMyPrView :: OnView()
{…
CViewDialog dlg (this);
Dlg.DoModal();
}
7.7. Пример создания приложения с архитектурой «документ–вид»
1.Создайте рабочую область (workspace).
2.В этой рабочей области создайте проект как приложение MFC AppWizard(exe). Выберите тип приложения SDI. Включите поддержку архитектуры Document/View.
3.На 6-м шаге мастера MFC AppWizard выберите базовый класс для класса вида.
4.Создайте класс объектов, с которыми будет работать ваше приложение.
5.Определите в классе документа поле – коллекцию для хранения ваших объектов.
6.Переопределите в классе документа методы (в случае необходимости):
126
virtual BOOL OnNewDocument( );
virtual BOOL OnOpenDocument( LPCTSTR lpszPathName ); virtual BOOL OnSaveDocument( LPCTSTR lpszPathName ); virtual void DeleteContents( );
virtual void Serialize( CArchive& ar );
7.Реализуйте класс отображения. Реализация этого класса зависит от выбранного базового типа. Например, если для отображения вы используете диалоговые окна (класс CFormView либо класс CView с диалогом CDialog для просмотра объектов), создайте в редакторе диалога шаблон диалогового окна с элементамиуправленияи ассоциируйте его склассом диалога.
8.Используя ClassWizard, добавьте в класс отображения (или диалога) переменные для обмена данными с элементами управления формы(диалогового окна).
9.Добавьте в меню пункты «Добавить объект» и «Просмотреть объекты».
10.Разработайте в редакторе диалога шаблон диалогового окна для ввода данных при создании объекта.
11.Создайте класс диалога, ассоциированный с этим шаблоном диалогового окна.
12.Используя ClassWizard, добавьте в класс диалога переменные для обмена данными с элементами управления диалогового окна.
13.Создайте обработчик сообщения «Добавить объект». Данные вводятся с диалогового окна, создается объект и добавляется в коллекцию.
14.Создайте обработчик сообщения «Просмотреть объекты». Объекты просматриваются в окне вида.
15.Переопределите функцию Serialize() для документа.
16.Отладьте программу и сохраните в файле коллекцию, содержащую не менее пяти объектов.
Методические указания
1. Если в качестве базового класса вида выбран класс CView, то класс вида имеет обработчики команд меню «Добавить объект»
127
и «Просмотреть объекты». Соответствующие диалоговые окна имеютвид(рис. 7.3).
а
б
Рис. 7.3
2. Если в качестве базового класса вида выбран класс CFormView, то класс вида может содержать управляющие элементы для просмотра объектов. Можно разместить на форме вида список Listbox, в котором показываются ключевые поля объекта. Полностью объект показывается в элементах Edit, также размещенных на форме. Просмотр объекта осуществляется по двойному щелчку по имени в списке. Соответствующая форма имеет вид
(рис. 7.4).
128
Рис. 7.4
3. Для ввода данных при создании объекта в этом случае создается диалоговое окно, имеющее вид (рис. 7.5).
Рис. 7.5
4. Если все поля объекта размещаются в одной строке Listbox,а, томожноформироватьэтустроку ипоказыватьвListbox,е (рис. 7.6).
129
Рис. 7.6
Рис. 7.7
5. Если в качестве базового класса вида выбран класс CListView, то для отображения объектов используется объект класса CListCtrl, содержащийся в отображении (рис. 7.7).
130