Delphi существует ли файл
Давайте ознакомимся с набором функции необходимых для работы.
function FileCreate(const FileName: String): integer;
Создаёт файл в указанном пути FileName и возвращает индекс созданного файла. В случае ошибки при создании, она вернет -1.
function FileOpen(const FileName: String; Mode: LongWord): integer;
- fmOpenRead - открытие только на чтение
- fmOpenWrite - открытие только на запись
- fmOpenReadWrite - открытие и на чтение и на запись
function FileRead(handle: integer; var Buffer; Count: integer): integer;
Читает открытый или созданный файл. Вместо пути она принимает индекс файла handle. Buffer - куда будет записано содержимое. Count - количество байтов которое нужно прочитать.
function FileWrite(handle: integer; var Buffer; Count: integer): integer;
Аналогичная функция чтению, но вместо чтения она записывает содержимое размером Count (в байтах) переменной Buffer в файл.
function FileClose(handle: integer);
Закрывает файл, чтобы другие программы тоже имели доступ к нему.
function FileSearch(const Name, DirList: string): String;
Осуществляет поиск файла Name в одной или более папках DirList, отделённых друг от друга точкой с запятой. Необходимо указывать не только название папки, но и полный адрес этой папки.
Имя файла может быть, как файловым именем, так и полным адресом файла.
Если файл будет найден, то возвращается полный адрес файла включая имя файла, в случае не нахождения искомого файла будет возвращена пустая строка.
ПРЕДУПРЕЖДЕНИЕ: ВСЕГДА сначала поиск будет проходить в текущей папке, независимо от перечисленных директорий. Если файл обнаруживается там, то путь файла возращён не будет, а только имя файла.
function FileSeek(Handle, Offset, Origin: Integer): Integer;
- File_Begin (0) - Смещение (offset) рассчитывается относительно начала файла
- File_Current (1) - Смещение рассчитывается относительно текущей позиции в файле
- File_End (2) - Смещение рассчитывается относительно конца файла
Все с теорией мы покончили, теперь что-нибудь считаем. вытащим на форму 2 кнопки и Memo и напишем в обработчике события 1 кнопки OnClick следующий код: функция SizeOf возвращает размер типа или самой переменно в байтах, т.к. заранее размер строки неизвестен. скомпилируем и нажмем кнопочку.
Теперь прочитаем это. создаём обработчик события 2 кнопки OnClick и пишем код:
Для работы с файлами в Delphi есть богатый набор функций, позволяющий выполнять все необходимые действия с файлами. Механизм использования каждой из такой процедуры или функции достаточно прост – указание директории и имени файла, над которым производится действие и, иногда, указание дополнительных параметров для дополнительного контроля выполняемых операций.
В данной статье описываются возможности манипуляции с уже существующими файлами. Механизмы создания, открытия и сохранения файла описаны в статье "Создание и работа с текстовыми файлами в Delphi".
Статьи, похожие по тематике
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Поделитесь ссылкой в социальных сетях:
Домашнее задание
Для закрепления пройденного не буду предлагать новой программы - давайте изменим эту. Итак, требуется:
С первого прочтения кажется сложным? На самом деле нет. Если начнёте делать - сообразите, что и как. И не бойтесь потратить на это полчаса, час. Программированию нельзя научить - ему можно только научиться самому. Одно лишь чтение статей ничего не даст - нужно пробовать, чем больше - тем лучше. В конце концов, позади 25 уроков - это достаточно много, пора начинать активно действовать.
Желаю успехов! До встречи на следующем уроке!
Автор: Ерёмин А.А.
Статья добавлена: 8 августа 2009
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Закрытие файла
По завершении работы с файлами, особенно в случае записи в них данных, необходимо корректно завершить работу с файловой переменной. Это делается для того, чтобы сохранить все внесенные в файл изменения.
Операции с файлами
Для чтения из файла, необходимо назначить режим чтения и использовать команду Readln(), которая будет вводить в строковую переменную по одной строке из файла. Затем с этой переменой можно выполнить необходимые действия.
Обычно для загрузки всех строк из файла используется оператор цикла. Для того, чтобы определить, что файл закончился используется функция EOF() (End Of File). Таким образом получается цикл, в котором последовательно в строковую переменную вводятся все строки файла и завершающийся после окончания фала:
Для записи, назначение режим записи в файл и командой Writeln() производится запись по строкам.
Переименование файла
Для переименования файла используется функция RenameFile. Строковые параметры здесь так же содержат путь исходного файла и путь файла с новым именем.
Функция переименования так же возвращает результат своего выполнения логическим значением.
Учитывая, что во втором параметре можно указать не только новое имя файла, но и новый путь, эту функцию можно так же использовать для перемещения файла. Данную функцию так же можно использовать для переименования и перемещения папок со всеми их вложениями.
Записи с вариантами
Записи с вариантами - такой тип записей, у которых создано несколько наборов полей, а используемый набор определяется специальным полем-селектором. При этом часть полей могут быть общими для всех наборов.
Например, мы хотим в программе хранить информацию об отрезке прямой на плоскости. Математически мы можем представить отрезок двумя способами:
- Двумя точками, каждая из которых имеет координаты X и Y (т.е. X1,Y1,X2,Y2).
- Одной точкой (X,Y), длиной отрезка и углом между ним и какой-либо осью (например, осью X).
Оба метода проиллюстрированы. Совершенно очевидно, что такую структуру удобно хранить в виде записи. Опишем первый вариант:
Для наглядности точки описаны отдельно, хотя короче будет поместить их в одну строку (X1,Y1,X2,Y2: Real).
Теперь второй вариант:
Всё хорошо, оба варианта рабочие и удобные. Но теперь представьте, что в программе мы должны предоставить пользователю возможность ввода отрезка и первым, и вторым способом, т.е. он сам будет решать, как ему удобнее. Что делать в этом случае? Не писать же 2 программы, базируясь то на одной структуре, то на другой? Вот тут-то нам и придут на помощь записи с вариантами.
Сначала давайте опишем простой перечислимый тип данных, который содержит два значения - тип описания отрезка:
Второй тип я назвал полярным, потому что это ни что иное, как полярные координаты. Что ж, теперь добавим в нашу запись переменную, которая будет определять тип описания отрезка:
Но тип данных должен быть описан ещё до компиляции программы, поэтому оба набора данных следует описать прямо сейчас. А для выбора варианта применяется уже известный нам оператор case :
Ещё раз: мы заводим переменную-селектор, применяем к ней оператор множественного выбора case, и для каждого из значений описываем нужный набор полей. Наборы необходимо заключать в круглые скобки. В нашем случае получится вот что:
Здесь есть одна особенность: оператор case не требуется закрывать командой end. Варианты наборов должны располагаться всегда в конце списка полей (т.е. сначала описываются фиксированные поля, а затем вариантные) - это объясняет отсутствие end для case - запись так и так будет закрыта с помощью следующего end.
В нашем случае структура всё ещё не оптимальна: координаты одной из точек у нас описаны в обоих наборах. Давайте вынесем их как постоянные поля:
Это окончательный вид нашей записи. Посмотрите ещё раз и осмыслите написанное.
Ну а теперь перейдём к более знакомым вещам - сделаем интерфейс для ввода информации об отрезке и запрограммируем внесение всех данных в запись.
Уверен, что с интерфейсной частью вы справитесь сами, поэтому привожу лишь код кнопки:
Сначала мы смотрим, какой способа ввода у нас выбран на форме и соответствующим образом устанавливаем переменную-селектор LType. А затем уже переносим данные из полей ввода в нашу запись: если первый способ - из 4 левых полей, если второй - из 4 правых.
С какой целью мы ввели отрезок? Ну например давайте посчитаем его длину. Для этого введём собственную функцию, которая на вход будет принимать запись, а на выходе будет выдавать длину отрезка. Если забыли математику, напомню способ вычисления длины:
- По двум точкам: длина - это квадратный корень из суммы квадратов разностей соответствующих координат.
- По точке, углу и длине: промолчу, ага.
Что может быть проще? Ну и в конец обработчика нажатия кнопки добавим:
Проверьте правильность работы, запустив программу и введя какие-нибудь данные. Помните, что программа работает с расчётом на то, что исходные данные верны, т.е. что вместо чисел вы не вписали "всем привет!".
Быстрый доступ к полям записей
В нашем примере у записи сравнительно мало полей - 4. Но бывают программы, где создаются записи с десятком полей и работа из-за этого замедляется. Хотя бы потому, что в коде приходится каждый раз набирать имя записи и точку, и лишь затем имя поля. Обрадую: мучаемся не только мы - компьютеру тоже приходится делать больше телодвижений. Каждый раз нужно определять адрес и искать запись в памяти, и лишь после этого можно найти значение поля. Чтобы облегчить участь и программисту и машине, был введён специальный оператор with (англ. "с"). К сожалению, о нём далеко не все знают, а ведь его использование увеличивает эффективность и кода, и работы самого программиста.
Итак, общая форма записи:
Не очень понятно? А теперь на нашем примере:
Что же мы имеем? А вот что: мы нашу запись "вынесли за скобку", и далее напрямую обращаемся к её полям. Удобно, не правда ли? Этот код абсолютно эквивалентен тому, что был написан нами ранее, только он более эффективен.
Несложно догадаться, что использование with для единичного обращения к записи бессмысленно:
В этом случае мы ни в чём не выигрываем - только пишем больше кода.
Помните про оператор with и почаще его используйте - и себе жизнь облегчите, и программы станут профессиональнее.
Подключение к файлу
Для связи программы с файлом используется специальная переменная – "Файловая переменная". Объявляется она так же как и любая переменная в Delphi. Тип это переменной может быть File для типизированных (хранящих данные определенного типа) файлов, а можно указать TextFile, что будет означать тип обычного текстового файла. Объявление переменной:
В исполняемом коде программы выполняется подключение к внешнему файлу:
Команда AssignFile, выполняет связь файловой переменной с внешним файлом. Вторым параметром указывается адрес файла. Он может быть задан относительным или абсолютным. Если указать только имя файла, то программа будет пытаться обнаружить его в той же директории, где она сама и находится. Абсолютный путь указывается от корневого диска:
Использование относительной директории дает возможность не привязываться к конкретным дискам и адресам. Например:
После того как выполнено подключение, выполняется процедура, устанавливающая режим работы с файлом. В основном это режим чтения или записи. Эти режимы назначаются процедурами Reset() ( для чтения) и rewrite() (для записи):
* Для команды Rewrite() следует учитывать, что при ее выполнении, она либо создает файл, указанный в файловой переменной, либо если он уже есть перезаписывает файл заново, удаляя старый без какого-то предупреждения.
Любую из указанных команд можно использовать без команды AssignFile(). Для этого достаточно вторым параметром указать путь к файлу. Таким образом, она сразу выполнит привязку файла к файловой переменной и назначит режим работы с этим файлом:
Проверка на наличие файла
Часто перед выполнением каких либо действий с файлом, необходимо убедиться в его существовании на диске. Для этих целей используется функция FileExists. Единственный строковый параметр функции содержит путь к файлу. При своем выполнении функция вернет значение true, если указанный файл есть. False, если файла нет.
Когда речь идет о работе программы с текстовым файлом, подразумеваются процедуры ввода данных из файла в программу или, наоборот, запись этих данных в файл программой. Для текстового файла допустима простая работа с файлом без особых дополнительных механизмов, которые применяются для работы со специализированными файлами, такими как при загрузке данных из Excel или работе программы с базой данных. Разумеется, Delphi располагает возможностями работать с файлами с использованием компонентов. Но в данной статье рассматривается механизм прямой работы с текстовым файлом без использования дополнительных компонентов.
Итак, в общем виде, работа с файлом заключается в следующих этапах:
1. подключение к файлу – связь с внешним файлом, указание режима подключения;
2. выполнение операций записи в файл или чтения из файла;
3. завершение работы с файлом.
Копирование файла
Копирование файла выполняется функцией CopyFile, параметрами которой служит путь к исходному файлу и путь, где должна быть расположена копия файла.
Третий параметр определяет, будет ли перезаписан файл в случае, если файл с таким именем уже есть. Если параметр задан значением True, то в случае если файл уже есть, функция выполнять копирование не будет и вернет значение False. Таким образом, можно добавить дополнительную проверку и защитить информацию от потери из-за перезаписи файла.
Если третьим параметром указано значение False, то функция будет копировать файл с перезаписью, если файл уже есть и в результате всегда возвращать значение True.
Так как пути к файлам задаются параметром типа PChar, то использование строковых переменных в этой функции будет вызывать ошибку. Такая проблема может произойти, если, например, путь к файлу задавать в компонентах Edit или OpenDialog. В этом случае, нужно выполнить приведение типов данных к нужному виду:
Хранение записей в файлах
Ну вот мы и подошли к тому, для чего пришлось затронуть тему работы с файлами. Использовать записи мы научились, но тут вопрос: а как их хранить? Сохранять в файлах отдельно каждое поле - совершенно неудобно. А потом его нужно оттуда ещё как-то прочитать. Неужели нет способа проще? Есть!
Мы можем создать типизированный файл на основе имеющегося типа записи. Помните, как мы описывали файлы? file of . , верно? Так вот, теперь в качестве типа будет выступать наша запись.
Вернёмся к программе, которая позволяет ввести отрезок. Теперь перед нами задача сохранить этот отрезок в файл. Ну, не в буквальном смысле, конечно - просто сохранить все его параметры.
Начнём с создания указателя на файл, который опишем указанным образом:
Этим мы сказали, что каждый элемент нашего файла - запись типа TLineSegment. А дальше всё как обычно - ничего нового: связываем указатель с файлом, открываем, записываем, закрываем. Без комментариев, что называется:
Теперь попробуем прочитать данные из этого файла. Создайте ещё одну кнопку "Загрузить". Код для неё будет такой:
Опять же, если всё было сделано верно, то вы увидите длину введённого ранее отрезка.
Теперь давайте изменим нашу программу таким образом, чтобы вводимые отрезки добавлялись в файл, т.е. чтобы файл содержал сразу несколько записей. Но здесь нас подстерегает проблема: функция Append(), предназначенная для добавления данных в конец в файла, работает только с текстовыми файлами. У нас же файл типизированный и здесь такой фокус не пройдёт. Будем выполнять обходной манёвр. Предлагаю вот что: создадим временный файл, перепишем туда все записи из существующего файла, добавим новую запись, после чего удалим старый файл, а новый переименуем. Хитро, сложно? На самом деле не очень.
Чтобы провернуть всё это, пришлось добавить 2 переменные - ещё одну запись и один файл. Под буквами "N" и "O" я подразумеваю "new" и "old" (новый и старый).
Разберём этот код подробно. Сначала делаем папку с программой рабочей, чтобы каждый раз не писать путь. Далее ассоциируем указатель с новым файлом, и открываем этот файл для записи. Далее проверяем, есть ли файл с предыдущими записями. Как мы договорились, если он есть, то нужно переписать из него все записи: связываемся с файлом, открываем его для чтения, а далее цикл по всем полям записи. Функция EOF() позволяет узнать, дошли ли мы до конца файла. Таким образом, пока файл не кончился, читаем из него одну запись и переписываем её в новый файл. После завершения закрываем старый файл. Осталось самое простое - записать новую запись, что мы и делаем. После этого старый файл lines.dat удаляем, а временный temp.dat переименовываем в новый lines.dat. Таким образом, достигнута требуемая цель. Запустите программу и добавьте в наш файл ещё несколько отрезков. О том, что добавление происходит успешно, можно судить по увеличивающемуся объёму файла.
Следующая задача: узнать, сколько записей в файле. Делается это очень просто - функцией FileSize() . Когда мы объявляем "файл из байтов" (file of byte), то получаем объём файла в байтах. Сейчас же мы узнаем, сколько записей в файле:
Код очень простой и понятный.
Ну и наконец последнее, о чём мне хотелось бы рассказать - это о "перемотке" файла. Я имею ввиду о том, как добраться до записи в середине файла, не перебирая все предыдущие через Read(). Такая задача встречается очень часто и решается она достаточно просто. Процедура Seek() перемещается по файлу на указанный по номеру элемент:
Пример: добавим на форму TListBox и кнопку "Обновить список":
Как видно, эта кнопка добавляет в ListBox список записей в файле. Теперь кнопка "Загрузить" должна загрузить выбранную в списке запись и отобразить длину отрезка:
Свойство ItemIndex у ListBox определяет номер строки, выбранной в данный момент (строки нумеруются с нуля). После открытия файла мы прыгаем на запись с таким номером, читаем её и затем определяем длину.
Просто? Думаю, что да. Работа с типизированными файлами принципиально ничем не отличается от работы с текстовыми. Зато обратите внимание, как легко можно оперировать записями! Теперь вы легко сможете создать простейшую базу данных.
Да, и помните, что при работе с типизированными файлами нельзя использовать функции ReadLn() и WriteLn() - они предназначены исключительно для текстовых файлов.
Перемещение файла
Чтобы при перемещении не выполнять два действия – копирование и удаление исходного файла, в Delphi имеется специальная функция MoveFile. Два параметра функции указывают путь исходного файла, и путь, куда должен быть перемещен файл.
Аналогично уже рассмотренным функциям, эта возвращает значение true, при успешном выполнении своих операций и false, при возникновении ошибки. Ошибка может возникнуть, например, при отсутствии исходного файла или наличии файла с заданным именем в новой директории.
При использовании компонентов и строковых переменных, здесь так же потребуется приведение типов данных:
Это функцию можно так же использовать для переименования файла, указав новое имя файла и сохранив старый путь.
Кроме того, функцию MoveFile можно применить для переименования или перемещения папки со всеми вложенными в нее файлами. В приведенном ниже примере, папка "myfolder" будет перемещена в поддиректорию "newfolder1" и переименована в "newfolder2".
Удаление файла
Удаление файла в Delphi осуществляется с помощью функции DeleteFile. В качестве единственного параметра задается путь удаляемого файла.
В результате своего выполнения функция DeleteFile возвращает результат логического типа: true, если файл был удален; false, если файл не был удален (например, если файл отсутствует).
Упакованные записи
Пару слов о том, что такое упакованные записи, и с чем их едят. По умолчанию память под записи выделяется не очень экономно - помимо самих данных добавляются и служебные байты, которые отделяют блоки данных друг от друга. Существует принудительный способ заставить Delphi упаковать запись, т.е. минимизировать занимаемую ей память. Делается это указанием слова packed перед словом record. Разница порой может быть достаточно ощутимой. Пример: запись из строки длиной 5 символов, одного символа и трёх чисел разного типа. Объявим две разные записи: одна обычная, а другая упакованная:
А теперь самое интересное: посмотрим, сколько памяти занимает каждая из записей. Сделаем это функцией SizeOf():
Тем не менее, не стоит пренебрегать этим способом экономии памяти. В некоторых случаях использование пакованных записей может создавать разные ошибки в работе программы. Понять, что дело именно в packed, удаётся далеко не сразу. Так что, если храните десяток отрезков - не торопитесь паковать - если и выиграете, то не сильно.
Комментарии читателей к данной статье
Доброго всем времени. Очень хорошие уроки. Все подробно описано и разжевано. Самое то для начинающих. Подскажите пожалуйста, будут ли еще уроки? Судя по дате, то выходить больше не будут. Очень жаль, только начал в раж входить =) . В любом случае [b]Ерёмину А.А[/b] от меня низкий поклон и громадное спасибо.
P.S. Большая просьба, если есть возможность, продолжите пожалуйста статьи по Delphi. Очень хочется изучить этот язык поглубже =) . Большое спасибо. Удачи!
Цитата:
А следующего урока я так понял нет. мде. моменты как по TCP на делфи работать и вообще по инету шариться видимо тут не узнать.
Не знаю в чём дело, жрать очень охота.
По теме: по-моемему не записи с вариантами, а записи записей - так это чаще называется. Хотя могу путать.
Ну а добавление в файл записей еще одну запись - почему бы файл не открыть на запись, указатель в конец поставить и дописать ее туда?
Здарова!
Все вроде понятно, кроме одного.
повторил все как автор, но у меня на форме (в ListBox-е) исчезают старые записи (при каждом обновлении повляются новые).
третью задачу из-за этого не могу сделать.
в чем там дело.
Примеры работы с текстовыми файлами в Delphi
Чтение в переменную одного значения из файла:
Загрузить все строки файла в компонент Memo:
Следует отметить, что для этой задачи проще воспользоваться командой самого компонента Memo LoadFromFile().
Записать строку в файл:
Записать в текстовый файл все строки из компонента Memo:
Как и для чтения из файла в Memo, так и здесь, имеется специальная команда:
Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.
В реальных программах иногда необходимо копировать, перемещать и удалять файлы. В Delphi для этих целей служат очень простые функции.
Эта функция возвращает true, если операция прошла успешно, и false, если неудачно.
Функция DeleteFiie умеет удалять только файлы и только по одному. У вас не получится работать сразу с несколькими файлами, и придется для каждого из них вызывать функцию удаления. Помимо этого, можно удалять только файлы. Если указать директорию, то операция не будет выполнена.
Для удаления директорий есть отдельная функция:
Функция возвращает true, если операция прошла успешно, и false, если неудачно.
Когда мы не указываем полный путь, а только имя файла или директории, то функции ищут эти файлы в текущей папке. Для изменения текущей папки служит функция chDir:
ChDir('Путь к папке, которая будет использоваться по умолчанию'); Это процедура, и у нее нет возвращаемого значения.
Текущую для программы директорию можно узнать с помощью функции GetCurrentDir, которой не надо ничего передавать, она просто возвращает текущую директорию.
Перед операциями над файлами и директориями желательно убедиться в их существовании. Для того чтобы узнать, существует ли файл, можно воспользоваться следующей функцией:
FileExists " 'Имя или полный путь к файлу');.
Если файл существует, то функция вернет true, иначе - false.
Узнать о существовании директории можно с помощью следующей функции:
Если директория существует, то вернет true, иначе - false.
Вот небольшой пример использования описанных функций:
В этом примере сначала изменяется текущая директория на корень диска С. После этого происходит проверка: если существует файл autoexec.bat, то он удаляется из текущей директории.
Использовать данные функции Delphi очень просто, но они имеют слишком мало возможностей и среди них нет хорошей функции для копирования и перемещения файлов. Среди справки Delphi можно найти описание функций копирования и перемещения, которые можно использовать в проектах. Для этого нужно только добавить их в свой проект.
Source, Dest: Integer; Len: Integer; Destination: const
GetMem(CopyBuffer, ChunkSize) ; try
Source:»FileOpen(FileName, fmShareDenyWrite);//Открыть файл-источник if Source " 0 then raise EFOpenError.CreateFmt(SFOpenError, [FileName]); try
Dest := FileCreate(Destination); //Создать файл-приемник if Dest " 0 then raise try
//Считать порцию файла
BytesCopied'.=FiieRead(Source,CopyBufЕегЛ,ChunkSize); if BytesCopied " 0 then //Если порция считана, то. //Записать ее в файл-приемник FileWrite(Dest, Copy-Buffer", BytesCopied); until BytesCopied " ChunkSize; finally
Процесс копирования очень прост. Процедура получает два имени файла: откуда копировать, и куда. После этого происходит проверка. Если в качестве второго параметра (путь к файлу, в который надо скопировать)' указана только директория без имени файла, то программа подставляет в качестве имени файла имя источника.
После этого источника открывается для чтения данных с запретом на запись со стороны других программ. Открыв источник, процедура создает файл приемника. Если он существовал, то без каких-либо предупреждений файл будет перезаписан. Дальше запускается цикл, в котором из файла источника считываются данные по 8 192 байт и тут же записываются в файл приемника. Таким образом, в цикле происходит копирование файла небольшими порциями. Чем больше порция, тем быстрее будет происходить копирование.
Процедура копирования - очень хороший пример использования функций работы с файлами. Все сделано очень грамотно и великолепно работает, хотя и не очень универсально. Например, нет вызова предупреждения о существовании результирующего файла перед его уничтожением. Но это не так уж сложно сделатьС помощью функции F і 1 е Е х і s t s.
Теперь посмотрим на реализацию функции перемещения файлов (листинг 3.14). |1иС™нг^
Эта функция также получает в качестве параметров два имени файла: источника и приемника. В начале функции происходит попытка переименовать файл источника в приемник. Если оба файла находятся на одном диске, то такая операция произойдет успешно, и файл-источник без копирования превратится в файл-приемник с помощью простого изменения пути расположения.
Если источник и приемник находятся на разных дисках, то такой трюк не пройдет, поэтому процедура вызовет функцию описанную выше, для копирования источника в новое место, а потом удалит файл запуска файла можно использовать следующую универсальную функцию (листинг 3.15).
Чтобы ее использовать, нужно добавить это описание в свой модуль. Только не забудьте добавить еще в раздел uses модуль shellAPi, иначе проект нельзя будет скомпилировать.
У функции четыре параметра.
П Имя ' файла, или полный путь к файлу, который надо запустить.
□ Параметры, которые надо передать запускаемой программе (то, что нужно написать в командной строке).
□ Директория по умолчанию, с которой должна работать программа. Если директория не указана, то будет использоваться та, в которой находится запускаемый файл.
□ Способ отображения запущенного файла. Набор способов идентичен тому, ЧТО МЫ ИСПОЛЬЮВатИ В функции Showwindow.
Вот простой пример использования данной функции:
С помощью этой же функции можно запускать Internet Explorer (или другой браузер, который установлен по умолчанию) и загрузить Интернет-страничку:
Если нужно создать электронное письмо, то это можно сделать следующим способом:
Функцию ShellExecute мы уже рассматривали в разд. 2.5, и все же я решил описать ее еще раз, чтобы выделить в отдельную процедуру. Применяя ее, вам не надо следить за типом pchar, который используется- для передачи строк, потому что наша функция ExecuteFile сама сделает необходимые преобразования.
И сейчас мы перейдем к реальному примеру, который будем .изучать на практике. Создайте новый проект и перенесите на форму два компонента: ShellTreeView И ShellListView. У компонента ShellTreeView В СВОЙСТВе нужно указать компонент чтобы связать в одно целое. У компонента ShellListView нужно установить свойству Mutiselect значение true, чтобы мы могли выбирать несколько файлов.
Теперь нужно добавить панель, на которой мы разместим четыре кнопки: Копировать, Переместить, Удалить, Свойства. Мою форму будущей программы вы можете увидеть на рис. 3.17.
Рис. 3.17. Форма будущей программы работы с несколькими файлами
Теперь перейдите в раздел uses и добавьте туда два модуля: shellapt. и FileCtrl. ПерВЫЙ МОДУЛЬ необходим ДЛЯ работы фуНКЦИИ SHFileOperation. Во ВЮрОМ есть фунКЦИЯ SelectDirectory, которая ВЫЮДИТ на экран стандартное окно выбора директории. Это окно мы будем использовать, когда нужно будет выбрать директорию, в которую надо скопировать или переместить файлы.
В разделе private добавим описание следующей функции:
private < Private declarations >function DoSHFileOp(Handle: THandle; OpMode: UInt; Src, Dest: string; DelRicleBin; Boolean): Boolean; Эта функция будет универсальная: для копирования, перемещения и удаления файлов. Нажмите "Ctrl"+"Shift"+"C", чтобы создать заготовку этой функции. В этой заготовке нужно написать следующее (листинг 3.16).
Листинг3.16. Универсальная функция для работы с файлами Г
function TForml.DoSHFileOp (Handle: THandle; CpMode: UInt; Src,.
Для функции SHFiieOperation нужен только один параметр- структура типа TSHFileOpStruct. Такой переменной является ipFiieOp. Прежде чем использовать эту структуру, мы заполним ее нулями с помощью функции Fiilchar, чтобы там случайно не оказались ненужные данные. Теперь перечислим свойства, которые нужно заполнить.
□ wnd - указатель на окно, которое будет являться владельцем выполняемого процесса (копирование, перемещение, удаление).
□ wFunc - операция, которую надо выполнить. Сюда будет записано передаваемое значение.
- путь-источник, который мы получаем в качестве третьего параметра.
рто - путь-приемник, который мы получаем в качестве четвертого параметра.
□ fFlags - флаги. Если в качестве данного параметра указано true, то мы выставляем флаг fof_allowundo. этот флаг говорит о том, что при удалении файлы будут попадать в корзину. Иначе будет установлен флаг fof_noconfirmmkdir, который указывает на то, что не надо запрашивать подтверждения при необходимости во время выполнения операции создать директорию. Вы можете также указывать следующие флаги (для того, чтобы выставить несколько флагов, пишите их через знак " + "):
• fof_simpleprogress - показать окно выполнения процесса, но не отображать имена файлов.
• IpszProgressTitle - текст, который будет отображаться в окне хода выполнения операции.
□ fAnyoperationsAborted - это свойство будет равно true, если пользователь прервал выполнение операции.
После раздела vaг и перед ключевым словом implementation напишите следующий код:
FileOpMode: array[0..3] of UInt =
Здесь мы объявили массив из четырех значений. Каждое из значений - это константа для обозначения определенной операции:
Теперь создадим обработчики событий для нажатия кнопок нашей панели. Сначала создайте обработчик события onclick для кнопки Копировать. В нем нужно написать следующий код (листинг 3.17).
for i := 0 to do if (ShellListViewl.items.item[i].Selected) then begin FSrc:=FSrc+
Прежде чем производить попытку копирования, надо проверить, выбрал ли пользователь какие-либо файлы. Если нет, то нужно выйти из процедуры, потому что копировать нечего. Эта проверка происходит во второй строке кода:
После этого на экран выводится окно выбора директории, в которую нужно будет скопировать выбранные файлы. Делается это с помощью функции Если пользователь ничего не выбрал, то происходит выход из процедуры. Внешний вид окна выбора директории вы можете увидеть на рис. 3.18.
Рис. 3.18. Окно выбора директории
Теперь нужно узнать директорию, из которой происходит копирование. Полный путь находится в свойстве path компонента ShellTreeviewl. Также проверяется, если последний символ пути не равен знаку его нужно добавить:
for i := 0 to ShellListViewl.items.Count-1 do if (ShellListViewl. items, item[i] .Selected) then begin FSrc:=FSrc+
После этого вызывается написанная нами ранее процедура DoSHFiieOp, указывая все необходимые параметры. В качестве второго параметра указана операция, которую надо выполнить- FiieOpMode[0], что равно команде focopy. Третий и четвертый параметр - это пути источника и приемника (откуда и куда надо копировать).
Теперь напишем код для кнопки Переместить. Для этого в обработчике события onclick соответствующей кнопки пишем следующее (листинг 3.18).
for i := 0 to ShellListViewl.items.Count-1 do if (ShellListViewl.items.item[il.Selected) then begin FSrc:=FSrc+
Этот код идентичен тому, что мы написали для кнопки Копировать. Разница только в вызове процедуры DoSHFileOp, где мы указываем операцию FileOpMode [2], что означает перемещение. А в остальном там так же определяется директория, из которой нужно копировать, и так же формируется строка из имен файлов для копирования, разделенных нулевым символом.
В обработчике нажатия кнопки Удалить пишем следующий код (листинг 3.19).
for i := 0 to FilesListView.items.Count-1 do if then begin DelFName:=DelFName+
И снова код похож на тот, что мы уже использовали дважды. Но есть все-таки две разницы:
1. Мы проверяем, находится ли какой-нибудь файл в режиме редактирования ЕііезіЛз^іе*.І8Ес!Шп§. Если да, ТО ВЬМДМ ИЗ процедуры.
2. В вызове процедуры ОоЗНЕііеОр в качестве второго параметра мы напрямую указываем константу БорЕЬЕТЕ, хотя можно было бы указать РііеОрМоає [ 1], что абсолютно то же самое.
В обработчике нажатия кнопки Свойства напишем следующий код (листинг 3.20).
Здесь мало строчек кода, но с ним придется разбираться. В начале происходит простая проверка на выделение. Если пользователь ничего не выбрал, то выходим, иначе в следующей строке произойдет ошибка. Дальше мы вызываем функцию SHObjectProperties, которая отображает стандартное окно свойств объекта. У этой функции 4 параметра.
О Указатель на окно-владельца.
□ Второй параметр может принимать значения $01 для принтера или $02 для пути к файлу или папке.
□ Так как мы используем файлы и папки, то здесь должен быть полный путь к этому объекту.
О Последний параметр оставляем равным nil.
На рис. 3.19 вы можете увидеть стандартное окно свойств, вызванное из нашей программы.
Рис. 3.19. Стандартное окно свойств объекта
Чтобы проект теперь скомпилировался, нужно сообщить о существовании функции зногое^Ргорегг^ез, о которой Ш1рЫ еще не знает. Для этого создайте файл stan.dardDialogs.pas и напишите в нем следующее (листинг 3.21).
windows, Messages, SHlObj,-
//Cancel the operation and close the dialog.
TSHObjectProperties = function(hwndOwner: HWND); uFlags:
Теперь добавьте в раздел uses имя нашего модуля standardDialogs и скомпилируйте проект. Теперь можете запустить проект и посмотреть результат.
На компакт-диске в директории \Примеры\Глава 3\File Operation вы можете увидеть пример данной программы и цветные версии рисунков.
В позапрошлом уроке мы познакомились с записями: узнали, что это такое, как их заводить в своих программах, и как с ними потом работать. В прошлом уроке мы вели разговор о работе с файлами и научились работать с содержимым файлов. Сегодня мы объединим полученные знания, попутно продолжив знакомство с записями.
Читайте также: