Explorar o código

Quick.Commons new date utils

Unknown %!s(int64=6) %!d(string=hai) anos
pai
achega
02712300a9

+ 22 - 2
Quick.Commons.pas

@@ -1,13 +1,13 @@
 { ***************************************************************************
 
-  Copyright (c) 2016-2018 Kike Pérez
+  Copyright (c) 2016-2019 Kike Pérez
 
   Unit        : Quick.Commons
   Description : Common functions
   Author      : Kike Pérez
   Version     : 1.5
   Created     : 14/07/2017
-  Modified    : 14/10/2018
+  Modified    : 18/01/2019
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -194,6 +194,10 @@ type
   {$ENDIF}
   //checks if two datetimes are in same day
   function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
+  //change Time of a DateTime
+  function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
+  //change Date of a DateTime
+  function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
   //returns n times a char
   function FillStr(const C : Char; const Count : Byte) : string;
   //checks if string exists in array of string
@@ -547,6 +551,22 @@ begin
   Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
 end;
 
+function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
+var
+  y, m, d : Word;
+begin
+  DecodeDate(aDate,y,m,d);
+  Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
+end;
+
+function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
+var
+  h, m, s, ms : Word;
+begin
+  DecodeTime(aDate,h,m,s,ms);
+  Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
+end;
+
 function FillStr(const C : Char; const Count : Byte) : string;
 var
   i   : Byte;

+ 215 - 0
Quick.Config.Base.pas

@@ -0,0 +1,215 @@
+{ ***************************************************************************
+
+  Copyright (c) 2015-2018 Kike Pérez
+
+  Unit        : Quick.Config
+  Description : Load/Save config from/to JSON file
+  Author      : Kike Pérez
+  Version     : 1.5
+  Created     : 26/01/2017
+  Modified    : 10/12/2018
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+
+unit Quick.Config.Base;
+
+interface
+
+{$i QuickLib.inc}
+
+uses
+  Classes,
+  SysUtils,
+  Rtti,
+  {$IFDEF FPC}
+  fpjson,
+  jsonparser,
+  fpjsonrtti,
+  Quick.Json.Serializer;
+  {$ELSE}
+  Quick.Json.Serializer,
+  DBXJSON,
+  System.JSON,
+  Rest.Json.Types,
+  Rest.Json;
+  {$ENDIF}
+
+type
+
+  TDateTimeZone = (tzLocal, tzUTC);
+
+  TAppConfig = class;
+
+  IAppConfigProvider = interface
+  ['{D55B1EBF-47F6-478B-8F70-9444575CB825}']
+    procedure Load(cConfig : TAppConfig);
+    procedure Save(cConfig : TAppConfig);
+  end;
+
+  TSerializeProperty = (spPublic, spPublished);
+
+  TAppConfigProviderBase = class(TInterfacedObject,IAppConfigProvider)
+  private
+    fCreateIfNotExists : Boolean;
+    fSerializeLevel : TSerializeProperty;
+  protected
+    procedure Load(cConfig : TAppConfig); virtual; abstract;
+    procedure Save(cConfig : TAppConfig); virtual; abstract;
+  public
+    constructor Create; virtual;
+    property CreateIfNotExists : Boolean read fCreateIfNotExists write fCreateIfNotExists;
+    property SerializeLevel : TSerializeProperty read fSerializeLevel write fSerializeLevel;
+  end;
+
+  TApplyConfigEvent = procedure of object;
+
+  {$IFDEF DELPHIXE2_UP}[JsonSerialize(TJsonMemberSerialization.&Public)]{$ENDIF}
+  TAppConfig = class
+  private
+    {$IFDEF FPC}
+    fOnApplyConfig : TApplyConfigEvent;
+    fDateTimeZone: TDateTimeZone;
+    fJsonIndent: Boolean;
+    fLastSaved : TDateTime;
+    {$ELSE}
+    {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
+    fOnApplyConfig : TApplyConfigEvent;
+    {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
+    fDateTimeZone: TDateTimeZone;
+    {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
+    fJsonIndent: Boolean;
+    {$IF CompilerVersion < 32.0}[JSONMarshalledAttribute(False)]{$ENDIF}
+    fLastSaved : TDateTime;
+    {$ENDIF}
+  protected
+    function GetProvider : IAppConfigProvider; virtual; abstract;
+  public
+    constructor Create; virtual;
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
+    property OnApplyConfig : TApplyConfigEvent read fOnApplyConfig write fOnApplyConfig;
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
+    property DateTimeZone : TDateTimeZone read fDateTimeZone write fDateTimeZone;
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
+    property JsonIndent : Boolean read fJsonIndent write fJsonIndent;
+    {$IFDEF DELPHIRX102_UP}[JsonIgnoreAttribute]{$ENDIF}
+    property LastSaved : TDateTime read fLastSaved write fLastSaved;
+    procedure Apply;
+    procedure DefaultValues; virtual;
+    procedure Load;
+    procedure Save;
+    function ToJSON : string;
+    procedure FromJSON(const json : string);
+  end;
+
+  {Usage: create a descend class from TAppConfig and add published properties to be loaded/saved
+
+  TMyConfig = class(TAppConfig)
+  private
+    fName : string;
+    fSurname : string;
+    fStatus : Integer;
+  published
+    property Name : string read fName write fName;
+    property SurName : string read fSurname write fSurname;
+    property Status : Integer read fStatus write fStatus;
+  end;
+
+  AppConfigProvider := TAppConfigJsonProvider<TMyConfig>.Create(MyConfig);
+  MyConfig.Name := 'John';
+  }
+
+implementation
+
+
+{ TAppConfigProviderBase }
+
+constructor TAppConfigProviderBase.Create;
+begin
+  fCreateIfNotExists := True;
+  fSerializeLevel := spPublished;
+end;
+
+{ TAppConfig }
+
+constructor TAppConfig.Create;
+begin
+  fDateTimeZone := TDateTimeZone.tzLocal;
+  fJsonIndent := True;
+  fLastSaved := 0;
+end;
+
+procedure TAppConfig.Apply;
+begin
+  if Assigned(fOnApplyConfig) then fOnApplyConfig;
+end;
+
+procedure TAppConfig.DefaultValues;
+begin
+  //inherit to set default values if no config exists before
+end;
+
+
+function TAppConfig.ToJSON : string;
+var
+  Serializer : TJsonSerializer;
+begin
+  Result := '';
+  try
+    serializer := TJsonSerializer.Create(slPublishedProperty);
+    try
+      Result := serializer.ObjectToJSON(Self,True);
+    finally
+      serializer.Free;
+    end;
+  except
+    on e : Exception do raise Exception.Create(e.Message);
+  end;
+end;
+
+procedure TAppConfig.FromJSON(const json : string);
+var
+  Serializer : TJsonSerializer;
+begin
+  try
+    serializer := TJsonSerializer.Create(slPublishedProperty);
+    try
+      {$IF NOT DEFINED(FPC) AND DEFINED(ANDROID)}
+      serializer.JsonToObject(Self,json);
+      {$ELSE}
+      Self := TAppConfig(serializer.JsonToObject(Self,json));
+      {$ENDIF}
+    finally
+      serializer.Free;
+    end;
+  except
+    on e : Exception do raise Exception.Create(e.Message);
+  end;
+end;
+
+procedure TAppConfig.Load;
+begin
+  GetProvider.Load(Self);
+end;
+
+procedure TAppConfig.Save;
+begin
+  GetProvider.Save(Self);
+end;
+
+end.

+ 171 - 0
Quick.Config.Json.pas

@@ -0,0 +1,171 @@
+{ ***************************************************************************
+
+  Copyright (c) 2015-2018 Kike Pérez
+
+  Unit        : Quick.Config.Provider.Json
+  Description : Save config to JSON file
+  Author      : Kike Pérez
+  Version     : 1.4
+  Created     : 21/10/2017
+  Modified    : 10/12/2018
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+unit Quick.Config.Json;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  {$IFDEF DELPHIXE_UP}
+  IOUtils,
+  {$ELSE}
+  Quick.Files,
+  {$ENDIF}
+  Rtti,
+  Quick.Json.Serializer,
+  {$IFDEF FPC}
+  fpjson,
+  fpjsonrtti,
+  {$ELSE}
+  Rest.Json.Types,
+  System.JSON,
+  {$ENDIF}
+  Quick.Config.Base;
+
+type
+
+  TAppConfigJsonProvider = class(TAppConfigProviderBase)
+  private
+    fFilename : string;
+    procedure Load(cConfig : TAppConfig); override;
+    procedure Save(cConfig : TAppConfig); override;
+  public
+    constructor Create; override;
+    property Filename : string read fFilename write fFilename;
+  end;
+
+  TAppConfigJson = class(TAppConfig)
+  private
+    fProvider : TAppConfigJsonProvider;
+    function GetProvider : IAppConfigProvider; override;
+  public
+    constructor Create; override;
+    destructor Destroy; override;
+    property Provider : TAppConfigJsonProvider read fProvider write fProvider;
+  end;
+
+
+implementation
+
+constructor TAppConfigJsonProvider.Create;
+begin
+  inherited Create;
+  fFilename := TPath.ChangeExtension(ParamStr(0),'json');
+end;
+
+procedure TAppConfigJsonProvider.Load(cConfig : TAppConfig);
+var
+  json : TStrings;
+  Serializer : TJsonSerializer;
+begin
+  //create object with rtti if nil
+  //if not Assigned(Config) then Config := InitObject;
+
+  if (not FileExists(fFilename)) and (CreateIfNotExists) then
+  begin
+    TAppConfig(cConfig).DefaultValues;
+    Self.Save(cConfig);
+  end;
+
+  try
+    json := TStringList.Create;
+    try
+      json.LoadFromFile(fFilename);
+      serializer := TJsonSerializer.Create(slPublishedProperty);
+      try
+        //Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+        //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        serializer.JsonToObject(cConfig,json.Text);
+      finally
+        serializer.Free;
+      end;
+    finally
+      json.Free;
+    end;
+  except
+    on e : Exception do raise e;
+  end;
+end;
+
+procedure TAppConfigJsonProvider.Save(cConfig : TAppConfig);
+var
+  json : TStrings;
+  Serializer : TJsonSerializer;
+  ctx : TRttiContext;
+  rprop : TRttiProperty;
+begin
+  //create object with rtti if nil
+  if not Assigned(cConfig) then cConfig := TAppConfigJson.Create;
+
+  try
+    json := TStringList.Create;
+    try
+      serializer := TJsonSerializer.Create(TSerializeLevel.slPublishedProperty);
+      try
+        //Streamer.Options := Streamer.Options + [jsoDateTimeAsString ,jsoUseFormatString];
+        //Streamer.DateTimeFormat := 'yyyy-mm-dd"T"hh:mm:ss.zz';
+        json.Text := serializer.ObjectToJson(cConfig,True);
+      finally
+        serializer.Free;
+      end;
+      json.SaveToFile(fFilename);
+      cConfig.LastSaved := Now;
+    finally
+      json.Free;
+    end;
+  except
+    on e : Exception do raise e;
+  end;
+end;
+
+
+{ TAppConfigJson }
+
+constructor TAppConfigJson.Create;
+begin
+  inherited;
+  fProvider := TAppConfigJsonProvider.Create;
+end;
+
+
+destructor TAppConfigJson.Destroy;
+begin
+  if Assigned(fProvider) then fProvider.Free;
+  inherited;
+end;
+
+function TAppConfigJson.GetProvider: IAppConfigProvider;
+begin
+  Result := fProvider;
+end;
+
+end.

+ 562 - 0
Quick.Config.Registry.pas

@@ -0,0 +1,562 @@
+{ ***************************************************************************
+
+  Copyright (c) 2015-2018 Kike Pérez
+
+  Unit        : Quick.Config.Provider.Registry
+  Description : Save config to Windows Registry
+  Author      : Kike Pérez
+  Version     : 1.2
+  Created     : 21/10/2017
+  Modified    : 12/09/2018
+
+  This file is part of QuickLib: https://github.com/exilon/QuickLib
+
+ ***************************************************************************
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ *************************************************************************** }
+unit Quick.Config.Registry;
+
+{$i QuickLib.inc}
+
+interface
+
+uses
+  Classes,
+  Windows,
+  SysUtils,
+  Registry,
+  Quick.Json.Serializer,
+  {$IFDEF DELPHIRX102_UP}
+    System.Json,
+    System.JSON.Types,
+  {$ELSE}
+    {$IFDEF FPC}
+    fpjson,
+    //jsonparser,
+    //fpjsonrtti,
+    Quick.Json.fpc.Compatibility,
+    {$ELSE}
+    Rest.Json.Types,
+    System.JSON,
+    Rest.Json,
+    {$ENDIF}
+  {$ENDIF}
+  Quick.Commons,
+  Quick.Config.Base;
+
+type
+
+  TAppConfigRegistryProvider = class(TAppConfigProviderBase)
+  private
+    fRootKey : HKEY;
+    fMainKey : string;
+    fRegConfig : TRegistry;
+    function JsonToRegistry(const StrJson : string) : Boolean;
+    function RegistryToJson(out StrJson : string) : Boolean;
+    class function IsSimpleJsonValue(v: TJSONValue): Boolean;
+    function IsRegKeyObject(const cCurrentKey : string = '') : Boolean;
+    function IsRegKeyArray(const cCurrentKey : string = '') : Boolean;
+    function ProcessPairRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
+    function ProcessElementRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
+    procedure ProcessPairWrite(const cCurrentKey: string; obj: TJSONObject; aIndex: integer);
+    procedure ProcessElementWrite(const cCurrentKey: string; arr: TJSONArray; aIndex, aMax : integer);
+    function AddRegKey(const cCurrentKey, NewKey : string) : Boolean;
+    function ReadRegValue(const cCurrentKey, cName : string) : TJSONValue;
+    procedure AddRegValue(const cCurrentKey, cName : string; cValue : TJSONValue);
+  protected
+    procedure Load(cConfig : TAppConfig); override;
+    procedure Save(cConfig : TAppConfig); override;
+  public
+    constructor Create; override;
+    destructor Destroy; override;
+    property HRoot : HKEY read fRootKey write fRootKey;
+    property MainKey : string read fMainKey write fMainKey;
+  end;
+
+  EAppConfig = Exception;
+
+  TAppConfigRegistry = class(TAppConfig)
+  private
+    fProvider : TAppConfigRegistryProvider;
+    function GetProvider : IAppConfigProvider; override;
+  public
+    constructor Create; override;
+    destructor Destroy; override;
+    property Provider : TAppConfigRegistryProvider read fProvider write fProvider;
+  end;
+
+
+implementation
+
+
+{ TAppConfigRegistryProvider }
+
+constructor TAppConfigRegistryProvider.Create;
+begin
+  inherited Create;
+  fRootKey := HKEY_CURRENT_USER;
+  fMainKey := '_AppConfig';
+  fRegConfig := TRegistry.Create(KEY_READ or KEY_WRITE);
+end;
+
+destructor TAppConfigRegistryProvider.Destroy;
+begin
+  if Assigned(fRegConfig) then fRegConfig.Free;
+  inherited;
+end;
+
+procedure TAppConfigRegistryProvider.Load(cConfig : TAppConfig);
+var
+  Serializer: TJsonSerializer;
+  json : string;
+begin
+  fRegConfig.Access := KEY_READ;
+  fRegConfig.RootKey := fRootKey;
+  if not fRegConfig.KeyExists('\Software\' + fMainKey) then
+  begin
+    if not CreateIfNotExists then raise EAppConfig.Create('Not exists MainKey in registry!');
+    Save(cConfig);
+  end;
+  RegistryToJson(json);
+  serializer := TJsonSerializer.Create(slPublishedProperty);
+  try
+    serializer.JsonToObject(cConfig,json);
+  finally
+    serializer.Free;
+  end;
+end;
+
+procedure TAppConfigRegistryProvider.Save(cConfig : TAppConfig);
+begin
+  JsonToRegistry(cConfig.ToJSON);
+end;
+
+function TAppConfigRegistryProvider.JsonToRegistry(const StrJson : string) : Boolean;
+var
+  jValue  : TJSONValue;
+  aCount : Integer;
+  i : Integer;
+  aCurrentKey : string;
+begin
+  Result := False;
+  if fMainKey = '' then raise EAppConfig.Create('MainKey not defined!');
+
+  fRegConfig.Access := KEY_READ or KEY_WRITE;
+  fRegConfig.RootKey := fRootKey;
+  aCurrentKey := '\Software\' + fMainKey;
+
+  if fRegConfig.KeyExists(aCurrentKey) then
+  begin
+    try
+     if fRegConfig.KeyExists(aCurrentKey + '_bak') then fRegConfig.DeleteKey(aCurrentKey + '_bak');
+     fRegConfig.MoveKey(aCurrentKey,aCurrentKey + '_bak',True);
+    except
+      raise EAppConfig.Create('Can''t write Config Registry');
+    end;
+  end;
+  try
+    if not AddRegKey('\Software',fMainKey) then
+    begin
+      raise EAppConfig.Create('Can''t create key');
+    end;
+
+    {$IFNDEF FPC}
+    jValue := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONValue;
+    {$ELSE}
+    jValue := TJSONObject.ParseJSONValue(StrJson) as TJSONValue;
+    {$ENDIF}
+    try
+      if IsSimpleJsonValue(jValue) then
+      begin
+        {$IFNDEF FPC}
+        AddRegValue(aCurrentKey,TJSONPair(jValue).JsonString.ToString.DeQuotedString('"'),TJSONPair(jValue).JsonValue);
+        {$ELSE}
+        AddRegValue(aCurrentKey,TJSONPair(jValue).JsonString.DeQuotedString('"'),TJSONPair(jValue).JsonValue);
+        {$ENDIF}
+      end
+      {$IFNDEF FPC}
+      else if jValue is TJSONObject then
+      {$ELSE}
+      else if jvalue.JSONType = jtObject then
+      {$ENDIF}
+      begin
+        aCount := TJSONObject(jValue).Count;
+        for i := 0 to aCount - 1 do
+          ProcessPairWrite(aCurrentKey,TJSONObject(jValue),i);
+      end
+      {$IFNDEF FPC}
+      else if jValue is TJSONArray then
+      {$ELSE}
+      else if jValue.JSONType = jtArray then
+      {$ENDIF}
+      begin
+        aCount := TJSONArray(jValue).Count;
+        for i := 0 to aCount - 1 do
+          ProcessElementWrite(aCurrentKey,TJSONArray(jValue),i,aCount);
+      end
+      else raise EAppConfig.Create('Error Saving config to Registry');
+      Result := True;
+    finally
+       jValue.Free;
+    end;
+    if fRegConfig.KeyExists(aCurrentKey + '_bak') then fRegConfig.DeleteKey(aCurrentKey + '_bak');
+  except
+    fRegConfig.DeleteKey(aCurrentKey);
+    fRegConfig.MoveKey(aCurrentKey+'_bak',aCurrentKey,True);
+  end;
+end;
+
+function TAppConfigRegistryProvider.RegistryToJson(out StrJson : string) : Boolean;
+var
+  jValue  : TJSONValue;
+  jPair : TJSONPair;
+  jArray : TJSONArray;
+  a, b : string;
+  aCount : Integer;
+  i : Integer;
+  aName : string;
+  aValue : TJSONValue;
+  aCurrentKey : string;
+  newObj : TJSONObject;
+  RegKeyList : TStringList;
+  RegValueList : TStringList;
+  RegKey : string;
+  RegValue : string;
+  RegKeyInfo : TRegKeyInfo;
+begin
+  Result := False;
+  //check if exists root key
+  fRegConfig.Access := KEY_READ;
+  fRegConfig.RootKey := fRootKey;
+  if fRegConfig.KeyExists('\Software\' + fMainKey) then
+  begin
+    fRegConfig.OpenKeyReadOnly('\Software\' + fMainKey);
+    aCurrentKey := '\Software\' + fMainKey;
+  end
+  else raise EAppConfig.Create('Can''t read key');
+
+  newObj := TJSONObject.Create;
+  try
+    //read root values
+    RegValueList := TStringList.Create;
+    try
+      fRegConfig.GetValueNames(RegValueList);
+      for RegValue in RegValueList do
+      begin
+        newObj.AddPair(RegValue,ReadRegValue(aCurrentKey,RegValue));
+      end;
+    finally
+      RegValueList.Free;
+    end;
+    //read root keys
+    RegKeyList := TStringList.Create;
+    try
+      fRegConfig.GetKeyNames(RegKeyList);
+      for RegKey in RegKeyList do
+      begin
+        fRegConfig.OpenKeyReadOnly(aCurrentKey + '\' + RegKey);
+        if IsRegKeyObject then
+        begin
+          jValue := ProcessPairRead(aCurrentKey + '\' + RegKey,Regkey,i);
+          newObj.AddPair(RegKey,jValue);
+        end
+        else if IsRegKeyArray then
+        begin
+          jValue := ProcessElementRead(aCurrentKey + '\' + RegKey,Regkey,i);
+          newObj.AddPair(RegKey,jValue);
+        end
+        else raise EAppConfig.Create('Unknow value reading Config Registry');
+      end;
+    finally
+      RegKeyList.Free;
+    end;
+    StrJson := newObj.ToJSON;
+  finally
+    newObj.Free;
+  end;
+end;
+
+function TAppConfigRegistryProvider.IsRegKeyObject(const cCurrentKey : string = '') : Boolean;
+begin
+  Result := not IsRegKeyArray(cCurrentKey);
+end;
+
+function TAppConfigRegistryProvider.IsRegKeyArray(const cCurrentKey : string = '') : Boolean;
+var
+  RegValue : string;
+  RegValueList : TStrings;
+  RegKey : string;
+  RegKeyList : TStrings;
+  n : Integer;
+begin
+  Result := False;
+  if cCurrentKey <> '' then fRegConfig.OpenKeyReadOnly(cCurrentKey);
+  //check if exists RegKey numeric (indicates is a Array)
+  RegKeyList := TStringList.Create;
+  try
+    fRegConfig.GetKeyNames(RegKeyList);
+    for RegKey in RegKeyList do
+      if TryStrToInt(RegKey,n) then
+      begin
+        Result := True;
+        Break;
+      end;
+  finally
+    RegKeyList.Free;
+  end;
+  //check if exists RegValue numeric (indicates is a Array)
+  RegValueList := TStringList.Create;
+  try
+    fRegConfig.GetValueNames(RegValueList);
+    for RegValue in RegValueList do
+      if TryStrToInt(RegValue,n) then
+      begin
+        Result := True;
+        Break;
+      end;
+  finally
+    RegValueList.Free;
+  end;
+end;
+
+class function TAppConfigRegistryProvider.IsSimpleJsonValue(v: TJSONValue): Boolean;
+begin
+  Result := (v is TJSONNumber)
+    or (v is TJSONString)
+    {$IFNDEF FPC}
+    or (v is TJSONTrue)
+    or (v is TJSONFalse)
+    {$ELSE}
+    or (v is TJsonBool)
+    {$ENDIF}
+    or (v is TJSONNull);
+end;
+
+function TAppConfigRegistryProvider.ReadRegValue(const cCurrentKey, cName : string) : TJSONValue;
+var
+  aValue : string;
+  RegInfo : TRegDataInfo;
+begin
+  if fRegConfig.OpenKeyReadOnly(cCurrentKey) then
+  begin
+    if fRegConfig.GetDataInfo(cName,RegInfo) then
+    case RegInfo.RegData of
+      rdInteger : Result := TJSONNumber.Create(fRegConfig.ReadInteger(cName));
+      rdString :
+        begin
+          aValue := fRegConfig.ReadString(cName);
+          if aValue.ToLower = 'true' then Result := TJSONBool.Create(True)
+           else if aValue.ToLower = 'false' then Result := TJSONBool.Create(False)
+            else Result := TJSONString.Create(aValue);
+        end;
+      else Result := TJSONNull.Create;
+    end;
+  end;
+end;
+
+function TAppConfigRegistryProvider.AddRegKey(const cCurrentKey, NewKey : string) : Boolean;
+begin
+  Result := fRegConfig.CreateKey(Format('%s\%s',[cCurrentKey,NewKey]));
+end;
+
+procedure TAppConfigRegistryProvider.AddRegValue(const cCurrentKey, cName : string; cValue : TJSONValue);
+var
+  aName : string;
+  aValue : string;
+begin
+  aName := cName.DeQuotedString('"');
+  aValue := cValue.ToString.DeQuotedString('"');
+  fRegConfig.OpenKey(cCurrentKey,True);
+  if cValue is TJSONNumber then  fRegConfig.WriteInteger(aName,StrToInt64(aValue))
+   else if cValue is TJSONString then fRegConfig.WriteString(aName,aValue)
+    else if cValue is TJSONBool then fRegConfig.WriteString(aName,aValue);
+      //else if cValue is TJSONNull then fRegConfig.WriteString(aName,'');
+end;
+
+function TAppConfigRegistryProvider.ProcessPairRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
+var
+  i : Integer;
+  jValue : TJSONValue;
+  RegValue : string;
+  RegValueList : TStrings;
+  RegKey : string;
+  RegKeyList : TStrings;
+  newObj : TJSONObject;
+begin
+  newObj := TJSONObject.Create;
+  //read root values
+  RegValueList := TStringList.Create;
+  try
+    fRegConfig.GetValueNames(RegValueList);
+    for RegValue in RegValueList do
+    begin
+      newObj.AddPair(RegValue,ReadRegValue(cCurrentKey,RegValue));
+    end;
+  finally
+    RegValueList.Free;
+  end;
+  //read root keys
+  RegKeyList := TStringList.Create;
+  try
+    fRegConfig.GetKeyNames(RegKeyList);
+    for RegKey in RegKeyList do
+    begin
+      fRegConfig.OpenKeyReadOnly(cCurrentKey + '\' + RegKey);
+      if IsRegKeyObject then
+      begin
+        jValue := ProcessPairRead(cCurrentKey + '\' + RegKey,Regkey,i);
+        newObj.AddPair(RegKey,jValue);
+      end
+      else if IsRegKeyArray then
+      begin
+        jValue := ProcessElementRead(cCurrentKey + '\' + RegKey,Regkey,i);
+        newObj.AddPair(RegKey,jValue);
+      end
+      else raise EAppConfig.Create('Unknow value reading Config Registry');
+    end;
+  finally
+    RegKeyList.Free;
+  end;
+  Result := TJsonValue(newObj);
+end;
+
+function TAppConfigRegistryProvider.ProcessElementRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
+var
+  i : Integer;
+  jValue : TJSONValue;
+  RegValue : string;
+  RegValueList : TStrings;
+  RegKey : string;
+  RegKeyList : TStrings;
+  newObj : TJSONArray;
+begin
+  newObj := TJSONArray.Create;
+  //read root values
+  RegValueList := TStringList.Create;
+  try
+    fRegConfig.GetValueNames(RegValueList);
+    for RegValue in RegValueList do
+    begin
+      newObj.AddElement(ReadRegValue(cCurrentKey,RegValue));
+    end;
+  finally
+    RegValueList.Free;
+  end;
+  //read root keys
+  RegKeyList := TStringList.Create;
+  try
+    fRegConfig.GetKeyNames(RegKeyList);
+    for RegKey in RegKeyList do
+    begin
+      fRegConfig.OpenKeyReadOnly(cCurrentKey + '\' + RegKey);
+      if IsRegKeyObject then
+      begin
+        jValue := ProcessPairRead(cCurrentKey + '\' + RegKey,Regkey,i);
+        newObj.AddElement(jValue);
+      end
+      else if IsRegKeyArray then
+      begin
+        jValue := ProcessElementRead(cCurrentKey + '\' + RegKey,Regkey,i);
+        newObj.AddElement(jValue);
+      end
+      else raise EAppConfig.Create('Unknow value reading Config Registry');
+    end;
+  finally
+    RegKeyList.Free;
+  end;
+  Result := TJsonValue(newObj);
+end;
+
+procedure TAppConfigRegistryProvider.ProcessPairWrite(const cCurrentKey: string; obj: TJSONObject; aIndex: integer);
+var
+  jPair: TJSONPair;
+  i : Integer;
+  aCount: integer;
+begin
+  jPair := obj.Pairs[aIndex];
+
+  if IsSimpleJsonValue(jPair.JsonValue) then
+  begin
+    AddRegValue(cCurrentKey,jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF},jPair.JsonValue);
+    Exit;
+  end;
+
+  if jPair.JsonValue is TJSONObject then
+  begin
+    aCount := TJSONObject(jPair.JsonValue).Count;
+    for i := 0 to aCount - 1 do
+      ProcessPairWrite(cCurrentKey + '\' + jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF}.DeQuotedString('"'), TJSONObject(jPair.JsonValue),i);
+  end
+  else if jPair.JsonValue is TJSONArray then
+  begin
+    aCount := TJSONArray(jPair.JsonValue).Count;
+    for i := 0 to aCount - 1 do
+      ProcessElementWrite(cCurrentKey + '\' + jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF}.DeQuotedString('"'), TJSONArray(jPair.JsonValue),i,aCount);
+  end
+  else raise EAppConfig.Create('Error Saving config to Registry');
+end;
+
+procedure TAppConfigRegistryProvider.ProcessElementWrite(const cCurrentKey: string; arr: TJSONArray; aIndex, aMax: integer);
+var
+  jValue: TJSONValue;
+  i : Integer;
+  aCount: integer;
+  dig : Integer;
+begin
+  jValue := arr.Items[aIndex];
+  dig := CountDigits(aMax);
+
+  if IsSimpleJsonValue(jValue) then
+  begin
+    AddRegValue(cCurrentKey,Zeroes(aIndex,dig),jValue);
+    Exit;
+  end;
+
+  if jValue is TJSONObject then
+  begin
+    aCount := TJSONObject(jValue).Count;
+    for i := 0 to aCount - 1 do
+      ProcessPairWrite(cCurrentKey + '\' + Zeroes(aIndex,dig),TJSONObject(jValue),i);
+  end
+  else if jValue is TJSONArray then
+  begin
+    aCount := TJSONArray(jValue).Count;
+    for i := 0 to aCount - 1 do
+      ProcessElementWrite(cCurrentKey + '\' + Zeroes(i,dig),TJSONArray(jValue),i,aCount);
+  end
+  else raise EAppConfig.Create('Error Saving config to Registry');
+end;
+
+{ TAppConfigRegistry }
+
+constructor TAppConfigRegistry.Create;
+begin
+  inherited;
+  fProvider := TAppConfigRegistryProvider.Create;
+end;
+
+destructor TAppConfigRegistry.Destroy;
+begin
+  if Assigned(fProvider) then fProvider.Free;
+  inherited;
+end;
+
+function TAppConfigRegistry.GetProvider: IAppConfigProvider;
+begin
+  Result := fProvider;
+end;
+
+end.
+

+ 15 - 0
samples/delphi/QuickConfig/ConfigToRegistry/ConfigToRegistry.dpr

@@ -0,0 +1,15 @@
+program ConfigToRegistry;
+
+uses
+  Vcl.Forms,
+  Main in 'Main.pas' {MainForm};
+
+{$R *.res}
+
+begin
+  ReportMemoryLeaksOnShutdown := True;
+  Application.Initialize;
+  Application.MainFormOnTaskbar := True;
+  Application.CreateForm(TMainForm, MainForm);
+  Application.Run;
+end.

+ 652 - 0
samples/delphi/QuickConfig/ConfigToRegistry/ConfigToRegistry.dproj

@@ -0,0 +1,652 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <ProjectGuid>{CDEBAD41-A241-457F-96FD-E367D8E3B0AE}</ProjectGuid>
+        <ProjectVersion>18.5</ProjectVersion>
+        <FrameworkType>VCL</FrameworkType>
+        <MainSource>ConfigToRegistry.dpr</MainSource>
+        <Base>True</Base>
+        <Config Condition="'$(Config)'==''">Debug</Config>
+        <Platform Condition="'$(Platform)'==''">Win64</Platform>
+        <TargetedPlatforms>3</TargetedPlatforms>
+        <AppType>Application</AppType>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
+        <Base_Win32>true</Base_Win32>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
+        <Base_Win64>true</Base_Win64>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
+        <Cfg_1>true</Cfg_1>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
+        <Cfg_1_Win32>true</Cfg_1_Win32>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
+        <Cfg_1_Win64>true</Cfg_1_Win64>
+        <CfgParent>Cfg_1</CfgParent>
+        <Cfg_1>true</Cfg_1>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
+        <Cfg_2>true</Cfg_2>
+        <CfgParent>Base</CfgParent>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
+        <Cfg_2_Win32>true</Cfg_2_Win32>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
+        <Cfg_2_Win64>true</Cfg_2_Win64>
+        <CfgParent>Cfg_2</CfgParent>
+        <Cfg_2>true</Cfg_2>
+        <Base>true</Base>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base)'!=''">
+        <DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
+        <DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
+        <DCC_E>false</DCC_E>
+        <DCC_N>false</DCC_N>
+        <DCC_S>false</DCC_S>
+        <DCC_F>false</DCC_F>
+        <DCC_K>false</DCC_K>
+        <DCC_UsePackage>RESTComponents;FireDACIBDriver;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
+        <Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
+        <UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
+        <UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
+        <SanitizedProjectName>ConfigToRegistry</SanitizedProjectName>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win32)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;UbuntuProgressPackage;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;svnui;JvGlobus;FireDACADSDriver;JvPluginSystem;JvMM;vacommpkgdXE11;tmsxlsdXE11;vcltouch;JvBands;vcldb;bindcompfmx;svn;Intraweb;JvJans;JvNet;inetdb;JvAppFrm;EssentialsDR;vcwdedXE11;vcwdXE11;FmxTeeUI;JvDotNetCtrls;AbbreviaVCLD;fmx;fmxdae;tmsdXE11;vclib;JvWizards;tmsexdXE11;dbexpress;IndyCore;vclx;JvPageComps;dsnap;JvDB;VCLRESTComponents;JclDeveloperTools;vclie;bindengine;DBXMySQLDriver;JvCmp;FireDACMySQLDriver;JvHMI;FireDACCommonODBC;LockBoxDR;bindcompdbx;IndyIPCommon;JvCustom;advchartdedxe11;vcl;IndyIPServer;GR32_D;JvXPCtrls;PngComponents;IndySystem;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;vclimg;vacommpkgdedXE11;TeeDB;Jcl;madBasic_;JvCore;JvCrypt;FireDACPgDriver;ibmonitor;FMXTee;SevenZippro;DbxCommonDriver;JvDlgs;JvRuntimeDesign;ibxpress;Tee;JvManagedThreads;xmlrtl;ibxbindings;fmxobj;vclwinx;JvTimeFramework;rtl;GR32_R;DbxClientDriver;QuickVCL;CustomIPTransport;vcldsnap;JvSystem;JvStdCtrls;DCEF_DX10;bindcomp;appanalytics;tmswizdXE11;CoolTrayIcon_D210_XE7;IndyIPClient;bindcompvcl;TeeUI;TMSFMXPackPkgDXE11;JvDocking;dbxcds;VclSmp;JvPascalInterpreter;adortl;JclVcl;Gauge3D;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;JvControls;JvPrintPreview;Analog_XE7;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Base_Win64)'!=''">
+        <DCC_UsePackage>DBXSqliteDriver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;vcltouch;vcldb;bindcompfmx;Intraweb;inetdb;EssentialsDR;vcwdXE11;FmxTeeUI;AbbreviaVCLD;fmx;fmxdae;tmsdXE11;vclib;tmsexdXE11;dbexpress;IndyCore;vclx;dsnap;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACMySQLDriver;FireDACCommonODBC;bindcompdbx;IndyIPCommon;vcl;IndyIPServer;IndySystem;advchartdxe11;dsnapcon;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDACPgDriver;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;Tee;xmlrtl;ibxbindings;fmxobj;vclwinx;rtl;DbxClientDriver;QuickVCL;CustomIPTransport;vcldsnap;DCEF_DX10;bindcomp;appanalytics;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;dsnapxml;dbrtl;inetdbxpress;IndyProtocols;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
+        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
+        <BT_BuildType>Debug</BT_BuildType>
+        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
+        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
+        <VerInfo_Locale>1033</VerInfo_Locale>
+        <Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1)'!=''">
+        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
+        <DCC_DebugDCUs>true</DCC_DebugDCUs>
+        <DCC_Optimize>false</DCC_Optimize>
+        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
+        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
+        <DCC_RemoteDebug>true</DCC_RemoteDebug>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
+        <DCC_RemoteDebug>false</DCC_RemoteDebug>
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2)'!=''">
+        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
+        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
+        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
+        <DCC_DebugInformation>0</DCC_DebugInformation>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
+        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
+        <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
+    </PropertyGroup>
+    <ItemGroup>
+        <DelphiCompile Include="$(MainSource)">
+            <MainSource>MainSource</MainSource>
+        </DelphiCompile>
+        <DCCReference Include="Main.pas">
+            <Form>MainForm</Form>
+            <FormType>dfm</FormType>
+        </DCCReference>
+        <BuildConfiguration Include="Release">
+            <Key>Cfg_2</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Base">
+            <Key>Base</Key>
+        </BuildConfiguration>
+        <BuildConfiguration Include="Debug">
+            <Key>Cfg_1</Key>
+            <CfgParent>Base</CfgParent>
+        </BuildConfiguration>
+    </ItemGroup>
+    <ProjectExtensions>
+        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
+        <Borland.ProjectType>Application</Borland.ProjectType>
+        <BorlandProject>
+            <Delphi.Personality>
+                <Source>
+                    <Source Name="MainSource">ConfigToRegistry.dpr</Source>
+                </Source>
+            </Delphi.Personality>
+            <Deployment Version="3">
+                <DeployFile LocalName="Win64\Debug\ConfigToRegistry.rsm" Configuration="Debug" Class="DebugSymbols">
+                    <Platform Name="Win64">
+                        <RemoteName>ConfigToRegistry.rsm</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win32\Debug\ConfigToRegistry.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>ConfigToRegistry.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win64\Debug\ConfigToRegistry.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win64">
+                        <RemoteName>ConfigToRegistry.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployClass Name="AdditionalDebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidClassesDexFile">
+                    <Platform Name="Android">
+                        <RemoteDir>classes</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidFileProvider">
+                    <Platform Name="Android">
+                        <RemoteDir>res\xml</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidGDBServer">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeArmeabiFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidLibnativeMipsFile">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\mips</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidServiceOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashImageDef">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStyles">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="AndroidSplashStylesV21">
+                    <Platform Name="Android">
+                        <RemoteDir>res\values-v21</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_DefaultAppIcon">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon144">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xxhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon36">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-ldpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon48">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-mdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon72">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-hdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_LauncherIcon96">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xhdpi</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage426">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-small</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage470">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-normal</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage640">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-large</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="Android_SplashImage960">
+                    <Platform Name="Android">
+                        <RemoteDir>res\drawable-xlarge</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DebugSymbols">
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyFramework">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.framework</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="DependencyModule">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.dll;.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="DependencyPackage">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                        <Extensions>.dylib</Extensions>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                        <Extensions>.bpl</Extensions>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="File">
+                    <Platform Name="Android">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
+                        <Operation>0</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1024">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch1536">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch2048">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPad_Launch768">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch320">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="iPhone_Launch640x1136">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectAndroidManifest">
+                    <Platform Name="Android">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceDebug">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSDeviceResourceRules">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSEntitlements">
+                    <Platform Name="iOSDevice32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSInfoPList">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectiOSResource">
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXDebug">
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXEntitlements">
+                    <Platform Name="OSX32">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>..\</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXInfoPList">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectOSXResource">
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\Resources</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Required="true" Name="ProjectOutput">
+                    <Platform Name="Android">
+                        <RemoteDir>library\lib\armeabi-v7a</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSDevice64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="iOSSimulator">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Linux64">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="OSX64">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win32">
+                        <Operation>0</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="ProjectUWPManifest">
+                    <Platform Name="Win32">
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo150">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <DeployClass Name="UWP_DelphiLogo44">
+                    <Platform Name="Win32">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                    <Platform Name="Win64">
+                        <RemoteDir>Assets</RemoteDir>
+                        <Operation>1</Operation>
+                    </Platform>
+                </DeployClass>
+                <ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
+                <ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
+                <ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
+            </Deployment>
+            <Platforms>
+                <Platform value="Win32">True</Platform>
+                <Platform value="Win64">True</Platform>
+            </Platforms>
+            <ModelSupport>False</ModelSupport>
+        </BorlandProject>
+        <ProjectFileVersion>12</ProjectFileVersion>
+    </ProjectExtensions>
+    <Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
+    <Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
+    <Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
+</Project>

BIN=BIN
samples/delphi/QuickConfig/ConfigToRegistry/ConfigToRegistry.res


+ 52 - 0
samples/delphi/QuickConfig/ConfigToRegistry/Main.dfm

@@ -0,0 +1,52 @@
+object MainForm: TMainForm
+  AlignWithMargins = True
+  Left = 0
+  Top = 0
+  Caption = 'Quick Config Demo'
+  ClientHeight = 493
+  ClientWidth = 720
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  OnClose = FormClose
+  OnCreate = FormCreate
+  DesignSize = (
+    720
+    493)
+  PixelsPerInch = 96
+  TextHeight = 13
+  object meInfo: TMemo
+    Left = 8
+    Top = 8
+    Width = 704
+    Height = 441
+    Anchors = [akLeft, akTop, akRight, akBottom]
+    ReadOnly = True
+    ScrollBars = ssBoth
+    TabOrder = 0
+  end
+  object btnLoadRegistry: TButton
+    Left = 407
+    Top = 464
+    Width = 145
+    Height = 25
+    Anchors = [akRight, akBottom]
+    Caption = 'Load From Registry'
+    TabOrder = 1
+    OnClick = btnLoadRegistryClick
+  end
+  object SaveRegistry: TButton
+    Left = 558
+    Top = 464
+    Width = 154
+    Height = 25
+    Anchors = [akRight, akBottom]
+    Caption = 'Save To Registry'
+    TabOrder = 2
+    OnClick = SaveRegistryClick
+  end
+end

+ 209 - 0
samples/delphi/QuickConfig/ConfigToRegistry/Main.pas

@@ -0,0 +1,209 @@
+unit Main;
+
+interface
+
+uses
+  Winapi.Windows,
+  Winapi.Messages,
+  System.SysUtils,
+  System.Variants,
+  System.Classes,
+  Vcl.Graphics,
+  Vcl.Controls,
+  Vcl.Forms,
+  Vcl.Dialogs,
+  Vcl.StdCtrls,
+  System.Generics.Collections,
+  Quick.Config.Base,
+  Quick.Config.Registry;
+
+type
+
+  TMyPriority = (msLow, msMed, msHigh);
+
+  TWinPos = record
+  public
+    PosX : Integer;
+    PosY : Integer;
+  end;
+
+  TProcessType = record
+    Id : Integer;
+    Priority : TMyPriority;
+    Redundant : Boolean;
+  end;
+
+  TWorker = class
+  private
+    fName : string;
+    fActive : Boolean;
+  published
+    property Name : string read fName write fName;
+    property Active : Boolean read fActive write fActive;
+  end;
+
+  TMyConfig = class(TAppConfigRegistry)
+  private
+    fTitle : string;
+    fHidden : Boolean;
+    fSessionName: string;
+    fSizes : TArray<Integer>;
+    fLastFilename : string;
+    fWindowPos : TWinPos;
+    fHistory : TArray<TProcessType>;
+    fComplex : TProcessType;
+    fModifyDate : TDateTime;
+    fWorkList : TObjectList<TWorker>;
+  published
+    property Sizes : TArray<Integer> read fSizes write fSizes;
+    property LastFilename : string read fLastFilename write fLastFilename;
+    property WindowPos : TWinPos read fWindowPos write fWindowPos;
+    property History : TArray<TProcessType> read fHistory write fHistory;
+    property Complex : TProcessType read fComplex write fComplex;
+    property ModifyDate : TDateTime read fModifyDate write fModifyDate;
+    property Title : string read fTitle write fTitle;
+    property SessionName : string read fSessionName write fSessionName;
+    property WorkList : TObjectList<TWorker> read fWorkList write fWorkList;
+  public
+    constructor Create; override;
+    destructor Destroy; override;
+    procedure DefaultValues; override;
+  end;
+
+  TMainForm = class(TForm)
+    meInfo: TMemo;
+    btnLoadRegistry: TButton;
+    SaveRegistry: TButton;
+    procedure FormCreate(Sender: TObject);
+    procedure SaveRegistryClick(Sender: TObject);
+    procedure btnLoadRegistryClick(Sender: TObject);
+    procedure SetConfig(cConfig: TMyConfig);
+    function TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+    procedure FormClose(Sender: TObject; var Action: TCloseAction);
+  end;
+
+var
+  MainForm: TMainForm;
+  ConfigTest : TMyConfig;
+  ConfigReg : TMyConfig;
+
+implementation
+
+{$R *.dfm}
+
+procedure TMainForm.btnLoadRegistryClick(Sender: TObject);
+begin
+  meInfo.Lines.Add('Load ConfigReg');
+  ConfigReg.Load;
+  meInfo.Lines.Add(ConfigReg.ToJSON);
+  if TestConfig(configtest,ConfigReg) then meInfo.Lines.Add('Test passed successfully!');
+ end;
+
+procedure TMainForm.SaveRegistryClick(Sender: TObject);
+begin
+  SetConfig(ConfigReg);
+  ConfigReg.Save;
+  meInfo.Lines.Add('Saved Config in Registry at ' + DateTimeToStr(ConfigReg.LastSaved));
+end;
+
+procedure TMainForm.SetConfig(cConfig : TMyConfig);
+var
+  winpos : TWinpos;
+  protype : TProcessType;
+  i : Integer;
+  worker : TWorker;
+begin
+  cConfig.LastFilename := 'library.txt';
+  cConfig.Sizes := [23,11,554,12,34,29,77,30,48,59,773,221,98,3,22,983,122,231,433,12,31,987];
+  winpos.PosX := 640;
+  winpos.PosX := 480;
+  cConfig.WindowPos := winpos;
+  protype.Priority := msHigh;
+  protype.Redundant := False;
+  cConfig.Complex := protype;
+  cConfig.Title := 'a fresh title';
+  cConfig.SessionName := 'First Session';
+  for I := 0 to 22 do
+  begin
+    worker := TWorker.Create;
+    worker.Name := 'Process ' + i.ToString;
+    worker.Active := Boolean(Random(1));
+    cConfig.WorkList.Add(worker);
+  end;
+  for i := 0 to 15 do
+  begin
+    protype.Id := i;
+    protype.Priority := msLow;
+    protype.Redundant := True;
+    cConfig.History := cConfig.History + [protype];
+  end;
+  cConfig.ModifyDate := Now();
+end;
+
+function  TMainForm.TestConfig(cConfig1, cConfig2 : TMyConfig) : Boolean;
+var
+  i : Integer;
+begin
+  Result := False;
+  try
+    Assert(cConfig1.LastFilename = cConfig2.LastFilename);
+    for i := Low(cConfig1.Sizes) to High(cConfig1.Sizes) do
+      Assert(cConfig1.Sizes[i] = cConfig2.Sizes[i]);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.WindowPos.PosX = cConfig2.WindowPos.PosX);
+    Assert(cConfig1.Complex.Priority = cConfig2.Complex.Priority);
+    Assert(cConfig1.Complex.Redundant  = cConfig2.Complex.Redundant);
+    Assert(cConfig1.Title = cConfig2.Title);
+    for i := 0 to cConfig1.WorkList.Count - 1 do
+    begin
+      Assert(cConfig1.WorkList[i].Name = cConfig2.WorkList[i].Name);
+      Assert(cConfig1.WorkList[i].Active = cConfig2.WorkList[i].Active);
+    end;
+    for i := 0 to High(cConfig1.History) do
+    begin
+      Assert(cConfig1.History[i].Priority = cConfig2.History[i].Priority);
+      Assert(cConfig1.History[i].Redundant = cConfig2.History[i].Redundant);
+    end;
+    Result := True;
+  except
+    ShowMessage('Configuration not has been saved previously or has a corruption problem');
+  end;
+end;
+
+procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+  if Assigned(ConfigReg) then ConfigReg.Free;
+end;
+
+procedure TMainForm.FormCreate(Sender: TObject);
+begin
+  ConfigReg := TMyConfig.Create;
+  ConfigReg.Provider.HRoot := HKEY_CURRENT_USER;
+  ConfigReg.Provider.MainKey := '_AppConfig';
+  //create config test to compare later
+  ConfigTest := TMyConfig.Create;
+  SetConfig(ConfigTest);
+end;
+
+{ TMyConfig }
+
+constructor TMyConfig.Create;
+begin
+  inherited;
+  WorkList := TObjectList<TWorker>.Create(True);
+  DefaultValues;
+end;
+
+procedure TMyConfig.DefaultValues;
+begin
+  inherited;
+  fTitle := 'Default value';
+end;
+
+destructor TMyConfig.Destroy;
+begin
+  if Assigned(WorkList) then WorkList.Free;
+  inherited;
+end;
+
+end.