Добавить в файл в delphi
В этом уроке рассмотрим очень важную тему в программировании - работа с файлами.
Практически в любой программе нужно копировать, открывать, изменять, сохранять, иногда удалять файлы.
Как известно, файлы имеют различные форматы и к ним применяются различные программы для обработки. Например, файлы рисунков BMP, текстовые файлы TXT и т.п. Файлы имеют различные имена и определенное расширение, имеющее в среде MS-DOS максимально три символа. Если у файла расширение RAR, то пользователь и операционная система знает, что это архиватор, причем windosw для обработки этого файла применяет средства, указанные в специальном разделе реестра.
Копирование файлов
Для копирования файлов применяется функция CopyFile. Формат ее такой:
CopyFile является функцией, которая возвращает флаг успешной или нет операции копирования.
Например, следующая строка:
Перемещение файлов
Для перемещения файлов применяется функция MoveFile. Она имеет следующий формат:
Ее параметры аналогичны вышерассмотренной команде за исключением отсутствия флага перезаписи.
Переименование файлов
У всех вышесказанных командах параметры исходного и конечного файла имеет тип PChar. Это строковый тип с завершающимся нулем. Возможно, вы раньше слышали о таком формате строковых данных. В такую переменную можно занести строку очень большой длины. Ее размер ограничивается наличием нулевого байта в конце. Теоретически такая переменная может иметь бесконечный размер. На практике она ограничивается размерами выделяемой памяти для программы (2Гб).
Преобразование обычной строковой переменной, типа String в PChar производится функцией:
При этом, для команд файловых операций возможны объединение строк. Например:
procedure TForm1.Button1Click(Sender: TObject);
Var InDir,OutDir:String; // объявление строковых переменных
InDir:='c:\1\'; // каталог исходных файлов
OutDir:='c:\2\'; // каталог записуемых файлов
Здесь налицо операция соединения двух строковых переменных.
В итоге этой процедуры будет копирование файлов c:\1\1.txt и c:\1\2.txt в каталог c:\2. Файлы копируются под теми же именами.
Удаление файлов
Работа с текстовыми файлами. Чтение из текстового файла
На прошлых уроках мы как, в компоненте Memo процесс загрузки и записи текстового файла делался следующим образом:
Все это благодаря свойству Lines, в котором хранятся строки.
Но на практике иногда необходимо прочитать только определенную строку или совершить операцию добавления строки в уже существующий файл.
Следующий пример обработки текстового файла очень похож на аналогичную на языке Pascal.
Знающие люди могут ощутить разницу, поскольку есть некоторые отличия.
Varf:TextFile; // объявление файловой переменной
st:String; // строковая переменная
AssignFile(f,'c:\1.txt'); // привязка названия файла к файловой переменной
// отключение контроля ошибок ввода-вывода
Reset(f); // открытие файла для чтения
// включение контроля ошибок ввода-вывода
ifIOResult<>0 then // если есть ошибка открытия, то
ShowMessage('Ошибка открытия файла C:\1.TXT');
Exit; // выход из процедуры при ошибке открытия файла
While not EOF(f) do // пока не конец файла делать цикл:
ReadLn(f,st); // читать из файла строку
ShowMessage(st); // выводить строку пользователю
CloseFile(f); // закрыть файл
Прокомментирую некоторые строки этого примера.
Команда AssignFile осуществляет привязку строки пути файла к файловой переменной. Все дальнейшие операции с файловой переменной автоматически осуществляются с указанным файлом. Для избежания путаниц, указывайте полный путь к файлу.
и являются директивами компилятору, что в этом месту соответственно следует отключить и включить контроль ошибок ввода-вывода. В данном случае при неудачной попытке открытия файла c:\1.txt (файл отсутствует или открыт для записи другой программой) наша программа не выдаст аварийной ошибки и продолжит выполнение данной процедуры. Это свойство полезно для обработки всех возможных случаев в работе программы.
Работа с текстовыми файлами. Запись в текстовый файл
procedure TForm1.Button1Click(Sender: TObject);
Var f:TextFile; // указатель на текстовый файл
AssignFile(f,'c:\1.txt'); // привязка названия к переменной
Append(f); // открыть файл для добавления
if IOResult<>0 then // если ошибка открытия (напр. файла нет)
Rewrite(f); // создать новый файл
if IOResult<>0 then // ошибка создания файла
ShowMessage('Ошибка создания файла C:\1.TXT');
WriteLn(f,'Привет'); // запись в файл строки с символами перевода строки
CloseFile(f); // закрыть файл
Процедура Append(Файл) открывает файл для записи и устанавливает указатель записи в конец файла, т.е. все добавляемые к файлу строки будут записаны в конец файла.
В нашем случае в самом начале файла 1.txt может не оказаться на диске, поэтому команда открытия файла для добавления вызовет ошибку. В этом случае срабатывает наш собственный контроль ошибок и выполняется команда создания файла.
Запись и чтение из файла не текстовых данных
Рассмотрим пример, в котором программа при выходе сохраняет свои размеры и положение окна на экране в файл и при последующем запуске восстанавливает состояние, которое было при выходе. Программа состоит из двух процедур OnShow и OnClose для окна Form1 программы.
procedure TForm1.FormShow(Sender: TObject);
Var f:file of Integer; // файловая переменная, тип integer
i:Integer; // целочистенная переменная
begin
if IOResult<>0 then Exit;
Read(f,i); //считать из файла значение
Form1.Top:=i; // верхнее положение окна
Form1.Left:=i; // левое положение окна
Form1.Width:=i; // ширина окна
Form1.Height:=i; // высота окна
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
Var f:file of Integer;
Сохранение данных в типизированный файл.
Предварительные замечания.
Прежде, чем начать разговор о нетипизиованных файлах, сделаем ещё несколько замечаний по поводу записи в типизированный файл в delphi.
Они будут необходимы нам в дальнейшем при работе с нетипизированными файлами.
Позиционирование указателя типизированного файла.
Типизированный файл, в отличие от текстового файла, позволяет прочитать отдельную запись. Так как длина всех записей одинакова, их можно пронумеровать и обращаться к записи по номеру, наподобие одномерного массива.
Для обращения к записи по её номеру существует процедура позиционирования:
seek(файловая_переменная, номер_записи) //помним, что отсчет ведутся от 0)
Создадим файл для хранения целых чисел. Запишем в него 5 значений. Проконтролируем записанные значения чтением из файла и отображение их в memo.
Определим размер файла функцией FileSize(ф.п.).
Затем установим указатель файла в четвёртую позицию (то есть номер_записи=3).
Изменим значение записи в этой позиции и вновь проконтролируем результат.
Для решения задачи подготовим форму:
Воспользуемся полученной информацией и ещё раз посмотрим, как в delphi записать в файл данные фиксированной длины и какие процедуры и функции для работы с файлами нам для этого понадобятся.
Создадим обработчики событий для первой и второй кнопок:
var vFileInt:File Of Integer; // создаём переменную для ссылки на типизированный файл
procedure TForm1.Button1Click(Sender: TObject);
rewrite(vFileInt); //создаём файл
j:=filePos(vFileInt); //контролируем положение указателя файла
write(vFileInt,j); //формируем значения и записываем их в файл.
j:=filePos(vFileInt); //опять контролируем положение указателя в файле
j:=fileSize(vFileInt); //проверяем размер файла (количество записей)
reset(vFileInt); //переоткрываем файл. При этом указатель файла устанавливается на 0.
while not EOF(vFileInt) do
read(vFileInt,j); //читаем файл и прочитанные значения отображаем в memo.
closeFile(vFileInt);
Форма после нажатия на первую кнопку:
procedure TForm1.Button2Click(Sender: TObject);
var j:integer; s:string;
reset(vFileInt);
seek(vFileInt,3); //устанавливаем указатель файла в четвёртую позицию (0,1,2,3)
write(vFileInt,j); //перезаписываем четвёртое значение
j:=filePos(vFileInt); //отображаем положение указателя файла после перезаписи.
reset(vFileInt);
while not EOF(vFileInt) do
read(vFileInt,j); //читаем и отображаем файл
closeFile(vFileInt);
Форма после нажатия на вторую кнопку:
Компонент TBitBtn
Продолжим знакомиться с компонентами. На вкладке Additional находится компонент TbitBtn.
Это кнопка с расширенным набором свойств.
Познакомимся с некоторыми из них, которые будут важны в данном занятии.
Если обычная кнопка TButton имеет минимальные возможности по формированию своего внешнего вида, то у TbitBtn таких возможностей гораздо больше.
Для записи в поток подготовим кнопу типа TbitBtn и настроим её так, чтобы она имела в конечном итоге вид:
Как видно из рисунка, на кнопке появилась пиктограмма (красный кружок), Название кнопки выведено в трёх строках. Изменён цвет шрифта.
Для отображения названия кнопки в нескольких строках посмотрим, как хранятся строки в компоненте memo.
В окне текст отображается в виде отдельных строк. А в свойстве Memo1.Text он хранится в виде:
В Object Inspector нельзя добиться вставки этих служебных символов в строку. Они будут воспроизведены как простой текст.
Чтобы служебные символы сыграли свою роль, надо отдельно сформировать строку с их присутствием и записать в свойство Caption.
Удобнее всего это сделать в обработчике создания формы:
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
Цвет символов можно изменить, раскрыв свойство Font, нажав на «+». В выпадающем списке Color можно выбрать нужный цвет символов.
Как видно на рисунке, для кнопки можно организовать подсказку. Для этого надо заполнить свойство Hint (в нашем случае там написано «подсказка») и разрешить её отображать (выставить свойство ShowHint в true).
И наконец, на кнопке отображена небольшая пиктограмма. Она подготавливается заранее в текстовом редакторе и загружается через свойcтво Glyph).
Замечание. Загрузка пиктограммы для отображения на кнопке имеет свои особенности, познакомиться с которыми можно в справочной литературе.
Простые и структурированные типы данных.
Под переменные стандартных типов отводится оговоренное количество байт памяти. Под Integer 4 байта, под Double 8 байт, под Char 1 байт и так далее.
Но команды, которые манипулируют данными, хранят адрес только первого байта переменной. Информация о том, сколько надо прочитать байт и как эту цепочку байт интерпретировать, также хранится в команде.
Совокупность длины переменной и способа интерпретации последовательности байт можно назвать типом данных.
Указанные типы называются простыми типами данных.
По мере развития вычислительной техники и возрастания её возможностей стали вводиться более сложные, структурированные типы данных.
Чтобы работать с типом данных «массив» надо хранить информацию о том, что мы имеем дело с последовательностью байт, где начинается эта
последовательность, указать общее количество байт и на какие «порции» надо делить эту последовательность (указать тип данных).
Обычный массив характерен тем, что длина всех элементов массива одинакова.
В отличие от него, динамический массив может иметь разную мощность по разным измерениям. Например, двумерный динамический массив может содержать по первому измерению 5 элементов, а по второму — 10.
Но тип всех элементов всё равно остаётся одинаковым. Например, Integer.
Тип данных «запись».
Объявляется запись следующим образом:
type tRec=record J:integer, sh:string[20]; ss:string; d:double; ar:array[1..3] of char; ex1,ex2:extended; end;
Нотация обращения к полям записи следующая:
vRec.d:=10.255; vRec.ex1:=456.89; vRec.ex2:=789.023;
Заметим, что полем может служить другая запись!
type tRec1=record JJ:integer, end;
type tRec=record J:integer, sh:string[20]; ss:string; d:double; ar:array[1..3] of char; ex1,ex2:extended; r1:tRec1 end;
Тогда для формирования значения JJ надо записать:
vRec.r1.JJ:=20;
Не прадо ли, очень похоже:
Form1.Memo1.Text ?
Теперь сделаем «петлю» и ещё раз вернёмся к типу «string».
Ещё раз о типе «string».
В типе «string» первые 12 байт служебные. В них указывается длина строки.
Номер кодовой таблицы символов (в какой язык интерпретировать числа, записанные в байтах, составляющих строку). Счётчик ссылок (он увеличивается на 1, когда выполняется s2:=s1, где s1 и s2 — строковые переменные).
Символы пронумерованы по порядку, начиная с 1. К символу номер N можно обратиться, записав s1[5]. Если, например, в s1 хранится слово «строка», то s1[4] вернёт символ «к».
На примере строки мы посмотрели, как усложняется описание типа. Непосредственно данным в памяти предшествует несколько байт, описывающих структуру этих данных.
Само обращение к данным происходит по ссылке (по адресу, который записан в переменной, объявленной как тип String).
Но и само описание структуры данных переменной сложного типа можно разместить отдельно от самих данных, оставив пере данными только ссылку на область памяти, где хранится описание (тип) структуры данных.
Записи являются как бы предшественниками такого типа данных, как объект.
Понятие «объект» как особый тип данных.
К полям записи обращаются по нотации «переменная_запись»«.»«имя_поля».
Такая же нотация характерна и для объекта. Вспомним, что компоненты Delphi — это объекты, встроенные в IDE (в среду разработки).
Но объекты принципиально отличаются от записей. Настолько же, насколько обычная переменная отличается от динамической.
Объекты содержат не только данные (которые в объекте называются полями), но и процедуры (и функции).
К этим процедурам можно обращаться с помощью всё той же нотации с «точкой», как и к полям с данными.
Например, вспомним, как мы очищали содержимое компонента Memo (удаляли из него весь текст).
Для этого мы использовали процедуру (в объектах встроенные процедуры называются методами!) Clear. Так как ей не нужны параметры, её можно писать без скобок, то есть вместо Clear() записать просто Clear.
Поэтому мы использовали следующее предложение:
Form1.Memo1.Clear;
Сам объект Memo1 создаётся по шаблону (типу) Tmemo.
Более того. Сами типы являются объектами, поставляемыми со средой IDE. В них содержится метод (процедура) Create, называемый конструктором.
Собственно, он и создаёт экземпляр объекта в программе по собственному образу и подобию. Объект — тип может быть только один в пределах видимости IDE. Но своих копий (экземпляров) он может создать сколько угодно (конечно, каждому экземпляру должно быть дано уникальное имя).
В программе экземпляр объекта оформляется как переменная объектного типа.
Здесь объявлены переменная Form1 три переменных типа Tmemo.
var Form1: Tform1; Memo1:TMemo; Memo2:TMemo; Memo3:TMemo; и так далее.
Tform1, Tmemo и другие встроенные в IDE объекты-типы называются Delphi компонентами. При размещении компонента на форму IDE вызывает конструктор объекта-типа автоматически при размещении компонента на форму.
Замечание. На будущее — типы, по которым создаются объекты, в объектном программировании называются «классами (Class)».
Работа с файлами важная вещь в любом языке программирования. Работа с файлами в Delphi позволяет считывать, сохранять информацию, и выполнять другие действия с файлами. В Delphi поддерживаются все операции с файлами - создание, поиск, чтение и запись, переименование как файлов, так и к директорий. В Delphi существует несколько способов работы с файлами.
Для "лирического" вступления нужно упомянуть компоненты Delphi, которые умеют работать с файлами. Они читают и сохраняют своё содержимое, строки типа String, в файл текстового формата. Это компоненты ListBox, ComboBox и Memo, расположенные на первой же вкладке палитры компонентов.
Каждая строка компонентов ListBox и ComboBox является объектом Items[i], а Memo - Lines[i], где i - номер строки, который отсчитывается от нуля. Добавление строк в компоненты выполняется методами Add и Insert:
begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;
Метод Add добавляет новую строку в конец. Метод Insert имеет дополнительный параметр, указывающий, после какой строки разместить новую строку. Доступ к строкам осуществляется так:
ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;
У компонента ComboBox дополнительно есть свойство Text, где (как и у компонента Edit) находится вводимый текст:
ComboBox1.Text := ' Вводимый текст ';
На выделенную в данный момент строку компонента ComboBox указывает свойство ItemIndex типа Integer, то есть это номер выделенной строки. Следовательно, получить саму выделенную строку компонента ComboBox можно следующей конструкцией:
или, пользуясь оператором присоединения
With ComboBox1 do
S:=Items[ItemIndex];
Вот как по нажатию клавиши Enter можно заносить в этот компонент вводимую в строку информацию и удалять нажатием Escape:
Выделите на Форме ComboBox и перейдите в Инспектор объектов, на вкладку Events. Щёлкните дважды по обработчику OnKeyPress. Система Delphi создаст заготовку обработчика. Напишите:
Ну а теперь собственно о сохранении содержимого в файл. Для этого выполните команду
ListBox1.Items.SaveToFile(' Имя_файла.txt ') ;
Впрочем, расширение можно поставить любое по желанию, не обязательно .txt, как и вообще без него обойтись. Но расширение .txt позволит легко открыть файл стандартным виндовским Блокнотом, что бывает очень удобно на этапе написания программы!
Для загрузки служит метод LoadFromFile:
ListBox1.Items.LoadFromFile(' Имя_файла.txt ') ;
Что делать, если в своей программе мы не работаем с компонентами Combobox, ListBox или Memo, а сохранять информацию нужно? Берём один из компонентов и делаем его невидимым, для этого в Инспекторе Объектов ставим в свойство Visible значение False. Функциональность его от этого не изменится!
Последний штрих - создадим программу, сохраняющую своё положение на экране в момент закрытия и там же открывающуюся. Нам нужно сохранить два параметра - значения свойств Формы Left и Top, это расстояние от левого и верхнего краёв экрана соответственно. Значения эти выражаются в пикселах и имеют тип Integer. Необходимо перевести эти числа в строку (тип String) с помощью оператора IntToStr. Итак, разместите на Форме невидимый ListBox, щёлкните по пустому месту Формы, чтобы её свйства появились в Инспекторе объектов, и перейдите на вкладку Events. Щёлкните по обработчику OnClose и в созданной заготовке напишите:
begin
ListBox1.Items.Clear;
ListBox1.Items.Add(IntToStr(Form1.Left));
ListBox1.Items.Add(IntToStr(Form1.Top));
ListBox1.Items.SaveToFile('MyFormPos.txt');
end ;
Этот обработчик сохраняет положение Формы на экране. Теперь напишем обработчик, помещающий Форму на прежнее место при старте программы. Создайте заготовку обработчика события OnCreate. Это событие происходит в момент "создания" Формы операционной системой. В этот момент и нужно присваивать ей необходимые свойства. Пишите:
begin
if FileExists('MyFormPos.txt') then
begin
ListBox1.Items.LoadFromFile('MyFormPos.txt');
Form1.Left:=StrToInt(ListBox1.Items[0]);
Form1.Top:=StrToInt(ListBox1.Items[1]);
end ;
end ;
В первой строке происходит проверка на существование файла, ведь если его не будет, произойдёт ошибка. Впрочем, программа после выдачи предупреждения откроется в том месте, где была на этапе проектирования, а при закрытии нужный файл будет воссоздан!
Затем в логических скобках begin / end содержится сам код, который будет выполнен только приналичии файла MyFormPos.txt в папке с программой, так как используется относительный путь. Можно указать конкретное местоположение, например, C:\Program Files\MyProg\MyFormPos.txt.
Проверку на существовование файла можно выполнить также с помощью контроля исключительных ситуаций. Если файл не существует, то произойдёт исключительная ситуация. Перехватив её с помощью специального оператора, мы сможем избежать ошибок в программе.
Конечно, профессиональные программы сохраняют своё положение в Реестре Windows. Но всему своё время.
Leha, добавлено 27.07.09, 09:30:54
Да. Великолепный пост. Добавил в мемориз. Mihan, добавлено 29.07.09, 08:24:43
Мда. Примерно тоже самое прочитал на севендей.ру. Уже много раз замечал. Такое ощущение, что они просто переписывают посты. Хотя. может меня и подглючивает . Автор, добавлено 29.07.09, 11:21:21
Робяты, ну никак понять не могу, почему все имена по-английски пишут!
Raven, добавлено 3.08.09, 14:49:46
Соглашусь с первым автором,и хочу сразу же задать вопрос.У меня в listbox выводится Имя а потом Номер в скобках тоесть вот так к примеру Елена(920*******) как сделать чтобы при нажатии на Елену в Edit записывался только номер Ответ, добавлено 3.08.09, 17:23:19
Можно вычислить номер символа "(" и скопировать текст от этого номера плюс один до номера символа ")" минус один. Как это делается, объяснять? Raven, добавлено 4.08.09, 11:10:38
Да объяснять=).Спасибо что ответили,я самоучка просто.Читаю книжку в данный момет библия для программиста в среде делфи,но пока ответа на свой вопрос там не нашел.Расскажите пожалуйста вы если не сложно.Заранее спасибо. Продолжаем разговор!, добавлено 4.08.09, 14:13:45
Нужно освоить работу со строками. Есть функция Pos, которая даёт позицию первого вхождения нужного символа. Копирование части строки производится функцией Copy. Вот как:
procedure TForm1.ListBox1Click(Sender: TObject);
var N1, N2, N3: Integer;
S: String;
begin
S:=ListBox1.Items[ListBox1.ItemIndex];
N1:=Pos('(', S); //Позиция символа (
N2:=Pos(')', S); //Позиция символа )
N3:=N2-N1; //Количество копируемых символов
Edit1.Text:=Copy(S, N1, N3);
end;
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
Не вышло? Ринат, добавлено 26.07.11, 14:18:08
Все получилось.
спасибо а как сделать чтоб сразу появлялась? без нажатия кнопки? Автор, добавлено 26.07.11, 14:26:54
Я так понимаю, что Delphi вы впервые видите. Так вот, в Delphi ничего само по себе не появляется. Всё происходит при выполнении какого-либо события. Нажатие кнопки Button, или кнопки на клавиатуре, или кнопки мышки, момента появления Формы на экране, изменения текста в компоненте и т.д.
Так что вы имеете в виду под словом "сразу"? В самом начале, при появлении программы? Ринат, добавлено 26.07.11, 21:04:38
Да, вы правы, с программированием я столкнулся впервые.
Я имел ввиду при появление формы на экране. Автор, добавлено 26.07.11, 21:16:14
Появление Формы на экране - это события такого объекта, ну или компонента, как Форма. Посмотрите, щёлкнув по пустому месту на Форме, слева Инспектор Объектов, в него загружены свойства Формы. В Инспекторе Объектов две вкладки - Properties (свойства) и Properties (события). Так вот, те события, на которые может реагировать Форма, находятся на вкладке Properties. За появление Формы на экране отвечает событие OnActivate, хотя лучше всё же воспользоваться OnCreate - событием создания Формы. Поместите в обработчик этого события вышеуказанные операторы.
procedure TForm1.Button1Click(Sender: TObject);
begin
MP1.DeviceType:=dtAutoSelect;
MP1.FileName:='имя_файла';
if not MP1.AutoOpen then MP1.Open;
MP1.Play;
end;
AVI сейчас допишу. Саша, добавлено 10.11.11, 18:19:55
А для этого не надо добавлять какие-то компоненты наподобие таймера или ещё чего-то? Автор, добавлено 10.11.11, 18:41:07
Чтобы просто был звук - больше ничего не надо. Но если вы хотите создать полноценный плейер, то конечно придётся что-то придумывать.
procedure TForm1.Button2Click(Sender: TObject);
begin
MP1.Display:=Panel1;
with OpenDialog1 do
if Execute then
begin
MP1.FileName:=FileName;
MP1.Open;
MP1.Play;
end;
end;
Тут нужно добавить OpenDialog, можно и в предыдущий пример его вставить. И ещё. Размер области воспроизведения, то бишь панели, нужно посмотреть заранее в свойствах файла, на вкладке "Сведения". Но лучше сделать панель побольше, и установить её свойство BevelInner и BevelOuter в bvNone, чтобы её было не видно. А то размеры у файлов разные.
Что касается формата *.3ds, то я не умею работать с 3d видео. Цельная книжка есть про это. Но, блин, изучению надо жизнь посвятить. Но если с вас требуют лабораторку, то наверное преподавали.
Вот, нашёл что нужно иметь модуль GLFile3DS. Он необходим для работы с форматом 3DS. Саша, добавлено 10.11.11, 19:17:47
Спасибо огромное! А что касается *.3ds то как я разговаривал с преподом, то он сказал что надо только показать грудо говоря jpg (или какую-то ещё) проэкцию этого файла но не редактировать его. может тут не надо того модуля? Автор, добавлено 10.11.11, 19:19:09
Не смогу по 3ds подсказать ничего. Звиняйте.
А про avi ещё. Чтобы масштабировать изображение, нужно воспользоваться свойством медиаплейера DispleyRect. Оно доступно только программно. Саша, добавлено 15.11.11, 04:10:29
Я случайно заметил одну особенность: если не создавать панель (Panel1) и не присваивать панели ничего дисплею, то видео выводится в отдельном окне со своим родным расширением.
Но без вопроса не обойдётся =) : как настроить полосу прокрутки для видео или же хотя бы для аудио? Понятно что нужен таймер и и ProgresBar, но как связать это всё во едино? Автор, добавлено 15.11.11, 09:00:43
Когда файл открыт, то свойство Mediaplayer.Length возвращает продолжительность трека в специфическом формате. Лучше всего предварительно задать отображение этой величины в миллисекундах:
Ну далее переводим в часы, минуты и секунды с помощью функции
function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Это что касается длины. А текущую позицию возвращает свойство. - правильно, Position! Измеряем по срабатыванию таймера и выводим в ProgressBar (лучше возьмите TrackBar). Опять же, свойство TrackBar.Max предварительно установите равным Mediaplayer.Length.
Есть проблемка с прокруткой. Чтобы прокрутить, нужно сначала остановить плеер, и таймер. А затем запустить с другим значением:
Я был удивлён, но TrackBar не имееет событий мыши. А то можно было бы останавливать по событию OnMouseDown. А впрочем, можно пользоваться событием OnEnter! Но запускать всё равно потом приходится.
А чтобы менять кадры при перемотке мышкой, придётся ввести второй таймер, чтобы работал когда воспроизведение останавливается, и задавал
MediaPlayer.Position:=TrackBar.Position;
Время срабатывания естественно сделать поменьше, а то будет тормозить.
Саша, добавлено 16.11.11, 18:59:41
Спасибо! =) Саша, добавлено 17.11.11, 01:24:40
Здравствуйте в очередной раз) Вот какая у меня проблема, когда открываю видео с помощью MedaiPlayer1, то функция Mediaplayer1.Length возвращяет уауое-то кривое значение (например продолжительность видео 40 мин. а возвращает значение примерно 1,17 мин.), но в случае с аудио файлами всё происходит нормально (то есть значение правильное). Но что самое интересное - видео проигрывается свыше возвращенного значения. В чём может быть дело? Автор, добавлено 17.11.11, 02:03:44
Странно. У меня фильм в программе определяется как 1 час 26 минут 55 секунд, с такой программой как Media Player Classic разница несущественная. Вот полный текст программы:
function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Может вы забыли формат длительности задать? Я закомментировал этот оператор, и продолжительность вместо полутора часов стала две минуты. Саша, добавлено 17.11.11, 03:32:39
Нет, он описан в процедуре TForm1.FormCreate. Но после того, как я удалил его от туда и прописал отдельно для каждой кнопки вызова медиа плеера - всё встало на свои места) Так-что спасибо) Саша, добавлено 20.11.11, 21:56:43
Автор, большое Вам спасибо за этот прекрасный сайт а особенно за ваши ответы на задаваемые вопросы! Я закончил то задание с *.3ds форматом, но дело сдвинулось с мёртвой точки только после того, как Вы написали что нуден модуль GLFile3DS. Как оказалось - это не совсем "сам по себе" модуль) Это часть проекта GLScene. Советую Вам хотя бы не много им поинтересоваться. Полезная вещь. Ещё раз огромное Вам спасибо за помощь и поддержку в трудной ситуации!
ПС
Если надумаете всё таки заняться этим GLScene-ом - то хорошо ищите как правильно его устанавливать. Даже на оф. сайте инструкция не совсем точная. Андрей, добавлено 18.12.11, 02:33:53
помогите, не получается сохранить файл.
пишу такод код, файла нет, ошибок тоже нет:
procedure TForm1.N3Click(Sender: TObject);
begin
with SaveDialog1, Memo1 do
if Execute then
Lines.SaveToFile('ф.txt');
CloseFile(SaveF);
end; Автор, добавлено 18.12.11, 06:59:18
Зачем вам диалог, если вы сохраняете в файл 'ф.txt' - его и ищите. Андрей, добавлено 18.12.11, 11:17:05
если писать вместо ф.txt, FilEname, как в вашем уроке, то файл не сохраняется. Помогите, что я не так делаю. Автор, добавлено 18.12.11, 15:44:10
Вот написали бы именно как делаете, я бы посмотрел. А так приходится гадать. Может, вы Filename в кавычках пишете. Тогда файл будет называться не как в диалоге вы задали, а именно Filename.txt Владимир, добавлено 11.01.12, 23:19:26
Спасибо за уроки начал недавно но кое что уже получается. Изучение затеял с целью
написания электронных тестов для учеников по химии. Однако столкнулся с такой проблемой как на форме разместить например H2O но чтобы 2 была маленькой. Понимаю что вопрос не в тему и может быть не простой но интересует общее направление поиска, больше не кого спросить. Заранее спасибо. Автор, добавлено 12.01.12, 08:30:21
Владимир, вариантов масса. В зависимости от того, как конструктивно построен тест, на каких компонентах. Ведь можно три метки Label рядом стоящие, размер - любой. Или можно картинку нарисовать и поместить в нужное место - компонент Image, или даже просто по Форме написать, на её канве. Владимир, добавлено 12.01.12, 21:23:09
Спасибо буду пробовать. Александр, добавлено 1.05.12, 14:03:59
создал на форме все как положенно, с такимеже названиями.
в код после implementation вставил
begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;
но почему-то не работает, при запуске выдает ошибку Александр, добавлено 1.05.12, 15:31:21
аааааааа, надо по форме два раза щелкнуть и писать, понял!! Александр, добавлено 1.05.12, 17:11:13
выручайте.
написал через add все отлично, затем использовал команду Insert.
вылетает ошибка "Debugger exception notification Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0056D0FD in modul 'Project1.exe'.Read of address 0000030C.Process stopped. Use Step or Run to continue."
Аноним, добавлено 1.05.12, 17:36:26
В ошибках разбираться недосуг. Вот как надо:
Memo1.Lines.Insert(0, 'Первая строка');
Александр, добавлено 1.05.12, 17:44:33
вы же в самом начале урока говорите что вот так:
ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;
я это копирю вставляю в программу и вылазит ошибка Александр, добавлено 1.05.12, 17:54:49
и не понятно почему
Каждый программист должен уметь работать с текстовыми файлами, файлами, содержащими записи, и файлами, которые не имеют определенной структуры или обрабатываются так, как если бы они не имели структуры. Вначале мы рассмотрим текстовые файлы, поскольку этот тип файлов используется наиболее часто.
Для получения доступа к текстовым файлам служат переменные типа Text:
Прежде чем можно будет приступить к работе с файлом, с помощью процедуры AssignFile его нужно присвоить переменной типа Text. Эта процедура принимает два параметра: переменную файла и имя файла.
После того как имя файла присвоено переменной файла, необходимо определить действия, которые нужно выполнять с файлом. Файл можно подготовить к чтению, записи или дополнению.
Чтобы подготовить файл к записи, необходимо использовать процедуру Rewrite, которая всегда создаст новый пустой файл. Если файл с таким же именем файла уже существует, процедура Rewrite вначале удаляет существующий файл, а затем заменяет его новым пустым файлом. Затем процедура открывает файл и устанавливает указатель позиции на начало файла.
При работе с текстовыми файлами процедуре Rewrite необходимо передавать только переменную типа Text:
Когда файл открыт и готов к записи, для записи текста в текстовый файл можно использовать стандартную процедуру WriteLn. При выполнении записи в текстовый файл первым параметром, переданным процедуре WriteLn, должна быть переменная файла:
По завершении работы с файлом его всегда следует закрывать, чтобы обеспечить корректное сохранение файла на диске и освободить любую память, занятую в процессе записи. Для закрытия файла служит процедура CloseFile, принимающая единственный параметр — файл, который нужно закрыть:
Пример программы записи строки текста в текстовый файл приведен в листинге 8.1.
Листинг 8.1. Запись текста в текстовый файл
Для подготовки файла к чтению используется процедура Reset. Эта процедура, подобно процедуре Rewrite, принимает только параметр типа файла. Ее можно считать безопасной в том смысле, что она успешно работает, если дисковод и/или каталог, указанный в имени файла, существует. В отличие от Rewrite, выполнение процедуры Reset будет невозможным, если файл, присвоенный переменной файла, не существует.
Для выполнения чтения данных из текстового файла можно использовать процедуру ReadLn. При этом первым передаваемым процедуре параметром должна быть переменная файла, а вторым — строковая переменная, которая будет временно хранить значение, считанное из файла.
Следующий пример демонстрирует считывание значений из текстового файла и их отображение на экране.
Листинг 8.2. Считывание текста из текстового файла
Этот код будет успешно работать до тех пор, пока существует файл data. txt. Если этот файл не существует, программа даст сбой. Во избежание остановки приложения при отсутствии файла необходимо выполнять проверку успешности открытия файла с помощью процедуры Reset.
Для выяснения наличия ошибок ввода-вывода необходимо непосредственно после вызова процедуры ввода-вывода, такой как Rewrite или Reset, вызвать функцию IOResult. Функция IOResult возвращает результат последней выполненной операции ввода-вывода. Если IOResult возвращает 0, это означает, что операция была выполнена успешно.
Для выполнения проверки ввода-вывода с помощью функции IOResult необходимо вначале отключить автоматическую проверку ввода-вывода. Для включения и отключения проверки ошибок ввода-вывода служит директива компилятора SI. Обычно автоматическую проверку ввода-вывода отключают перед вызовом процедуры ввода-вывода и снова включают сразу после выполнения этого вызова:
Следующий пример иллюстрирует выполнение проверки ввода-вывода и считывание текста из файла только в случае успешного его открытия.
Листинг 8.3. Проверка ошибок ввода-вывода
Помните, что после обращения к процедуре ввода-вывода функцию IOResult можно вызывать только один раз. Это обусловлено тем, что она сбрасывает результат выполнения последней операции ввода-вывода в 0. Поэтому, если вызвать функцию IOResult дважды подряд, первое обращение к ней правильно сообщит об ошибке, но второе обращение сообщит (ошибочно), что операция была выполнена успешно.
Когда нужно выполнить считывание всего текстового файла, его необходимо считывать последовательно до достижения конца файла. Для определения конца файла служит функция Eof. Эта функция принимает единственный параметр файла и возвращает булевское значение, указывающее, был ли достигнут конец файла:
Как правило, наиболее рациональный способ считывания текстового файла предусматривает использование цикла while, продолжающего итерации вплоть до достижения конца файла. Следующий пример иллюстрирует копирование содержимого одного текстового файла в другой с использованиемцикла while not Eof (результаты можно видеть на рис. 8.1).
Листинг 8.4. Копирование текстового файла
Рис. 8.1. Копирование текстового файла
Простейший способ считывания всего файла в память — его считывание в динамический массив строк. Для этого необходимо знать количество строк текста в файле. Поскольку никаких стандартных функций для выполнения этой задачи не существует, потребуется создать такую функцию. Для вычисления количества строк в текстовом файле необходимо в цикле while not Eof подсчитать количество строк в файле, а затем вызвать процедуру Reset, чтобы вернуться к начальной позиции файла.
В следующем примере цикл while not Eof в функции GetLineCount используется для получения количества строк текстового файла. Полученный результат затем используется в вызове функции SetLength для изменения размера динамического массива.
Листинг 8.5. Загрузка текстового файла в динамический массив
Как только приложение загрузило весь текстовый файл в динамический массив, файл можно закрыть и продолжить работу со строками в памяти. Конечно, со строками в массиве можно выполнять любые действия, но этот код всего лишь с помощью функции Uppercase преобразует (временно) символы строк в прописные и отображает их на экране.
Типизированные файлы представляют собой двоичные файлы, которые содержат элементы одинакового размера. Обычно типизированные файлы — это файлы, содержащие записи. Чтобы создать типизированный файл, вначале, используя следующий синтаксис, необходимо создать новый файловый тип данных:
В следующем коде продемонстрировано создание нового файлового типа, который можно использовать для считывания и записи записей в типизированном файле:
Обратите внимание, что строковые поля в объявлении записи имеют явно определенную длину. Длина строки должна быть определена явно, поскольку размер всей записи должен оставаться постоянным. Если требуется сохранить запись в файле на диске, обычные строки использовать нельзя, поскольку их длина может изменяться в любое время и компилятор не может определить их длину во время компиляции.
Существует несколько различий между текстовыми и типизированными файлами:
- При сбросе типизированного файла в нем можно выполнять считывание и запись (при сбросе текстового файла в нем можно выполнять только считывание).
- При выполнении считывания или записи из типизированного файла необходимо использовать процедуры Read и Write, а не ReadLn и WriteLn.
В листинге 8.6 демонстрируется работу с типизированными файлами.
Листинг 8.6. Работа с типизированными файлами
Еще одно существенное различие между текстовыми и типизированными файлами состоит в том, что в то время как текстовые файлы допускают только последовательный доступ, типизированные файлы допускают произвольный доступ к записям файла. Произвольный доступ возможен вследствие того, что все записи в файле имеют одинаковый размер, поэтому для считывания конкретной записи процедуре достаточно пропустить определенное, легко определяемое количество байт.
Для определения количества записей в файле можно использовать функцию FileSize. Для перехода к определенной записи в файле можно использовать процедуру Seek. Эта процедура принимает два параметра: переменную файла и целочисленное значение, указывающее номер записи (начиная с О), к которой необходимо выполнить переход.
Нетипизированные файлы — это файлы без определенной структуры. В общем случае, нетипизированные файлы — это типизированные файлы, в которых вместо записей используются байты. Объявление переменной нетипизированного файла выглядит следующим образом:
При работе с нетипизированными файлами обращения к процедурам Reset и Rewrite выглядят несколько иначе. Обычно обе эти процедуры в качестве заданного по умолчанию размера записи используют 128 байт. При работе с нетипизированными файлами этот размер должен быть установлен равным 1 байту. Это можно выполнить, передавая 1 в качестве второго параметра в обоих вызовах:
Для считывания и записи данных в нетипизированные файлы применяются процедуры BlockRead и BlockWrite. Объявления этих процедур показаны ниже:
Первый параметр — переменная нетипизированного файла, используемая для доступа к файлу на диске. Второй параметр — буфер, который процедуры используют для передачи данных в файл и из него.
Обычно этот буфер представляет собой статический массив байтов, но он может быть также и записью. Третий параметр указывает количество передаваемых байтов. Обычно это число равно размеру массива, который легко определить с помощью функции SizeOf. Необязательный параметр-переменная AmtTransferred можно использовать для отслеживания точного числа байтов, переданных в файл и из него.
Приложение, код которого представлен в листинге 8.7, использует процедуры BlockRead и BlockWrite для предоставления пользователю возможности копирования файлов. Приложение также дает пользователю возможность указывать имена исходного и целевого файлов в командной строке, как показано на рис. 8.2.
Рис. 8 .2. Передача параметров приложению
Листинг 8.7. Копирование файлов с помощью процедур BlockRead и BlockWrite
Для выяснения количества параметров, которые пользователь передал приложению, применяется функция ParamCount. Эта функция не принимает никаких параметров и возвращает значение 0. если пользователь вызвал приложение без дополнительных параметров.
Для считывания параметров, переданных приложению, служит функция ParamStr, которая принимает единственный параметр типа Integer — индекс параметра. Если передать этой функции значение О, она возвратит путь и имя файла приложения. Индексы пользовательских параметров, если они переданы, начинаются с 1.
Вначале приложение проверяет, передал ли пользователь два параметра в командной строке. Если да, то ParamStr (1) содержит путь к исходному файлу, а ParamStr (2) — путь к файлу назначения.
Копирование выполняется в процедуре BlockCopyFile.
Ее первая строка:
использует функцию LowerCase для временного преобразования имен обоих файлов в строчные буквы и проверяет, указывают ли оба имени файлов на один и тот же файл. Если файл назначения и файл-источник совпадают, никакое копирование не требуется и оператор if-then вызывает процедуру Exit для выхода из процедуры.
Основная часть процедуры BlockCopyFile — цикл while, который вызывает процедуры BlockRead и BlockWrite:
Процедура BlockRead считывает из файла 1 Кбайт данных, записывает эти данные в массив Buffer и обновляет переменную BytesRead, которая всегда содержит точное количество переданных байтов. Выполнение цикла будет повторяться до тех пор, пока процедура BlockRead продолжает считывать данные из файла. Когда эта процедура достигнет конца файла, значение переменной BytesRead будет сброшено в 0, условие цикла while станет ложным и копирование файла завершится.
Читайте также: