Сегодня рассмотрим ещё один простой способ определения специальных папок Windows. К специальным относятся такие директории как, например: «Мои документы», «Application Data», «Cookies» и т.д. В разное время развития операционной системы Windows, как и в разное время развития Delphi предлагалась масса различных способов определения путей к специальным директориям от самых простых — использование GetWindowsDirectory до таких «экзотических» как работа с интерфейсом ISHFolder и т.д.
Сегодня расмотрим более простой, на мой взгляд, способ получения всех без исключения системных папок. При этом мы воспользуемся всего одним заголовочным модулем Delphi — SHFolder.pas. Этот модуль содержит необходимы типы данных и константы для работы с библиотекой shfolder.dll, которая доступна во всех версиях Windows, начиная с Win95.
В начале немного теории. В модуле SHFolder.pas вы найдете всего одну функцию — SHGetFolderPath. Функция получает путь к папке, определенной значением CSIDL. Следует отметить, что её не рекомендуется использовать в Windows Vista и выше, т.к. в бибилотеках ОС Win Vista и Windows 7 эта функция осталась только для обратной совместимости. Вместо этого рекоммендуется использовать функцию SHGetKnownFolderPath, которая, кстати сказать, по большому счёты не отличается от своей предшественницы. Т.к. я использую в работе только ОС Win XP, то для меня вполне хватит и обычной SHGetFolderPath.
Функция имеет следующее описание:
function(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWord; pszPath: PAnsiChar): HRESULT;
Первый параметр hwnd — зарезервирован и не используется. При вызове функции достаточно присвоить ему значение 0.
csidl— определяет путь к какой директории мы хотим получить. Параметр может принимать следующие значения:
Константа | Значение | Путь к директории по умолчанию |
CSIDL_PERSONAL | $0005 | C:\Documents and Settings\%User%\Мои документы |
CSIDL_APPDATA | $001A | C:\Documents and Settings\%User%\Application Data |
CSIDL_LOCAL_APPDATA | $001C | C:\Documents and Settings\%User%\Local Settings\Application Data |
CSIDL_MYMUSIC | $000d | C:\Documents and Settings\%User%\Мои документы\Моя музыка |
CSIDL_INTERNET_CACHE | $0020 | C:\Documents and Settings\%User%\Local Settings\Temporary Internet Files |
CSIDL_COOKIES | $0021 | C:\Documents and Settings\%User%\Cookies |
CSIDL_HISTORY | $0022 | C:\Documents and Settings\%User%\Local Settings\History |
CSIDL_COMMON_APPDATA | $0023 | C:\Documents and Settings\All Users\Application Data |
CSIDL_WINDOWS | $0024 | C:\WINDOWS |
CSIDL_SYSTEM | $0025 | C:\WINDOWS\system32 |
CSIDL_PROGRAM_FILES | $0026 | C:\Program Files |
CSIDL_MYPICTURES | $0027 | C:\Documents and Settings\%User%\Мои документы\Мои рисунки |
CSIDL_PROGRAM_FILES_COMMON | $002b | C:\Program Files\Common Files |
CSIDL_COMMON_DOCUMENTS | $002e | C:\Documents and Settings\All Users\Документы |
CSIDL_RESOURCES | $0038 | C:\WINDOWS\resources |
CSIDL_RESOURCES_LOCALIZED | $0039 | C:\WINDOWS\resources\%LangID% |
CSIDL_COMMON_ADMINTOOLS | $002f | C:\Documents and Settings\All Users\Главное меню\Программы\Администрирование |
CSIDL_ADMINTOOLS | $0030 | C:\Documents and Settings\Главное меню\Программы\Администрирование |
Параметр можно использовать совместно с флагом CSIDL_FLAG_CREATE (для версий Win 2k и выше). В этом случае, если заданная в параметре csidl директория не будет найдена, то функция автоматически её создаст и вернет путь по умолчанию.
- hToken — маркер доступа. Для версий Windows 2000 и ниже всегда приравниваеся к NULL, для остальных версий может принимать ненудевое значение.
- dwFlags — определяет какой путь будет возвращен функцией: по умолчанию или текущий. Соответственно, может принимать всего два значения: SHGFP_TYPE_DEFAULT и SHGFP_TYPE_CURRENT.
- pszPath — указатель на строку WideChar.
Небольшой пример использования SHGetFolderPath. В первом случае мы попробуем получить путь к папке «Мои документы», а во втором — к папке с локализованными ресурсами. При этом, во втором случае, если путь не будет найден, то создадим необходимую директорию:
1. Как получить путь к папке «Мои документы»
var buf: array [1..MAX_PATH] of widechar; begin Memo1.Lines.Clear; if Succeeded(SHGetFolderPath(0,CSIDL_PERSONAL,0,SHGFP_TYPE_CURRENT,@buf)) then Memo1.Lines.Add(buf); end;
Результат выполнения функции:
C:\Documents and Settings\%User%\Мои документы
2. Как получить путь к папке с локализованными ресурсами или создать её, вернув путь по умолчанию
var buf: array [1..MAX_PATH] of widechar; begin Memo1.Lines.Clear; if Succeeded(SHGetFolderPath(0,CSIDL_RESOURCES_LOCALIZED or CSIDL_FLAG_CREATE,0,SHGFP_TYPE_CURRENT,@buf)) then Memo1.Lines.Add(buf); end;
Результат выполнения функции:
C:\WINDOWS\resources\419
Аналогичным образом можно получать/создавать другие специальные директории Windows. По-моему рассмотреный выше вариант получения путей вполне приемлим для работы в ОС до Windows Vista. Ну, а если нужна поддержка более поздних версий, то тут уже надо использовать последние версии библиотеки и, вдимо, придётся использовать интерфейс ISHFolder.
Ну, а если нужна поддержка более поздних версий, то тут уже надо использовать последние версии библиотеки и, вдимо, придётся использовать интерфейс ISHFolder.
Чем это плохо то?
Alexo, ничем :) Просто не все любят использовать интерфейсы
Про параметр hToken в SHGetFolderPath есть в блоге Марко Кэнтуhttp://blog.marcocantu.com/blog/SHGetFolderPath_Default_User.html
Я последнее время предпочитаю аналогичные функции из JCL — там как раз есть походяшие обёртки.