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.