- •Овсянник в.Н. Лабораторные работы по курсу «Объектно-ориентированное программирование»
- •13. Разработка приложения с архитектурой «документ-вид». Часть 2 120
- •14. Разработка приложения с архитектурой «документ-вид». Часть 3 135
- •1.Разработка типового консольного приложения
- •1.1.Методические указания
- •1. Запуск и настройка ис mvs-2008.
- •2.Поиск данных в массиве
- •3.Обработка текстового файла
- •4.Задача «куча камней»
- •5.Реализация алгоритма полного перебора
- •6. Исследование погрешностей вычислений
- •7.Поиск экстремумов с ограничениями или «Брачное агенство»
- •Постановка задачи
- •Задание
- •Листинг файла mAgency.Cpp (с главной функцией)
- •Листинг файла Lib.H
- •Листинг файла Lib.Cpp
- •8.Приложение с окном вида
- •9.Разработка графического редактора
- •Задание.
- •9.1.Проектирование программы
- •9.2.Разработка интерфейса
- •Установка флагов
- •Создание меню и панели инструментов
- •Обработка сообщений о нажатии кнопки мыши
- •9.3.Рисование
- •9.4.Растягивание фигур
- •9.5.Обновление изображения
- •9.6.Сохранение метафайла на диске и его загрузка
- •10.Приложение, основанное на модальном диалоговом окне
- •Методические указания Модальные и немодальные диалоговые окна
- •Ресурсы и элементы управления
- •Сценарий создания приложения
- •Разбор приложения
- •Усовершенствование приложения
- •11.Приложение с контекстным меню и строкой состояния
- •11.1.Методические указания к первой части работы
- •11.2.Сценарий выполнения первой части работы
- •11.3.Методические указания ко второй части работы Строка состояния
- •Определение секций в строке состояния
- •Строка сообщений
- •Индикатор состояния
- •Управление строкой состояния
- •11.4.Сценарий выполнения второй части работы
- •12.Разработка приложения с архитектурой «документ-вид». Часть 1
- •12.1.Сценарий создания приложения
- •13.Разработка приложения с архитектурой «документ-вид». Часть 2
- •13.1.Методические указания Класс коллекций cObList
- •13.2.Сценарий выполнения работы
- •14.Разработка приложения с архитектурой «документ-вид». Часть 3
- •14.1.Методические указания
- •15.Класс вектор
- •15.1.Пример класса tVector
- •15.2.Класс tVector с перегруженными операциями
- •16.Приложение с таблицей
- •16.1.Вариант 1 Сценарий выполнения работы
- •16.2.Вариант 2 Сценарий выполнения работы
16.2.Вариант 2 Сценарий выполнения работы
Любой юзер знает, что список файлов, выводимый в окне Проводника Windows, можно сортировать путем щелчка по заголовку соответствующего столбца таблицы. В данной работе приводится сценарий создания приложения, в котором на основе управляющего элемента List Control (MFC класс CListCtrl) показана последовательность создания подобного списка.
Шаг 1. Создайте заготовку приложения, включающего поддержку MFC и архитектуры документ-вид. В качестве базового для класса вида выберите класс CFormView для того, чтобы можно было в окне приложения разместить управляющий элемент List Control. Предполагается, что проекту присвоено имя SL (Sort List).
Шаг 2. В окне приложения разместите управляющий элемент List Control и задайте для него значение свойства View==Report. Можно собрать приложение, запустить его на выполнение и убедиться в том, что среда MVS способна создавать работоспособные каркасы приложений (рис. 1). Строки и столбцы списка, по сути дела таблицы, нам придется создавать путем написания программного кода, а не путем задания каких-либо свойств управляющих элементов, как это реализовано в Delphi.
|
Рис. 1. Окно приложения с элементом List Control
Шаг 3. Создание столбцов таблицы. Первым делом с помощью мастера создадим переменную objList (рис. 2) для получения доступа к нашему управляющему элементу список как к экземпляру класса CListCtrl.
|
Рис. 2. Добавление переменной objList, являющейся объектом класса CListCtrl
Далее добавим в функцию CSLView::OnInitialUpdate() код, который задает число столбцов в списке и их наименования, отображаемые в заголовке списка:
|
Назначение и смысл членов структуры LV_COLUMN можно (и нужно!) узнать из MSDN.
Замечание. Если бы элемент List Control был размещен в диалоговом окне, то приведенный выше код надо было бы добавить в функцию OnInitDialog() класса диалогового окна.
Если Вы теперь запустите приложение на выполнение, то увидите пока еще пустую таблицу, но уже с наименованиями столбцов (рис. 3).
|
Рис. 3. Список с добавленными столбцами
Шаг 4. Описание структур данных для хранения элементов списка. Для того чтобы впоследствии можно было сортировать элементы списка по выбранному столбцу, надо сначала значения этих элементов каким-то образом задать в массиве структур и разместить в списке (классе CListCtrl) указатели на них. В дальнейшем для сортировки списка мы будем просто сортировать этот массив по выбранному компоненту структуры. Так как в список можно заносить только строковые данные, то компоненты структуры должны иметь строковый тип либо их надо преобразовать в строковый тип перед занесением в список.
В соответствии с архитектурой документ-вид мы должны размещать данные в классе документа. Предварительно создайте заголовочный файл Student.h с таким содержимым:
|
Для того чтобы файл Student.h был добавлен средой MVS-2005 в перечень файлов проекта, создайте его с помощью команды ProjectèAdd New Item.
Тип TStudent представляет собой структуру из двух указателей на строки (null-terminated string).
Подключите файл Student.h с помощью директивы include в заголовочный файл документа SLDoc.h и добавьте в класс документа массив (вектор) структур:
|
Проанализировав приведенный код, Вы легко обнаружите, что в классе документа мы создали массив (вектор) структур TStudent, воспользовавшись шаблонным классом vector.
Таким образом, мы решили разместить данные в классе документа, как это и предписано технологией документ-представление, но пока физически этого не сделали.
Попробуйте компилировать приложение. Есть ошибки компиляции? Может быть, надо включить в файл SLDoc.h еще какой-нибудь заголовочный файл с объявлением шаблонного класса vector и директиву using namespace std;?
Шаг 5. Ввод данных из текстового файла и занесение их в список. Создайте текстовый файл такого, например, содержания:
|
Как Вы уже догадались, каждая запись файла содержит фамилию студента и его отметку, допустим, среднюю или лучшую. Для изложения сценария этого достаточно, не так ли?
Теперь надо прочитать эти данные из (текстового) файла. Для этого предлагается создать в классе вида CSLView обработчик события ID_FILE_OPEN, которое генерируется системой при выборе пользователем команды меню FileèOpen. Создайте этот обработчик и наполните его таким (самоочевидным?) кодом:
|
|
|
|
Для того чтобы от выполнения этой работы был толк, осмыслите приведенный программный код. Попробуйте компилировать приложение и запустить его на выполнение. Если будут ошибки – избавьтесь от них.
Когда Вам удастся собрать приложение и запустить его на выполнение, то окно приложения должно приобрести примерно такой вид, как на рис. 4. (Если это не так, то надо, естественно, приобрести новый компьютер, по крайней мере с полутораядерным процессором.)
Работа со списком, т.е. добавление новых строк, сводится к вызову одной из перегруженных функций CListCtrl::InsertItem(), которая собственно и вставляет новую строку. Версия функции CListCtrl::InsertItem() с единственным параметром типа LV_ITEM вставляет пустую строку, если компонент структуры LV_ITEM.pszText указывает на пустую строку, как в приведенном выше тексте функции CSLView::OnFileOpen(). Занесение данных в столбцы строки в данном примере выполняется с помощью функции CListCtrl::SetItemText(), первый параметр которой указывает на номер строки, а второй – на номер столбца. Попробуйте закомментировать строки с вызовом функции CListCtrl::SetItemText(), запустите приложение на выполнение и пощелкайте мышью в первом столбце строк таблицы. Несмотря на то, что список пустой, вы обнаружите присутствие пяти строк (рис. 5). С помощью функции CListCtrl::SetItemData() мы сохраняем в объекте objList указатели на данные, помещенные в соответствующую строку списка, что нужно только для последующей сортировки данных списка.
|
Рис. 4. Список с данными
|
Рис. 5. Список с пустыми строками
Приведенный в функции CSLView::OnFileOpen() способ вставки столбцов и строк и собственно заполнения списка конкретными данными не является единственно возможным. Класс CListCtrl предлагает много разных член-функций, которые позволяют выполнять со списком разнообразные операции, в том числе, например, помещать в список изображения. Читайте MSDN или шарьте в Интернете!
Шаг 6. Сортировка данных в списке. Вы хорошо знаете, что если в окне Проводника щелкнуть по заголовку какого-либо столбца со списком файлов, то список будет чудесным образом отсортирован по данному столбцу, что не только приятно, но и полезно. Выполним и мы такую сортировку. Для этого, как Вы догадываетесь, надо создать обработчик соответствующего события.
В окне ClassView выберите класс вида CSLView, вызовите для него окно свойств, в нем выберите вкладку Events, в ней раскройте ветвь IDC_LIST1 (если Вы не изменяли идентификатор списка CListCtrl) и уже в этой ветви создайте обработчик OnHdnItemclickList1() события HDN_ITEMCLICK (рис. 6). Текст обработчика наполните таким нехитрым содержанием:
|
|
Рис. 6. Добавление обработчика события HDN_ITEMCLICK
Если Вы попытаетесь компилировать приложение, то увидите сообщение об ошибке:
'SortFunc' : undeclared identifier
Первый параметр функции CListCtrl::SortItems() должен быть именем функции «обратного вызова» (callback function), которая должна выполнять сравнение сортируемых значений и возвращать его результат в виде целого числа. Как следует из MSDN, эта функция должна иметь такой формат:
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2,
LPARAM lParamSort);
Функция сравнения CompareFunc() должна возвращать:
отрицательное значение, если первый параметр больше второго;
положительное значение, если первый параметр меньше второго;
нулевое значение при равенстве значений параметров.
Параметр lParam1 должен быть 32-битовым значением, ассоциированным с первым сравниваемым значением, а lParam2 – соответственно вторым. Это те величины, которые были указаны в члене lParam структуры LVITEM, когда они помещались в список. Параметр lParamSort такой же, как и второй параметр функции SortItems().
С учетом сказанного текст функции может быть таким:
|
Если Вас удивляет, что число хвостов студентов сравниваются с помощью функции strcmp(), предназначенной для сравнения строк текста, то вспомните, что число хвостов, как и фамилия, хранятся в виде строк текста (см. выше массив строк Data). Так как в ХАИ (пока) число хвостов студента не может превышать девяти (одна цифра), то такой подход работает. При большем числе хвостов начнутся глюки, для устранения которых необходимо будет преобразовывать строку в число и сравнивать уже числовые значения.
Запустите приложение на выполнение и убедитесь в том, что оно работает корректно, т.е. список выводится и сортируется.
Проверьте, что в окне Debug при запуске отладочной версии приложения нет сообщений об утечках памяти, т.е. содержащих текст «Detected memory leaks!». Если такие сообщения есть, то надо найти и устранить их причину, а иначе такое приложение постепенно украдет память Вашего компьютера, а преподаватель не зачтет лабу.
Список литературы
1. Круглински Д., Уингоу С., Шеферд Дж. Программирование на Microsoft Visual C++ для профессионалов/Пер. с англ. – СПб:Питер; М.: Издательско-торговый дом "Русская редакция", 2000. - 864с.
2. Холзнер С. Visual C++ 6: учебный курс – СПб.: Изд-во «Питер», 2000. – 576с.
3. Конспект лекций в файле VC_Lect.doc
4. Овсянник_Язык_С++_не_для_чайников.doc
Resource language - значение Русский
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
Resource language - значение Английский
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
