30. august 2013 - 12:59
#10
Det er mit eget program der styrer det hele.
Det er et led i et større projekt hvor jeg er ved at lave nogle generelle moduler til at styre gemme/læse opsætning af program enten i DB, INI, Registry eller XML
Min klasse til XML er nedenfor hvis det giver mening
//*********************************************************
// Class for connecting to XML file
// Used for storing settings
// © OZ8HP Hugo Pedersen
//*********************************************************
unit U_Storage.Xml;
{$I Defines.inc}
interface
uses
Forms, SysUtils, Windows, XmlIntf, XMLDoc;
type
TSettingsConn = class
private
fModified: boolean;
fConfigfile: string;
fXMLDoc: TXMLDocument;
public
constructor Create(const FileName: string); overload;
constructor Create; overload;
property ConfigFile: string read fConfigFile write fConfigFile;
procedure SaveFile;
function ReadString(aSection, aKey, aDefault: string): string;
procedure WriteString(aSection, aKey, aValue: string);
function Readboolean(const aSection, aKey: string; aDefault: boolean): boolean;
procedure Writeboolean(const aSection, aKey: string; aValue: boolean);
function ReadDate(const aSection, aKey: string; const aDefault: TDate): TDate;
procedure WriteDate(const aSection, aKey: string; const aValue: TDate);
function ReadInteger(const aSection, aKey: string; aDefault: integer): integer;
procedure WriteInteger(const aSection, aKey: string; aValue: integer);
procedure AppendSection(const aSection: string);
procedure ClearSection(const aSection : string);
procedure InsertSection(const Old, New : string);
procedure UpdateFile;
end;
var
SettingsConn: TSettingsConn;
implementation
uses
Vcl.Dialogs,
U_AppConsts;
// Start of functions and procedures for helping class
function CleanaValue(aValue: string): string;
begin
aValue := StringReplace(aValue, ' ', '_', [rfReplaceAll, rfIgnoreCase]);
Result := aValue;
end;
function SettingsFileBuild: string;
begin
Result := ChangeFileExt(Application.ExeName, '.xml');
{$IFDEF USESETTINGS}
Result := ExtractFilePath(Application.ExeName) + 'settings.xml';
{$ENDIF}
end;
// End of functions and procedures for helping class
{ TSettingsConn }
constructor TSettingsConn.Create(const FileName: string);
begin
inherited Create;
fConfigfile := FileName;
fXMLDoc := TXMLDocument.Create(Application);
fXMLDoc.Options := [doNodeAutoIndent];
if FileExists(fConfigfile) then
fXMLDoc.LoadFromFile(fConfigfile)
else
begin
fXMLDoc.Active := True;
fXMLDoc.AddChild('Configuration');
fXMLDoc.SaveToFile(fConfigfile);
end;
end;
constructor TSettingsConn.Create;
begin
Create(SettingsFileBuild);
end;
procedure TSettingsConn.SaveFile;
begin
if not fModified then
Exit;
fXMLDoc.Active := True;
fXMLDoc.SaveToFile(fConfigfile);
fModified := False;
end;
// *****************************************************************************
// Everything in XML is read/write as strings
// *****************************************************************************
function TSettingsConn.ReadString(aSection, aKey, aDefault: string): string;
var
Node: IXMLNode;
Child: IXMLNode;
begin
aSection := CleanaValue(aSection);
aKey := CleanaValue(aKey);
Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);
if not Assigned(Node) then
begin
Result := aDefault;
Exit;
end;
Child:= Node.ChildNodes.FindNode(aKey);
if not Assigned(Child) then
begin
Result := aDefault;
Exit;
end;
Result := Child.Text;
end;
procedure TSettingsConn.WriteString(aSection, aKey, aValue: string);
var
Node: IXMLNode;
Child: IXMLNode;
begin
aSection := CleanaValue(aSection);
aKey := CleanaValue(aKey);
if ReadString(aSection, aKey, '') = aValue then
Exit;
Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(aSection);
if not Assigned(Node) then
Node := fXMLDoc.DocumentElement.AddChild(aSection);
Child:= Node.ChildNodes.FindNode(aKey);
if not Assigned(Child) then
Child:= Node.AddChild(aKey);
Child.Text := aValue;
fModified := True;
SaveFile;
end;
// *****************************************************************************
// All other datatypes are converted and read/write as string
// *****************************************************************************
function TSettingsConn.Readboolean(const aSection, aKey: string; aDefault: boolean): boolean;
begin
Result := boolean(ReadInteger(aSection, aKey, integer(aDefault)));
end;
function TSettingsConn.ReadDate(const aSection, aKey: string; const aDefault: TDate): TDate;
begin
Result := StrToDate(ReadString(aSection, aKey, DateToStr(aDefault)));
end;
function TSettingsConn.ReadInteger(const aSection, aKey: string; aDefault: integer): integer;
begin
Result := StrToInt(ReadString(aSection, aKey, IntToStr(aDefault)));
end;
procedure TSettingsConn.Writeboolean(const aSection, aKey: string; aValue: boolean);
begin
WriteInteger(aSection, aKey, Integer(aValue));
end;
procedure TSettingsConn.WriteDate(const aSection, aKey: string; const aValue: TDate);
begin
WriteString(aSection, aKey, DateToStr(aValue));
end;
procedure TSettingsConn.WriteInteger(const aSection, aKey: string; aValue: integer);
begin
WriteString(aSection, aKey, IntToStr(aValue));
end;
// *****************************************************************************
// *****************************************************************************
// Following procedures are here to make all connections look the same
// They are standard in FastIniFile
// *****************************************************************************
procedure TSettingsConn.AppendSection(const aSection: string);
begin
// Dummy procedure to make class look like other connection classes
end;
procedure TSettingsConn.ClearSection(const aSection : string);
begin
// Dummy procedure
end;
procedure TSettingsConn.InsertSection(const Old, New : string);
begin
// Dummy procedure
end;
procedure TSettingsConn.UpdateFile;
begin
// Dummy procedure
end;
// Getters and setters
initialization
SettingsConn := TSettingsConn.Create;
finalization
FreeAndNil(SettingsConn);
end.