Delphi создать файл если не существует
var F: File ;
Описанная таким образом файловая переменная считается нетипизированной, и позволяет работать с файлами с неизвестной структурой. Данные считываются и записываются побайтно блоками, размер которых указывается при открытии файла, вплоть от 1 байт.
Но чаще используются файлы, состоящие из последовательности одинаковых записей. Для описания такого файла к предыдущему описанию добавляется указание типа записи:
var F: File of тип_записи ;
В качестве типа могут использоваться базовае типы, или создаваться свои. Важно только, чтобы для типа был точно известен фиксированный размер в байтах, поэтому, например, тип String в чистом виде применяться не может, а только в виде String[N], как указывалось в уроке Delphi 5.
Данные, считанные из файла или записываемые в файл, содержатся в обычной переменной, которая должна быть того же типа, что и файловая. Поэтому сначала в программе лично я описываю нужный тип, а затем ввожу две переменные этого типа - файловую и обычную:
Для текстовых файлов отдельно укажу, что тип файловой переменной в этом случае TextFile, а тип обычной - String.
Для открытия файла нужно указать, где он расположен. Для этого файловая переменная должна быть ассоциирована с нужным файлом, который определяется его адресом. Адрес файла может быть абсолютным, с указанием диска и каталогов ('C:\Мои документы\Мои рисунки\FileName.ini'), или относительным, тогда он создаётся в папке с .exe файлом программы. Для задания относительного адреса достаточно указать имя файла с нужным расширением. Делается это оператором AssignFile :
AssignFile(SaveF, 'C:\Мои документы\Мои рисунки\FileName.ini');
AssignFile(SaveF, 'FileName.ini');
Теперь файл должен быть открыт.
Открытие файла оператором Rewrite приведёт воссозданию файла заново, т.е. существующий файл будет без предупреждения уничтожен, и на его месте будет создан новый пустой файл заданного типа, готовый к записи данных. Если же файла не было, то он будет создан.
Открытие файла оператором Reset откроет существующий файл к считыванию или записи данных, и его указатель будет установлен на начало файла :
Каждый из этих операторов может иметь второй необязательный параметр, имеющий смысл для нетипизированных файлов, и указывающий длину записи нетипизированного файла в байтах:
Rewrite(SaveF, 1);
Reset(SaveF, 1);
Чтение файла производится оператором Read :
Запись в файл производится оператором Write :
При этом чтение и запись производится с текущей позиции указателя, затем указатель устанавливается на следующую запись. Можно проверить, существует ли нужный файл, оператором FileExists :
if FileExists('FileName.ini')
then Read(SaveF, SaveV);
Принудительно установить указатель на нужную запись можно оператором Seek(SaveF, N), где N - номер нужной записи, который, как и почти всё в программировании, отсчитывается от нуля:
Seek(SaveF, 49); - установка указателя на 50-ю запись.
При последовательном чтении из файла рано или поздно будет достигнут конец файла, и при дальнейшем чтении произойдёт ошибка. Проверить, не достигнут ли конец файла, можно оператором EOF (аббревиатура End Of File), который равен true, если прочитана последняя запись и указатель находится в конце файла:
while (not EOF(SaveF)) do
Read(SaveF, SaveV);
Для текстовых файлов вместо Read и Write используются операторы Readln и Writeln, умеющие определять конец строки. приведена процедура чтения текстового файла.
Оператор Truncate(SaveF) позволяет отсечь (стереть или, если хотите, удалить!) все записи файла, начиная от текущей позиции указателя, и до конца файла.
В конце работы с файлом его необходимо закрыть. Это делается оператором CloseFile(SaveF) ;
Теперь можно изменить программу из первой части урока, запоминающую своё положение на экране. Описание переменных опускаю, оно приведено на рисунке выше.
Создаём обработчик события Формы OnCreate со следующим содержимым:
procedure TForm1.FormCreate(Sender: TObject) ;
begin
AssignFile(SaveF, 'Init.ini') ;
if FileExists('Init.ini') then
begin
Reset(SaveF) ;
Read(SaveF, SaveV) ;
Form1.Left := SaveV.X ;
Form1.Top := SaveV.Y ;
Form1.Caption:=SaveV.Caption ; //Наши переменные дополнительно сохраняют заголовок Формы!
end ;
end ;
Теперь необходимо создать обработчик события OnClose :
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction) ;
begin
Rewrite(SaveF) ; //Нет необходимости проверять наличие файла, создадим его заново!
SaveV.X := Form1.Left ;
SaveV.Y := Form1.Top ;
SaveV.Caption := Form1.Caption ;
Write(SaveF, SaveV) ;
CloseFile(SaveF) ;
end ;
В данном случае файл считывается и записывается туда, куда мы ему указали. Но необходимо также уметь выбрать нужный файл в работающей программе. Описание этого - в заключительной части урока.
Немогу разобраться.
Есть своя программа, она должна создавать рядом с собой файл (текстовый из МЕМО), создаёт только один раз, при следуюшем запуске матюкаеться что файл уже есть.
Как написать условие типа:
Если 'файл.тхт' отсутствует, то Memo1.Lines.SaveToFile('Файл.txt'); .
Примечание: в коде есть условие на то что файл скрыт, скорее всего изза этого к нему нет доступа.
Проверка существования файла
Привет, надо организовать, проверку файлов на существование, путем делфи. Как можно это сделать.
Проверка на существования файла
Привет, прошу тапками не швыряться, я новичок, только начал изучение :) Пытаюсь сделать вот такую.
Проверка существования INI файла
Вот код: if not FileExists('MyScrSaverSetting.ini') then begin with.
Не работает, тупо не создаёт файл. или матюкаеться.
Мне надо: если файла нет то создать, а если есть то хотяб не матюкаться.
Он создан, но прога матюкаються потому что он являеться скрытым, и не хочет работать дальше. Можно подробнее.
Решение
nikityan, БогДелфей упомянул о функции FileExists() - она предназначена для определения - есть на диске файл с указанным именем или нет.
Использовать её можно, например, так:
Mawrat, здравствуй!
Вопрос.
1. Так нормально выглядит код, по поводу проверок?
Есть программа, работает, может выключаться, может непрерывно долго стоять в работе, но суть вот в чем.
Создаю *.txt файл (журнал сбора данных от событий определенных), создаю каждый месяц папку с названием месяца (пример 02_2015).
2. Допусти программа включена в промежутке с 31 января 23:59 до 1 февраля 0:05, как мне сделать чтобы создалась папка с датой в названии и новый файл (создался) стал писаться туда?
Проверка существования потока
Пытаюсь сделать динамическое создание нескольких потоков. Суть вот в чем. Программе дается задача.
Проверка существования записи
Доброго времени суток Мне нужно организовать проверку существования записи в файле Если запись.
Проверка существования процесса
Всем привет,помогите у меня есть программа она запускается нормально, но мне нужно чтоб когда.
Проверка на существования файлов
Проверяю при загрузке программы на существование файла. Но не могу понять как сделать так чтобы.
В позапрошлом уроке мы познакомились с записями: узнали, что это такое, как их заводить в своих программах, и как с ними потом работать. В прошлом уроке мы вели разговор о работе с файлами и научились работать с содержимым файлов. Сегодня мы объединим полученные знания, попутно продолжив знакомство с записями.
Комментарии читателей к данной статье
1. Вы используете методы доступа к файлам, которые устарели лет на 15-20, сегодня они используются исключительно в целях обучения.
2. Ошибка, соответствующая строке "File access denied", не документирована. Для Rewrite может быть: запрет создать файл в указанном месте (недостаток прав) , файл уже существует и кем-то открыт. Читайте подробнее описание ошибок функции CreateFile в MSDN, именно она вызывается в конце концов, и именно её ошибки возвращаются
3. "программа будет пытаться читать и писать в файл из нескольких мест, иногда одновременно" - одновременную запись и чтение реализовать практически нереально с помощью таких функций. Из-за того, что файл открывается с неправильными параметрами общего доступа и существует буферизация при чтении данных из файла.
Теоретически можно преобразовать переменную типа файл в структуру TFileRec, подменить Handle на созданный с помощью FileOpen с правильными параметрами совместного доступа, а потом использовать стандартные Pascal-style функции, но зачем? Для низкоуровневого доступа к файлам с совместным доступом используйте FileRead, FileWrite с FileSeek, или на худой конец - TFileStream. Такие файлы очень редко бывают текстовыми.
". одновременную запись и чтение реализовать практически нереально с помощью таких функций . "
В этом выражении ключевое слово "практически". Кто сказал, что запись/чтение будет происходить в БУКВАЛЬНОМ смысле одновременно? Даже "многозадачное" ядро процессора не является многозадачным, как таковым, а лишь выполняет очередь операций с учётом приоритета по времени, и делает это оЧень быстро.
Алексей Кузьминов Мудрец (11100) сказав "практически", я имел в виду всего лишь то, что что я знаю способы (несколько способов) реализовать одновременный доступ к файлу/общей памяти с помощью этих функций, но я не смогу объяснить, как это сделать по причинам: 1. займёт много времени 2. отсутствие контроля того, что же вы поняли из рассказанного, и нужно ли вам это К сожалению, я вынужден понимать вам именно БУКВАЛЬНО.
Почему слово ключевое? Объясню суть происходящего в моей программе: есть одна функция для чтения из одного файла, и эта функция вызывается из разных мест моей программы; вызовы могут происходить как последовательно (в разное время) , так и "параллельно" (одновременно).
В любом случае в функции команда открытия файла вписана в блок try (попытаться) ; если произойдёт ошибка
(которую команда try отловит на команду except, без описания ошибки) , то логическая переменная примет значение ЛОЖЬ (сразу после строки except), и по этой логической переменной произойдёт переход в начало цикла с постусловием (repeat находится перед try). И так до тех пор, пока кто то, кто вызвал функцию записи в файл, не закроет файл - будет выполняться этот цикл. Таким образом я реализовал ту самую "параллельность" записи. "Очередь задач" не напоминает ?
Что же касается возможности отсутствия файла, как такового, то перед вызовом функции чтения (да, такая тоже есть) проверяется наличие файла, и если он существует, то только тогда произойдёт вызов функции (чтения) .
Как я решил свою проблему, о которой написал в вопросе: опять же try, в случае исключения файл будет удалён, и после чего всё равно выполнится команда Rewrite(); ведь эта команда по идее должна создать новый файл? А я писал (опять же, в вопросе) , что если файла не существует - то команда Rewrite выполняется удачно.
Зачем мне всё это? Всё очень просто: программа во время запуска проверяет, существует ли указанный файл, и если существует, то вызывается функция чтения, и содержимое файла сохраняется в глобальную переменную. Во время выполнения программы к глобальной переменной дополняется то, что необходимо записать, после вызова Rewrite просто напросто записывается содержимое этой глобальной переменной.
Всё через жопу (а кто сказал, что будет легко ?), но работает.
Алексей Кузьминов Мудрец (11100) Как бы я решал вашу задачу: При запуске открывал файл на чтение CreateFile(GENERIC_READ or FILE_SHARE_READ or FILE_SHARE_WRITE, OPEN_EXISTING, ..) если INVALID_HANDLE_VALUE - читал значение по умолчанию, если получилось - создал бы объект THandleStream с таким дескриптором и прочитал бы то что нужно, потом удалил этот объект и вызвал CloseHandle для дескриптора. Когда нужно записать данные в файл: CreateFile(GENERIC_WRITE or FILE_SHARE_READ, CREATE_ALWAYS, ..) - проверил результат, записал, закрыл дескриптор. Обратите внимание: закрываю дескриптор СРАЗУ. Но если всё работает, то в чём был вопрос?
Ну и да: ручное редактирование содержимого текстового файла во время выполнения программы не предполагается; даже если туда (в файл) что то кто то добавил, и этот кто то не является моей программой - это что то будет удалено вместе с файлом, и произойдёт запись того, что хранится в глобальной переменной.
Ну и в примечание:
". сегодня они используются исключительно в целях обучения . ". По этому поводу скажу вот что: я пишу курсовую работу, и мне плевать на эти ваши "новые методы" доступа к фалам.
В моём случае программа будет пытаться читать и писать в файл из нескольких мест, иногда одновременно, поэтому с потоком будет тяжело.
Но как я сказал, Rewrite генерит denied даже тогда, когда нет параллельного доступа.
Ну и да, вытяжка из интернет-справочника:
Если файл не существует, то он будет создан.
Если файл уже существует, содержание будет потеряно, и новые данные добавятся в начало.
Второй пункт не выполнен
Проверь из-под отладчика, что имя файла - правильное.
Проверь, что все ок с правами доступа, особенно если файл лежит в папке с программой: попробуй создавать его в моих документах или папке временных файлов.
Проверь, что файл действительно не открыт: в момент ошибки попытайся создать, удалить, скопировать фай любым файл-менеджером типа фара.
Попробуй погуглить код ошибки, который скажет Дельфи, по нему будет видно, что не так с файлом. Если 103 - то файл точно забыли закрыть.
Убедись, что файл не открыт (не залочен) вирусом (антивирусом) .
И таки да, я бы советовал держать содержимое файла в памяти, в том же TSTringList и время от времени тупо сбрасывать его на диск. Если, конечно, файл меньше двух гигов.
Я держу содержимое файла в в обычном string'е, и при возникновении какого то из прописанных в коде событий происходит сброс данных на диск.
Объект INIFILES - работа с INI файлами
Почему иногда лучше использовать INI-файлы, а не реестр?
1. INI-файлы можно просмотреть и отредактировать в обычном блокноте.
2. Если INI-файл хранить в папке с программой, то при переносе папки на другой компьютер настройки сохраняются. (Я еще не написал ни одной программы, которая бы не поместилась на одну дискету :)
3. Новичку в реестре можно запросто запутаться или (боже упаси), чего-нибудь не то изменить.
Поэтому для хранения параметров настройки программы удобно использовать стандартные INI файлы Windows. Работа с INI файлами ведется при помощи объекта TIniFiles модуля IniFiles. Краткое описание методов объекта TIniFiles дано ниже.
Constructor Create('d:\test.INI');
Создать экземпляр объекта и связать его с файлом. Если такого файла нет, то он создается, но только тогда, когда произведете в него запись информации.
WriteBool(const Section, Ident: string; Value: Boolean);
Присвоить элементу с именем Ident раздела Section значение типа boolean
WriteInteger(const Section, Ident: string; Value: Longint);
Присвоить элементу с именем Ident раздела Section значение типа Longint
WriteString(const Section, Ident, Value: string);
Присвоить элементу с именем Ident раздела Section значение типа String
ReadSection (const Section: string; Strings: TStrings);
Прочитать имена всех корректно описанных переменных раздела Section (некорректно описанные опускаются)
ReadSectionValues(const Section: string; Strings: TStrings);
Прочитать имена и значения всех корректно описанных переменных раздела Section. Формат :
имя_переменной = значение
EraseSection(const Section: string);
Удалить раздел Section со всем содержимым
ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
Прочитать значение переменной типа Boolean раздела Section с именем Ident, и если его нет, то вместо него подставить значение Default.
ReadInteger(const Section, Ident: string; Default: Longint): Longint;
Прочитать значение переменной типа Longint раздела Section с именем Ident, и если его нет, то вместо него подставить значение Default.
ReadString(const Section, Ident, Default: string): string;
Прочитать значение переменной типа String раздела Section с именем Ident, и если его нет, то вместо него подставить значение Default.
Free;
Закрыть и освободить ресурс. Необходимо вызвать при завершении работы с INI файлом
Property Values[const Name: string]: string;
Доступ к существующему параметру по имени Name
Статья добавлена: 1 июня 2005
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Записи с вариантами
Записи с вариантами - такой тип записей, у которых создано несколько наборов полей, а используемый набор определяется специальным полем-селектором. При этом часть полей могут быть общими для всех наборов.
Например, мы хотим в программе хранить информацию об отрезке прямой на плоскости. Математически мы можем представить отрезок двумя способами:
- Двумя точками, каждая из которых имеет координаты 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 правых.
С какой целью мы ввели отрезок? Ну например давайте посчитаем его длину. Для этого введём собственную функцию, которая на вход будет принимать запись, а на выходе будет выдавать длину отрезка. Если забыли математику, напомню способ вычисления длины:
- По двум точкам: длина - это квадратный корень из суммы квадратов разностей соответствующих координат.
- По точке, углу и длине: промолчу, ага.
Что может быть проще? Ну и в конец обработчика нажатия кнопки добавим:
Проверьте правильность работы, запустив программу и введя какие-нибудь данные. Помните, что программа работает с расчётом на то, что исходные данные верны, т.е. что вместо чисел вы не вписали "всем привет!".
Хранение записей в файлах
Ну вот мы и подошли к тому, для чего пришлось затронуть тему работы с файлами. Использовать записи мы научились, но тут вопрос: а как их хранить? Сохранять в файлах отдельно каждое поле - совершенно неудобно. А потом его нужно оттуда ещё как-то прочитать. Неужели нет способа проще? Есть!
Мы можем создать типизированный файл на основе имеющегося типа записи. Помните, как мы описывали файлы? 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() - они предназначены исключительно для текстовых файлов.
Статьи, похожие по тематике
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Поделитесь ссылкой в социальных сетях:
Комментарии читателей к данной статье
Доброго всем времени. Очень хорошие уроки. Все подробно описано и разжевано. Самое то для начинающих. Подскажите пожалуйста, будут ли еще уроки? Судя по дате, то выходить больше не будут. Очень жаль, только начал в раж входить =) . В любом случае [b]Ерёмину А.А[/b] от меня низкий поклон и громадное спасибо.
P.S. Большая просьба, если есть возможность, продолжите пожалуйста статьи по Delphi. Очень хочется изучить этот язык поглубже =) . Большое спасибо. Удачи!
Цитата:
А следующего урока я так понял нет. мде. моменты как по TCP на делфи работать и вообще по инету шариться видимо тут не узнать.
Не знаю в чём дело, жрать очень охота.
По теме: по-моемему не записи с вариантами, а записи записей - так это чаще называется. Хотя могу путать.
Ну а добавление в файл записей еще одну запись - почему бы файл не открыть на запись, указатель в конец поставить и дописать ее туда?
Здарова!
Все вроде понятно, кроме одного.
повторил все как автор, но у меня на форме (в ListBox-е) исчезают старые записи (при каждом обновлении повляются новые).
третью задачу из-за этого не могу сделать.
в чем там дело.
Добавление элементов в контекстное меню "Создать"
1. Создать новый документ, поместить его в папку Windows/ShellNew
2. В редакторе реестра найти расширение этого файла, добавить новый подключ, добавить туда строку: FileName в качестве значения которой указать имя созданного файла.
В проводнике контекстное меню "Открыть в новом окне"
1. Найти ключ HKEY_CLASSES_ROOT\Directory\Shell
2. Создать подключ: opennew в котором изменить значение (По умолчанию) на: "Открыть в новом окне"
3. Под этим ключом создать еще подключ command (По умолчанию) = explorer %1
Использование средней кнопки мыши Logitech в качестве двойного щелчка
Подключ HKEY_LOCAL_MACHINE\SoftWare\Logitech и там найти параметр DoubleClick заменить 000 на 001
Новые звуковые события
Например создает звуки на запуск и закрытие WinWord
HKEY_CURRENT_USER\AppEvents\Shemes\Apps добавить подключ WinWord и к нему подключи Open и Close.
Теперь в настройках звуков видны новые события
Путь в реестре для деинсталяции программ:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
Работа с реестром в Delphi
В Delphi есть объект TRegistry при помощи которого очень просто работать с реестром.
Реестр предназначен для хранения системных переменных и позволяет зарегистрировать файлы программы, что обеспечивает их показ в проводнике с соответствующей иконкой, вызов программы при щелчке на этом файле, добавление ряда команд в меню, вызываемое при нажатии правой кнопки мыши над файлом. Кроме того, в реестр можно внести некую свою информацию (переменные, константы, данные о инсталлированной программы . ). Программу можно добавить в список деинсталляции, что позволит удалить ее из менеджера "Установка/Удаление программ" панели управления.
Для работы с реестром применяется ряд функций API :
RegCreateKey (Key: HKey; SubKey: PChar; var Result: HKey): Longint;
Создать подраздел в реестре. Key указывает на "корневой" раздел реестра, в SubKey - имя раздела - строится по принципу пути к файлу в DOS (пример subkey1\subkey2\ . ). Если такой раздел уже существует, то он открывается (в любом случае при успешном вызове Result содержит Handle на раздел). Об успешности вызова судят по возвращаемому значению, если ERROR_SUCCESS, то успешно, если иное - ошибка.
RegOpenKey(Key: HKey; SubKey: PChar; var Result: HKey): Longint;
Открыть подраздел Key\SubKey и возвращает Handle на него в переменной Result. Если раздела с таким именем нет, то он не создается. Возврат - код ошибки или ERROR_SUCCESS, если успешно.
RegCloseKey(Key: HKey): Longint;
Закрывает раздел, на который ссылается Key. Возврат - код ошибки или ERROR_SUCCESS, если успешно.
RegDeleteKey(Key: HKey; SubKey: PChar): Longint;
Удалить подраздел Key\SubKey. Возврат - код ошибки или ERROR_SUCCESS, если нет ошибок.
RegEnumKey(Key: HKey; index: Longint; Buffer: PChar;cb: Longint): Longint;
Получить имена всех подразделов раздела Key, где Key - Handle на открытый или созданный раздел (см. RegCreateKey и RegOpenKey), Buffer - указатель на буфер, cb - размер буфера, index - индекс, должен быть равен 0 при первом вызове RegEnumKey. Типичное использование - в цикле While, где index увеличивается до тех пор, пока очередной вызов RegEnumKey не завершится ошибкой (см. пример).
RegQueryValue(Key: HKey; SubKey: PChar; Value: PChar; var cb: Longint): Longint;
Возвращает текстовую строку, связанную с ключом Key\SubKey.Value - буфер для строки; cb- размер, на входе - размер буфера, на выходе - длина возвращаемой строки. Возврат - код ошибки.
RegSetValue(Key: HKey; SubKey: PChar; ValType: Longint; Value: PChar; cb: Longint): Longint;
Задать новое значение ключу Key\SubKey, ValType - тип задаваемой переменной, Value - буфер для переменной, cb - размер буфера. В Windows 3.1 допустимо только Value=REG_SZ. Возврат - код ошибки или ERROR_SUCCESS, если нет ошибок.
Быстрый доступ к полям записей
В нашем примере у записи сравнительно мало полей - 4. Но бывают программы, где создаются записи с десятком полей и работа из-за этого замедляется. Хотя бы потому, что в коде приходится каждый раз набирать имя записи и точку, и лишь затем имя поля. Обрадую: мучаемся не только мы - компьютеру тоже приходится делать больше телодвижений. Каждый раз нужно определять адрес и искать запись в памяти, и лишь после этого можно найти значение поля. Чтобы облегчить участь и программисту и машине, был введён специальный оператор with (англ. "с"). К сожалению, о нём далеко не все знают, а ведь его использование увеличивает эффективность и кода, и работы самого программиста.
Итак, общая форма записи:
Не очень понятно? А теперь на нашем примере:
Что же мы имеем? А вот что: мы нашу запись "вынесли за скобку", и далее напрямую обращаемся к её полям. Удобно, не правда ли? Этот код абсолютно эквивалентен тому, что был написан нами ранее, только он более эффективен.
Несложно догадаться, что использование with для единичного обращения к записи бессмысленно:
В этом случае мы ни в чём не выигрываем - только пишем больше кода.
Помните про оператор with и почаще его используйте - и себе жизнь облегчите, и программы станут профессиональнее.
Статьи, похожие по тематике
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Поделитесь ссылкой в социальных сетях:
Упакованные записи
Пару слов о том, что такое упакованные записи, и с чем их едят. По умолчанию память под записи выделяется не очень экономно - помимо самих данных добавляются и служебные байты, которые отделяют блоки данных друг от друга. Существует принудительный способ заставить Delphi упаковать запись, т.е. минимизировать занимаемую ей память. Делается это указанием слова packed перед словом record. Разница порой может быть достаточно ощутимой. Пример: запись из строки длиной 5 символов, одного символа и трёх чисел разного типа. Объявим две разные записи: одна обычная, а другая упакованная:
А теперь самое интересное: посмотрим, сколько памяти занимает каждая из записей. Сделаем это функцией SizeOf():
Тем не менее, не стоит пренебрегать этим способом экономии памяти. В некоторых случаях использование пакованных записей может создавать разные ошибки в работе программы. Понять, что дело именно в packed, удаётся далеко не сразу. Так что, если храните десяток отрезков - не торопитесь паковать - если и выиграете, то не сильно.
Домашнее задание
Для закрепления пройденного не буду предлагать новой программы - давайте изменим эту. Итак, требуется:
С первого прочтения кажется сложным? На самом деле нет. Если начнёте делать - сообразите, что и как. И не бойтесь потратить на это полчаса, час. Программированию нельзя научить - ему можно только научиться самому. Одно лишь чтение статей ничего не даст - нужно пробовать, чем больше - тем лучше. В конце концов, позади 25 уроков - это достаточно много, пора начинать активно действовать.
Желаю успехов! До встречи на следующем уроке!
Автор: Ерёмин А.А.
Статья добавлена: 8 августа 2009
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Читайте также: