Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 999 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Самостоятельная работа 1:

SDI-приложение MFC

Самостоятельная работа 1: 12 || Самостоятельная работа 2 >

Сохранение и загрузка данных Документа

Напишем код, который будет отвечать за сохранение Документа в файле и загрузку ранее сохраненных Документов. Этот процесс основан на функции 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 разделов, некоторые из которых обозначают следующее

  1. Circle - определяет заголовок окна приложения
  2. Null
  3. Circle
  4. Null - определяет наименование фильтра в строке Files of type диалогового окна Save As или Open
  5. Null - определяет фильтр в строке File name диалогового окна Save As или Open
  6. Circle.Document
  7. Circle.Document
  • Измените прямо в таблице или через панель Properties содержимое разделов 1, 4 и 5 как показано ниже
1.	Программа рисования окружности - лабораторная работа 
4.	CIR Files (*.cir) 
5.	.cir

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

Программа рисования окружности - лабораторная работа\n\nCircle\nCIR Files (*.cir)\n.cir\nCircle.Document\nCircle.Document
  • Постройте приложение и выполните программу. Должно получиться окно со следующим заголовком

Замечание. Возможно, что Ваш проект не настроен на корректное отображение русского языка и может получиться нечто следующее


В этом случае нужно выполнить такие действия:

  1. При открытом файле ресурсов в панели редактирования ресурсов для узла String Table вызвать контектсное меню Properties
  2. В выпадающем списке Language выбрать язык Русский
  3. Вернуться к таблице String Table со строкой заголовка, которая может оказаться испорченной после компиляции, и вновь восстановить строку заголовка
  4. Сохранить измененный ресурс и выполнить программу

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

При начальной загрузке документа он безымянный, поэтому имеет в заголовке 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"

Заменить иконку главного окна приложения можно несколькими способами, например:

  1. Физически скопировать файл нужной иконки в каталог res проекта приложения и заменить его имя на имя проекта Circle.ico
  2. Физически скопировать файл нужной иконки в каталог res проекта приложения и зарегистрировать ее в файле Circle.rc
  3. Без физического копирования установить связь с нужной иконкой и присвоить ей идентификатор 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 -архитектуры. Особенность такой архитектуры состоит в том, что окно-рамка приложения может включать в себя только один текущий документ. При открытии нового документа содержимое старого документа замещается новым.

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

Заготовка приложения генерируется мастерами по предварительным настройкам, запрашиваемым у разработчика. Дальнейшая работа программиста состоит в последовательной модификации заготовки кода в соответствии со спецификацией своей задачи и выбранных методов решения. Это позволяет разработчику больше сосредоточиться на предметной области проекта и не отвлекаться на частные вопросы системной реализации.

Сочетание этапов визуального проектирования и последующего кодирования позволяют представить технологию решения более наглядной и структурированной. Процесс программирования становится более последовательным и более свободным от систематических ошибок. Это существенно сокращает сроки проектирования и делает программный код надежным и легко модифицируемым.

На экране сосуществуют текст и графика потому, что все перед выводом преобразуется в растровую графику.


Самостоятельная работа 1: 12 || Самостоятельная работа 2 >
Александр Даниленко
Александр Даниленко
Стоит Windows 8 Pro, Visual Studio 2010 Express Edition .