Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Общие принципы работы с файламиСодержание книги
Похожие статьи вашей тематики
Поиск на нашем сайте
В предыдущих примерах мы сохраняли текст в файл и считывали текст из файла при помощи свойств: Memo1.Lines.SaveToFile() Memo1.Lines.LoadFromFile() Этот метод удобен и хорош, однако он не позволяет нам контролировать весь процесс записи в файл и чтения из файла. То есть, эти функции весь процесс чтения и записи выполняют скрыто от нас. Однако бывает, когда программист испытывает необходимость контроля этих процессов, кроме того, не для всех типов эти функции доступны. Например, у нас есть текст в строковой переменной. Мы уже говорили, что строковая переменная может хранить почти неограниченное количество символов, то есть в переменную мы можем записать весь текстовый файл, включая и символы перехода на другую строку и возврата каретки (#13 #10). С функциями SaveToFile() и LoadFromFile() могут работать данные, которые имеют тип TStrings, а простые строки не могут их вызывать. Поэтому приходится делать записи в файл напрямую, и также напрямую их считывать. Для работы с файлами многие программисты предпочитают использовать функции WinAPI. Несмотря на грозное звучание, ничего особо сложного в этих функциях нет, тем не менее, такие функции имеют один крупный недостаток. Корпорация MicroSoft постоянно вносит какие-то изменения в свои операционные системы. Так, в первых версиях Windows, для чтения файлов использовалась функция WinAPI _lread. Потом появилась функция ReadFile и Microsoft стала рекомендовать использовать в программировании именно ее. А затем появилась функция ReadFileEx, которая позволяет работать с файлами больших размеров. После каждого изменения этих функций очень часто приходится переделывать всю программу, чтобы она могла работать с новой операционной системой. А это отнимает много времени и создает дополнительные неудобства и для программистов, и для пользователей. Поэтому в Delphi рекомендуется использовать встроенный специализированный объект TFileStream. Если Microsoft введет какие-то новшества, Borland учтет их в объекте, и нам останется лишь перекомпилировать нашу программу, не меняя ее кода. Кроме того, использование TFileStream намного проще, чем функции WinAPI. TFileStream - это объект, и как каждый объект, его нужно вначале объявить, а затем проинициализировать. Первым делом необходимо создать переменную типа TFileStream: var f: TFileStream; Таким образом, мы объявили переменную типа объект TFileStream, и в дальнейшем можем работать с этой переменной, как с объектом. То есть, указывать имя этой переменной, а после точки выбирать свойства, методы и события этого объекта. Однако объявить переменную мало, требуется еще проинициализировать ее. f:= TFileStream.Create(параметры); У метода Create объекта TFileStream может быть три параметра, причем третий параметр необязателен, его можно не указывать. Разберемся с этими параметрами. Имя файла – этот параметр – простая строка, которая может содержать только имя файла, или полное имя файла, включая и адрес. Режим открытия. Здесь можно указать один из следующих параметров:
Права, с которыми будет открыт файл. Этот параметр необязателен, его можно не указывать. Он имеет следующие возможные значения:
Пример: f:= TFileStream.Create('C:\MyFile.txt', fmOpenReadWrite, fmShareExclusive); Для чего нужны права доступа к файлу? Например, текстовый файл может быть открыт стандартной программой "Блокнот", этот же файл мы можем открыть из нашего собственного текстового редактора. Редактор менеджера файлов FAR также может открыть этот текстовый файл. И программа MS Word тоже может его открыть! Теперь предположим, что наша программа делает запись в файл. В это же самое время какая-то другая программа также сохраняет изменения в этом файле. Наша программа сделала изменения и закрыла файл, а другая программа даже не подозревает об этих изменениях, и просто перезаписывает файл со своими изменениями. Таким образом, наши изменения просто теряются! То же самое может произойти, если ваша программа выполнена в сетевом варианте. Например, есть какой-то специальный файл, в который сотрудники отдела записывают свои изменения. Этот файл может находиться на каком-то сетевом диске, и доступ к этому файлу имеет каждый сотрудник. И у каждого сотрудника установлена ваша программа. Таким образом, если одновременно двое сотрудников будут производить изменения в файле, то данные одного из них потеряются, так как программа другого перезапишет файл без учета этих изменений. Если вы пишете однопользовательскую программу, и доступ к файлу будет иметь только она, то про третий параметр можете вовсе забыть. После того, как Вы создали объект, проинициализировали его и поработали с ним, файл нужно закрыть и освободить память, занимаемую этим объектом. Для этого достаточно вызвать метод: f.Free; Теперь осталось разобраться со структурой файла, и методами чтения из него, и записи в него. Начнем со структуры. Когда вы только открыли файл, позиция курсора устанавливается на начало, и любая попытка чтения или записи будет применена к этой позиции курсора. Чтобы прочитать (записать) в другую позицию, требуется передвинуть курсор. Для этого используют методSeek, который имеет два параметра:
Итак, чтобы передвинуть курсор от начала файла на 10 байт, нужно выполнить команду: f.Seek(10, soFromBeginning); Метод Seek – это функция, она всегда возвращает количество байт смещения от начала файла. Этим свойством можно воспользоваться, чтобы узнать общее количество байт в файле: Размер_Файла:= f.Seek(0, soFromEnd); Правда, если нам требуется просто посмотреть размер файла, то этот трюк не совсем подходящий: нам придется открыть файл, переместиться в его конец, и затем закрыть его. Как узнать размер файла более подходящим способом, узнаем позже. Для чтения из файла нужно использовать метод Read, у которого тоже есть два параметра:
Разберем пример чтения из файла 10 символов, начиная с 15-й позиции: var f: TFileStream; //объявляем переменную buf: array [0..10] of Char; //буфер для хранения прочитанных данных begin //открываем файл filename.txt для чтения и записи: f:= TFileStream.Create('c:\filename.txt', fmOpenReadWrite); //перемещаемся на 15 символов вперед: f.Seek(15, soFromBeginning); //читаем в буфер 10 символов из установленной позиции: f.Read(buf, 10); Memo1.Lines.Add(buf); //скопировали эти 10 символов в Memo //уничтожаем объект и тем самым закрываем файл: f.Free; end; Метод Read возвращает количество реально прочитанных байт. Оно должно быть равно тому количеству байт, которые мы указали при вызове этого метода. Есть две причины, по которым это количество может быть не равно указанному: 1. При чтении был достигнут конец файла, и функция прочитала меньше байт, чем планировалось. 2. Ошибка на диске или любая другая проблема. Для записи в файл используется метод Write. Есть два параметра и у него: 1. Переменная, содержимое которой нужно записать. 2. Число байт для записи. Пользоваться методом записи можно точно также, как и методом чтения. Примечание: после чтения или записи позиция курсора смещается на количество прочитанных или записанных байт. То есть, позиция курсора устанавливается после прочитанного или записанного блока. В следующей лекции мы продолжим изучение работы с файлами. Лекция 20. Работа с файлами В этой лекции вы познакомитесь с методами обработки файлов, узнаете три типа файлов, которые можно обрабатывать в Delphi. Изучите много функций и процедур, напишите программу для копирования файла. Файлы Под словом файл в Delphi (и в любом языке программирования) понимается область внешней памяти ПК (жесткий диск, дискета, компакт- диск и т.п.), которая имеет имя. Файлы в Delphi могут обрабатываться различными способами, в том числе и через функции WinAPI. Файлы могут быть трех вариантов: 1. Типизированные. Такие файлы принадлежат к какому-то типу данных, и могут работать только с ним. Это очень удобно для создания файлов записей. Такие файлы мы будем изучать чуть позже. 2. Текстовые файлы. Такой тип файлов предназначен для работы с текстом. 3. Нетипизированные файлы. Предназначены для побайтовой работы с файлами любого типа. Например, такой тип удобно использовать для копирования файла, его переноса или переименования. Файлы объявляются следующим образом: var f1: File of <тип>; //типизированные файлы f2: TextFile; //текстовый тип файлов f3: File; //нетипизированные файлы Однако, присвоив какой-то переменной файловый тип, мы еще не можем работать с файлом. Для этого мы вначале должны связать эту переменную с файлом. Делается это следующим образом: AssignFile(f1, 'filename.txt'); //связывание переменной с файлом После этой функции, мы можем обращаться с переменной f1 как с файлом filename.txt. Однако, если такого файла нет, мы получим ошибку, поэтому перед использованием связывания желательно делать проверку на наличие файла. Такая проверка проводится функцией FileExists(). Ее синтаксис следующий: FileExists('c:\01\myfile.txt'); В качестве параметра в функцию передается адрес файла и его имя. Можно передавать только имя, но тогда программа будет искать файл в текущей директории. Функция возвращает True, если такой файл существует, и False в противном случае. Поэтому мы можем использовать ее для проверки наличия файла: adres:= 'c:\01\myfile.txt'; if FileExists(adres) then begin AssignFile(f1, adres); //связали файловую переменную с файлом … //дальнейшая работа с файлом end; //if В дальнейшем, при работе с файлом, может возникнуть исключительная ситуация. Внимание! Такой термин мы встречаем в первый раз, однако он очень важен для понимания. Что такое исключительная ситуация? Это любая ошибка программы, которая может произойти во время работы. Например, вы открыли какой-то сетевой файл и начали работу с ним. А другой пользователь в это время взял, да удалил этот файл. При попытке чтения из несуществующего файла, или записи в него, произойдет ошибка и создастся исключительная ситуация. Если вы не обработаете эту ошибку, то компьютер, скорее всего, намертво повиснет. Поэтому в любой ситуации, когда имеется риск возникновения исключительной ситуации, программист ВСЕГДА должен ее обработать. Для этого существует блок try-finally-end: try //блок кода, в котором может произойти ошибка finally //код, который должен выполниться в любом случае, //например, код закрытия файла end; //try Если наша программа совершила непоправимую ошибку, то код, заключенный в блоке finally выполнится в любом случае. Таким кодом обычно делают закрытие файла. Если даже ошибка и совершится, файл все равно будет закрыт и программа не повиснет, а будет продолжать работу. Приучите себя ВСЕГДА использовать этот блок при работе с сомнительным кодом. Как бы хороша ни была программа, всегда найдется пользователь, который заставит ее сделать ошибку. Давайте создадим проект, который будет копировать файл в другое место, и на этом примере познакомимся с реальной работой с файлами. Создаем новый проект. Устанавливаем на форму Edit, в поле которого будем писать, куда мы хотим копировать файл. Также над ним можно установить Label, в котором введем: "Укажите папку, куда мы будем копировать". Устанавливаем на форму кнопку, на которой пишем "Копировать файл". Также с вкладки Dialogs устанавливаем на форму компонент OpenDialog, чтобы мы могли выбрать файл для копирования.
Рис. 20.1. Внешний вид приложения Далее, нам осталось обработать нажатие на кнопку. Все наши действия по открытию файла и его копированию будут происходить в процедуре нажатия на кнопку. Вот полный листинг этой процедуры: procedure TForm1.Button1Click(Sender: TObject); var fFrom, fTo: File; //нетипизированные файл-источник, и файл-копия colRead, colWrite: Integer; //количество прочитанных и записанных байт buf: array [1..2048] of Char; //буфер символов для копируемого текста filename: string; //переменная с адресом и именем файла begin //если нет адреса, куда копировать, то выходим if Edit1.Text = '' then begin ShowMessage('Укажите папку, куда нужно копировать файл!'); Edit1.SetFocus; Exit; end; //if
//если не выбрали файл, то выходим if not OpenDialog1.Execute then Exit; //смотрим адрес и имя файла: filename:= OpenDialog1.FileName;
try //связываем переменные с файлами: AssignFile(fFrom, filename); //откуда AssignFile(fTo, Edit1.Text+'\'+ExtractFileName(filename)); //куда
//открываем файл для чтения: Reset(fFrom, 1); //открываем файл для записи: Rewrite(fTo, 1);
//обнуляем переменные colRead:= 0; colWrite:= 0;
//копируем, пока не наступит конец файла: while colRead = colWrite do begin BlockRead(fFrom, buf, SizeOf(buf), colRead); if colRead = 0 then break; BlockWrite(fTo, buf, colRead, colWrite); end; //while
finally //закрываем файлы CloseFile(fFrom); CloseFile(fTo); ShowMessage('Файл скопирован!'); end; //try end; Теперь разберем этот код и познакомимся с новыми функциями. После того, как с помощью функций AssignFile() мы связали переменные с файлами, откуда мы собираемся копировать, и куда, мы пользуемся функциями Reset и Rewrite. Reset открывает файл только для чтения. Все попытки изменить такой файл приведут к ошибке. При открытии файла указатель (курсор) устанавливается на начало файла. Эта функция работает немного по- разному с разными типами файлов. В случае нетипизированного файла, функция Reset имеет два параметра – файловую переменную и длину записи в байтах. Мы указали в примере, что наша запись – 1 байт. Так удобней для обработки кода. Rewrite имеет такие же параметры, что и Reset, но она открывает файл для записи. Причем если файла нет, то он создается, а если есть – перезаписывается. Указатель также устанавливается в первую позицию. Далее мы "обнулили" переменные типа Integer. Об этих переменных речь впереди, а пока нам нужно, чтобы они были равны друг другу и имели значение 0. Дальше мы начинаем условный цикл while, где проверяется равенство этих двух переменных. А вот дальше идет интересная функция BlockRead. Она предназначена для работы только с нетипизированными файлами, для работы с файлами другого типа используют функцию Read и Readln. Функция BlockRead считывает информацию сразу блоками, что значительно ускоряет процесс копирования файлов. Эта функция имеет четыре параметра, причем последний необязателен. Разберемся с этими параметрами. 1. Переменная файлового типа, ранее связанная с файлом функцией AssignFile(). 2. Буфер, куда будут записываться прочитанные данные. Поскольку файл нетипизирован, данные могут быть любого типа – символьные, как в текстовом файле, или двоичные, как в программе, то есть, исполняемом файле. В качестве буфера у нас служит массив символов, куда мы эти данные и считываем. Чем больше такой массив, тем больше данных запишется за один раз, и тем быстрее будет происходить копирование. Однако увлекаться увеличением буфера тоже не стоит. В данном случае мы использовали такой размер, какой указан в справочной системе самой Delphi по функции BlockRead. Дальнейшее увеличение размера буфера не приносит заметных преимуществ. 3. Количество байт, которые нужно прочитать. Здесь мы использовали функцию SizeOf(), которая возвращает размер массива. Тем самым мы указали, что нужно прочитать максимальное количество байт, которое поместится в этот массив. 4. Необязательный параметр – это переменная целого типа. После чтения данных, в эту переменную заносится количество реально прочитанных байт. Вообще-то количество реально прочитанных байт должно соответствовать количеству указанных байт, которые нужно прочитать. Однако есть несколько исключений. Во-первых, может произойти ошибка чтения данных. Во-вторых, размер реально прочитанных байт может быть меньше заявленного размера, если мы прочитали файл до конца, и последний прочитанный кусочек оказался меньше, чем размер буфера. И в-третьих, он может вовсе равняться нулю, если курсор (указатель) стоит на конце файла. Итак, мы вызываем функцию BlockRead. Мы указываем файл, из которого нужно читать, буфер, куда нужно поместить прочитанные данные, указываем количество байт, которые нужно прочитать, и даем переменную, куда запишется количество реально прочитанных байт. И если мы прочитали 0 байт, это означает, что мы добрались до конца файла. В этом случае мы выполняем директиву break, которая заканчивает цикл while. Если же количество прочитанных байт больше нуля, значит, в буфере есть прочитанные данные, следовательно, их нужно записать. Для этого мы вызываем процедуру BlockWrite, которая имеет такие же параметры, но не читает данные, а записывает их. Посмотрите, в качестве третьего параметра мы используем переменную colRead, в которой хранится количество прочитанных ранее байт. То есть, если в последнем кусочке у нас оказалось меньше байт, чем мы можем поместить в буфер, значит, такое же количество мы должны записать. Вот и все премудрости копирования файлов! Не забываем, что работа файла нередко приводит к ошибке, поэтому ее нужно поместить в блок try..finally..end. В дальнейшей практике, при необходимости копировать файл желательно прибегать именно к такому способу, как к более быстрому и надежному. В нашем примере осталось пара недостатков. Как копирование файла выглядит с точки зрения пользователя? Он полагает, что, отдав программе команду копировать, он получает точную копию файла, равную оригиналу во всем. А как копирование файла выглядит с точки зрения программиста? Программист понимает, что он открывает исходный файл, откуда будет брать данные, и создает новый файл, куда эти данные он потом запишет. Все хорошо, вот только дата и время создания файла будут разные – копия будет иметь текущую дату. Особой роли это не играет, однако иногда нужно и дату присваивать ту, которую имеет исходный файл. Как это сделать, мы поговорим на следующей лекции. Второй недостаток: мы твердо полагаем, что пользователь ввел в поле Edit адрес в таком формате: C:\MyDir Затем к этому адресу мы добавляем обратный слэш ("\"). А если он сам уже поставил его?: C:\MyDir\ Тогда, в результате кода AssignFile(fTo, Edit1.Text+'\'+ExtractFileName(filename)); //куда Мы получим ошибку, так как имя файла может выглядеть так: "C:\MyDir\\myfile.dat". Попробуйте самостоятельно организовать проверку на наличие обратного слэша в конце адреса. Например, if Edit1.Text[Length(Edit1.Text)] <> '\' then Edit1.Text:= Edit1.Text + '\'; А затем прибавлять имя файла к адресу уже без этого знака: AssignFile(fTo, Edit1.Text+ ExtractFileName(filename)); //куда Перенос файла осуществляется точно так же, однако после того, как мы скопировали файл, и закрыли оба файла, исходный файл нужно удалить. Для этого существует функция DeleteFile(), в качестве параметра которой мы указываем адрес и имя удаляемого файла. В нашем примере мы можем указать OpenDialog1.FileName. Функция вернет истину, если удаление произошло успешно, и ложь в противном случае. Лекция 21. Записи В этой лекции вы познакомитесь с записями. Записи – очень удобный тип, важность которого трудно переоценить. Вы создадите свой тип записи, глобальную переменную этого типа, и даже типизированный файл, в который будете сохранять эту запись, и считывать ее. Записи Запись – это структура данных, состоящая из полей различного типа. Можно сказать, что запись – это мини-объект, который имеет свойства, но не имеет методов и событий. Для чего нужны записи? Да много для чего. Их можно использовать для сохранения настроек программы вместо ini-файлов, из записей можно сделать небольшую базу данных на пользователей программы, и так далее. Использование записей ограничено только воображением программиста. Записи объявляются в разделе type перед разделом var, и могут быть как локальными для процедур и функций, так и глобальными. Разумеется, если вы используете записи для сохранения параметров программы, желательно их делать глобальными. В языке C / C++ такой тип называется структурой, а в Delphi – записью. Синтаксис объявления записи следующий: type <имя_записи> = record ...; //описание полей end; //record Однако мало описать такую запись, потом нужно еще объявить переменную типа этой записи: var myPerem: имя_записи; В дальнейшем можно обращаться к отдельным полям записи, указывая эту переменную: myPerem.имя_поля Давайте посмотрим, как можно сохранить в записи размеры и положение формы. Создайте новый проект. Перед разделом глобального блока var создайте раздел type. Неважно, что выше уже есть такой раздел, мы можем создать еще один, главное, чтобы он был перед var. type myForm = record Left: Integer; Top: Integer; Width: Integer; Height: Integer; end; // record Теперь у нас есть описанная запись myForm, в которой имеется 4 поля: Left, Top, Width и Height. Как вы уже догадались, в эти поля мы будем записывать положение и размеры формы. Теперь внимание! Запись – это фактически новый тип данных! Мы можем объявить сколько угодно переменных типа myForm, а также использовать типизированный файл, присвоив ему тип myForm. Посмотрите на следующие примеры: var perem: myForm; //переменная нашего типа ar: array [0..10] of myForm; //массив f: File of myForm; //типизированный файл Вернемся к нашему проекту. Ниже записи имеется глобальный раздел var, где описана переменная Form1. Ниже ее добавим еще одну переменную: myF: myForm; Теперь мы можем при разрушении формы создать двоичный файл, в котором будут сохраняться положение и размер формы. Создайте обработчик событий onDestroy для формы, и в нем напишите следующий код: var f: File of myForm; //типизированный файл begin //сохраняем данные в запись: myF.Left:= Form1.Left; myF.Top:= Form1.Top; myF.Width:= Form1.Width; myF.Height:= Form1.Height;
//создаем или перезаписываем файл: try AssignFile(f, 'my.dat'); Rewrite(f); Write(f, myF); finally CloseFile(f); end; // try Обратите внимание, что мы не делаем проверку на существование файла, поскольку если файла нет, он будет создан, а если есть – перезаписан. Кроме того, в качестве имени мы используем строку 'my.dat'. Файл с таким именем будет создан в текущей папке. Поскольку наша программа не меняет папок, то текущей будет являться та, в которой находится программа. Сохраните проект, скомпилируйте, посмотрите, как работает программа. Закройте ее и файловым менеджером перейдите в папку с проектом. Посмотрите, появился ли файл my.dat, попробуйте его прочитать. Как видите, данные в файле хранятся в двоичном виде, что-либо прочитать там довольно сложно. Иногда удобней пользоваться таким способом, потому что всегда может найтись пользователь, который попытается играть с настройками в текстовых файлах. Ini – файлы имеют текстовый тип, и пользователь будет иметь возможность изменять там настройки вручную. Неважно, если мы сохраняем только размеры и положение формы, но мы можем сохранять и другие, более серьезные параметры! Однако пароли напрямую сохранять не получится – текст все же будет виден. Насчет текста... Тип string имеет динамический характер. Другими словами, размер переменной такого типа может изменяться в процессе работы программы. Тип динамического характера (строка String или динамический массив) можно указать в записи, однако его нельзя использовать в типизированном файле, так как размер поля должен быть заранее известен. Перейдем в раздел, где мы описывали наш тип данных. После описания поля Height опишем еще одно поле: Caption: String[50]; //размер строки задан жестко, его можно использовать в файле Теперь перейдем в обработку события onDestroy, и добавим строку: myF.Caption:= Form1.Caption; в разделе сохранения данных в запись. Еще раз сохраните, откомпилируйте и запустите программу. Закройте ее и посмотрите на файл my.dat. Как видите, надпись в заголовке формы появляется в файле без изменений, так что любые ваши пароли все-таки можно будет прочитать. Измените заголовок формы, снова скомпилируйте проект и посмотрите в файл – строка по-прежнему читается. Теперь нам нужно при открытии формы применить все эти настройки. Если вы помните пример с ini – файлом, настройки мы применяли в событии формы onCreate, также поступим и здесь. Создайте это событие для формы. Здесь нам придется проверять наличие файла – ведь если программа запускалась у клиента впервые, то файла там еще не было, он будет создан при закрытии программы. Поэтому будем применять настройки в том случае, если файл существует. var f: File of myForm; begin //если файла нет - выходим: if not FileExists('my.dat') then Exit;
//открываем файл и считываем настройки в запись: try AssignFile(f, 'my.dat'); Reset(f); Read(f, myF); //считываем запись в нашу глобальную переменную finally CloseFile(f); end; //try
//применяем полученные настройки: Form1.Left:= myF.Left; Form1.Top:= myF.Top; Form1.Height:= myF.Height; Form1.Width:= myF.Width; Form1.Caption:= myF.Caption; end; Конечно, в типизированный файл можно сохранять более одной записи, однако такой прием мы изучим после того, как познакомимся с динамическими массивами. Такой способ сохранения параметров кажется менее удобным, чем ini-файлы, однако компенсируется тем, что здесь можно сохранять данные любого типа – строки и даты, целые и вещественные числа, логические данные и даже массивы. Самостоятельно измените программу. Добавьте на форму один CheckBox, состояние которого (включен или нет) будем сохранять в файл. Добавьте в запись еще одно поле логического типа, и в зависимости от того, установлена ли галочка в CheckBox, записывайте в него либо True, либо False.
|
||||
Последнее изменение этой страницы: 2017-02-07; просмотров: 411; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.148.115.43 (0.013 с.) |