
- •Содержание
- •Введение
- •Лабораторная работа №1 разработка программы на базе каркаса приложений
- •Лабораторная работа №2 создание остова приложения
- •Лабораторная работа №3 создание приложения с диалоговым интерфейсом.
- •Лабораторная работа №4 создание приложений с одно-документным интерфейсом
- •Лабораторная работа № 5 создание приложения с многодокументным интерфейсом.
- •Лабораторная работа № 6 создание приложений для построения графических изображений
- •Лабораторная работа № 7 создание приложений баз данных
- •Лабораторная работа № 8 создание приложений для работы с файлами.
- •Лабораторная работа № 9 создание справочной системы для приложения под windows
- •Лабораторная работа № 10 создание многопоточных приложений.
- •Список литературы.
Лабораторная работа № 5 создание приложения с многодокументным интерфейсом.
Цель работы – приобретение навыков построения приложений, основанных на многодокументном интерфейсе и архитектуре документ-вид, с использованием инструментальных средств студии разработчика 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);
CObject* pObject=pCRuntimeClass->CreateObject();
// Далее идут аналогичные операторы для CСhildFrame и CМdiView.
Эти объекты будут принадлежать классам, определенным программистом, а значит, каркас получит доступ к тем виртуальным методом, которые он переопределяет.
Чтобы стать доступным каркасу, шаблон должен быть присоединен к списку документных шаблонов приложения с помощью метода CwinApp::AddDocTemplate. Для создания ещё одного варианта набора из документа, рамки и облика достаточно присоединить к списку документных шаблонов приложения ещё один шаблон с описаниями нужных классов.
Задание №1. Создать многодокументный текстовый редактор, выполнив следующие действия:
Создать остов приложения с именем Мdi, выбрав тип интерфейса Multiple Document и отменив установки Docking toolbar, Initial status bar, Printig and print preview, а на последнем этапе задав в качестве базового класса для CMdiView класс CEditView.
Откомпилировать проект и запустить полученное многодокументное приложение на исполнение, открыть несколько текстовых файлов или создать новые и проверить команды меню Edit, а также команды меню Windows.
Задание №2. Создать многодокументный редактор-словарь переводчика, выполнив следующие действия:
Создать остов одно-документного приложения, выбрав тип интерфейса Single Document, задав имя проекта Dict и заменив базовый класс CView на CFormView для класса облика CDictView.
Выбрать построенный мастером AppWizard ресурс формы с идентификатором IDD_DICT_FORM.
Разместить в форме два окна для редактирования термина и его определения с идентификаторами соответственно IDC_Termin и IDC_Translate, задав при этом для второго окна свойство Multiline и отключив свойство Auto HScroll.
Для окон редактирования вставить поясняющий текст: «Термин» и «Определение термина».
Разместить в форме три командные кнопки для выполнения операций над словарем: «Добавить/Заменить», «Найти» и «Удалить», определив их идентификаторы соответственно как IDC_Add, IDC_Find и IDC_Del.
Разместить в форме окно списка для отображения словаря, определив для него идентификатор IDC_LDict.
Связать окно IDC_Termin с переменной m_strTermin категории Value типа CString, имеющей статус public.
Связать окно IDC_Translate с переменной m_strTranslate категории Value типа CString, имеющей статус public.
Связать окно IDC_LDict с переменной m_strLDict категории Controls типа CListBox, имеющей статус public.
С помощью мастера ClassWizard создать остовы методов обработки сообщений для трех командных кнопок, связав эти остовы с классом CDictView и задав им следующие имена:
для кнопки с идентификатором IDC_Add - OnAddOrUpdate;
для кнопки с идентификатором IDC_Find - OnFind;
для кнопки с идентификатором IDC_Del - OnDel.
11. Для представления словаря как документа выбрать класс отображения строк в строки CMapStringToSting и добавить в класс документа CDictDoc новую переменную для словаря:
public:
CMapStringToString m_Dict; //-имя словаря терминов.
Доопределить в класс CDictDoc специальный метод Serialize для сохранения и загрузки словаря из файла, остов которого создан мастером AddWizard:
void CDictDoc::Serialize(CArchive& ar)
{ if (ar.IsStoring())
{}
else
{m_Dict.Serialize(ar);} //-новая строка для чтения/записи;
}
Переопределить метод OnInitialUpdate, который автоматически вызывается при создании или открытки уже созданного документа:
void CDictView::OnInitialUpdate()
{ CFormView::OnInitialUpdate();//-для базового класса;
m_strLDict.ResetContent();//-список терминов очищается;
CString strKey, //-термин-ключ;
strValue; //-определение термина;
CMapStringToString& 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); //-обновление окон редактирования;
}
Включить в класс CDictView обработчик сообщения от кнопки «Добавить/Заменить»:
void CDictView::OnAddOrUpdate()
{ if(!UpdateData()) //-если данные прочитаны из окон с ошибкой;
return;
int nIndex=FindKeyInList(m_strTermin);
if(nIndex!=LB_ERR) //-если термин найден, то;
m_strLDict.DeleteString(nIndex); //-удаление элемента для замены;
CString s=m_strTermin+_T("<->")+m_strTranslate;
m_strLDict.SetCurSel(nIndex); //- выделить текущий элемент по индексу;
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,m_strTranslate)!=TRUE)
m_strTranslate=":-В словере нет термина"+m_strTermin;
else
FindKeyInList(m_strTermin);
UpdateData(FALSE);
}
Включить в класс CDictView обработчик сообщения от кнопки «Удалить»:
void CDictView::OnDel()
{ if(!UpdateData()) //-если термин не введен, то;
return;
if(GetDocument()->m_Dict.Lookup(m_strTermin,m_strTranslate)!=TRUE)
m_strTranslate=":-В словере нет удаляемого термина"+m_strTermin;
else
{int nIndex=FindKeyInList(m_strTermin);
m_strLDict.DeleteString(nIndex);
GetDocument()->m_Dict.RemoveKey(m_strTermin);}
UpdateData(FALSE);
GetDocument()->SetModifiedFlag();
}
Добавить в класс CDictView вспомогательную функцию поиска термина в списке:
int CDictView::FindKeyInList(CString& strKey)
{ CString 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,s1);
if(s==s1) break;
}
while(TRUE);
m_strLDict.SetTopIndex(Index); //-установить элемент вверху;
m_strLDict.SetCurSel(Index); //- выделить текущий элемент;
return Index;
}
Скомпилировать проект Dict и проверить его работоспособность.
Включить классы CDictDoc и CDictView проекта Dict в галерею компонентов с помощью команды Add to Component Gallary контекстного меню окна просмотра классов.
Открыть проект Mdi и с помощью команды Project/ Add to Project/ Components and Controls из папки Gallary вставить в него классы CDictDoc и CDictView.
Дополнить метод InitInstance() класса CMdiApp фрагментом кода, обеспечивающим включение документного шаблона для создания объектов новых классов:
CMultiDocTemplate* pDictDocTemplate; //- в файл Мdi.cpp;
pDictDocTemplate = new CMultiDocTemplate(
IDR_DICTTYPE,
RUNTIME_CLASS(CDictDoc),
RUNTIME_CLASS(CChildFrame),
RUNTIME_CLASS(CDictView));
AddDocTemplate(pDictDocTemplate);
В файл Mdi.h вставить директивы:
# include “DictDoc.h”
# include “DictView.h”
Определить идентификатор 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 двойной щелчок для вызова таблицы строк, с помощью контекстного меню (правая кнопка мыши) вызвать команду 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> - имя типа документа для хранения в системном реестре.
Для идентификатора ресурса IDR_MDITYPE аналогичным образом зададим следующую строку:
\nTextDoc\nТекстовый документ\nФайл типа текстовый документ(*.tek)\n.tek\n MdiTextDocument\nТекстовый документ приложения Mdi.
Создать меню для идентификатора IDR_DICTTYPE из вкладки Resource View ресурс Menu вызвать команду Insert Copy контекстного меню для IDR_МDITYPE., установить язык ресурса Russian, затем с помощью щелчка правой кнопки мыши и команды Properties заменив IDR_МDITYPE на IDR_DICTTYPE.
Создать для IDR_DICTTYPE таблицу ускорителей, открыв таблицу ускорителей элемент Accelerator вкладки Resource View. С помощью команды Insert Accelerator создать новый ускоритель IDR_ACCELERATOR1 и установить идентификатор IDR_DICTTYPE.
Создать для IDR_DICTTYPE иконку как копию значка IDR_МDITYPE. Выбрать во вкладке Resource View ресурс Icon. В контекстном меню для IDR_МDITYPE выбрать команду Insert Copy, заменить идентификатор ресурса на IDR_DIСТTYPE, а затем с помощью редактора ресурсов отредактировать копию значка по своему усмотрению (включив в него надпись ”СЛОВАРЬ”).
Для обеспечения регистрации типов используемых в приложении документов дополнить метод СMdiApp::InitInstance() следующими операторами, обеспечивающими запись необходимой информации в системном реестре Windows:
EnableShellOpen();
RegisterShellFileTypes(TRUE);
Скомпилировать проект Mdi, создать текстовый файл и словарь, сохранить их, а затем открыть в нескольких окнах и убедиться в работоспособности текстового редактора и словаря во всех открытых окнах.
Задание №3. Модифицировать текстовый редактор–словарь, включив в него средства взаимодействия между документами, которые обеспечивали бы следующие возможности:
а) быстрое копирование фрагментов текста из одного окна в другое;
б) нахождение определения термина, указанного курсором в тексте;
в) вставка термина в любое место любого текстового документа, а также и его определения;
г) наличие нескольких словарей по темам;
д) представление пользователю списков открытых текстовых документов и словарей.
Контрольные вопросы:
Перечислите отличия многодокументного интерфейса от одно-документного интерфейса.
Укажите недостатки многодокументных приложений, создаваемых мастером AppWizard.
Каково назначение документного шаблона?
Где и каким образом создается документный шаблон?
Где создаются документы и облики при выполнении команд New и Open?
Опишите порядок создания интерфейса для приложения-словаря переводчика.
Перечислите этапы для реализации динамического обмена данными для окон редактирования.
Каково назначение класса CMapStringToString и каковы его основные методы?
Для каких целей используется метод Serialize()?
Опишите этапы создания словаря переводчика.
Как реализованы обработчики сообщений от командных кнопок приложения Dict?
Перечислите дополнения, которые необходимо сделать в методе InitInstance() для включения новых типов документов?
Как создаются ресурсы строк, меню и пиктограмм?
Каково назначение таблицы ускорителей для многодокументного интерфейса?
Опишите процедуру регистрации типов документов в системном реестре Windows?