качестве максимально возможной длины пути. Здесь налицо небольшой парадокс: хотя такая файловая система как FAT32, и реализована так, что может поддерживать неограниченную вложенность каталогов, в реальности не получится создать даже два вложенных каталога с именем длиной 255 символов.
Примечание
При доскональной проверке вышесказанного выяснилось, что не получится создать даже один каталоге именем длиной 255 символов в корневой папке диска (например, С: ). Каталог может иметь имя длиной максимум 244 символа. С учетом длины имени корневой папки (получается 247) можно предположить, что в таком случае система резервирует оставшиеся 13 символов, чтобы в папке можно было сохранять файлы с именем в формате 8.3 (MS-DOS).
Системные папки WINDOWS и system
Приходилось ли вам хоть раз писать приложения, работоспособность которых зависела от расположения системных папок Windows? Если да, то вы наверняка хорошо знаете, как неустойчиво предположение о том, что папка WINDOWS всегда C:WIND0WS, a system всегда C:WINDOWSsystem. Ведь при установке операционной системы ничто не мешает поместить ее, например, на диск Е:, а папку для Windows назвать Linux. Кроме того, системная папка Windows на платформе NT имеет имя system32, и кто знает, какое имя она будет иметь в следующей версии Windows. В таких и многих других случаях выручат API-функции: GetWindowsDirectory и GetSystemDirectory. Они обе принимают в качестве параметров строковый буфер и его длину и возвращают количество символов, записанных в переданный буфер, или 0 в случае ошибки.
Для этих функций удобно реализовывать функции-оболочки, работающие со стандартными для Delphi строками, что, собственно, и сделано при написании этой главы (все реализованные функции вы можете найти в модуле PathFunctions, расположенном на диске, прилагаемом к книге, в папке с названием подраздела). Итак, функция определения папки Windows приведена в листинге 4.11.
Листинг 4.11.
Определение папки WINDOWS
function GetWinDir(): String;
var
buffer: String;
len: UINT;
begin
SetLength(buffer, MAX_PATH + 1);
len := GetWindowsDirectory(PAnsiChar(buffer), MAX_PATH);
SetLength(buffer, len);
GetWinDir := buffer;
end;
По аналогии реализуется функция определения расположения системной папки, только вместо GetWindowsDirectory вызывается фyнкцияGetSystemDirectory.
Имена для временных файлов
Для централизованного хранения временных данных, необходимых при работе приложений, в Windows предусмотрена специальная папка Temp. Ее расположение может варьироваться. Причем в многопользовательских версиях Windows (NT, 2000, ХР) местоположение папки для временных файлов может быть различным для различных пользователей. Итак, расположение папки Temp поможет определить API- функция GetTempPath. Она принимает следующие параметры: строковый буфер и длину этого буфера. Возвращает количество символов, записанных в переданную строку, или 0, если возникла ошибка. Функция-оболочка, скрывающая работу со строковым буфером и преобразование типов, реализуется аналогично двум ранее рассмотренным функциям (листинг 4.12).
Листинг 4.12.
Определение расположения папки для временных файлов
function GetTempDir(): String;
var
buffer: String;
len: UINT;
begin
SetLength (buffer, MAX_PATH + 1);
len := GetTempPath(MAX_PATH, PAnsiChar(buffer));
SetLength(buffer, len);
GetTempDir := buffer;
end;
Кроме того, Windows API предусматривает очень полезную функцию, избавляющую программиста от необходимости подбирать имена временных файлов так, чтобы они были уникальными в пределах заданной папки (это не обязательно должна быть папка Temp ). Имя этой функции – GetTempFileName. Пример ее использования приведен в листинге 4.13.
Листинг 4.13.
Определение имени временного файла
function GetTempFile(prefix: String = '~mytmp'): String;
var
buffer, dir: String;
begin
dir := GetTempDir ();
//Получение имени временного файла (система сама определяет
имя,
//уникальное для заданной папки)
SetLength(buffer, MAX_PATH + 1);
GetTempFileName(PAnsiChar(dir), PAnsiChar(prefix), 0,
PAnsiChar (buffer));
GetTempFile := buffer;
end;
Приведенная в листинге 4.13 функция в качестве папки для временных файлов использует папку Temp. Однако функцию GetTempFileName можно использовать для получения имен файлов в пределах любой папки.
Кроме пути папки, в которой необходимо создать временный файл, функция GetTempFileName принимает строку-префикс для имени временного файла и целочисленное значение (третий параметр). Если третий параметр не равен нулю, то его значение в шестнадцатеричной форме просто прибавляется справа к строке prefix. Никаких проверок на уникальность получившегося имени файла при этом не производится. Если же третий параметр установить в 0, то система сама сформирует шестнадцатеричное значение так, чтобы имя файла было уникальным в заданной папке. Кроме того, при этом создается и сам файл.
Буфер (последний параметр функции GetTempFileName) должен вмещать как минимум МАХРАТН символов, так как функция записывает в него полный путь временного файла.
Пример работы функций определения папки для временных файлов, получения имени для временного файла, а также определения системных папок Windows приводится на рис. 4.2.
Рис. 4.2. Папки WINDOWS, system, Temp и имя для временного файла
Прочие системные пути
В Windows существует ряд других системных путей, которые так или иначе могут пригодиться. Определяются они не менее просто, чем пути к системным папкам (листинг 4.14).
Листинг 4.14. Определение прочих системных путей
function GetSpecialDir(dirtype: Integer): String;
var
buffer: String;
begin
SetLength(buffer, MAX_PATH + 1);
SHGetSpecialFolderPath(0, PAnsiChar (buffer), dirtype, False);
GetSpecialDir := buffer;
end;
Здесь используется функция командной оболочки файловой системы (Windows Shell) SHGetSpecialFolderPath, ее объявление находится в модуле ShlObj. Среди параметров этой функции самыми значимыми для нас (кроме буфера длиной минимум МАХРАТН символов для помещения в него пути) являются два последних. Третий параметр функции SHGetSpecialFolderPath используется для указания того, расположение какой именно папки нас интересует. Если четвертый параметр функции SHGetSpecialFolderPath не равен False, то запрошенная папка будет создана, если до этого она не существовала.
Пример использования функции GetSpesialDir для составления списка (в элементе управления ListView) некоторых системных путей приведен в листинге 4.15. Из него вы также сможете узнать имена целочисленных констант, идентифицирующих некоторые папки.
Листинг 4.15.
Использование функции GetSpecialDir
procedure TForm3.Button1Click(Sender: TObject);
var
item: TListItem;
begin
lvwPathes.Clear;
//Определение путей некоторых системных каталогов
//..Рабочий стол
item := lvwPathes.Items.Add();
item.Caption := 'Рабочий стол
item.SubItems.Insert(0, GetSpecialDir (CSIDL_DESKTOPDIRECTORY));
//..Избранное
item := lvwPathes.Items.Add ();
item.Caption := 'Избранное
item.SubItems.Insert(0, GetSpecialDir (CSIDL_FAVORITES));
//..Шрифты
item := lvwPathes.Items.Add();
item.Caption := 'Шрифты
item.SubItems.Insert(0, GetSpecialDir(CSIDL_FONTS));
//..Мои документы
item := lvwPathes.Items.Add();
item.Caption := 'Мои документы
item.SubItems.Insert(0, GetSpecialDir(CSIDL_PERSONAL));
//..Последние документы
item := lvwPathes.Items.Add();
item.Caption := 'Последние документы
item.SubItems.Insert(0, GetSpecialDir(CSIDL_RECENT));
//..История
item := lvwPathes.Items.Add();
item.Caption := 'История
item.SubItems.Insert(0, GetSpecialDir (CSIDL_HISTORY));
//..Отправить
item := lvwPathes.Items.Add();
item.Caption :=