Описание вспомогательных, если их можно так назвать, полей и методов. Это те поля и методы которые находятся в личной (private) и защищенной (protected) секции класса. Они не доступны вашей программе, а только методам самого класса или его потомка (для protected). Однако ими интенсивно пользуются доступные методы.

Из файла Source\RTL\WIN\windows.pas:

HKEY = Integer;
PHKEY = ^HKEY;

Из файла Source\VCL\registry.pas:

TRegistry = class(TObject)
    private
FCurrentKey:HKEY;
FRootKey:HKEY;
FLazyWrite:Boolean;
FCurrentPath:string;
FCloseRootKey:Boolean;
procedure SetRootKey(Value:HKEY);

    protected

procedure ChangeKey(Value:HKey; const Path:string);
function GetBaseKey(Relative:Boolean):HKey;
function GetData(const Name:string; Buffer:Pointer; BufSize:Integer; var RegData:TRegDataType):Integer;
function GetKey(const Key:string):HKEY;
procedure PutData(const Name:string; Buffer:Pointer; BufSize:Integer; RegData:TRegDataType);
procedure SetCurrentKey(Value:HKEY);

    public

property CurrentKey:HKEY read FCurrentKey;
property CurrentPath:string read FCurrentPath;
property LazyWrite:Boolean read FLazyWrite write FLazyWrite;
property RootKey:HKEY read FRootKey write SetRootKey;
...

end;

function IsRelative const Value:string):Boolean;


ChangeKey

Закрывает текущий ключ и готовится к открытию нового ключа.

procedure TRegistry.ChangeKey(Value:HKey; const Path:string);
begin
CloseKey;
FCurrentKey := Value;
FCurrentPath := Path;

end;

С помощью метода CloseKey освобождается дескриптор текущего ключа, а поля FCurrentKey и FCurrentPath заполняются новыми значениями.


GetBaseKey

Возвращает дескриптор ключа, от которого читается путь.

function TRegistry.GetBaseKey(Relative:Boolean):HKey;
begin
if (CurrentKey = 0) or not Relative then
Result := RootKey else
Result := CurrentKey;

end;

Возвращает дескриптор ключа. При этом для ключа, начинающегося с символа '\' (слеш означает, что имя ключа абсолютно, т.е. считается от корневого ключа), выбирается дескриптор корневого ключа. Иначе (ключ относительный) дескриптор текущего ключа (открытого в данный момент).


GetData

Читает из текущего ключа значение параметра в буфер. Если параметр с указанным именем отсутствует, то возбуждает исключение.

function TRegistry.GetData(const Name:string; Buffer:Pointer; BufSize:Integer; var RegData:TRegDataType):Integer;
    procedure Error;
    begin
raise ERegistryException.CreateFmt(SRegGetDataFailed, [Name]);

    end;
var
    DataType: Integer;

begin
DataType := REG_NONE;
if RegQueryValueEx(CurrentKey, PChar(Name), nil, @DataType, PByte(Buffer), @BufSize) <> ERROR_SUCCESS then Error;
RegData := DataTypeToRegData(DataType);
Result := BufSize;

end;

Вызывается функция RegQueryValueEx для текущего ключа и указанного имени параметра. Кроме того, передаются указатели на: переменную принимающую значение типа данных, буфер принимающий сами данные и переменную сообщающую длину буфера, причем по возвращению она примет значение длины скопированных в буфер данных (для строковых с учетом терминального нуля). После окончания функции RegData заполняется с помощью функции преобразования DataTypeToRegData потому, что значения типов для Windows и Delphi не полностью совпадают (например, REG_BINARY = 3, а rdBinary = 4). В случае успеха функция GetData возвращает значение длины полученных данных. При отсутствии параметра с указанным именем или в случае любой другой неудачи вызывается исключение.

Обратите внимание, сами данные принимаются, функцией GetData, через переменную Buffer, как не типизированная последовательность байт длиной BufSize, а тип данных передается отдельно. Такое решение позволяет с помощью одной функции читать данные (значение параметра) любого типа.


PutData

Записывает в текущий ключ значение параметра из буфера. Если параметр с указанным именем не существует, то создает его.

procedure TRegistry.PutData(const Name:string; Buffer:Pointer; BufSize:Integer; RegData:TRegDataType);
procedure Error;
begin
raise ERegistryException.CreateFmt(SRegSetDataFailed, [Name]);

end;

const
RegDataToDataType: array [TRegDataType] of Integer = (REG_NONE, REG_SZ, REG_EXPAND_SZ, REG_DWORD, REG_BINARY);
begin
if RegSetValueEx(CurrentKey, PChar(Name), 0, RegDataToDataType[RegData], Buffer, BufSize) <> ERROR_SUCCESS then Error;

end;

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

Обратите внимание, сами данные передаются, в процедуру PutData, через переменную Buffer, как не типизированная последовательность байт длиной BufSize, а тип данных передается отдельно. Такое решение позволяет с помощью одной процедуры записывать данные (значение параметра) любого типа.


GetKey

Открывает ключ по указанному пути и возвращает его дескриптор.

function TRegistry.GetKey(const Key:string):HKEY;
var
S: string;
Relative: Boolean;
begin
S := Key;
Relative := IsRelative(S);
if not Relative then Delete(S, 1, 1);
Result := 0;
if RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_ALL_ACCESS, Result) <> ERROR_SUCCESS then
RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_READ, Result);

end;

Определяется относительность пути и в случае если он абсолютный, удаляется лидирующий слеш, потому, что для функций Windows требуется относительный путь. С помощью функции RegOpenKeyEx делается попытка открыть ключ, т.е. получить дескриптор в переменой Result, с полным доступом, если не удачно, то хотя бы на чтение.


SetCurrentKey

Назначает указанный дескриптор ключа в качестве текущего.

procedure TRegistry.SetCurrentKey(Value:HKEY);
begin
FCurrentKey := Value;

end;

Дескриптор записывается в поле FCurrentKey и, при очередном открытии файла, будет использоваться как текущий ключ.


SetRootKey

Устанавливает новый корневой каталог.

procedure TRegistry.SetRootKey(Value:HKEY);
begin
if RootKey <> Value then
begin
if FCloseRootKey then
begin
RegCloseKey(RootKey);
FCloseRootKey := False;

end;

FRootKey := Value;
CloseKey;
end;

end;

Проверяет, отличается ли дескриптор нового ключа от старого и если отличается, то приступает к переназначению, иначе заканчивается. Поле FCloseRootKey имеет значение True если подключен реестр удаленного компьютера и в этом случае необходимо закрыть этот дескриптор. Далее устанавливается новое значение дескриптора корневого ключа и закрывается (освобождается) дескриптор текущего ключа.


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

IsRelative

Определяет, является ли указанный путь относительным.

function IsRelative(const Value:string):Boolean;
begin
Result := not ((Value <> '') and (Value[1] = '\'));

end;

Принимает значение True, если строка пустая или первый символ не равен слеш ('\').


Подробное описание доступных (public) методов. Все они находятся в доступной секции класса.

Methods Методы


CloseKey

Закрывает дескриптор текущего ключа и очищает свойства CurrentKey и CurrentPath.

procedure TRegistry.CloseKey;
begin
if CurrentKey <> 0 then
begin
if LazyWrite then
RegCloseKey(CurrentKey) else
RegFlushKey(CurrentKey);

FCurrentKey := 0;
FCurrentPath := '';

end;

end;

Если ключ еще не закрыт, то он закрывается в зависимости от значения LazyWrite. При этом, если LazyWrite равно True, ключ закрывается с отложенной записью на диск (может быть несколько секунд), иначе немедленно (естественно запись на диск происходит в случае модификации ключа) и освобождается память, занятая ключом. Поля FCurrentKey и FCurrentPath очищаются. Функция RegCloseKey записывает данные в кэш оперативной памяти и возвращает управление программе, а реальную запись на диск производит операционная среда позже, в фоновом режиме. В отличие от нее функция RegFlushKey не возвращает управления программе до тех пор, пока не закончится операция физической записи на диск. По этому функция RegFlushKey сильно замедляет выполнение программы, и пользоваться ей надо только в случае крайней необходимости. Для нас это означает, что LazyWrite, по возможности, должна иметь значение True.


CreateKey

Создает ключ по указанному пути.

function TRegistry.CreateKey(const Key:string):Boolean;
var
TempKey: HKey;
S: string;
Disposition: Integer;
Relative: Boolean;
begin
TempKey := 0;
S := Key;
Relative := IsRelative(S);
if not Relative then Delete(S, 1, 1);
Result := RegCreateKeyEx(GetBaseKey(Relative), PChar(S), 0, nil, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nil, TempKey, @Disposition) = ERROR_SUCCESS;
if Result then RegCloseKey(TempKey)
else raise ERegistryException.CreateFmt(SRegCreateFailed, [Key]);

end;

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

В последнем параметре функции RegCreateKeyEx возвращается значение, которое определяет, был ли действительно создан ключ или только открыт существующий, но это значение, как видите, не используется, и узнать сей факт не возможно. Кроме того, у функции есть еще, по крайней мере, два очень интересных параметра, но ими TRregisry не дает управлять. Один из них, пятый в функции, позволяет создавать так называемые энергозависимые (volatile - к сожалению, не знаю как по-русски) ключи, которые не сохраняются после перезагрузки системы. Правда Windows95 не поддерживает такие ключи и видимо по этому метод CreateKey создает только энергонезависимые ключи, которые сохраняются после перезагрузки системы.


DeleteKey

Удаляет ключ и все его подключи, по указанному пути.

function TRegistry.DeleteKey(const Key:string):Boolean;
var
I, Len: Integer;
Relative: Boolean;
S, KeyName: string;
OldKey, DeleteKey: HKEY;
Info: TRegKeyInfo;
begin
S := Key;
Relative := IsRelative(S);
if not Relative then Delete(S, 1, 1);

Определяется относительность пути и в случае если он абсолютный удаляется лидирующий слеш. Дело в том, что сам-то Windows оперирует относительными путями.

OldKey := CurrentKey;
DeleteKey := GetKey(Key);
if DeleteKey <> 0 then

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

try
SetCurrentKey(DeleteKey);
if GetKeyInfo(Info) then
begin
SetString(KeyName, nil, Info.MaxSubKeyLen + 1);
for I := 0 to Info.NumSubKeys - 1 do
begin
Len := Info.MaxSubKeyLen + 1;
if RegEnumKeyEx(DeleteKey, I, PChar(KeyName), Len, nil, nil, nil, nil) = ERROR_SUCCESS then
Self.DeleteKey(PChar(KeyName));

end;

end;

Устанавливаем ключ, подлежащий удалению как текущий ключ. Данный не хитрый ход приходится применять только потому, что метод GetKeyInfo возвращает сведенья о текущем ключе. Если вызов этого метода проходит успешно, а сведения возвращаются в переменной Info, то переходим к перебору всех подключей. Но сначала создаем строку KeyName длиной равной длине самого длинного имени подключа. Далее запрашиваем имя очередного подключа (функция RegEnumKeyEx) и рекурсивно вызываем метод DeleteKey для удаления всех подключей перед удалением основного ключа. Таким образом, метод DeleteKey вызывается для каждого подключа уровней ниже основного, до тех пор, пока не будут удалены все вложенные подключи.

finally
SetCurrentKey(OldKey);
RegCloseKey(DeleteKey);

end;
Result := RegDeleteKey(GetBaseKey(Relative), PChar(S)) = ERROR_SUCCESS;

end;

После удаления всех подключей восстанавливается старый текущий ключ (переменная OldKey) и закрывается ключ, предназначенный на удаление. И на конец с помощью функции RegDeleteKey удаляется только что закрытый ключ, который и требовалось удалить.

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


DeleteValue

Удаляет параметр с указанным именем (и имя и значение) для текущего ключа.

function TRegistry.DeleteValue(const Name:string):Boolean;
begin
Result := RegDeleteValue(CurrentKey, PChar(Name)) = ERROR_SUCCESS;

end;

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


GetDataInfo

Дает сведенья о размере значения и типе параметра по его имени для текущего ключа.

TRegDataType = (rdUnknown, rdString, rdExpandString, rdInteger, rdBinary);
TRegDataInfo = record
RegData: TRegDataType;
DataSize: Integer;

end;

Данный тип служит для получения сведений о размере значения и типе параметра.

function TRegistry.GetDataInfo(const ValueName:string; var Value:TRegDataInfo):Boolean;
var
DataType: Integer;
begin
FillChar(Value, SizeOf(TRegDataInfo), 0);
Result := RegQueryValueEx(CurrentKey, PChar(ValueName), nil, @DataType, nil, @Value.DataSize) = ERROR_SUCCESS;
Value.RegData := DataTypeToRegData(DataType);

end;

Заполняет переменную Value нулями и вызывает функцию RegQueryValueEx для текущего ключа, передавая имя параметра. При этом по возвращению из функции переменная Value в поле DataSize содержит размер значения параметра в байтах, а поле RegData заполняется с помощью функции преобразования DataTypeToRegData потому, что значения типов для Windows и Delphi не полностью совпадают (например, REG_BINARY = 3, а rdBinary = 4). Возвращает True в случае успеха и False иначе.


GetDataSize

Дает размер (в байтах) значения параметра с указанным именем для текущего ключа.

function TRegistry.GetDataSize(const ValueName:string):Integer;
var
Info: TRegDataInfo;
begin
if GetDataInfo(ValueName, Info) then
Result := Info.DataSize else
Result := -1;

end;

Вызывается метод GetDataInfo, если удачно, то возвращается значение поля DataSize (размер значения в байтах), в если нет, то -1.


GetDataType

Дает тип значения параметра с указанным именем для текущего ключа.

function TRegistry.GetDataType(const ValueName:string):TRegDataType;
var
Info: TRegDataInfo;
begin
if GetDataInfo(ValueName, Info) then
Result := Info.RegData else
Result := rdUnknown;

end;

Вызывается метод GetDataInfo , если удачно, то возвращается поле RegData (тип значения), а если нет, то устанавливается rdUnknown.


GetKeyInfo

Дает информацию о текущем ключе.

TRegKeyInfo = record
NumSubKeys: Integer;
MaxSubKeyLen: Integer;
NumValues: Integer;
MaxValueLen: Integer;
MaxDataLen: Integer;
FileTime: TFileTime;

end;

Данный тип необходим для получения информации о ключе. Поля предназначены для возврата в них следующих значений:

function TRegistry.GetKeyInfo(var Value:TRegKeyInfo):Boolean;
begin
FillChar(Value, SizeOf(TRegKeyInfo), 0);
Result := RegQueryInfoKey(CurrentKey, nil, nil, nil, @Value.NumSubKeys, @Value.MaxSubKeyLen, nil, @Value.NumValues, @Value.MaxValueLen, @Value.MaxDataLen, nil, @Value.FileTime) = ERROR_SUCCESS;
if SysLocale.FarEast and (Win32Platform = VER_PLATFORM_WIN32_NT) then
with Value do
begin
Inc(MaxSubKeyLen, MaxSubKeyLen);
Inc(MaxValueLen, MaxValueLen);

end;

end;

Заполняет переменную Value нулями и вызывает функцию RegQueryInfoKey для текущего ключа, подставляя адреса соответствующих полей. Если поддерживаются DBCS (double-byte character set) символы (SysLocale.FarEast := True) и операционная среда WindowsNT, удвоить значение полей длин, потому что два байта на символ. Возвращает True в случае успеха и False иначе.


GetKeyNames

Возвращает список всех дочерних ключей принадлежащих текущему ключу.

procedure TRegistry.GetKeyNames(Strings:TStrings);
var
I, Len: Integer;
Info: TRegKeyInfo;
S: string;
begin
Strings.Clear;
if GetKeyInfo(Info) then
begin
SetString(S, nil, Info.MaxSubKeyLen + 1);
for I := 0 to Info.NumSubKeys - 1 do
begin
Len := Info.MaxSubKeyLen + 1;
RegEnumKeyEx(CurrentKey, I, PChar(S), Len, nil, nil, nil, nil);
Strings.Add(PChar(S));

end;

end;

end;

Очищает список и вызывает метод GetKeyInfo, дающий информацию о текущем ключе, с целью выяснить максимальную длину имени дочернего ключа и количество этих ключей. Если вызов прошел успешно, то создает вспомогательную переменную S размером как самое длинное имя дочернего ключа плюс терминальный ноль. И в цикле с помощью функции RegEnumKeyEx получает имя за именем, добавляя их в список.


GetValueNames

Возвращает список всех имен параметров принадлежащих текущему ключу.

procedure TRegistry.GetValueNames(Strings:TStrings);
var
I, Len: Integer;
Info: TRegKeyInfo;
S: string;
begin
Strings.Clear;
if GetKeyInfo(Info) then
begin
SetString(S, nil, Info.MaxValueLen + 1);
for I := 0 to Info.NumValues - 1 do
begin
Len := Info.MaxValueLen + 1;
RegEnumValue(CurrentKey, I, PChar(S), Len, nil, nil, nil, nil);
Strings.Add(PChar(S));

end;

end;

end;

Очищает список и вызывает метод GetKeyInfo, дающий информацию о текущем ключе, с целью выяснить максимальную длину имен параметров и их количество. Если вызов прошел успешно, то создает вспомогательную переменную S размером как самое длинное имя параметра плюс терминальный ноль. И в цикле с помощью функции RegEnumValue получает имя за именем, добавляя их в список.


HasSubKeys

Возвращает True, если текущий ключ имеет хотя бы один дочерний ключ.

TRegKeyInfo = record
NumSubKeys: Integer;
MaxSubKeyLen: Integer;
NumValues: Integer;
MaxValueLen: Integer;
MaxDataLen: Integer;
FileTime: TFileTime;

end;

Данный тип необходим для получения информации о ключе. Поля предназначены для возврата в них следующих значений:

function TRegistry.HasSubKeys:Boolean;
var
Info: TRegKeyInfo;
begin
Result := GetKeyInfo(Info) and (Info.NumSubKeys > 0);

end;

Вызывает метод GetKeyInfo и в случае удачи проверяет поле NumSubKeys временной переменной Info. Если принять на вооружение описанный прием, то самим методом можно и не пользоваться. Это будет более рационально, так как вы заодно получите в свое распоряжение переменную, которая просто напичкана полезными сведеньями.


KeyExists

Проверка наличия ключа по указанному пути.

function TRegistry.KeyExists(const Key:string):Boolean;
var
TempKey: HKEY;
begin
TempKey := GetKey(Key); if TempKey <> 0 then RegCloseKey(TempKey);
Result := TempKey <> 0;

end;

Вызывает метод GetKey, который пытается открыть указанный ключ и если ему это удается, т.е. ключ существует, возвращает дескриптор отличный от нуля. Это обстоятельство служит основанием для немедленного закрытия ключа (функция RegCloseKey).


LoadKey

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

function TRegistry.LoadKey(const Key, FileName:string):Boolean;
var
S: string;
begin
S := Key;
if not IsRelative(S) then Delete(S, 1, 1);
Result := RegLoadKey(RootKey, PChar(S), PChar(FileName)) = ERROR_SUCCESS;

end;

Если путь абсолютный, удаляется лидирующий слеш, потому что Windows оперирует относительными путями. Вызывается функция RegLoadKey для корневого ключа. Возвращает True в случае удачи и False иначе.


MoveKey

Переносит ключ, его дочерние ключи и параметры в новое место и с новым именем.

procedure TRegistry.MoveKey(const OldName, NewName:string; Delete:Boolean);
var
SrcKey, DestKey: HKEY;

Метод MoveKey содержит три вспомогательные процедуры. Первая, по порядку описания, MoveVlue осуществляет копирование имени и значения для одного параметра.

procedure MoveValue(SrcKey, DestKey: HKEY; const Name:string);
var
Len: Integer;
OldKey, PrevKey: HKEY;
Buffer: PChar;
RegData: TRegDataType;
begin
OldKey := CurrentKey;
SetCurrentKey(SrcKey);

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

try
Len := GetDataSize(Name);
if Len > 0 then
begin
Buffer := AllocMem(Len);

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

try
Len := GetData(Name, Buffer, Len, RegData);
PrevKey := CurrentKey;
SetCurrentKey(DestKey);
try
PutData(Name, Buffer, Len, RegData);

По имени параметра, с помощью метода GetData, получает значение параметра, длину данных этого значения и тип данных. Во временной переменой PrevKey сохраняет ключ источника и назначает ключ приемника в качестве текущего ключа. Вызывая метод PutData записывает данные из буфера в ключ приемника в качестве нового параметра. Тип данных передаваемых через буфер не важен (некоторая последовательность байт), а сам тип передается через переменную RegData.

finally
SetCurrentKey(PrevKey);

end;

finally
FreeMem(Buffer);

end;

end;

finally
SetCurrentKey(OldKey);

end;

end;

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

Вторая процедура CopyValues читает по очереди все параметры источника и с помощью процедуры MoveValue переносит их в ключ приемника.

procedure CopyValues(SrcKey, DestKey: HKEY);
var
I, Len: Integer;
KeyInfo: TRegKeyInfo;
S: string;
OldKey: HKEY;
begin
OldKey := CurrentKey;
SetCurrentKey(SrcKey);

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

try
if GetKeyInfo(KeyInfo) then
begin
MoveValue(SrcKey, DestKey, '');
SetString(S, nil, KeyInfo.MaxValueLen + 1);
for I := 0 to KeyInfo.NumValues - 1 do
begin
Len := KeyInfo.MaxValueLen + 1;
if RegEnumValue(SrcKey, I, PChar(S), Len, nil, nil, nil, nil) = ERROR_SUCCESS then
MoveValue(SrcKey, DestKey, PChar(S));

end;

end;

Вызывает метод GetKeyInfo, для того чтобы узнать количество параметров и размер самого длинного имени параметра. Копирует так называемый параметр по умолчанию (имя равно пустой строке) и для передачи имен параметров создает строку длинной на единицу больше чем размер самого длинного имени. Далее в цикле с помощью функции RegEnumValue получает имя за именем, копируя каждый из них в приемник.

finally
SetCurrentKey(OldKey);

end;

end;

В завершающей части защищенного блока восстанавливает текущий ключ.

Третья процедура CopyKeys рекурсивно копирует все дочерние ключи и принадлежащие им параметры.

procedure CopyKeys(SrcKey, DestKey: HKEY);
var
I, Len: Integer;
Info: TRegKeyInfo;
S: string;
OldKey, PrevKey, NewSrc, NewDest: HKEY;
begin
OldKey := CurrentKey;
SetCurrentKey(SrcKey);

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

try
if GetKeyInfo(Info) then
begin
SetString(S, nil, Info.MaxSubKeyLen + 1);
for I := 0 to Info.NumSubKeys - 1 do
begin
Len := Info.MaxSubKeyLen + 1;
if RegEnumKeyEx(SrcKey, I, PChar(S), Len, nil, nil, nil, nil) = ERROR_SUCCESS then

Вызывает метод GetKeyInfo, для того чтобы узнать количество дочерних ключей и размер самого длинного имени ключа. Для передачи имен ключей создает строку длинной на единицу больше чем размер самого длинного имени. Организует цикл, в котором с помощью функции RegEnumKeyEx получает имя очередного дочернего ключа.

begin
NewSrc := GetKey(PChar(S));
if NewSrc <> 0 then
try
PrevKey := CurrentKey;
SetCurrentKey(DestKey);
try
CreateKey(PChar(S));
NewDest := GetKey(PChar(S));
try
CopyValues(NewSrc, NewDest);
CopyKeys(NewSrc, NewDest);
finally
RegCloseKey(NewDest);

end;

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

finally
SetCurrentKey(PrevKey);

end;

finally
RegCloseKey(NewSrc);

end;

end;

end;

end;

finally
SetCurrentKey(OldKey);

end;

end;

В завершающей части защищенных блоков восстанавливается ключ источника, закрывается ключ нового источника и восстанавливается текущий ключ.

begin
if KeyExists(OldName) and not KeyExists(NewName) then
begin
SrcKey := GetKey(OldName);
if SrcKey <> 0 then
try
CreateKey(NewName);
DestKey := GetKey(NewName);

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

if DestKey <> 0 then
try
CopyValues(SrcKey, DestKey);
CopyKeys(SrcKey, DestKey);
if Delete then DeleteKey(OldName);
finally
RegCloseKey(DestKey);

end;

finally
RegCloseKey(SrcKey);

end;

end;

end;

Если открытие прошло удачно копирует параметры и дочерние ключи. Процедура CopyKeys рекурсивно обходит все дочерние ключи, копируя их параметры и их дочерние ключи, пока не будет скопировано все. Когда этот процесс закончится, проверит значение Delete и если она равна True, удалит ключ источника со всеми входящими в него ключами и параметрами. Закрывает ключи приемника и источника.

Обратите внимание, что при копировании внутрь себя произойдет зацикливание.


OpenKey

Открывает существующий или создает и открывает новый ключ.

function TRegistry.OpenKey(const Key:string; CanCreate:Boolean):Boolean;
var
TempKey: HKey;
S: string;
Disposition: Integer;
Relative: Boolean;
ErrorCode: Integer;
begin
S := Key;
Relative := IsRelative(S);
if not Relative then Delete(S, 1, 1);
TempKey := 0;
if not CanCreate or (S = '') then
begin
ErrorCode := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_ALL_ACCESS, TempKey);
if ErrorCode <> ERROR_SUCCESS then
ErrorCode := RegOpenKeyEx(GetBaseKey(Relative), PChar(S), 0, KEY_READ, TempKey);

Result := ErrorCode = ERROR_SUCCESS;

end else
Result := RegCreateKeyEx(GetBaseKey(Relative), PChar(S), 0, nil, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nil, TempKey, @Disposition) = ERROR_SUCCESS;

if Result then

begin
if (CurrentKey <> 0) and Relative then S := CurrentPath + '\' + S;
ChangeKey(TempKey, S);

end;

end;

Удаляется лидирующий слеш и в зависимости от значения CanCreate открывается или создается новый ключ. Если открытие закончилось успехом, то имеем два открытых дескриптора. Дескриптор текущего (теперь уже старого) ключа и новый переданный в переменной TempKey. Теперь с помощью процедуры ChangeKey освобождаем старый дескриптор и сохраняем новый.

Если параметры ключа не модифицировались, то закрывать его не обязательно. Однако не оставляйте на долго ключ открытым, все-таки реестр это база данных.


ReadBinaryData

Для текущего ключа читает и помещает в буфер двоичное значение указанного параметра.

function TRegistry.ReadBinaryData(const Name:string; var Buffer; BufSize:Integer):Integer;
var
RegData: TRegDataType;
Info: TRegDataInfo;
begin
if GetDataInfo(Name, Info) then
begin
Result := Info.DataSize;
RegData := Info.RegData;
if (RegData = rdBinary) and (Result <>then
GetData(Name, @Buffer, Result, RegData)
else ReadError(Name);

end else Result := 0;

end;

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


ReadBool

Для текущего ключа возвращает логическое представление значения указанного параметра.

function TRegistry.ReadBool(const Name:string):Boolean;
begin
Result := ReadInteger(Name) <> 0;

end;

Вызывается метод ReadInteger. Если полученное целое не равно нулю, то возвращается True, иначе False.


ReadCurrency

Для текущего ключа возвращает денежное представление значения указанного параметра.

function TRegistry.ReadCurrency(const Name:string):Currency;
var
Len: Integer;
RegData: TRegDataType;
begin
Len := GetData(Name, @Result, SizeOf(Currency), RegData);
if (RegData <> rdBinary) or (Len <> SizeOf(Currency)) then
ReadError(Name);

end;

Вызывает метод GetData, который помещает в возвращаемое значение в величину равную значению параметра, устанавливает размер и тип этого значения. Если тип значения не соответствует бинарному или размер значения не равен размеру денежного типа (8 байт), то возбуждается исключение.


ReadDate

Для текущего ключа возвращает дата-время представление значения указанного параметра.

function TRegistry.ReadDate(const Name:string):TDateTime;
begin
Result := ReadDateTime(Name);

end;

Вызывает метод ReadDateTime, без каких либо преобразований.


ReadDateTime

Для текущего ключа возвращает дата-время представление значения указанного параметра.

function TRegistry.ReadDateTime(const Name:string):TDateTime;
var
Len: Integer;
RegData: TRegDataType;
begin
Len := GetData(Name, @Result, SizeOf(TDateTime), RegData);
if (RegData <> rdBinary) or (Len <> SizeOf(TDateTime)) then
ReadError(Name);

end;

Вызывает метод GetData, который помещает в возвращаемое значение в величину равную значению параметра, устанавливает размер и тип этого значения. Если тип значения не соответствует бинарному или размер значения не равен размеру дата-время типа (8 байт), то возбуждается исключение.


ReadFloat

Для текущего ключа возвращает вещественное представление значения указанного параметра.

function TRegistry.ReadFloat(const Name:string):Double;
var
Len: Integer;
RegData: TRegDataType;
begin
Len := GetData(Name, @Result, SizeOf(Double), RegData);
if (RegData <> rdBinary) or (Len <> SizeOf(Double)) then
ReadError(Name);

end;

Вызывает метод GetData, который помещает в возвращаемое значение в величину равную значению параметра, устанавливает размер и тип этого значения. Если тип значения не соответствует бинарному или размер значения не равен размеру вещественного типа (8 байт), то возбуждается исключение.


ReadInteger

Для текущего ключа возвращает целое значение указанного параметра.

function TRegistry.ReadInteger(const Name:string):Integer;
var
RegData: TRegDataType;
begin
GetData(Name, @Result, SizeOf(Integer), RegData);
if RegData <> rdInteger then ReadError(Name);

end;

Вызывает метод GetData, который помещает в возвращаемое значение в величину равную значению параметра и устанавливает тип этого значения. Если тип значения не соответствует целому, то возбуждается исключение.


ReadString

Для текущего ключа возвращает строковое значение указанного параметра.

function TRegistry.ReadString(const Name:string):string;
var
Len: Integer;
RegData: TRegDataType;
begin
Len := GetDataSize(Name);
if Len > 0 then
begin
SetString(Result, nil, Len);
GetData(Name, PChar(Result), Len, RegData);
if (RegData = rdString) or (RegData = rdExpandString) then
SetLength(Result, StrLen(PChar(Result)))
else ReadError(Name);

end
else Result := '';

end;

С помощью метода GetDataSize определяет длину строки, включая терминальный нуль. Если длина больше нуля, то вызовом функции SetString создает строку и заполняет ее вызовом метода GetData. Если тип значения параметра строковый, то возвращенная строка типа PChar преобразуется в Delphi-подобную, путем установки длины строки SetLength. Иначе вызывается исключение.


ReadTime

Для текущего ключа возвращает дата-время представление значения указанного параметра.

function TRegistry.ReadTime(const Name:string):TDateTime;
begin
Result := ReadDateTime(Name);

end;

Вызывает метод ReadDateTime, без каких либо преобразований.


RenameValue

Меняет имя параметра для текущего ключа.

procedure TRegistry.RenameValue(const OldName, NewName:string);
var
Len: Integer;
RegData: TRegDataType;
Buffer: PChar;
begin
if ValueExists(OldName) and not ValueExists(NewName) then
begin
Len := GetDataSize(OldName);
if Len > 0 then
begin
Buffer := AllocMem(Len);
try
Len := GetData(OldName, Buffer, Len, RegData);
DeleteValue(OldName);
PutData(NewName, Buffer, Len, RegData);
finally
FreeMem(Buffer);

end;

end;

end;

end;

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


ReplaceKey

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

function TRegistry.ReplaceKey(const Key, FileName, BackUpFileName:string):Boolean;
var
S: string;
Relative: Boolean;
begin
S := Key;
Relative := IsRelative(S);
if not Relative then Delete(S, 1, 1);
Result := RegReplaceKey(GetBaseKey(Relative), PChar(S), PChar(FileName), PChar(BackUpFileName)) = ERROR_SUCCESS;

end;

Если путь абсолютный, удаляется лидирующий слеш, потому что Windows оперирует относительными путями. Вызывается функция RegReplaceKey для указанного ключа. Возвращает True в случае удачи и False иначе.

В качестве ключа, участвующего в операции замены, можно использовать только ключи первого уровня вложенности от HKEY_LOCAL_MACHINE и HKEY_USER (т.е. являющиеся непосредственными потомками этих двух ключей). Следовательно, в качестве ключа можно использовать любой корневой ключ, при этом строка Key должна быть равна nil. Или имя любого ключа (но не путь), в том числе и вашего, для ключей HKEY_LOCAL_MACHINE и HKEY_USER.


RestoreKey

Загружает в указанный ключ содержимое файла. Только WindowsNT.

function TRegistry.RestoreKey(const Key, FileName:string):Boolean;
var
RestoreKey: HKEY;
begin
Result := False;
RestoreKey := GetKey(Key);
if RestoreKey <> 0 then
try
Result := RegRestoreKey(RestoreKey, PChar(FileName), 0) = ERROR_SUCCESS;
finally
RegCloseKey(RestoreKey);

end;

end;

Указанный ключ открывается путем вызова метода GetKey. Если открытие прошло успешно, вызывается функция RegRestoreKey и по ее окончанию ключ закрывается функцией RegCloseKey.


SaveKey

Сохраняет указанный ключ в файле в виде улья (часть реестра).

function TRegistry.SaveKey(const Key, FileName:string):Boolean;
var
SaveKey: HKEY;
begin
Result := False;
SaveKey := GetKey(Key);
if SaveKey <> 0 then
try
Result := RegSaveKey(SaveKey, PChar(FileName), nil) = ERROR_SUCCESS;
finally
RegCloseKey(SaveKey);

end;

end;

Открывает указанный ключ путем вызова метода GetKey. Если открытие прошло успешно, вызывается функция RegSaveKey. А когда она закончится, ключ закрывается вызовом функции RegCloseKey. Файл, в котором сохраняется ключ, не должен существовать. Ключ сохраняется со всеми параметрами и дочерними ключами (улей - часть реестра).


UnLoadKey

Удаляет ключ созданный с помощью метода LoadK

main_back.gif (3425 bytes)
Используются технологии uCoz