Чтобы использовать возможности окна открытия файла, достаточно воспользоваться функцией, представленной в листинге 2.23.
function ShowOpen(strFilter: string; nFilterIndex: Integer= 0;
strInitFileName: string = '';
var
ofn: OPENFILENAME;
begin
ZeroMemory(Addr(ofn), SizeOf(ofn));
//Формирование буфера (260 символов)
SetLength(strInitFileName, MAX_PATH);
PrepareFilterString(strFilter);
//Заполнение структуры для окна
ofn.lStructSize:= SizeOf(ofn);
ofn.hWndOwner:= hParentWnd;
ofn.hInstance:= hAppInst;
ofn.lpstrFilter:= PAnsiChar(strFilter);
ofn.nFilterIndex:= nFilterIndex;
ofn.lpstrFile:= PAnsiChar(strInitFileName);
ofn.nMaxFile:= MAX_PATH;
ofn.lpstrTitle:= pAnsiChar(strTitle);
ofn.Flags:= OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_HIDEREADONLY;
//Отображение окна и обработка результата
if(GetOpenFileName(ofn) = True) then
ShowOpen:= ofn.lpstrFile;
end;
Приведенная в листинге 2.23 функция возвращает непустую строку – полный путь файла в случае, если пользователь выбрал или ввел имя файла. Здесь главной трудностью является заполнение довольно большой структуры OPENFILENAME. В данном примере используются только базовые возможности окна открытия файла и лишь некоторые из поддерживаемых им флагов (поле Flags):
• OFN_FILEMUSTEXIST – при этом установленном флаге, если окно успешно завершило свою работу, можно быть уверенным, что результирующий путь является путем существующего файла;
• OFN_PATHMUSTEXIST – данный флаг не дает ввести имя файла в несуществующей папке (например, при вводе c: \docs\mydoc1.doc, если папки docs не существует, будет выдано соответствующее сообщение);
• OFN_HIDEREADONLY – позволяет скрыть флажок Только для чтения.
Теперь отдельно рассмотрим, зачем в приведенном примере вызывается дополнительная функция PrepareFilterString (листинг 2.24).
procedure PrepareFilterString(var strFilter: string);
var
i: Integer;
begin
for i:= 1 to length(strFilter) do
if (strFilter[i] = '|') then strFilter[i]:= #0;
end;
Дело в том, что при задании фильтров (поле lpstrFile) требуется, чтобы каждое название и обозначение фильтров были отделены символом #0, а за последним фильтром шла последовательность из двух нулевых символов. На практике задавать строку из нескольких фильтров в следующем виде недостаточно удобно:
'Текстовые файлы'+ #0 + '*.txt'+ #0 + 'Все файлы'+ '*.*'+ #0 + #0
Поэтому часто применяются другие разделители, которые впоследствии преобразуются в символы #0. В данном случае в качестве разделителя используется символ |, благодаря чему приведенная выше строка фильтра может быть записана так:
'Текстовые файлы|*.txt |Все файлы|*.*||'
Согласитесь, что получилось более кратко и понятно.
Теперь обратимся к окну сохранения файла. Для его вызова достаточно переделать код из листинга 2.23 следующим образом (листинг 2.25).
function ShowSave(strFilter: string; nFilterIndex: Integer = 0;
strInitFileName: string = '';
strTitle: string = 'Сохранение файла'):string;
var
ofn: OPENFILENAME;
begin
ZeroMemory(Addr(ofn), SizeOf(ofn));
//Формирование буфера (260 символов)
SetLength(strInitFileName, MAX_PATH);
PrepareFilterString(strFilter);
//Заполнение структуры для окна
ofn.lStructSize:=