Лабораторная работа № 8-9. СОЗДАНИЕ ПРИЛОЖЕНИЯ С

МНОГОДОКУМЕНТНЫМ ИНТЕРФЕЙСОМ

Цель работы - приобретение навыков построения приложений, основанных на многодокументном интерфейсе и архитектуре документ-вид, с использованием инструментальных средств студии разработчика Visual C++.

Приложения с многодокументным интерфейсом MDI(Multiple Document Interface) позволяют пользователю работать одновременно с несколькими документами. Мастер приложений AppWizard создает остовы таких приложений автоматически. Однако эти остовы имеют два существенных недостатка: открываемые одновременно документы должны быть одного и того же типа и между ними почти отсутствует взаимодействие. Таким образом, MDI-приложения, остовы которых строит AppWizard, мало, что дают в сравнении с SDI-приложениями и программисту, и пользователю.

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

Каркас MDI-приложений таков, что он обеспечивает в процессе работы создание нескольких объектов-документов. За их создание отвечает специальный объект - документный шаблон класса CMultiDocTemplate, который формируется с помощью метода InitInstance(), инициализирующего объект-приложение проекта. Кроме того, каркас создает два вида объектов, являющихся окнами-рамками: главное окно-рамка и окно-рамка документа, при этом Windows-окно, связанное с окном-рамкой документа является дочерним по отношению к Windows-окну, связанному с главным окном-рамкой.

Документный шаблон MDI-каркаса следующим образом управляет процессом создания новых документов:

BOOL CMdiApp::InitInstance()

{

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate (

IDR MDITYPE,

RUNTIME_CLASS(CMdiDoc),

RUNTIME_CLASS(CChildFrame),

RUNTIME_CLASS(CMdiView)); AddDocTemplate (pDocTemplate); CMainFrame* pMainFrame = new CMainFrame; if(!pMainFrame->LoadFrame(IDR_MAINFRAME))

return FALSE; m_pMainWnd = pMainFrame;

return TRUE;

}

Здесь RUNTIME_CLASS является макросом, позволяющим по имени некоторого класса получить ссылку на специальную структуру типа CRuntimeClass, описывающую этот класс.

Идентификатор IDR_MDITYPE задает целый ряд ресурсов, связанных с документом, например, меню приложения.

Документный шаблон получает при своем создании описания трех классов:

а) класса документа CMdiDoc;

б) класса окна-рамки документа CСhildFrame;

в) класса облика CМdiView.

Все эти описания будет хранить созданный документный шаблон. При выборе пользователем команд New или Open главного меню каркас приложения, используя метод CreateObject() и описания классов, имеющихся в документном шаблоне, создает объекты этих классов:

CRunTimeClass*pCRuntimeClass=RUNTIME_CLASS(CMdiDoc);

CObj ect* pObj ect=pCRuntimeClass->CreateObj ect();

// Далее идут аналогичные операторы для CСhildFrame и CМdiView.

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

Чтобы стать доступным каркасу, шаблон должен быть присоединен к списку документных шаблонов приложения с помощью метода CwinApp::AddDocTemplate. Для создания ещё одного варианта набора из документа, рамки и облика достаточно присоединить к списку документных шаблонов приложения ещё один шаблон с описаниями нужных классов.

Задание №1.

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

1. Создать остов приложения с именем Мdi, выбрав тип интерфейса Multiple Document и отменив установки Docking toolbar, Initial status bar, Printig and print preview, а на последнем этапе задав в качестве базового класса для CMdiView класс CEditView.

2. Откомпилировать проект и запустить полученное многодокументное приложение на исполнение, открыть несколько текстовых файлов или создать новые и проверить команды меню Edit, а также команды меню Windows.

Задание №2.

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

1. Создать остов одно-документного приложения, выбрав тип интерфейса Single Document, задав имя проекта Dict и заменив базовый класс CView на CFormView для класса облика CDictView.

2. Выбрать построенный мастером AppWizard ресурс формы с идентификатором IDD_DICT_FORM.

3. Разместить в форме два окна для редактирования термина и его определения с идентификаторами соответственно IDC_Termin и IDC_Translate, задав при этом для второго окна свойство Multiline и отключив свойство Auto HScroll.

4. Для окон редактирования вставить поясняющий текст: «Термин» и «Определение термина».

5. Разместить в форме три командные кнопки для выполнения операций над словарем: «Добавить/Заменить», «Найти» и «Удалить», определив их идентификаторы соответственно как IDC_Add, IDC_Find и IDC_Del.

6. Размстить в форме окно списка для отображения словаря, определив для него идентификатор IDC_LDict.

7. Связать окно IDC_Termin с переменной m_strTermin категории Value типа CString, имеющей статус public.

8. Связать окно IDC_Translate с переменной m_strTranslate категории Value типа CString, имеющей статус public.

9. Связать окно IDC_LDict с переменной m_strLDict категории Controls типа CListBox, имеющей статус public.

10. С помощью мастера ClassWizard создать остовы методов обработки сообщений для трех командных кнопок, связав эти остовы с классом CDictView и задав им следующие имена:

a) для кнопки с идентификатором IDC_Add - OnAddOrUpdate;

b) для кнопки с идентификатором IDC_Find - OnFind;

c) для кнопки с идентификатором IDC_Del - OnDel.

11. Для представления словаря как документа выбрать класс отображения строк в строки CMapStringToSting и добавить в класс документа CDictDoc новую переменную для словаря:

public:

CMapStringTo String m_Dict; //-имя словаря терминов.

12. Доопределить в класс CDictDoc специальный метод Serialize для сохранения и загрузки словаря из
файла, остов которого создан мастером AddWizard:

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

{}

else

{m_Dict.Serialize(ar);} //-новая строка для чтения/записи;

}

Куракбаева Н. С

13.Переопределить метод OnInitialUpdate, который автоматически вызывается при создании или открытки уже созданного документа:

void CDictView::OnInitialUpdate()
{ CFormView:: OnInitialUpdate () ;//-для базового класса;
m_strLDict.ResetContent();//-список терминов очищается;
CString strKey, //-термин-ключ;

strValue; //-определение термина;

СМар StringTo String& map=GetDocument() ->m_Dict;
POSITION pos=map.GetStartPosition();
while(pos!=NULL) //-перепись словаря в список;

{map.GetNextAssoc(pos, strKey, strValue);
CString s=strKey+_T("<->")+strValue;
m_strLDict.AddString(s);}
pos=map.GetStartPosition();
if(pos!=NULL) //-инициализация окон для термина;

map.GetNextAssoc(pos, m_strTermin, m_strTranslate); else

{ m_strTermin=_T(""); m_strTranslate=_T("");} UpdateData(FALSE); //-обновление окон редактирования;

}

14.Включить в класс CDictView обработчик сообщения от кнопки «Добавить/Заменить»:
void CDictView::OnAddOrUpdate()
{ if(!UpdateData()) //-если данные прочитаны из окон с ошибкой;

return;

intnIndex=FindKeyInList(m_strTermin); if(nIndex!=LB_ERR) //-если термин найден, то;

m_strLDict.DeleteString(nIndex); //-удаление элемента для замены; CString s=m_strTermin+_T("<->")+m_strTranslate;

m_strLDict.SetCurSel(nIndex); //- выделить текущий эл5Емент по

индексу;m_strLDict.AddString(s); //-добавление нового термина;GetDocument()-

>m_Dict[m_strTermin]=m_strTranslate;UpdateData(FALSE);GetDocument()->SetModifiedFlag(); //-
словарь изменен;}Включить в класс CDictView обработчик сообщения от кнопки «Найти»:void
CDictView::OnFind() {if(!UpdateData()) //-если данные не поступили из

окон:return;if(GetDocument()->m_Dict.Lookup(m_strTermin,_strTranslate)!=TRUE)

m_strTranslate=":-В словере нет термина"+m_strTermin; else

FindKeyInList(m_strTermin); UpdateData(FALSE);

}

15.Включить в класс CDictView обработчик сообщения от кнопки «Удалить»:
void CDictView::OnDel()
{if(!UpdateData()) //-если термин не введен, то;

return; if(GetDocument()->m_Dict.Lookup(m_strTermin,m_strTranslate)!=TRUE)

m_strTranslate=":-В словере нет удаляемого термина"+m_strTermin; else

{intnIndex=FindKeyInList(m_strTermin);

m_strLDict. Delete String(nIndex);

GetDocument()->m_Dict.RemoveKey(m_strTermin);} UpdateData(FALSE); GetDocument()->SetModifiedFlag();

}

16.Добавить в класс CDictView вспомогательную функцию поиска термина в списке: int CDictView: :FindKeyInList(CString& strKey) { C String strValue;

if(GetDocument()->m_Dict.Lookup(strKey,strValue)! =TRUE) return LB ERR;

CString s=strKey+"<->"+strValue;

int Index=-1;

CString s1=_T("");

do

{

Index=m_strLDict.FindStringExact(Index,s); m_strLDict.GetText(Index,s 1); if(s==s1) break;

}

while(TRUE);

m_strLDict.SetTopIndex(Index); //-установить элемент вверху;

m_strLDict.SetCurSel(Index); //- выделить текущий элемент;

return Index;

}

18.Скомпилировать проект Dict и проверить его работоспособность.

19.Включить классы CDictDoc и CDictView проекта Dict в галерею компонентов с помощью команды Add to Component Gallary контекстного меню окна просмотра классов.

20.Открыть проект Mdi и с помощью команды Project/ Add to Project/ Components and Controls из папки Gallary вставить в него классы CDictDoc и CDictView.

21. До полнить метод InitInstance() класса CMdiApp фрагментом кода, обеспечивающим включение документного шаблона для создания объектов новых классов:

CMultiDocTemplate* pDictDocTemplate; //- в файл Мdi.cpp;

pDictDocTemplate = new CMultiDocTemplate( IDR DICTTYPE, RUNTIME_CLASS(CDictDoc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CDictView)); AddDocTemplate(pDictDocTemplate); 22.В файл Mdi.h вставить директивы:

# include "DictDoc.h"

# include "DictView.h"

23. Определить идентификатор IDR_DICTTYPE с помощью команды View/ Resource Symbols/ New, введя в поле Name IDR_DICTTYPE, а в поле Value число - значение идентификатора, которое должно быть больше значений идентификаторов IDR_MAINFRAME и IDR_MDITYPE.

Для идентификатора ресурса IDR_DICTTYPE в окне Workspace выбрать вкладку Resource View. Для ресурса String Table с помощью контекстного меню установить свойство Language (язык) в значение Russian. Затем для String Table двойной 1Еелчок для вызова таблицы строк, с помощью контекстного меню (правая кнопка мыши) вызвать команду New String/ String Properties и задать в поле ID идентификатор IDR_DICTTYPE, а в поле Caption следующую строку :\nDictDoc\nСловарь\nФайл типа словарь (*.dic)\n.dic\nMDIDictionary\nСловарь приложения Mdi.В общем случае структура строки такова:<windows Title>\n<docName>\n<fileNewName>\n<filterName>\n<filterExt>\n <regFileTypeId>\n<regFileTypeName>,гд < windows Title> - имя, являющееся частью заголовка главного окна и используемое для приложения с SDI-интерфейсом;

<docName> - базовая часть стандартного имени документа, открываемого командой New, за которой идет порядковый номер документа, по умолчанию - Untitled;

<fileNewName> - имя типа документа, которое появляется в списке типов для команды New;

<filterName> - описание типа документа и фильтра для команды File/ Open;

<filterExt> - расширение для документа данного типа;

<regFileTypeId> - идентификатор типа документа для хранения в системном реестре;

<regFileTypeName> - имя типа документа для хранения в системном реестре.

24. Для идентификатора ресурса IDR_MDITYPE аналогичным образом зададим следующую строку:

\nTextDoc\nТекстовый документ\nФайл типа текстовый документ(*.tek)\n.tek\n

MdiTextDocument\nТе кстовый документ приложения Mdi.

25.Создать меню для идентификатора IDR_DICTTYPE из вкладки Resource View ресурс Menu вызвать команду Insert Copy контекстного меню для IDR_МDITYPE., установить язык ресурса Russian, затем с помощью щелчка правой кнопки мыши и команды Properties заменив IDR_МDITYPE на IDR DICTTYPE.

26.Создать для IDR_DICTTYPE таблицу ускорителей, открыв таблицу ускорителей элемент Accelerator вкладки Resource View. С помощью команды Insert Accelerator создать новый ускоритель IDR ACCELERATOR1 и установить идентификатор IDR_DICTTYPE.

27.Создать для IDR_DICTTYPE иконку как копию значка IDR_МDITYPE. Выбрать во вкладке Resource View ресурс Icon. В контекстном меню для IDR_МDITYPE выбрать команду Insert Copy, заменить идентификатор ресурса на IDR_DIСТTYPE, а затем с помощью редактора ресурсов отредактировать копию значка по своему усмотрению (включив в него надпись "СЛОВАРЬ").

28. Для обеспечения регистрации типов используемых в приложении документов дополнить метод СMdiApp::InitInstance() следующими операторами, обеспечивающими запись необходимой информации в системном реестре Windows:

EnableShellOpen();

RegisterShellFileTypes(TRUE);

30.Скомпилировать проект Mdi, создать текстовый файл и словарь, сохранить их, а затем открыть в нескольких окнах и убедиться в работоспособности текстового редактора и словаря во всех открытых окнах.

Қурманқожа Е. Ж

Задание№3.

Модифицировать текстовый редактор-словарь, включив в него средства взаимодействия между документами, которые обеспечивали бы следующие возможности:

а) быстрое копирование фрагментов текста из одного окна в другое;

б) нахождение определения термина, указан=Еого курсором в тексте;в) вставка термина в любое место любого текстового документа, а также и его определения;г) наличие нескольких словарей по темам;д) представление пользователю списков открытых текстовых документов и словарей.

Контрольные вопросы:

1. Перечислите отличия многодокументного интерфейса от одно-
документного интерфейса.Укажите недостатки многодокументных приложений, создаваемых мастером АррWizard.Каково назначение документного шблона?

2. Где и каким образом создается документный шаблон?

3. Где создаются документы и облики при выполнении команд New и Open?

4. Опишите порядок создания интерфейса для приложения-словаря переводчика.

5. Перечислите этапы для реализации динамического обмена данными для окон редактирования.

6. Каково назначение класса CMapStringToString и каковы его основные методы?

7. Для каких целей используется метод Serialize()?

8. Опишите этапы создания словаря переводчика.

9. Как реализованы обработчики сообщений от командных кнопок приложения Dict?

10. Перечислите дополнения, которые необходимо сделать в методе InitInstance() для включения новых типов документов?

11. Как создаются ресурсы строк, меню и пиктограмм?

12. Каково назначение таблицы ускорителей для многодокументного интерфейса?

13. Опишите процедуру регистрации типов документов в системном реестре Windows?

Наши рекомендации