DmitryKz В библиотеке EhLib есть TPropStorageEh.
В библиотеке DevExpress есть TPropertiesStore.
Ну и я когдато на заре писал? удобно, чем, что:
- легко расширяется
- не требует подробных указаний, что именно сохранять.
Код: unit VIniValue;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TIniOption = (ioFormCoordinate, ioGridWidth, ioEditValue);
TSetIniOptions = set of TIniOption;
TVIniValue = class(TComponent)
private
FormOnCreate : TNotifyEvent;
FormOnDestroy: TNotifyEvent;
FIniFileName: String;
FAutomatic: Boolean;
FIniOptions: TSetIniOptions;
procedure NewFormOnCreate(Sender : TObject);
procedure NewFormOnDestroy(Sender : TObject);
procedure SetIniFileName(const Value: String);
protected
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); override;
procedure Load;
procedure Save;
published
property Automatic: Boolean read FAutomatic write FAutomatic default True;
property IniFileName: String read FIniFileName write SetIniFileName;
property IniOptions: TSetIniOptions read FIniOptions write FIniOptions;
end;
procedure Register;
implementation
uses
TypInfo, IniFiles, VVCLUtl, VStrUtl;
procedure Register;
begin
RegisterComponents('Victory Common', [TVIniValue]);
end;
{ TVIniValue }
constructor TVIniValue.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAutomatic := True;
end;
procedure TVIniValue.Loaded;
function EqualAddr(Addr1, Addr2: TNotifyEvent): Boolean;
begin
Result := CompareMem(@TMethod(Addr1), @TMethod(Addr2), 8);
end;
begin
inherited Loaded;
if not (csDesigning in ComponentState) then begin
if FIniFileName = '' then FIniFileName := Name;
FIniFileName := ExtractFilePath(ParamStr(0)) + FIniFileName;
if FAutomatic and (Owner is TForm) and not EqualAddr((Owner as TForm).OnCreate, NewFormOnCreate) then begin
FormOnCreate := (Owner as TForm).OnCreate;
(Owner as TForm).OnCreate := NewFormOnCreate;
FormOnDestroy := (Owner as TForm).OnDestroy;
(Owner as TForm).OnDestroy := NewFormOnDestroy;
end;
end;
end;
procedure TVIniValue.NewFormOnCreate(Sender: TObject);
begin
if Assigned(FormOnCreate) then FormOnCreate(Self);
if FAutomatic then Load;
end;
procedure TVIniValue.NewFormOnDestroy(Sender: TObject);
begin
if FAutomatic then Save;
if Assigned(FormOnDestroy) then FormOnDestroy(Self);
end;
procedure TVIniValue.Load;
var
IniFile: TIniFile;
Prop : PPropInfo;
i,j,V: Integer;
s: String;
begin
IniFile := TIniFile.Create(IniFileName);
try
if ioFormCoordinate in IniOptions then begin
V := IniFile.ReadInteger(Owner.Name, 'FormTop', -1);
if V <> -1 then TForm(Owner).Top := V;
V := IniFile.ReadInteger(Owner.Name, 'FormLeft', -1);
if V <> -1 then TForm(Owner).Left := V;
V := IniFile.ReadInteger(Owner.Name, 'FormHeight', -1);
if V <> -1 then TForm(Owner).Height := V;
V := IniFile.ReadInteger(Owner.Name, 'FormWidth', -1);
if V <> -1 then TForm(Owner).Width := V;
V := IniFile.ReadInteger(Owner.Name, 'WindowState', -1);
if (TForm(Owner).FormStyle <> fsMDIChild) and (V <> -1) and TWinControl(Owner).Showing then TForm(Owner).WindowState := TWindowState(V);
end;
for i := 0 to Owner.ComponentCount -1 do begin
if ioEditValue in IniOptions then begin
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Text');
if (Prop <> nil) and (Prop^.PropType^.Kind in [tkString,tkLString,tkWString]) then begin
s := GetStrProp(Owner.Components[i], Prop);
SetStrProp(Owner.Components[i], Prop, IniFile.ReadString(Owner.Name,Owner.Components[i].Name,s));
end;
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Value');
if (Prop <> nil) and (Prop^.PropType^.Kind in [tkString,tkLString,tkWString]) then begin
s := GetStrProp(Owner.Components[i], Prop);
SetStrProp(Owner.Components[i], Prop, IniFile.ReadString(Owner.Name,Owner.Components[i].Name,s));
end;
if (Prop <> nil) and (Prop^.PropType^.Kind = tkInteger) then begin
j := GetOrdProp(Owner.Components[i], Prop);
SetOrdProp(Owner.Components[i], Prop, IniFile.ReadInteger(Owner.Name,Owner.Components[i].Name,j));
end;
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Checked');
if (Prop <> nil) then begin
j := GetOrdProp(Owner.Components[i], Prop);
SetOrdProp(Owner.Components[i], Prop, Ord(IniFile.ReadBool(Owner.Name,Owner.Components[i].Name,Boolean(j))));
end;
end;
end;
finally
IniFile.Free;
end;
end;
procedure TVIniValue.Save;
var
IniFile: TIniFile;
Prop : PPropInfo;
i: Integer;
WS: TWindowState;
begin
IniFile := TIniFile.Create(IniFileName);
try
if ioFormCoordinate in IniOptions then begin
WS := TForm(Owner).WindowState;
if TForm(Owner).WindowState <> wsNormal then TForm(Owner).WindowState := wsNormal;
IniFile.WriteInteger(Owner.Name, 'FormTop', TForm(Owner).Top);
IniFile.WriteInteger(Owner.Name, 'FormLeft', TForm(Owner).Left);
IniFile.WriteInteger(Owner.Name, 'FormHeight', TForm(Owner).Height);
IniFile.WriteInteger(Owner.Name, 'FormWidth', TForm(Owner).Width);
IniFile.WriteInteger(Owner.Name, 'WindowState', Integer(WS));
TForm(Owner).WindowState := WS;
end;
for i := 0 to Owner.ComponentCount -1 do begin
if ioEditValue in IniOptions then begin
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Text');
if (Prop <> nil) and (Prop^.PropType^.Kind in [tkString,tkLString,tkWString]) then
IniFile.WriteString(Owner.Name,Owner.Components[i].Name,GetStrProp(Owner.Components[i], Prop));
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Value');
if (Prop <> nil) and (Prop^.PropType^.Kind in [tkString,tkLString,tkWString]) then
IniFile.WriteString(Owner.Name,Owner.Components[i].Name,GetStrProp(Owner.Components[i], Prop));
if (Prop <> nil) and (Prop^.PropType^.Kind = tkInteger) then
IniFile.WriteInteger(Owner.Name,Owner.Components[i].Name,GetOrdProp(Owner.Components[i], Prop));
Prop := GetPropInfo(Owner.Components[i].ClassInfo, 'Checked');
if (Prop <> nil) then
IniFile.WriteBool(Owner.Name,Owner.Components[i].Name,Boolean(GetOrdProp(Owner.Components[i], Prop)));
end;
end;
finally
IniFile.Free;
end;
end;
procedure TVIniValue.SetIniFileName(const Value: String);
var
S: String;
begin
FIniFileName := Value;
S := Copy(FIniFileName, Length(FIniFileName)-4, 4);
S := AnsiLowerCase(S);
if S <> '.ini' then FIniFileName := FIniFileName+'.ini';
end;
end.