17.07.2011

Delphi and TAppSettings

Delphi has had Inifle-Support for as long as I can remember. Inifiles are great for storing Application- and Usersettings, but I found myself doing the same things in each Application I wrote. Retrieve an appropiate directory for storing the actual file, creating and freeing the TInifile-Object.
I wanted something that I can just add to my project to store and retrieve simple values in a TInifile-like manner. Here is the result: TAppSettings. It relies on the aforementioned JSON-Library "Delphi Web Utils".
type
  TAppSettings = class
  protected
    fFilename : string;
    fSaveOnFree: boolean;
    fSettings : TJSONObject;
    function createOrGetSection(aSection : string) : TJSONObject;
  public
    constructor Create(aFilename : string);
    destructor Destroy; override;
    procedure Save;

    function getInteger(aSection, aKey : string; aDefault : integer) : integer;
    function getString(aSection, aKey : string; aDefault : string) : string;
    function getFloat(aSection, aKey : string; aDefault : double ) : double;
    function getBool(aSection, aKey : string; aDefault : boolean) : boolean;

    procedure setValue(aSection, aKey : string; aValue : integer); overload;
    procedure setValue(aSection, aKey : string; aValue : string); overload;
    procedure setValue(aSection, aKey : string; aValue : double); overload;
    procedure setValue(aSection, aKey : string; aValue : boolean); overload;

    property SaveOnFree : boolean read fSaveOnFree write fSaveOnFree;
    procedure OpenPathInExplorer;
  end;

As an example the getter and setter for integer:
function TAppSettings.getInteger(aSection, aKey: string;
  aDefault: integer): integer;
var
  section : TJSONObject;
begin
  result := aDefault;
  section := fSettings.optJSONObject(aSection);
  if section <> nil then result := section.optInt(aKey);
end;

function TAppSettings.createOrGetSection(aSection: string): TJSONObject;
begin
  result := fSettings.optJSONObject(aSection);
  if result = nil then
  begin
    result := TJSONObject.create;
    fSettings.put(aSection,result);
  end;
end;

procedure TAppSettings.setValue(aSection, aKey: string; aValue: integer);
var
  section : TJSONObject;
begin
  section := createOrGetSection(aSection);
  section.put(aKey, aValue);
end;

This alone doesn't help with the initial problem, it just changes the format of the file. The interesting part is at the bottom of the unit.
interface

const
  COMPANY_NAME = 'MyCompany';

[...]

var
  AppSettings, UserSettings : TAppSettings;

[...]

function GetSpecialFolder(Folder: Integer): String;
var
  Path: array[0..MAX_PATH] of char;
begin
  If SHGetSpecialFolderPath(0, @Path, Folder, false)
    then Result:=Path
    else Result:='';
end;

function GetApplicationName : string;
begin
  result := ExtractFilename(ParamStr(0));
  delete(result,length(result)-3,4);
end;

initialization
begin
  ForceDirectories(GetSpecialFolder(CSIDL_COMMON_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName);
  ForceDirectories(GetSpecialFolder(CSIDL_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName);
  AppSettings := TAppSettings.Create(GetSpecialFolder(CSIDL_COMMON_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName+'\settings.json');
  UserSettings := TAppSettings.Create(GetSpecialFolder(CSIDL_APPDATA)+'\'+COMPANY_NAME+'\'+GetApplicationName+'\settings.json');
end;

finalization
begin
  AppSettings.Free;
  UserSettings.Free;
end;

Adding this unit to your project automatically creates two Objects of TAppSettings, one for UserSettings and one for ApplicationSettings. Before I wrote TAppSettings I always had two procedures "LoadIni" and "SaveIni" in my application where I would load and save all my application settings, because that were the only places I could access the settings. Now I just use the settings wherever I need them.

You can download the complete unit here.

Keine Kommentare: