Логотип
Vicking.narod.ru
Программирование
Исходные тексты и утилиты

Сохранение настроек в реестр


Гостевая книга
 
 

Лень движет прогресс! Это я к тому, что чем больше я ленюсь набирать тексты программ, тем больше я придумываю всяких инструментов, чтобы облегчить себе труд. На этот раз я изобрел (быть может велосипед, но САМ!) компонент, который свои свойства, объявленные в разделе published, сохраняет в реестре, где укажет ему пользователь.

Как с ним работать?
Итак, у Вашей программы есть какие-то настройки которые хотелось бы сохранять в реестре. Тогда подключаете модуль Config.pas к проекту. Объявляете новый класс, производный от TConfiguration. Теперь объявляете свои свойства в разделе published, они будут сохраняться в реестр и читаться из него соответственно. И все! Теперь можно писать в свойства все, что необходимо, а затем вызвать метод Save. Для чтения данных из реестра, вызывайте метод Load, далее считывайте данные из свойств объекта.

Как класс утроен?
Класс объявлен следующим образом:

type
  TConfiguration = class(TComponent)
  private
    FRoot: Cardinal;
    FKey: string;
  public
    constructor Create(AOwner: TComponent;
      ARoot: Cardinal; AKey: string); reintroduce;
    destructor Destroy; override;
    procedure Save; virtual;
    procedure Load; virtual;
    property Root: Cardinal read FRoot;
    property Key: string read FKey;
  published

  end;

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

Так как класс TConfiguration является производным от TComponent, то он уже имеет два published-свойства: Name и Tag.

Метод Save производит сохранение данных в реестр. Если соответствующие ключи отсутствуют, то они будут созданы автоматически. Его реализация выглядит следующим образом:

procedure TConfiguration.Save;
var
  PropList: PPropList;
  PropCount, i: Integer;
  reg: TRegistry;
begin
  PropCount := GetTypeData(ClassInfo).PropCount;
  GetMem(PropList, SizeOf(PPropInfo)*PropCount);
  reg := TRegistry.Create;
  try
    reg.RootKey := Root;
    PropCount := GetPropList(ClassInfo, [tkInteger,
      tkChar, tkFloat, tkLString, tkInt64],PropList);
    for i:=0 to PropCount - 1 do
    begin
      if (PropList[i].PropType^^.Kind = tkInteger)
        or (PropList[i].PropType^^.Kind = tkInt64)
        or (PropList[i].PropType^^.Kind = tkFloat) then
      begin
        reg.OpenKey(Key, True);
        reg.WriteString(PropList[i].Name,
          FloatToStr(GetPropValue(Self,PropList[i].Name)));
        reg.CloseKey;
        Continue;
      end;
      if (PropList[i].PropType^^.Kind = tkLString)
        or (PropList[i].PropType^^.Kind = tkChar) then
      begin
        reg.OpenKey(Key, True);
        reg.WriteString(PropList[i].Name,
          GetPropValue(Self,PropList[i].Name));
        reg.CloseKey;
        Continue;
      end;
      {------- Другие типы данных -------}
    end;
  finally
    FreeMem(PropList);
    reg.Free;
  end;
end;

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

procedure TConfiguration.Load;
var
  PropList: PPropList;
  PropCount, i: Integer;
  reg: TRegistry;
  val: String;
begin
  // получаем общее количество свойств
  PropCount := GetTypeData(ClassInfo).PropCount;

  // резервируем память
  GetMem(PropList, SizeOf(PPropInfo)*PropCount);

  // создаем объект реестра
  reg := TRegistry.Create;
  try
    // устанавливаем корневой каталог
    reg.RootKey := Root;

    // получаем кол-во отфильтрованных свойств
    PropCount := GetPropList(ClassInfo,
      [tkInteger, tkChar, tkFloat, tkLString, tkInt64], PropList);

    // перебираем их по очереди
    for i:=0 to PropCount - 1 do
    begin
      // если числовой тип
      if (PropList[i].PropType^^.Kind = tkInteger)
        or (PropList[i].PropType^^.Kind = tkInt64)
        or (PropList[i].PropType^^.Kind = tkFloat) then
      begin
        // открываем (создаем) ключ
        reg.OpenKey(Key, True);
        // пытаемся читать из реестра
        val := reg.ReadString(PropList[i].Name);
        //если удалось, то пишем значение в свойство
        if val <> '' then
          SetPropValue(Self,PropList[i].Name, StrToFloatDef(val,0));
        // зарываем ключ
        reg.CloseKey;
        Continue;
      end;
      // Если строковой тип
      if (PropList[i].PropType^^.Kind = tkLString)
        or (PropList[i].PropType^^.Kind = tkChar) then
      begin
        reg.OpenKey(Key, True);
        val := reg.ReadString(PropList[i].Name);
        SetPropValue(Self,PropList[i].Name, val);
        reg.CloseKey;
        Continue;
      end;

      {------- Другие типы данных -------}

    end;
  finally
    // высвобождаем память
    FreeMem(PropList);
    reg.Free;
  end;
end;

Какие ограничения?
В данной реализации следующие ограничения на типы данных: разрешается сохранять любые числа (дробные и целые), строки, а также одиночные символы (Char) . Не предусмотрена возможность сохранения перечислимых типов, классов, массивов и т.п. Однако, у Вас всегда остается возможность перегрузить методы Save и Load.

Найти модуль можно здесь: config.zip (2 КБ)


© Зинкевич Виктор, 2005 г.

 



Hosted by uCoz