Більш складний приклад перегляду атрибутів файлів у CBuilder

Прості приклади, які ви бачили в цьому розділі, показували, як зробити одну або дві справи, але не показували реального закінченого прикладу використання Windows API. У цьому прикладі ми розглянемо не одну або дві функції API, а одночасно цілу групу функцій, визначену для файлової системи Windows. Приклад, який ми збираємося зробити, – простий броузер атрибутів файлів. У ньому можна буде вибрати диск, каталог, а потім буде відображена інформація про цей диск, каталог і файли, що знаходяться там.

Windows API надає багатий набір функцій, які працюють саме із файловою системою. Є функції, що дозволяють знайти файли, що підходять під заданий критерій (наприклад, файлову маску), функції визначення обсягу простору на диску і функції, повертають імена позначок диска.

У цьому прикладі ми розглянемо використання всіх цих функцій для відображення потрібної користувачеві інформації.

приклад

Мал. 9.4. Форма програми FileAttributeViewer

На рис. 9.4 наведено форму, з якою ми будемо працювати в цьому прикладі. Ви можете зрозуміти, що за інформацію ми будемо показувати, виходячи з типів керуючих елементів, наведених тут. Декілька позначок статичного тексту потрібні для відображення інформації про диск (логічний диск), тоді як сітка рядків потрібна для відображення інформації про окремі файли в каталозі, вибраному користувачем. Кнопка Перегляд потрібна для запуску процесу, а діалог відкриття файлів потрібен для вибору каталогу, з яким потрібно працювати.

Найперша дія, яку ми маємо виконати, — ініціалізувати сітку рядків, щоб заголовки стовпців дозволяли користувачеві зрозуміти, що за інформацію він бачить. Додайте наступний код методFormCreate(обробник події формиOnCreate):

void __fastcall TForm1::FormCreate(TObject *Sender)

StringGrid1->Cells[0][0] = "File Name"; StringGrid1->Cells[1][0] = "Attributes"; StringGrid1->Cells[2][0] = "Size";

StringGrid1->ColW >ClientWidth / 3; StringGrid1->ColW >ClientWidth / 3; StringGrid1->ColW >ClientWidth / 3; StringGrid1->RowCount = 1;

Насамперед користувач вибиратиме каталог з вікна діалогу відкриття файлів (використовуючи кнопку Перегляд). Створіть обробник натискання на кнопку Перегляд і додайте в обробник код:

void __fastcall TForm1::Button1Click(TObject *Sender)

// По-перше, записати диск та каталог

ExtractFileDrive (OpenDialog1->FileName) ; AnsiString strDirectory =

// Отримати ім'я мітки диска

char szVolName [_MAX_PATH] ; DWORD dwVolumeSerialNumber=0;

DWORD dwMaxVolumeLength = _MAX_PATH;

DWORD dwFileSystemFlags = 0;

char szFileSystemNameBuffer [_MAX_PATH]; strDrive += "\";

GetVolumeInformation (strDrive.c_str(), szVolName, //буфер для мітки диска

_MAX_PATH // Довжина буфера

// буфер для серійного номера диска

//Покажчик на максимальну довжину імені

//файла у системі

//Покажчик на прапори файлової системи

//вказівник на ім'я файлової системи

_MAX_PATH //Довжина буфера для імені файлової системи

// Обробка мітки "вільне місце на диску" char szBuffer [80] ;

DWORD dwSectorsPerCluster, dwBytesPerSector; DWORD dwFreeClusters, dwClusters;

DWORD dwFreeSpace; GetDiskFreeSpace(strDrive.c_str(), &dwSectorsPerCluster,

dwSectorsPerCluster * dwBytesPerSector * dwFreeClusters; sprintf(szBuffer, "% ld", dwFreeSpace) ; DriveFreeSpaceLabel->Caption = szBuffer;

// Розміститиінформацію у мітки

DriveLabel->Caption = strDrive + "[" + szVolName + "]"; DirectoryLabel->Caption = strDirectory;

AnsiString strAll = strDirectory + "\\*.*";

// Тепер отримуємо всі файли в каталозі, використовуючи

// функцію API FindFile WIN32_FIND_DATA FindFileData;

HANDLE hFirstFileHandle = FindFirstFile (strAll.c_str(),

// Збільшити кількість рядків у сітці

// Отримати розмір файлу

(FindFileData.nFileSizeHigh * MAXDWORD) + FindFileData.nFileSizeLow;

// Отримати атрибути файлу

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)

// Розмістити дані у сітку рядків StringGrid1->Cells[0][nRow] = FindFileData.cFileName;

StringGrid1->Cells[1][nRow] = strArchive; sprintf(szBuffer, "% ld", lFileSize) ; StringGrid1->Cells[2][nRow] = szBuffer;

if (FindNextFile (hFirstFileHandle, &FindFileData)

if (GetLastError() == ERROR_NO_MORE_FILES) break;

Це надто великий шматок коду, щоб розібрати його відразу весь. Давайте розглядати його частинами, щоб спробувати зрозуміти, що відбувається. Спочатку користувач вибирає конкретний файл у якомусь каталозі у вікні діалогу відкриття файлу. Коли файл вибрано, програма отримує букву диска та каталог, у яких лежить файл, використовуючи допоміжні функціїExtractFileDriveтаExtractFileDir. Ці функції, описані в заголовному файлі vcl\sysutils.hpp у каталозі з системою CBuilder, повернуть вам частини повного шляху файлу, що визначають ім'я диска і каталог. У разі каталогу ця інформація включає також і диск (наприклад, D:\dir\), так що ми пізніше можемо використовувати її для пошуку файлів в каталозі.

Коли ми маємо ім'я (літера) диска, на якому знаходиться файл, нашим наступним кроком буде отримання мітки для цього диска. Ім'я мітки диска – це ім'я диска, яке з'являється у списках каталогів цього диска. Наприклад, ваш диск C: у Windows Explorer (та інших списках каталогів) виглядає приблизно як C: (Windows 95). Ім'я мітки диска в даному випадку в дужках, тобто Windows 95. Хоча вони й не дуже інформативні для жорстких дисків, як C:, але дуже корисні для однозначного визначення компакт-диска або іншого пристрою, що знімається.

Після інформації про позначку диска наша програма отримує інформацію про кількість вільного місця на диску. Ви, напевно, думаєте, що це робиться викликом однієї функції типуGetDriveFreeSpace? Тут ви помиляєтесь. При запиті про вільне місце на диску функція API повертає три різні значення, які потім потрібно скомбінувати, щоб

одержати кількість вільного місця на диску. Інформація, яку ми отримуємо, включає SectorsPerCluster, тобто кількість секторів в одному кластері жорсткого диска, потім BytesPerSector, що є кількість байтів в одному секторі диска, та кількість вільних кластерів. До речі, це дуже важливі параметри диска. Деякі жорсткі диски дозволяють вам займати місце побайтно, інші вирівнюють все по межі найближчого кластера. Ось чому розмір файлу не відображає насправді розмірдискового простору, який займає цей файл.

Три значення перемножуються, і результат заноситься в подвійне слово (DWORD)dwFreeSpace. Потім ця інформація форматується та поміщається у мітку, що відображає вільний простір на диску.

Разом з вільним місцем на диску у відповідні поля статичного тексту (мітки) розміщуються ім'я каталогу, ім'я диска та позначка диска. Наступний крок — відображення інформації про файли, що знаходяться в одному каталозі з вибраним файлом.

Для пошуку всіх файлів у каталозі використовуються функції APIFindFirstFileтаFindNextFile. Ці функції знайдуть вам файли, які підходять під заданий критерій, наприклад, всі файли (*.*), всі вихідні файли (*.cpp) або всі бібліотечні файли (*.lib). Крім того, так як ви можете задавати будь-яку маску, ви можете знайти всі файли, що починаються з «Fred», використовуючи маску Fred*.* або навіть усі файли з Fred всередині їхнього імені, обравши *Fred* як маску. Маска файлів нечутлива до регістру символів, так що файли з великими та маленькими літерами не відрізнятимуться.

Джерело: Теллес М. - Borland C ++ Builder. Бібліотека програміста – 1998