Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
New Документ Microsoft Word (3).doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
1 Мб
Скачать
☆

12.Разработка приложения с архитектурой «документ-вид». Часть 1

Невозможно создать программу с полной защитой от дураков, ибо дураки крайне изобретательны

Закон Мерфи

Цель работы – освоить разработку приложения, основанного на архитектуре «документ-вид» (4 час.)

Сценарий этой работы основан на материале глав 16 и 17 работы [1]. Характерной особенностью этого приложения является не только его ориентация на архитектуру «документ-представление», но и использование класса CFormView в качестве базового для окна вида.

Суть работы состоит в следующем. Создается каркас SDI-приложения с архитектурой «документ-вид» и в качестве базового класса для класса представления выбирается CFormView. Этот класс подобен классу CDialog в том смысле, что он может быть носителем управляющих элементов: полей ввода, переключателей, списков и т.п. – в отличие от базового класса CView. На следующем шаге Вы должны разработать свой собственный класс, предназначенный для обработки некоторых данных, отличающийся от описанного ниже класса CStudent количеством и типами компонент. В качестве примера в данном сценарии приводится класс CStudent, который содержит только фамилию студента и целочисленный балл. Далее необходимо разместить в окне представления управляющие элементы, предназначенные для ввода (и отображения) данных и реализовать сохранение введенных данных в классе документа.

Задание.

  1. Ознакомьтесь с теоретической частью работы по конспекту лекций (разделы 9, 5.3-5.5).

  2. Создайте приложение в соответствии с приведенным ниже сценарием. Разработайте свой собственный класс и, соответственно, свои управляющие элементы для ввода данных.

  3. Выполните отладку и добейтесь работоспособности приложения.

  4. Осмыслите полученный результат, примененный инструментарий и приемы программирования.

  5. Ответьте на коварные вопросы преподавателя и получите наивысшую оценку. Если удастся продать свое приложение (а за ним уже давно гоняются шпиёны из Microsoft) – поделитесь доходами с кафедрой, например, купите хотя бы один новый компьютерный класс.

12.1.Сценарий создания приложения

Шаг 1 (решительный). Создание каркаса приложения.

Создайте новый проект, присвойте ему имя, выберите Project types=MFC и Templates=MFC Application. В данном сценарии я выбрал для проекта незамысловатое, т.е. гениальное, имя FRM. Придавите ОК. На вкладке Application type:

  • шлепните по радиокнопке Single document;

  • слегка щелкните по радиокнопке MFC Standard;

  • в списке Resource language не забудьте выбрать элемент со значением Русский;

  • установите переключатель Use Unicode libraries.

Значения остальных свойств не изменяйте под страхом смерти, т.е. незавершения отладки приложения при жизни.

Перейдите к вкладке Generated Classes и для класса представления CFRMView выберите в качестве базового класс CFormView вместо коварно предлагаемого по умолчанию класса CView (рис. 1). Завершите создание каркаса приложения торжественным шлепком по кнопке Finish. Постройте и запустите приложение на выполнение, чтобы посмотреть на его внешний вид. Окно вида напоминает диалоговое окно, но вместе с тем в нем присутствует меню и панель инструментов, что не может не радовать, так как досталось даром.

Шаг 2. Добавление в приложение собственного класса.

Свой собственный класс проще всего добавить в проект с помощью команды меню ProjectèAdd class, в результате выполнения которой появится диалоговое окно, посредством которого Вы и сможете создать свой класс. В этом окне выберите Categories=MFC и Templates=MFC Class и нажмите кнопку Add. В другом появившемся окне выберите в качестве базового (Base class) класс CObject и задайте имя своего класса, например, CStudent. Обратите внимание, что мастер предлагает имена файлов Student.h и Student.cpp, в которых будет располагаться объявление класса и его реализация соответственно. Если не боитесь проклятий возможных читателей вашего проекта – изменяйте имена файлов. Нажмите Finish, если не страшно.

Рис. 1. Выбор базового класса CFormView для класса вида CFRMView

Вы могли бы изменить имена файлов, сгенерированные мастером, но я бы этого не рекомендовал.

Файлы Student.h и Student.cpp добавлены в проект, но файл Student.h пока никуда не подключается с помощью директивы препроцессора include – это надо будет впоследствии сделать вручную, так как мастер не может догадаться, где мы собираемся использовать данный класс.

Содержимое файлов Student.h и Student.cpp должно быть таким:

// Файл Student.h

#pragma once

// CStudent command target

class CStudent : public CObject

{

public:

CStudent();

virtual ~CStudent();

};

// Student.cpp : implementation file

//

#include "stdafx.h"

#include "FRM.h"

#include "Student.h"

// CStudent

CStudent::CStudent()

{

}

CStudent::~CStudent()

{

}

// CStudent member functions

Шаг 3. Добавление членов в класс CStudent.

Для того чтобы класс CStudent был полезен, надо добавить в него член-данные, парочку конструкторов и функцию Dump, предназначенную для вывода отладочной информации. Кроме того, добавьте в файлы макросы DECLARE_DYNAMIC и IMPLEMENT_DYNAMIC, которые гарантируют, что имя класса будет доступно при выводе диагностической информации. Модифицируйте файлы Student.h и Student.cpp в соответствии с приведенными ниже листингами.

// Файл Student.h

#pragma once

class CStudent : public CObject

{

DECLARE_DYNAMIC(CStudent)

public:

CString m_strName; // фамилия студента

int m_nGrade; // отметка

CStudent(); // конструктор по умолчанию

CStudent(const char* szName, int nGrade); // конструктор с параметрами

virtual ~CStudent();

#ifdef _DEBUG

void Dump(CDumpContext& dc) const;

#endif // _DEBUG

};

// Student.cpp : implementation file

#include "stdafx.h"

#include "FRM.h"

#include "Student.h"

// CStudent

IMPLEMENT_DYNAMIC(CStudent, CObject)

CStudent::CStudent()

{

m_nGrade = 0;

}

CStudent::CStudent(const char* szName, int nGrade)

{

m_strName = szName;

m_nGrade = nGrade;

}

CStudent::~CStudent()

{

}

// CStudent member functions

#ifdef _DEBUG

void CStudent::Dump(CDumpContext& dc) const

{

CObject::Dump(dc);

dc << "m_strName = " << m_strName << "\nm_nGrade = " <<m_nGrade;

}

#endif // _DEBUG

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

Шаг 4. Редактирование меню приложения.

Оставим пока класс CStudent и займемся интерфейсом программы. На вкладке Resource View выберите идентификатор IDR_MAINFRAME в ветви Menu и, незаметно для ИС, замените имеющиеся команды в меню Правка на единственную команду Clear АLL. Введите константу ID_EDIT_CLEARALL как идентификатор команды Clear АLL (см. вкладку Properties).

Шаг 5. В редакторе диалоговых окон измените диалоговое окно IDD_FRM_FORM. Открыв диалоговый ресурс IDD_FRM_FORM в ветви Dialog, сгенерированный мастером, добавьте элементы управления для ввода имени студента и целочисленного балла (рис. 2). Не изменяйте установленных по умолчанию свойств формы Style=Child и Visible=False.

Рис. 2. Окно представления с управляющими элементами

Присвойте элементам управления идентификаторы, указанные табл. 1.

Таблица 1.

Элемент управления

ID

Элемент ввода фамилии

IDC_NAME

Элемент ввода отметки

IDC_GRADE

Кнопка «Принять»

IDC_ENTER

Шаг 6. Добавьте обработчики сообщений для CFRMView. Выберите класс CFRMView (вкладка Class View) и добавьте указанные ниже обработчики сообщений (табл. 2). Оставьте имена функций по умолчанию.

Таблица 2.

Идентификатор ресурса

Сообщение

Обработчик сообщения

IDC_ENTER

BN_CLICKED

OnBnClickedEnter

ID_EDIT_CLEARALL

COMMAND

OnEditClearall

ID_EDIT_CLEARALL

UPDATE_COMMAND_UI

OnUpdateEditClearall

Шаг 7. Добавьте переменные для CFRMView.

Добавьте для элементов ввода Фамилии и Отметки студента переменные, свойства которых приведены в табл. 3. Напомню, что для добавления таких переменных надо в окне редактора ресурсов выбрать элемент ввода, с помощью ПКМ вызвать контекстное меню и в нем выбрать команду Add variable.

Таблица 3.

Идентификатор ресурса

Имя переменной

Категория

Тип переменной

IDC_GRADE

m_nGrade

Value

int

IDC_NAME

m_strName

Value

CString

Задайте для m_nGrade минимальное значение 0, максимальное — 100. Заметьте, что мастер генерирует код, необходимый для проверки данных, вводимых пользователем (найдите этот код).

Шаг 8. Добавьте прототип вспомогательной функции UpdateControlsFromDoc. В окне ClassView выберите класс CFrmView щелкните ПКМ и выберите команду AddèAdd Function (добавить функцию-член). Заполните диалоговую форму, чтобы добавить следующую функцию:

private:

void UpdateControlsFromDoc();

Шаг 9. Отредактируйте файл FRMView.cpp. Отредактируйте код функций так, как показано ниже:

Так как пока у нас в классе документа переменной m_student нет, то и программа компилироваться без ошибок не будет.

Функция OnBnClickedEnter() заменяет функцию OnOK(), которую можно было бы ожидать в классе диалогового окна. Она передает данные из полей ввода в переменные-члены объекта «вид», а потом в документ. Добавьте код, выделенный полужирным шрифтом:

В сложной программе, допускающей несколько представлений данных, команда Clear All передавалась бы непосредственно документу. В нашем же простом примере она доставляется объекту «вид». Обработчик сообщения обновления пользовательского интерфейса отключает элемент меню, если объект CStudent в документе уже пуст. Договоримся, что объект будет считаться пустым, если член m_nGrade==0. Отредактируйте обработчики команды меню в соответствии со следующим листингом:

Шаг 10. Добавьте переменную типа CStudent в класс CFRMDoc. Это можно сделать, используя окно ClassView и контекстное меню, тогда директива #include “Student.h”будет добавлена автоматически.

public:

CStudent m_student;

Вот теперь приложение должно компилироваться, хотя у компилятора может быть и свое мнение по этому поводу.

Конструктор класса CStudent вызывается при создании объекта «документ», а деструктор вызывается автоматически при уничтожении документа.

Шаг 11. Отредактируйте файл FRMDoc.cpp. Для инициализации объекта CStudent воспользуйтесь конструктором CFRMDoc:

CFRMDoc::CFRMDoc() : m_student("", 0)

{

TRACE("Document object constructed\n");

}

Мы не определим, правильно ли работает программа FRM, пока не выведем содержимое документа по завершении программы. Для этого воспользуемся деструктором, который вызовет функцию Dump() документа, а та — функцию CStudent::Dump(). А посему отредактируйте код деструктора класса документ и функции Dump() этого же класса. Вы, конечно, заметили, что функция Dump(afxDump) будет вызываться только в отладочной конфигурации приложения, так как ее вызов окружен директивой условной компиляции #ifdef _DEBUG … #endif.

Шаг 12. Соберите и протестируйте приложение FRM. Введите какое-нибудь имя и балл, а затем щелкните кнопку Принять. Закройте приложение. Появились ли в окне Debug сообщения, аналогичные показанным ниже?

a CFRMDoc at $00358FF0

m_strTitle = _CrtDbgReport: String too long or IO Error

m_strPathName =

m_bModified = 0

m_pDocTemplate = $00358DF8

a CStudent at $00359044

m_strName = Smith

m_nGrade = 34

Примечание. Чтобы увидеть эти сообщения, компилируйте программу для конфигурации Debug и запустите ее под управлением отладчика (F5, а не Ctrl+F5).

Некоторые пояснения к строке

m_strTitle = _CrtDbgReport: String too long or IO Error

В ней выводится заголовок окна приложения, который в нашем случае представляет собой строку «Без названия - FRM». Сообщение «String too long or IO Error» означает, что функция Dump не может вывести символы кириллицы. Попробуйте с помощью команды приложения ФайлèОткрыть открыть любой файл с именем, не содержащим символов кириллицы, и вы увидите имя этого файла в обсуждаемой строке.

Если Вы попробуете ввести фамилию символами кириллицы, Вы также в окне Debug увидите сообщение «m_strName = String too long or IO Error». В документе фамилия будет сохраняться корректно, но вот в окне отладки мы в лучшем случае увидим «крякозябры». Вывести символы кириллицы в окно отладки можно, например, так:

char Buf[300];

char * GetANSI(CString str)

{

WideCharToMultiByte(1251,WC_NO_BEST_FIT_CHARS,

str,-1,Buf,sizeof(Buf),0,0);

return Buf;

}

TRACE(GetANSI(m_student.m_strName));

А вы не забыли разработать свой собственный класс и добавить на форму элементы, предназначенные для ввода его член-данных?

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]