Электронная библиотека » Александр Чиртик » » онлайн чтение - страница 15

Текст книги "Delphi. Трюки и эффекты"


  • Текст добавлен: 22 января 2014, 03:26


Автор книги: Александр Чиртик


Жанр: Программирование, Компьютеры


сообщить о неприемлемом содержимом

Текущая страница: 15 (всего у книги 24 страниц) [доступный отрывок для чтения: 8 страниц]

Шрифт:
- 100% +
7.3. Реестр

Далее будет рассмотрено несколько примеров использования в программах на Delphi одного из важнейших хранилищ информации Windows – системного реестра.

Краткие сведения о реестре Windows

Что же представляет собой системный реестр и для чего он предназначен? Реестр состоит из нескольких файлов с довольно сложной организацией записей, формирующих иерархическую структуру (родитель—потомки), а точнее, несколько веток структуры. Благодаря наличию специальных функций мы можем работать с реестром именно как с иерархической структурой, а не как с набором записей в файле.

Реестр Windows является отличным примером организации централизованного хранения данных, в основном, настроек программ. Реестр является хорошей альтернативой большим INI-файлам, доставшимся в наследство от 16-разрядных версий Windows, главным образом из-за возможности лучше структурировать информацию (ведь секции разделов в реестре могут быть много раз вложенными). В реестре хранятся и данные, которые могут пригодиться сразу многим программам: например, расположения СОМ-серверов, пути приложений, ассоциированных с различными типами файлов.

В реестре могут быть объекты двух типов: разделы (во многом аналогичны папкам файловой системы) и параметры (имеют имя, тип и значение).

Данные реестра сгруппированы в несколько ветвей (рис. 7.6). Для запуска показанной на рис. 7.6 программы Редактор реестра достаточно набрать в командной строке Regedit либо отыскать файл Regedit. ехе в каталоге Windows.

Информация, помещаемая в различных разделах реестра, группируется по следующим признакам.

• HKEY_CURRENT_USER – в этом разделе хранится информация, используемая для текущего пользователя, осуществившего вход в систему. Этой информацией могут быть, например, значения переменных окружения, фон Рабочего стола, вид меню Пуск.

• HKEY_USERS – содержит настройки системы для различных пользователей, а также настройки, используемые по умолчанию для нового пользователя.

• HKEY_LOCAL_MACHINE – самая большая и главная ветвь реестра, содержащая параметры Windows, приложений, оборудования, ассоциации расширений файлов, расположение СОМ-серверов и еще много чего полезного.

• HKEY_CURRENT_CONFIG – в этом разделе хранятся значения параметров Windows, отличающихся от стандартных. Он является псевдонимом для ветви HKEY_LOCAL_MACHINESYSTEMCurrentControlSetHardware ProfilesX Current.

• HKEY_CLASSES_ROOT – в системах Windows 95/98/NT 4.0 и более ранних этот раздел является псевдонимом для ветви HKEY_LOCAL_MACHINESOFTWAREClasses. В Windows 2000/ХР содержимое этого раздела составляется из содержимого разделов HKEY_LOCAL_MACHINESOFTWAREClasses и HKEY_CURRENT_USERSoftwareClasses.

Доступ к разделам реестра происходит по дескрипторам. Дескриптор раздела можно получить при его создании или открытии, указав дескриптор одной из рассмотренных выше корневых ветвей, а также путь требуемого раздела. Для хранения дескрипторов корневых ветвей реестра определены одноименные константы.

Средства работы с реестром

Для работы с реестром предусмотрена целая группа API-функций. Однако зачем изобретать велосипед, испытывая на себе «удобство» работы с этими функциями? Ведь Borland предоставила нам в распоряжение замечательный по своей простоте класс TRegistry. Использованию этого класса как раз и посвящено несколько следующих абзацев.

Итак, класс TRegistry находится в модуле Registry. Если кому-то все же станет интересно использование API для работы с реестром, то можете заглянуть в этот модуль и там посмотреть, как реализованы методы класса TRegistry.

Примечание

Помимо TRegistry, в модуле Registry можно найти такие классы, KaKTReglniFile и TRegistrylniFile, позволяющие работать с реестром, как будто бы это INI-файл. В ряде случаев использование этих классов вместо TRegistry позволит сократить размер программы, да и значительно ее упростить.

В табл. 7.1 приведены свойства класса TRegistry.

Таблица 7.1. Свойства класса TRegistry

Список констант, которые могут объединяться операцией or для формирования значения свойства Access:

• KEY_QUERY_VALUE – получение значений параметров раздела;

• KEY_ENUMERATE_SUB_KEYS – возможность составления списка подразделов;

• KEY_SET_VALUE – создания параметров в разделе, задание их значений;

• KEY_CREATE_SUB_KEY – создание подразделов;

• KEY_CREATE_LINK – создание символических ссылок (здесь не рассматривается);

• KEY_NOTIFY – право на уведомление об изменении раздела и его подразделов (здесь не рассматривается);

• KEY_READ – комбинация значений KEY_QUERY_VALUE, KEY_ENUMERATE_ SUB_KEYS И KEY_NOTIFY;

• KEY_WRITE – комбинация3Ha4eHtriiKEY_SET_VALUE HKEY_CREATE_SUB_KEY;

• KEY_ALL_ACCESS – комбинация значений KEY_READ, KEY_WRITEH KEY_ CREATEJLINK.

Приводить список всех методов класса TRegistry в книге нерационально, да и незачем. Благо, названия методов говорят сами за себя, к тому же Delphi поставляется с неплохой справочной системой. Здесь же мы остановимся на рассмотрении некоторых особенностей работы с методами класса TRegistry.

Итак, работая с разделами реестра, важно (в общем случае) соблюдать следующую последовательность.

1. Установить значение свойства RootKey, если корневой раздел отличен от HKEY_CURENT_USER. Установить значение свойства Access, если не нужен полный доступ.

2. Открыть методом ОрегКеу или создать методом CreateKey раздел реестра. Если использовать OperKeyReadOnly, то задавать значение свойства Access, как сказано в пункте 1, не имеет смысла.

3. Произвести нужные операции с элементами раздела.

4. Не забыть закрыть раздел, по крайней мере, если вы собираетесь использовать один и тот же объект TRegistry для последовательной работы с несколькими разделами (метод ОрепКеу не закрывает ранее открытый раздел).

Теперь несколько слов о проверке успешности работы методов класса TRegistry. Итак, большинство методов этого класса, осуществляющих доступ к разделам реестра, реализованы как функции, возвращающие True в случае успеха и False при возникновении ошибки. Вероятно, по каким-то чрезвычайно сложным соображениям разработчики класса TRegistry реализовали-таки функцию (!) CreateKey генерирующей исключение ERegistryException в случае неудачи, а не возвращающей значение True или False.

Для чтения/записи параметров разного типа в классе TRegistry предусмотрены пары Read– и Write-методов. Использовать их крайне просто, в чем вы убедитесь далее. Главное, при использовании этих методов не забывать определить тип значений параметров, если он заранее вам точно не известен, например с помощью функции GetDataType. Следует также помнить, что методы работы с параметрами генерируют исключение ERegistryException при возникновении ошибок.

И напоследок о параметре (По умолчанию) – он может присутствовать в каждом разделе. Для обращения к этому параметру используйте пустую строку в качестве имени раздела. Только нужно учитывать, что, в отличие от более ранних версий Windows, в Windows 2000/ХР этот параметр автоматически не создается.

Хранение настроек программы в реестре

Первый простой пример демонстрирует, как можно использовать реестр для сохранения небольшого объема данных между запусками приложения.

Пусть нужно, чтобы формы приложения запоминали свое расположение, размер, введенные и выбранные в элементах управления данные. В таком случае необходимость в сотый раз перетаскивать часто открываемую форму на удобное место не будет раздражать пользователя. Если же форма требует постоянного ввода похожих данных, то восстановление выбранных и введенных в прошлый раз значений будет только плюсом.

Теперь о деле: есть форма для фильтрации запроса к базе данных, она показанна на рис. 7.7.

Рис. 7.7. Форма фильтра для поиска товара


Содержимое формы не суть важно, а важно то, что при нажатии кнопки ОК положение, размер формы, а также данные, введенные пользователем, будут сохранены в реестре при помощи процедуры SaveFilter (листинг 7.14).

Листинг 7.14. Сохранение параметров формы в реестре

procedure TForm1.OKClick(Sender: TObject);

begin

SaveFilter();

//Выполняем требуемые действия…

end;

//Процедура сохраняет параметры в реестр

procedure TForm1.SaveFilter();

var

reg: TRegistry; //По умолчанию: RootKey = HKEY_CURRENT_USER

strShops: String;

i: Integer;

begin

reg := TRegistry.Create();

try

//Открываем или создаем раздел, в котором будут

//сохранены параметры формы

reg.OpenKey(strBaseKey + 'Form1', True);

//Сохранение параметров

//1. Размер и положение формы

reg.WriteInteger('Width', Width);

reg.WriteInteger('Height', Height);

reg.WriteInteger('Top', Top);

reg.WriteInteger('Left', Left);

//2. Последнее введенное наименование

reg.WriteString('txtName.Text', txtName.Text);

//3. Выбранные магазины

strShops := '';

for i := 0 to lstShops.Count–1 do

if lstShops.Selected[i] then

strShops := strShops + lstShops.Items[i] + ',';

reg.WriteString('lstShops.Selection', strShops);

//4. Применение сортировки

reg.WriteBool('chkSort.Checked', chkSort.Checked);

except

on ERegistryException do

MessageBox(Handle, 'Ошибка при сохранении фильтра',

'Поиск товара', MB_ICONEXCLAMATION)

;

end;

reg.CloseKey();

reg.Free();

end;

В рассматриваемом примере константа strBaseKey, определяющая положение раздела для сохранения настроек, задана следующим образом:

const

strBasekey = 'SoftwareDelphi. Трюки и эффектыНастройки программы';

Открыв Редактор реестра, можно удостовериться в правильном сохранении требуемых нам параметров (рис. 7.8).

Рис. 7.8. Параметры формы, записанные в реестр


Считывание параметров формы можно производить, например, при ее создании. Тогда в обработчике события Create достаточно поместить вызов процедуры LoadFilter (листинг 7.15).

Листинг 7.15. Загрузка параметров формы из реестра

procedure TForm1.FormCreate(Sender: TObject);

begin

LoadFilter();

end;

//Процедура загружает параметры из реестра

procedure TForm1.LoadFilter();

var

reg: TRegistry; //По умолчанию: RootKey = HKEY_CURRENT_USER

strShops: String;

shopStart, shopEnd: Integer;

begin

reg := TRegistry.Create();

try

//Открываем раздел, в котором сохранены параметры формы

reg.OpenKey(strBaseKey + 'Form1', False);

//Загрузка сохраненных ранее параметров

//1. Размер и положение формы

Width := reg.ReadInteger('Width');

Height := reg.ReadInteger('Height');

Top := reg.ReadInteger('Top');

Left := reg.ReadInteger('Left');

//2. Последнее введенное наименование

txtName.Text := reg.ReadString('txtName.Text');

//3. Выбранные в прошлый раз магазины

strShops := reg.ReadString('lstShops.Selection');

shopStart := 1;

for shopEnd := 0 to Length(strShops) do

if strShops[shopEnd] = ',' then

begin

//Получение имени магазина и выделение его в списке

SelectShop(Copy(strShops, shopStart,

shopEnd – shopStart));

shopStart := shopEnd + 1;

end;

//4. Применение сортировки

chkSort.Checked := reg.ReadBool('chkSort.Checked');

except

on ERegistryException do

//Игнорируем ошибки (просто не

//будут зачитаны данные из реестра,

//например, при первом запуске программы)

;

end;

reg.CloseKey();

reg.Free();

end;

//Процедура выделяет магазин с заданным названием

//(если он есть в списке)

procedure TForm1.SelectShop(strShopName: String);

var

i: Integer;

begin

for i := 0 to lstShops.Count–1 do

if lstShops.Items[i] = strShopName then

begin

lstShops.Selected[i] := True;

Exit;

end;

end;

Некоторая сложность алгоритма загрузки списка выбранных магазинов обусловлена желанием добиться того, чтобы при изменении списка не выделялись ранее не выбранные магазины (иначе можно было бы просто сохранять индексы).

Примечание

Чтобы при первом запуске процедуры LoadFilter не появлялись сообщения об исключениях (при работе в отладчике Delphi), снимите флажок Stop on Delphi Exceptions на вкладке Language Exceptions диалогового окна Debugger Options (меню Tools → Debugger Options).

Автозапуск программ

Так уж повелось, что, рассматривая работу с реестром, редко удается удержаться от рассказа, как можно организовать автоматический запуск приложений, минуя пресловутое меню Автозагрузка. Коснемся этой темы и мы: рассмотрим наиболее простые способы автоматического запуска не сервисных (!) программ.

Итак, в ветвях реестра HKEY_CURRENT_USER и HKEY_LOCAL_MACHINE находятся разделы SoftwareMicrosoftWindowsCurrentVersionRunи Software Microsof tWindowsCurrentVersionRunOnce. В первом (Run) сохраняются пути приложений, запускаемых при каждой загрузке Windows. В разделе же RunOnce обычно регистрируются приложения типа инсталляторов, которые запускаются при первой с момента регистрации перезагрузке Windows, но до запуска программы Проводник. При запуске приложения, зарегистрированного в ключе RunOnce, соответствующая запись из этого раздела автоматически удаляется.

От выбора ветви реестра (HKEY_LOCAL_MACHINE ИЛИ HKEY_CURRENT_USER) зависит, в сеансе всех ли пользователей будет запускаться приложение.

Рассмотрим создание простейшей программы, способной определить, запускается ли она автоматически, а если запускается, то каким образом. Программа также будет уметь создавать и удалять параметры в нужных разделах реестра для задания нужного режима запуска.

Пусть на форме приложения расположены три переключателя (рис. 7.9). Процедура, приведенная в листинге 7.16, устанавливает состояния переключателей в зависимости от того, в каком разделе ветви HKEY_LOCAL_MACHINE расположен параметр с именем, совпадающим с именем программы (это условность, котора я нужна для работы нашего примера).

Рис. 7.9. Форма после определения варианта режима запуска приложения

Листинг 7.16. Определение режима запуска приложения

procedure TForm1.GetRunMode();

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_LOCAL_MACHINE;

//Определение, как запускается программа (по наличию значений

//в соответствующих разделах)

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersionRun',

False)

then

begin

if reg.ValueExists(Application.Title) then

begin

//Программа есть в разделе Run —

//запускается при каждой загрузке Windows

optAutoRun.Checked := True;

reg.CloseKey();

Exit;

end;

reg.CloseKey();

end;

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion

RunOnce', False)

then

begin

if reg.ValueExists(Application.Title) then

begin

//Программа есть в разделе RunOnce —

//запускается один раз при старте Windows

optRunOnce.Checked := True;

reg.CloseKey();

Exit;

end;

reg.CloseKey();

end;

//Автозапуск программы (рассматриваемым способом) не включен

optRunNone.Checked := True;

reg.Free();

end;

Параметры запуска изменяются (в рассматриваемом приложении) при нажатии кнопки Применить (листинг 7.17).

Листинг 7.17. Применение режима запуска

procedure TForm1.cmbApplyClick(Sender: TObject);

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_LOCAL_MACHINE;

//Отмена прошлого режима

//..удаление параметра из раздела Run

if not optAutoRun.Checked then

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion

Run', False)

then

begin

reg.DeleteValue( Application.Title );

reg.CloseKey();

end;

//..удаление параметра из раздела RunOnce

if not optRunOnce.Checked then

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion

RunOnce',False)

then

begin

reg.DeleteValue( Application.Title );

reg.CloseKey();

end;

//Установка нового режима (создание параметра в соотвествующем

//разделе)

if optAutoRun.Checked then

//..добавление параметра в раздел Run

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion

Run', True)

then

begin

reg.WriteString( Application.Title, Application.ExeName);

reg.CloseKey();

end;

if optRunOnce.Checked then

//..добавление параметра в раздел RunOnce

if reg.OpenKey('SoftwareMicrosoftWindowsCurrentVersion

RunOnce',True)

then

begin

reg.WriteString( Application.Title, Application.ExeName);

reg.CloseKey();

end;

//Для верности обновим показания на форме по данным из реестра

GetRunMode();

reg.Free();

end;

При желании вы можете изменить ветвь реестра на HKEY_CURRENT_USER, если приложение (которое вы будете делать) запускалось только для определенных пользователей.

Запуск приложения из командной строки

Сразу оговоримся, что из командной стр оки (например, из окна Запуск программы, открываемого командой Пуск Выполнить) можно запустить любое приложение: достаточно только ввести его полный или относительный (относительно рабочей папки) путь. Однако, возможно, вы замечали, что некоторые приложения можно запускать, просто вводя в командной строке имя приложения, например msaccess или winword. Займемся обеспечением возможности запуска приложения таким ускоренным способом.

Чтобы зарегистрировать приложение для быстрого запуска, можно поместить его путь в ветвь реестра SOFTWAREMicrosoftWindowsCurrentVersionApp Paths корневого раздела HKEY_CURRENT_USER ИЛИ HKEY_LOCAL_MACHINE. Путь ЕХЕ-файла приложения должен быть записан в параметр (По умолчанию) подраздела, имеющего такое же имя, как и ЕХЕ-файл приложения (включая расширение).

Пример процедуры, регистрирующей приложение для быстрого запуска, приведен в листинге 7.18.

Листинг 7.18. Регистрация приложения для запуска из командной строки

procedure RegisterQuickStart();

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_LOCAL_MACHINE;

//Регистрируем программу для запуска по имени из

//командной строки

if reg.OpenKey(paths + '' + Application.Title + '.exe', True)

then

begin

reg.WriteString('', Application.ExeName);

reg.CloseKey();

end;

reg.Free();

end;

Для отмены быстрого запуска приложения из командной строки можно воспользоваться процедурой, приведенной в листинге 7.19.

Листинг 7.19. Отмена быстрого запуска приложения

procedure UnregisterQuickStart();

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_LOCAL_MACHINE;

//Удаляем сведения о программе из реестра

reg.DeleteKey(paths + '' + Application.Title + '.exe');

reg.Free();

end;

В приведенных выше листингах значение константы paths равно:

const paths = 'SOFTWAREMicrosoftWindowsCurrentVersionAppPaths';

Регистрация типов файлов

Теперь рассмотрим вопрос, нередко интересующий программистов, приложения которых должны уметь сохранять и загружать данные из файлов. Логично задавать всем таким файлам одно расширение: получается тип файлов приложения.

Открытие файлов (документов) приложения из самого приложения организовать несложно: достаточно применить диалог открытия файла. Но как заставить, например, Проводник автоматически запускать наше приложение при выборе соответствующего файла? Сделать это тоже несложно: достаточно внести небольшие изменения в раздел реестра HKEY_CLASSES_ROOT.

Итак, перечень операций, которые нужно произвести для регистрации собственного типа файла (пусть, MYDOC).

1. Создать раздел HKEY_CLASSES_ROOT.mydoc, в параметр (По умолчанию) которого записать имя типа файла, например TricksDelphi. DocumentSample.

2. Создать раздел HKEY_CLASSES_ROOT<HMH_THna>, например HKEY_CLASSES_ ROOTTricksDelphi. DocumentSample. Если в параметр (По умолчанию) этого раздела записать строку, то она будет отображаться в качестве описания типа файла.

3. Если нужно, чтобы для документа использовался определенный значок, необходимо создать раздел HKEY_CLASSES_ROOT<HMH_THna>DefaultIcon, в параметр (По умолчанию) которого записать полный путь ЕХЕ-или DLL-файла, из которого брать значок, и через запятую – номер значка (см. гл. 4).

4. Наконец, для автоматического запуска приложения при выборе файла заданного типа создаем paздeлHKEY_CLASSES_ROOT<имя_типa>Shell OpenCommand, в параметр (По умолчанию) которого записываем строку вида <путь_приложения> %1 для передачи имени документа в командной строке.

Пример процедуры, которая производит все вышеперечисленные манипуляции, приводится в листинге 7.20.

Листинг 7.20. Регистрация типа файла

procedure RegisterAppDocuments();

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_CLASSES_ROOT;

//Вносим информацию о нашем типе файла в реестр

//..само расширение

if reg.OpenKey('.mydoc', True) then

begin

reg.WriteString('', 'TricksDelphi.DocumentSample');

reg.CloseKey();

end;

//..описание типа файла

if reg.OpenKey('TricksDelphi.DocumentSample', True) then

begin

reg.WriteString('', 'Документ TricksDelphi.DocumentSample');

reg.CloseKey();

end;

//..значок для файлов MYDOC-типа

if reg.OpenKey('TricksDelphi.DocumentSampleDefaultIcon', True)

then

begin

reg.WriteString('', Application.ExeName + ', 1');

reg.CloseKey();

end;

//..приложение, открывающее MYDOC-документ

if reg.OpenKey('TricksDelphi.DocumentSampleShellOpenCommand',

True)

then

begin

reg.WriteString('', Application.ExeName + ' %1');

reg.CloseKey();

end;

reg.Free();

end;

Результат работы этой процедуры показан на рис. 7.10.

Рис. 7.10. Результат регистрации типа файла


Теперь при выборе в файловой оболочке наше приложение запускается с путем выбранного файла (правда, в формате 8.3) в качестве аргумента командной строки. Как перевести путь из короткой формы в длинную (если это вообще надо), рассказано в разд. 4.2. Если вы не знакомы с тем, как получать доступ к аргументам командной строки, можете взглянуть на листинг 7.21 (тут происходит отображение имени открываемого файла в текстовом поле на форме).

Листинг 7.21. Определение имени открываемого файла

procedure TForm1.FormCreate(Sender: TObject);

begin

if ParamCount() > 0 then

begin

//Обрабатываем данные командной строки…

txtDoc.Text := 'Имя открываемого файла: ' + ParamStr(1);

end;

end;

Уничтожение сведений о типе файла возможно путем простого удаления созданных ранее разделов, например так, как сделано в листинге 7.22.

Листинг 7.22. Удаление из реестра сведений о типе файла

procedure UnregisterAppDocuments();

var

reg: TRegistry;

begin

reg := TRegistry.Create();

reg.RootKey := HKEY_CLASSES_ROOT;

//Удаление из реестра информации о типе файла

reg.DeleteKey('.mydoc');

reg.DeleteKey('TricksDelphi.DocumentSample');

reg.Free();

end;


Страницы книги >> Предыдущая | 1 2 3 4 5 6 7 8
  • 0 Оценок: 0

Правообладателям!

Данное произведение размещено по согласованию с ООО "ЛитРес" (20% исходного текста). Если размещение книги нарушает чьи-либо права, то сообщите об этом.

Читателям!

Оплатили, но не знаете что делать дальше?


Популярные книги за неделю


Рекомендации