Национальный исследовательский институт «МИЭТ»
Кафедра ВТ
Курс: «Объектно-ориентированное программирование» для групп МП-21, 22 и 23
Лабораторная работа №2 «Интерфейсы и классы»
Составил: доцент кафедры ВТ, к.т.н. Тельминов О.А.
Москва, 2012
2
Цель работы: получить навыки работы в среде разработки Visual Studio 2008 (С++) по взаимодействию элементов управления на форме и пользовательских классов.
1. Модель взаимодействия «ведущий – ведомый»
Устройство обработки информации, как правило, состоит из отдельных модулей. При проектировании устройства назначается протокол передачи данных – набор правил, определяющих обмен данными между модулями.
На рисунке 1 приведен пример, когда ведущий модуль на команду типа 1 ожидает в ответ подтверждение типа 1, команда типа 2 отрабатывается ведомым модулем без подтверждения. Разновидностью команды может являться запрос информации, на который ожидается ответ.
В данном примере в качестве ведущего модуля выступает блок управления и индикации, в качестве ведомого – перемещаемый датчик температуры. Команда типа 1 – перемещение датчика в указанное положение и подтверждение датчика о выполнении команды. Команда типа 2 – переход в спящий режим, подтверждение ее выполнения не предусмотрено. Ответ на запрос типа 1 – информация о температуре в измеряемой точке и положении датчика.
Ведущий модуль содержит терминал – клавиатуру и дисплей для взаимодействия с оператором, а также блок управления, реализующий основную логику работы всего устройства.
Ведомый модуль содержит датчик температуры и сервопривод для его перемещения. В данном случае ведомый модуль не имеет возможности самостоятельно отправить запрос или команду ведущему модулю – например, о выходе температуры из диапазона или неисправности сервопривода.
|
Команда_1 |
|
|
|
|
|
Подтвержд_1 |
|
Ведущий |
Команда_2 |
Ведомый |
|
||
модуль |
|
модуль |
|
Запрос_1 |
|
|
|
|
|
|
|
|
Ответ_1 |
|
|
|
|
Рисунок 1. Команды и запросы отправляет ведущий модуль, ведомый только подтверждает прием команды или отвечает на запрос
Рассмотрим на программном примере «терминал» для ввода и отображения результата вычисления – соответствует ведущему модулю, и вычислитель квадратного корня – соответствует ведомому модулю. Команды и подтверждения (запросы и ответы), необходимые для взаимодействия модулей приведены в таблице 1.
Обратите внимание, что команды (запросы) принадлежат ведомому модулю и вызываются ведущим модулем. Доступ ведомого модуля к ведущему отсутствует. Кроме того, проверка на корректность аргумента производится на стороне ведомого модуля – вычислитель получает подтверждение корректности входных данных в ответ на команду их установки.
Таблица 1. Реализация действий терминала с помощью команд вычислителя
Ведущий модуль – |
Ведомый модуль – вычислитель корня |
|||
терминал |
||||
|
|
|
||
Действие |
Команда (запрос) |
Подтверждение |
Действие |
|
(ответ) |
||||
|
|
|
||
|
|
|
|
|
1 |
2 |
3 |
4 |
|
Вычислить |
Команда установки |
Возвращаемое |
Внутренняя |
|
|
входных данных |
значение: |
переменная x |
|
|
вычислителя |
0 – аргумент |
изменяется только при |
|
|
int SetX (double _x) |
неотрицательный; |
неотрицательных |
|
|
|
-1 – иначе |
входных данных |
|
|
|
|
|
|
|
double Calc() |
Возвращаемое |
Вычисление корня из |
|
|
|
значение: |
значения внутренней |
3
|
|
корень из значения |
переменной x |
|
|
внутренней |
|
|
|
переменной x |
|
Запрос текущего |
double GetX() |
Возвращаемое |
Передача значения |
значения входных |
|
значение: |
внутренней |
данных вычислителя |
|
значение внутренней |
переменной x |
|
|
переменной x |
|
В таблице 2 приведены описания внутренних элементов модулей. Для терминала указаны только управляющие элементы, необходимые вспомогательные элементы будут добавлены в процессе программирования. Для вычислителя необходима внутренняя переменная, доступ к которой напрямую запрещен с целью защиты от ввода некорректных данных. Запись в переменную осуществляется после проверки. Остальные функции предназначены для получения результата вычисления и текущего значения переменной.
Таблица 2. Состав модулей и описание внутренних элементов
Ведущий модуль – терминал |
Ведомый модуль – вычислитель |
||
Внутренний элемент |
Описание |
Внутренний элемент |
Описание |
1 |
2 |
|
|
Содержит аргумент, |
|
Поле для ввода текста |
вводится |
|
пользователем |
||
(Edit) |
||
Начальное значение |
||
|
||
|
после запуска: «0» |
|
|
Активирует |
|
|
вычисление корня, при |
|
|
нажатии |
|
|
пользователем; |
|
|
предварительная |
|
|
проверка поля Edit на |
|
Кнопка (Button) |
предмет корректности |
|
ввода числа (содержит |
||
|
||
|
знаки 0..9 и |
|
|
десятичный |
|
|
разделитель) |
|
|
Заголовок: |
|
|
«Вычислить» |
|
|
|
|
|
Заголовок: |
|
|
– начальное значение |
|
|
«Вычисление корня»; |
|
|
– ответ при успешном |
|
Надпись (Label) |
вычислении корня; |
|
|
– «Введите |
|
|
неотрицательное |
|
|
число» при ошибке |
|
|
ввода |
|
|
|
3 |
4 |
требуется защита от double x ввода отрицательного
значения
– обновление x и
int SetX(double _x) возврат 0, если _x
неотрицательно;
– возврат -1 иначе,
Возвращает значение int GetX(double _x) внутренней
переменной x
Вычисляет значение
void Calc() корня из значения внутренней
переменной x
Для проверки работоспособности приложения разработан тест (таблица 3)
Таблица 3. План тестирования приложения
№ |
Объект проверки |
Способ проверки |
теста |
|
|
|
|
|
1 |
2 |
3 |
1. |
Начальное значение параметров Edit, Button, Label |
Запуск приложения, визуально |
2. |
Начальное значение внутренней переменной |
Запуск приложения до |
4
1 |
2 |
3 |
|
вычислителя |
breakpoint, установленной в |
|
|
точке создания вычислителя. |
|
|
Анализ значения переменной |
3. |
Ввод нечисловых данных в поле Edit (принятие решения |
Label: «Введите |
|
без отправки запроса вычислителю) |
неотрицательное число»; |
|
|
убедиться в режиме |
|
|
трассировки |
4. |
Ввод отрицательного числа в поле Edit (принятие |
Label: «Введите |
|
решения на основе ответа вычислителя) |
неотрицательное число»; |
|
|
убедиться в режиме |
|
|
трассировки |
5. |
Ввод «0» |
Label: «0» |
6. |
Ввод «99» |
Анализ значения Label и |
|
|
принятие решения о |
|
|
корректности |
7. |
Ввод максимального положительного числа с плавающей |
Анализ значения Label и |
|
точкой |
принятие решения о |
|
|
корректности |
8. |
Ввод максимального отрицательного числа с плавающей |
Анализ значения Label и |
|
точкой |
принятие решения о |
|
|
корректности |
Создадим новый проект MFC (библиотека Microsoft Foundation Classes) в Visual C++,
шаблон “MFC Application”. Определим имя проекта MFC01. В следующем окне выберем Application Type = “Dialog based” (приложение будет состоять из одной формы с элементами управления, как калькулятор Windows), Use Unicode libraries = , остальные установки оставить по умолчанию.
Запустите приложение. Если возникнет окно с ошибкой “No Debugging Information”, выберите в левой части среды разработки вкладку “Solution Explorer”, щелкните правой кнопкой мыши по Solution и последовательно выполните Clean, Rebuild. После повторного запуска ошибка пропадет. Появится диалоговая форма с двумя кнопками и надписью “TODO…”.
Создадим класс Engine, отвечающий за работу ведомого устройства – вычислителя. В левой части среды разработки на вкладке “Solution Explorer”, щелкните правой кнопкой мыши и создайте новый класс (Create/New class). Проверьте содержимое файлов Engine.cpp и Engine.h, найдите объявление класса и реализацию конструктора и деструктора.
Добавим внутреннюю переменную x класса Engine. В левой части среды разработки на вкладке “Class View” щелкните правой кнопкой мыши и создайте переменную (Engine/Add/Add variable…). Выберите тип доступа Access = private, тип переменной double, имя x. Аналогично добавьте необходимые функции с указанием Return type (тип возвращаемого значения), Function name (имя функции). Каждый параметр определяется типом (Parameter type) и именем (Parameter name) и добавляется кнопкой Add.
Заполним тело функции SetX: int ret = -1;
if (_x >= 0)
{
x = _x; ret = 0;
}
return ret;
Самостоятельно заполните тела остальных функций, учитывая что sqrt() объявлена в <math.h>. Убедитесь, что в поле инициализации конструктора переменная x обнуляется.
Обеспечим доступ из класса ведущего модуля (диалоговой формы) в MFC01Dlg.h:
–добавим #include “Solution.h”;
–в классе “class CMFC01Dlg : public CDialog” добавим объект: private:
Engine slave;
5
Далее добавим элементы управления на форму MFC01Dlg: Label, Edit и Button. Для этого используйте панель инструментов в правой части среды разработки.
Добавим обработчик нажатия на кнопку – функцию, автоматически вызываемую при нажатии на эту кнопку. Для этого дважды кликните по кнопке на форме.
Свяжем переменную XValue с элементом управления ЕDIT1 для доступа к тексту. Щелкните правой кнопкой мыши по кнопке ЕDIT1 и выберите Add Value. В окне настроек выберите Category = Value.
Пример работы со строкой Unicode:
DDX_Text(pDX, IDC_EDIT1, XValue);
Рассмотрим работу со строками Unicode.
UpdateData(true);//загрузить данные из элементов управления в переменные
CString s;
//преобразование числа в строку s.Format(_T("%d"),-152);
//преобразование строки в число int uns = _tcstoul(s, 0, 10);
int sig = _tcstol (XValue, 0, 10);
//преобразование char* в строку char *str = "По-русски.";
s = str;
//преобразование строки в char* char str2[300];
CT2A ascii(s, 1251); //866-DOS, 1251-Win std::ofstream ofs("h:\\1.txt");
//strcpy(str2, ascii.m_psz); ofs<<ascii.m_psz<<std::endl; ofs.close();
double ddd = 10.0; s.Format(_T("%f"),ddd);
GetDlgItem(IDC_STATIC1)->SetWindowText(s);
UpdateData(false);//загрузить данные из переменных в элементы управления
}
else
{
GetDlgItem(IDC_STATIC1)->SetWindowText(_T("Ошибка данных: введите неотрицательное число"));
//UpdateData(false);//загрузить данные из переменных в элементы управления
}
Функции для работы с комбобокса (также SetCurSel()) //в настройках комбобокса отключить автосортировку m_SecondCombo.AddString(L"Строка начальная"); m_SecondCombo.AddString(L"Строка средняя");
6
m_SecondCombo.AddString(L"Строка конечная"); m_SecondCombo.SetCurSel(1);
2.Задание
1.Завершите и протестируйте рассмотренную выше программу.
2.Разработайте по аналогии свою программу по вариантам (номер в списке группы по модулю 2): интерфейсная форма + исполнитель (вычислитель). Подготовьте доклад и отчет в электронной форме о выполненной работе.
Вариант 0. Калькулятор.
Вариант 1. Пульт управления домашним кинотеатром. Вариант 2. Пульт управления стереосистемой. Вариант 3. Бортовой компьютер автомобиля.