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

16.1.Вариант 1 Сценарий выполнения работы

Даже чайник знает, что список файлов, выводимый в окне Проводника 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.

Замечание. Если бы элемент ListControl был размещен в диалоговом окне, то приведенный выше код надо было бы добавить в функцию OnInitDialog() класса диалогового окна.

Если Вы теперь запустите приложение на выполнение, то увидите пока еще пустую таблицу, но уже с наименованиями столбцов (рис. 3).

Рис. 3. Список с добавленными столбцами

Шаг 4. Задание начальных значений элементов списка. Для того чтобы впоследствии можно было сортировать элементы списка по выбранному столбцу, надо значения этих элементов задать в массиве структур и разместить в списке (классе CListCtrl) указатели на них. В дальнейшем для сортировки списка мы будем просто сортировать этот массив по выбранному компоненту структуры. Так как в список можно заносить только строковые данные, то для компонент структуры проще всего выбрать строковый тип.

В соответствии с архитектурой документ-вид мы должны размещать данные в классе документа. Предварительно создайте заголовочный файл Student.h с таким содержимым:

Как Вы думаете, что обозначает ключевое слово static перед объявлением массива объектов-строк? Если понадобится (а нам это понадобится) включать файл Student.h в более чем один другой файл, то линкер выдаст сообщение об ошибке: имя Data[][2] определено повторно. Именно для предотвращения этой ошибки и используют в данном контексте ключевое слово static, которое указывает линкеру на необходимость использования так называемой «внутренней» компоновки (internal linkage), при которой имя Data[][2] видимо только внутри данного компилируемого модуля (файла).

Правда, Б.Страуструп считает такой подход устаревшим и предлагает использовать вместо него неименованное пространство имен, что приводит к тому же результату:

Выбор того или иного способа – за Вами.

Для того чтобы файл Student.h был добавлен средой MVS-2008 в перечень файлов проекта, создайте его с помощью команды ProjectèAdd Class.

Тип TStudent представляет собой структуру из двух указателей на строки.

Подключите файл Student.h с помощью директивы include в заголовочный файл документа SLDoc.h и добавьте в класс документа массив указателей на данные Group и число строк списка (число студентов) Count:

Конструктор и деструктор класса документа (файл SLDoc.cpp) наполните таким кодом:

CSLDoc::CSLDoc()

{

Count=sizeof Data / sizeof Data[0];

Group=new PStudent [Count];

for(int i=0;i<Count;i++)

{

Group[i]=new TStudent;

Group[i]->Name =(LPTSTR)(LPCTSTR)Data[i][0];

Group[i]->Tails=(LPTSTR)(LPCTSTR)Data[i][1];

}

}

CSLDoc::~CSLDoc()

{

for(int i=0;i<Count;i++) delete Group[i];

delete [] Group;

}

Проанализировав приведенный код, Вы легко обнаружите, что в классе документа мы создали массив указателей на структуру TStudent, которая в свою очередь содержит два указателя на строки: «Имя студента» и «Число хвостов» студента.

Таким образом, в классе документа мы задали все значения элементов списка. Пусть Вас не смущает то обстоятельство, что данные в конечном итоге заданы в виде констант. Если Вы подключите свой могучий интеллект, то элементарно сообразите, что эти данные можно загрузить из файла или, на худой конец, из полноценной БД.

Эти данные пока находятся в классе документа и не отображаются каким-либо чудодейственным образом в управляющем элементе (списке) CListCtrl. Восполним этот пробел на следующем шаге.

Шаг 5. Занесем данные в список CListCtrl следующим образом:

Если теперь собрать приложение и запустить его на выполнение, то окно приложения должно приобрести примерно такой вид, как на рис. 4. (Если это не так, то надо, естественно, приобрести новый компьютер, по крайней мере с полутораядерным процессором.)

Работа со списком, т.е. добавление новых строк, сводится к вызову одной из перегруженных функций CListCtrl::InsertItem(), которая собственно и вставляет новую строку. Версия функции CListCtrl::InsertItem() с единственным параметром типа LV_ITEM вставляет пустую строку, если компонент структуры LV_ITEM.pszText указывает на пустую строку, как в приведенном выше тексте функции CSLView::OnInitialUpdate(). Занесение данных в столбцы строки в данном примере выполняется с помощью функции CListCtrl::SetItemText(), первый параметр которой указывает на номер строки, а второй – номер столбца. Попробуйте закомментировать строки с вызовом функции CListCtrl::SetItemText(), запустите приложение на выполнение и пощелкайте мышью в первом столбце строк таблицы. Несмотря на то, что список пустой, вы обнаружите присутствие пяти строк (рис. 5). С помощью функции CListCtrl::SetItemData() мы сохраняем в объекте список указателей на данные, помещенные в соответствующую строку списка, что нужно только для последующей сортировки данных списка.

Рис. 4. Список с данными

Рис. 5. Список с пустыми строками

Приведенный в функции CSLView::OnInitialUpdate() способ вставки столбцов и строк и собственно заполнения списка конкретными данными не является единственно возможным. Класс 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). Так как (пока) число хвостов студента не может превышать девяти (одна цифра), то такой подход работает. При большем числе хвостов начнутся глюки, для устранения которых необходимо будет преобразовывать строку в число и сравнивать уже числовые значения.

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

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