Разработка приложений для Internet

Метод DirectoryView


Метод DirectoryView класса CFtpViewDlg выполняет львиную долю работы всего нашего приложения. Именно этот метод после соединения с сервером FTP определяет названия и основные характеристики объектов в заданном каталоге сервера, а затем отображает их в списке IDC_FTP_LIST на главной диалоговой панели приложения:

BOOL CFtpViewDlg::DirectoryView()

{

   // Переменная, сигнализирующая о получении последнего

   // элемента каталога

   BOOL     fResult;

   // Временная переменная, определяющая тип объекта -

   // файл или каталог

   BOOL     fDirectory;

Метод DirectoryView заполняет список IDC_FTP_LIST именами каталогов и файлов сервера FTP. Чтобы удалить из списка элементы, занесенные в него ранее, вызываем метод DeleteAllItems для объекта m_FtpList, управляющего этим списком (см. метод DoDataExchange):

// Удалить все элементы из списка IDC_FTP_LIST

m_FtpList.DeleteAllItems();

Для поиска файлов и каталогов на сервере FTP предназначен класс CFtpFileFind, входящий в состав библиотеки классов MFC. Метод DirectoryView создает объект этого класса. В качестве параметра конструктору класса CFtpFileFind передается указатель m_FtpConnection на объект, представляющий соединение с сервером FTP:



CFtpFileFind m_FtpFileFind(m_FtpConnection);

Далее мы вызываем для только что созданного объекта m_FtpFileFind метод FindFile. Он выполняет поиск каталогов и файлов в каталоге, путь которого указан в качестве параметра:

// Получаем имена всех объектов текущего каталога

if(fResult =

   m_FtpFileFind.FindFile(_T(sCurentDirectory + "/*")))

{

        . . .

}

Если каталог не содержит других объектов - каталогов и файлов, или в случае возникновения ошибки, метод FindFile возвращает ненулевое значение. Тогда на экран выводится сообщение File's not found or error и работа метода DirectoryView завершается.

В случае, если метод FindFile завершается успешно, это означает, что указанный каталог содержит другие каталоги или файлы. Тогда мы начинаем в цикле вызывать метод FindNextFile. Он получает имя очередного файла или каталога и мы отображаем его вместе с некоторой дополнительной информацией в списке объектов каталога. Когда метод FindNextFile вернет значение FALSE, это значит, что мы считали последний объект каталога. В этом случае мы добавляем этот последний объект к списку, завершаем цикл и выходим из метода DirectoryView:


for(int n = 0;fResult; n++)

{

   // Получаем очередной объект из каталога

   fResult = m_FtpFileFind.FindNextFile();

   . . .

}

После обращения к методу FindNextFile можно вызывать другие методы класса CFtpFileFind. Они позволяют определить различные характеристики обнаруженных объектов. Например, вы можете узнать являются ли они каталогами или файлами, получить их имя, размер, дату создания и т. д.

Так, сначала мы определяем, является ли очередной объект, полученный методом FindNextFile файлом или каталогом и записываем полученный результат в fDirectory. Если мы получили каталог, то метод IsDirectory возвращает значение 1, а если файл, то - 0. Мы будем использовать значение fDirectory, сравнивая его с константой DIRECTORY, определенной как 0 и FILE, определенной как 1 в файле FtpViewDlg.h.

Далее с помощью метода GetFileName определяется имя объекта (файла или каталога) и записывается во временную строку fileName класса CString:

CString   fileName;

// Определяем имя объекта

fileName = m_FtpFileFind.GetFileName();

Теперь, когда мы узнали тип объекта и его имя можно добавить элемент к первой колонке в списке. Для этого необходимо заполнить поля структуры lv_item и передать ее методу InsertItem объекта, управляющего списком:

// Структура для добавления нового элемента к списку

LV_ITEM   lv_item;  

. . .

// Заполняем структуру lv_item, сведениями об

// очередном объекте каталога сервера FTP. Указываем,

// что в список добавляется текст и изображение

lv_item.mask = LVIF_TEXT | LVIF_IMAGE;

// Указываем номер строки в списке

lv_item.iItem = n;

// Заполняем первую колонку

lv_item.iSubItem = 0;

// Выбираем изображение для нового элемента списка в

// зависимости от типа объекта

lv_item.iImage = (fDirectory) ? DIRECTORY : FILE;

// Указываем имя каталога или файла

lv_item.pszText = fileName.GetBuffer(MIN_LEN_BUF);

 // Добавляем новый элемент к списку IDC_FTP_LIST

 m_FtpList.InsertItem(&lv_item);

После заполнения первой колонки списка необходимо заполнить вторую, записав в нее длину файла или, если данный элемент списка описывает каталог, то строку Dir. Точно также как в случае с именем объекта, сначала заполняется структура lv_item, а затем она передается методу InsertItem.



Обратите внимание, что в отличие от первой колонки, во второй колонки не используется пиктограмма, поэтому в поле mask структуры lv_item заносится только константа LVIF_TEXT. Другое отличие состоит в том, что полю iSubItem структуры lv_item присваивается значение 1, указывающее, что мы будем добавлять элемент во вторую колонку (нумерация iSubItem начинается с нуля):

//============= Определяем длину файла =============

// Длинна файла

DWORD dwLength = 0;

// Временные строка для формирования текстового

// представления длинны файла

CString sLength;

// Заполняем колонку Length для новой записи и

// записываем в нее длину файла или строку Dir, если

// новый объект - каталог.

// Добавляется только текст без пиктограммы

lv_item.mask = LVIF_TEXT;

// Указываем номер строки в списке

lv_item.iItem = n;

// Заполняем вторую колонку

lv_item.iSubItem = 1;

// Если очередной объект является каталогом, то

// вместо в колонке Length записываем строку Dir

if(fDirectory)

{

   lv_item.pszText = "Dir";

}

// Если очередной объект является файлом, то

// записываем его длину в колонку Length

else

{

   // Определяем длину файла

   dwLength = m_FtpFileFind.GetLength();

   // Формируем текстовое представление длины файла

   sLength.Format("%d", dwLength);

   lv_item.pszText = sLength.GetBuffer(MIN_LEN_BUF);

}

       

// Добавляем запись во второй колонке списка (колонка

// Length)

m_FtpList.SetItem(&lv_item);

Теперь остается заполнить только третью и четвертую колонки списка, в которых надо записать дату и время создания или изменения файла (каталога). Для определения этих данных вызывается метод GetLastWriteTime класса CFtpFileFind, который записывает полученную информацию в объект mTime класса CTime:

// Дата и время создания каталога или файла

CTime mTime; 

// Временные строки для формирования текстового

// представления даты и времени

CString sDate;

CString sTime;

// Определяем время изменения файла или каталога



if(!m_FtpFileFind.GetLastWriteTime(mTime))

   break;

Затем мы подготавливаем структуру lv_item, заполняя ее поля соответствующими значениями:

// Добавляется только текст без пиктограммы

lv_item.mask = LVIF_TEXT;

// Указываем номер строки в списке

lv_item.iItem = n;

// Заполняем третью колонку

lv_item.iSubItem = 2;

// Выделяем из объекта mTime день, месяц и год

sDate = mTime.Format("%d.%m.%y");

// Записываем сформированную дату в структуру lv_item

lv_item.pszText = sDate.GetBuffer(MIN_LEN_BUF);

Чтобы добавить запись в колонке Date обращаемся к методу SetItem и передаем ему указатель на структуру lv_item:

// Добавляем запись во второй колонке списка (колонка Date)

m_FtpList.SetItem(&lv_item);

Затем мы немного модифицируем только что заполненную структуру lv_item, изменяя в ней только поля iSubItem и pszText:

// Заполняем четвертую колонку, записываем в нее

// время последнего изменения файла (каталога)

lv_item.iSubItem = 3;

// Выделяем из объекта mTime часы, минуты и секунды

sTime = mTime.Format("%H:%M:%S");

// Записываем сформированную строку, содержащую время

lv_item.pszText = sTime.GetBuffer(MIN_LEN_BUF);

Опять вызываем метод SetItem, передавая ему модифицированную структуру lv_item. Этот вызов добавит информацию о времени последнего изменения файла в колонке Time:

// Добавляем запись во второй колонке списка (колонка Time)

m_FtpList.SetItem(&lv_item);

Когда при очередном вызове метод FindNextFile возвращает нулевое значение, значит найден последний объект из каталога. В список добавляется последняя строка и на этом работа цикла заполнения списка завершается. Заканчиваем поиск объектов в данном каталоге вызывая метод Close и возвращаем управление с помощью оператора return:

// Заканчиваем поиск объектов в каталоге, закрываем

// объект m_FtpFileFind

m_FtpFileFind.Close();


Содержание раздела