Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
SDI-приложение MFC
Сохранение и загрузка данных Документа
Напишем код, который будет отвечать за сохранение Документа в файле и загрузку ранее сохраненных Документов. Этот процесс основан на функции Serialize(), которая обеспечивает сериализацию (десериализацию) данных при их сохранении на диске и вызывается автоматически, когда вибирается пункт меню Save, Save As, Open или закрепленные за ними кнопки на панели инструментов. Сериализация и десериализация - это специальные методы упаковки/распаковки данных, чтобы они однозначно восстанавливались в соответствующие значения переменных класса документа.
- панели Class View выделите класс CCircleDoc двойным щелчком мыши
В результате таких действий откроется файл CircleDoc.h в редакторе кода, курсор станет на имени класса в его объявлении и вверху появятся два раскрывающихся списка: в левом будет имя класса, а в правом - список его функций-членов.
- Раскройте правый список методов класса и двойным щелчком мыши позиционируйтесь на методе Serialize()
В результате откроется файл CircleDoc.cpp, где находится этот метод, и курсор установится на реализации метода.
Заготовка функции Serialize() выглядит так
Заготовка функции Serialize() в файле CircleDoc.cpp void CCircleDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here // Сюда добавить код сохранения } else { // TODO: add loading code here // Сюда добавить код загрузки } }
Ссылка ar соответствует потоку (открытому каналу связи), связанному с архивом (файлом), открытым на запись или чтение. Заготовка пока ничего не читает и ничего не сохраняет.
-
Модифицируйте код заготовки метода Serialize() следующим образом
Код функции Serialize() в файле CircleDoc.cpp void CCircleDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here // Сюда добавить код сохранения ar << m_PosX << m_PosY; } else { // TODO: add loading code here // Сюда добавить код загрузки ar >> m_PosX >> m_PosY; } }
Существует строгое правило сериализации и десериализации: последовательность данных, перечисленных для сохранения, должна строго соответствовать данным, перечисленным для загрузки
Изменение заголовка окна приложения и назначение фильтра
- Выполните команду View/Other Windows/Resource View, в появившейся панели раскройте дерево ресурсов и двойным щелчком на узле String Table вызовите редактор ресурсов с таблицей String Table, позволяющей просматривать и редактировать различные строки, используемые программой
В верхней части таблицы редактора ресурсов имеется строка с идентификатором IDR_MAINFRAME
Значением этой строки является
Circle\n\nCircle\n\n\nCircle.Document\nCircle.Document
Символы \n служат разделителями 7 разделов, некоторые из которых обозначают следующее
- Circle - определяет заголовок окна приложения
- Null
- Circle
- Null - определяет наименование фильтра в строке Files of type диалогового окна Save As или Open
- Null - определяет фильтр в строке File name диалогового окна Save As или Open
- Circle.Document
- Circle.Document
- Измените прямо в таблице или через панель Properties содержимое разделов 1, 4 и 5 как показано ниже
1. Программа рисования окружности - лабораторная работа 4. CIR Files (*.cir) 5. .cir
Новое значение строки должно быть таким
Программа рисования окружности - лабораторная работа\n\nCircle\nCIR Files (*.cir)\n.cir\nCircle.Document\nCircle.Document
- Постройте приложение и выполните программу. Должно получиться окно со следующим заголовком
Замечание. Возможно, что Ваш проект не настроен на корректное отображение русского языка и может получиться нечто следующее
В этом случае нужно выполнить такие действия:
- При открытом файле ресурсов в панели редактирования ресурсов для узла String Table вызвать контектсное меню Properties
- В выпадающем списке Language выбрать язык Русский
- Вернуться к таблице String Table со строкой заголовка, которая может оказаться испорченной после компиляции, и вновь восстановить строку заголовка
- Сохранить измененный ресурс и выполнить программу
После таких действий должно получиться окно с нормальным заголовком.
При начальной загрузке документа он безымянный, поэтому имеет в заголовке Untitled. При каждом новом выполнении команды New меню File генерируется безымянный документ. Щелчок мыши в клиентской области окна устанавливается флаг модификации документа в обработчике OnLButtonDown(), поэтому при закрытии документа должно выдаваться стандартное предупреждение
Наши изменения строки ресурсов заметны не только в заголовке окна приложения. Команды File/Save As и File/Open приложения вызывают стандартные диалоговые окна с назначенным нами фильтром
Изменение иконки приложения
Среда проектирования Visual Studio .NET 2005 при создании нового MFC -проекта генерирует стандартную иконку, которая имеет имя, совпадающее с именем приложения Circle.ico и размещается в папке res каталога проекта. На эту иконку ссылается идентификатор IDR_MAINFRAME. Чтобы убедиться в этом
- Через панель Solution Explorer раскройте узел Resource Files и для файла Circle.rc выполните команду View Code контекстного меню
Мы видим, что в секции Icon содержится код привязки файла иконки к идентификатору ресурсов
Секция Icon в файле ресурсов Circle.rc ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON "res\\Circle.ico" IDR_CircleTYPE ICON "res\\CircleDoc.ico"
Заменить иконку главного окна приложения можно несколькими способами, например:
- Физически скопировать файл нужной иконки в каталог res проекта приложения и заменить его имя на имя проекта Circle.ico
- Физически скопировать файл нужной иконки в каталог res проекта приложения и зарегистрировать ее в файле Circle.rc
- Без физического копирования установить связь с нужной иконкой и присвоить ей идентификатор IDR_MAINFRAME иконки главного окна
- Через Проводник Windows скопируйте файл иконки из прилагаемого каталога Source в каталог res проекта, например
- В панели Solution Explorer вызовите контекстное меню для корневого узла Circle проекта и выполните команду Add/Resource
-
В появившемся диалоговом окне установите тип ресурса Icon и выполните кнопку Import, чтобы зарегистрировать в ресурсах нужный файл иконки
Оболочка присвоит добавленному ресурсу идентификатор по умолчанию IDI_ICON1 и сделает запись в файле ресурсов
Секция Icon в файле ресурсов Circle.rc ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDR_MAINFRAME ICON "res\\Circle.ico" IDR_CircleTYPE ICON "res\\CircleDoc.ico" IDI_ICON1 ICON "res\\2.ICO
- В панели Resource View выделите ресурс старой иконки с идентификатором IDR_MAINFRAME и через контекстное меню или клавишей Delete отсоедините его от проекта
- В панели Resource View выделите ресурс IDI_ICON1 новой иконки и через панель Properties измените его имя на IDR_MAINFRAME
- Постройте приложение и убедитесь в появлении новой иконки
Русификация меню
Русифицируем меню приложения и удалим ненужные кнопки и пункты. Это мы сделаем для иллюстрации возможностей среды, а вообще-то английские названия данного приложения уместны и понятны.
- В панели Resource View раскройте узел Menu и выделите ресурс IDR_MAINFRAME
- Раскройте панель Properties и установите Language=Русский (если он не установлен)
- В панели Resource View дважды щелкните по ресурсу IDR_MAINFRAME, чтобы открыть редактор меню
- Вызовите и закрепите на экране панель Properties, которая отражает стандартные свойства каждого пункта меню
- Последовательно выделяя пункты меню, замените значение свойства Caption (название пункта) и Prompt (длинная подсказка в строке состояния и всплывающая подсказка, отделенные символом новой строки) на русское содержимое, соблюдая синтаксис
- Меню верхнего уровня Edit в нашем проекте не используется, как и соответствующие кнопки панели инструментов, поэтому удалите их
Панель инструментов на редактирование можно вызвать двойным щелчком на идентификаторе IDR_MAINFRAME в папке Toolbar панели Resource View, а ненужные пиктограммы для удаления просто стаскивать мышью с этой панели.
Для редактирования текстов можно использовать и другой способ. Поскольку пункты меню и кнопки панели инструментов привязаны к одним и тем же действиям, то они имеют одни и те же идентификаторы ресурсов, хранящиеся в строковом ресурсе String Table. Поэтому через панель Resource View можно вызвать редактор String Table и править названия длинных и всплывающих подсказок прямо в таблице.
Текст в центре клиентской области
Дополним нашу программу выводом текста в центре окна представления документа, которое является клиентской областью окна-рамки всего приложения.
-
Введите в класс документа объявление новой переменной m_strText
Для быстрого позиционирования вызовите панель Class View и дважды кликните на классе CCircleDoc. В рабочей области откроется файл CircleDoc.h в режиме редактирования. Код объявления переменной класса будет таким
Объявление новой переменной в файле CircleDoc.h class CCircleDoc : public CDocument { protected: // create from serialization only CCircleDoc(); DECLARE_DYNCREATE(CCircleDoc) // Attributes public: int m_PosX; // координата x (по горизонтали) центра круга int m_PosY; // координата y (по вертикали) центра круга CString m_strText; // для хранения текста ........................................ };
-
В конструктор класса введите инициализацию текстовой переменной. Для этого в правом верхнем раскрывающемся списке выберите имя конструктора CCircleDoc, которое совпадает с именем класса Документа. Откроется файл CCircleDoc.cpp в режиме редактирования, в который внесите свое изменение
Файл CircleDoc.cpp - инициализация новой переменной CCircleDoc::CCircleDoc() // конструктор класса { // TODO: add one-time construction code here m_strText = "Привет студентам от Снеткова В.М.!!!"; }
-
В файле CircleView.cpp выберите функцию OnDraw() и поместите в нее код вывода текста в центр клиентской области приложения. Для этого нужно определить
- ширину и высоту клиентской области
- ширину и высоту текста
- вычислить начальную позицию для вывода текста
- вывести сам текст
Рисование текста в функции OnDraw() файла CircleView.cpp void CCircleView::OnDraw(CDC* pDC) { CCircleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // TODO: add draw code for native data here // Задать границы прямоугольника, в которых // будет нарисован круг CRect rect; rect.left = m_PosX - 20; rect.top = m_PosY - 20; rect.right = m_PosX + 20; rect.bottom = m_PosY + 20; // Нарисовать круг pDC->Ellipse(&rect); // Вывод текста в центре клиентской области окна-рамки GetWindowRect(&rect); // определение размеров клиентской области CSize size = pDC->GetTextExtent(pDoc->m_strText); // размеры текста int width = rect.right - rect.left; // ширина клиентской области int height = rect.bottom - rect.top;// высота клиентской области int x = (width - size.cx) / 2; // позиция вывода по ширине int y = (height - size.cy) / 2; // позиция вывода по высоте pDC->TextOut(x, y, pDoc->m_strText); // вывод строки с текстом }
- Запустите приложение и получите окончательный результат
Выводы
В результате последовательности шагов мы получили вполне работоспособную программу SDI -архитектуры. Особенность такой архитектуры состоит в том, что окно-рамка приложения может включать в себя только один текущий документ. При открытии нового документа содержимое старого документа замещается новым.
Попутно мы познакомились с некоторыми особенностями среды проектирования, существенно облегчающей жизнь разработчика. В центре всего процесса проектирования приложения стоит объектно-ориентированный подход, основанный на работе с классами и широко применяющий свойство наследования классов.
Заготовка приложения генерируется мастерами по предварительным настройкам, запрашиваемым у разработчика. Дальнейшая работа программиста состоит в последовательной модификации заготовки кода в соответствии со спецификацией своей задачи и выбранных методов решения. Это позволяет разработчику больше сосредоточиться на предметной области проекта и не отвлекаться на частные вопросы системной реализации.
Сочетание этапов визуального проектирования и последующего кодирования позволяют представить технологию решения более наглядной и структурированной. Процесс программирования становится более последовательным и более свободным от систематических ошибок. Это существенно сокращает сроки проектирования и делает программный код надежным и легко модифицируемым.
На экране сосуществуют текст и графика потому, что все перед выводом преобразуется в растровую графику.