Кто-нибудь знает, как сохранить общие настройки шрифтов моей
формы/пенели/списка и пр. пр. в регистрах; конечно, можно легко обойтись
построчным сохранением, но, к примеру, в случае сохранения свойств шрифтов
количество строк выйдет за пределы разумного - кто нибудь может подсказать мне
решение покороче и полегче?
Delphi имеет маленький секрет, позволяющий рекурсивно сохранять в регистрах
любые публичные свойства объектов. В качестве примера покажем как это работает
для TFont.
uses TypInfo;
{ Определяем тип-набор для доступа к битам целого. }const
BitsPerByte = 8;
type
TIntegerSet = setof 0..SizeOf(Integer) * BitsPerByte - 1;
{ Сохраняем набор свойств в виде подключа. Каждый элемент перечислимого типа -
отдельная логическая величина. Истина означает что элемент включен в набор,
Ложь - элемент в наборе отсутствует. Это позволит пользователю
с помощью редактора ресурсов (REGEDIT) легко изменять конфигурацию. }procedure SaveSetToRegistry(const Name: string; Value: Integer;
TypeInfo: PTypeInfo; Reg: TRegistry);
var
OldKey: string;
I: Integer;
begin
TypeInfo := GetTypeData(TypeInfo)^.CompType;
OldKey := '\' + Reg.CurrentPath;
ifnot Reg.OpenKey(Name, True) thenraise ERegistryException.CreateFmt('Не могу создать ключ: %s',
[Name]);
{ Организуем цикл для всех элементов перечислимого типа. }with GetTypeData(TypeInfo)^ dofor I := MinValue to MaxValue do{ Записываем логическую величину для каждого установленного элемента. }
Reg.WriteBool(GetEnumName(TypeInfo, I), I in
TIntegerSet(Value));
{ Возвращаем родительский ключ. }
Reg.OpenKey(OldKey, False);
end;
{ Сохраняем объект в регистрах в отдельном подключе. }procedure SaveObjToRegistry(const Name: string; Obj: TPersistent;
Reg: TRegistry);
var
OldKey: string;
begin
OldKey := '\' + Reg.CurrentPath;
{ Открываем подключ для объекта. }ifnot Reg.OpenKey(Name, True) thenraise ERegistryException.CreateFmt('Не могу создать ключ: %s',
[Name]);
{ Сохраняем свойства объекта. }
SaveToRegistry(Obj, Reg);
{ Возвращаем родительский ключ. }
Reg.OpenKey(OldKey, False);
end;
{ Сохраняем в регистрах метод путем записи его имени. }procedure SaveMethodToRegistry(const Name: string; const Method:
TMethod;
Reg: TRegistry);
var
MethodName: string;
begin{ Если указатель на метод содержит nil, сохраняем пустую строку. }if Method.Code = nilthen
MethodName := ''
else{ Находим имя метода. }
MethodName := TObject(Method.Data).MethodName(Method.Code);
Reg.WriteString(Name, MethodName);
end;
{ Сохраняем в регистре каждое свойство в виде значения текущего
ключа. }procedure SavePropToRegistry(Obj: TPersistent; PropInfo: PPropInfo;
Reg: TRegistry);
beginwith PropInfo^ docase PropType^.Kind of
tkInteger,
tkChar,
tkWChar:
{ Сохраняем порядковые свойства в виде целочисленного значения. }
Reg.WriteInteger(Name, GetOrdProp(Obj, PropInfo));
tkEnumeration:
{ Сохраняем имена перечислимых величин. }
Reg.WriteString(Name, GetEnumName(PropType, GetOrdProp(Obj,
PropInfo)));
tkFloat:
{ Сохраняем реальные числа как Doubles. }
Reg.WriteFloat(Name, GetFloatProp(Obj, PropInfo));
tkString,
tkLString:
{ Сохраняем строки как строки. }
Reg.WriteString(Name, GetStrProp(Obj, PropInfo));
tkVariant:
{ Сохраняем вариантные величины как строки. }
Reg.WriteString(Name, GetVariantProp(Obj, PropInfo));
tkSet:
{ Сохраняем набор как подключ. }
SaveSetToRegistry(Name, GetOrdProp(Obj, PropInfo), PropType,
Reg);
tkClass:
{ Сохраняем класс как подключ, а его свойства
в виде значений подключа. }
SaveObjToRegistry(Name, TPersistent(GetOrdProp(Obj, PropInfo)),
Reg);
tkMethod:
{ Сохраняем в регистрах метод путем записи его имени. }
SaveMethodToRegistry(Name, GetMethodProp(Obj, PropInfo), Reg);
end;
end;
{ Записываем объект в регистр, сохраняя опубликованные свойства. }procedure SaveToRegistry(Obj: TPersistent; Reg: TRegistry);
var
PropList: PPropList;
PropCount: Integer;
I: Integer;
begin{ Получаем список опубликованных свойств. }
PropCount := GetTypeData(Obj.ClassInfo)^.PropCount;
GetMem(PropList, PropCount * SizeOf(PPropInfo));
try
GetPropInfos(Obj.ClassInfo, PropList);
{ Сохраняем каждое свойство в виде значения текущего ключа. }for I := 0 to PropCount - 1 do
SavePropToRegistry(Obj, PropList^[I], Reg);
finally
FreeMem(PropList, PropCount * SizeOf(PPropInfo));
end;
end;
{ Сохраняем опубликованные свойства в виде значения данного ключа.
Корневой улей - HKEY_CURRENT_USER. }procedure SaveToKey(Obj: TPersistent; const KeyPath: string);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
tryifnot Reg.OpenKey(KeyPath, True) thenraise ERegistryException.CreateFmt('Не могу создать ключ: %s',
[KeyPath]);
SaveToRegistry(Obj, Reg);
finally
Reg.Free;
end;
end;
Секрет Дельфи!
Код, который вы предоставили, - это обертка вокруг компонента TRegistry для сохранения и загрузки публичных свойств объекта в реестре Windows. Идея заключается в том, чтобы рекурсивно хранить свойства как набор булевых значений, которые можно легко редактировать с помощью REGEDIT.
Вот разбивка кода:
SaveSetToRegistry: Процедура принимает целочисленное значение и сохраняет его в виде набора булевых значений в реестре. Она использует цикл для перебора всех элементов типа перечисления и записывает булевое значение для каждого элемента, который является частью множества.
SaveObjToRegistry: Процедура сохраняет публичные свойства объекта в реестре, вызывая SaveToRegistry.
SaveMethodToRegistry: Процедура сохраняет метод как строку в реестре, либо пустую, если указатель на метод равен nil, либо имя метода иначе.
SavePropToRegistry: Процедура сохраняет свойство как значение соответствующего типа в реестре. Она обрабатывает различные типы свойств (целочисленное, символ, перечисление, вещественное, строка, вариант, множество, класс и метод).
SaveToRegistry: Это основная процедура, которая рекурсивно перебирает публичные свойства объекта и сохраняет их в реестре с помощью вышеуказанных процедур.
SaveToKey: Процедура вызывает SaveToRegistry с конкретным путем ключа.
Чтобы использовать этот код, вы создаете экземпляр TRegistry, открываете желаемый ключ в реестре (например, HKEY_CURRENT_USER), а затем вызываете SaveToRegistry или SaveToKey, чтобы сохранить свойства объекта. При загрузке свойств можно использовать соответствующие процедуры (например, LoadSetFromRegistry) для получения значений из реестра.
Обратите внимание, что это реализация является специфичной для Delphi и может не работать с другими языками программирования или фреймворками. Кроме того, будьте осведомлены о ограничениях и безопасности при работе с реестром Windows.
Объекты и TRegistry - это тайный способ Delphi для рекурсивного сохранения любых публичных свойств объектов в регистрах Windows.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.