{
  iniquick. pas
    Modifico wdstate.pas (ver debajo) añadiendo una StringList
    para guardar valores. Me quedo sólo con el INI

  wdwstate.pas
    v2.0 of 18/10/1999
      Components that can record read and restore a window's state, position and
      size using ini files or the registry.
}

{
  History
  - v1.0 of 15/08/1999
      Original version of TIniQuick component that stores window state
      information in ini files.
  - v2.0 of 18/10/1999
      Re-write which added TPJRegWdwState component that stores window state
      information in registry. Extracted common functionality of TIniQuick and
      TPJRegWdwState into new abstract base class TCustomIniquick. TIniQuick
      presents same interface and functionality as version 1. TRegWdwState is
      not compile under Delphi 2.
}

{
  Dependencies
      NONE
}

{
  Legal notice
    This component is copyright © P.D.Johnson, 1999.
    The source code and help files can be freely distributed on a not-for-profit
    basis providing that:
      + the source code is not altered.
      + this readme file is distributed with it unchanged
    By not-for-profit I mean that you may recover out of pocket expenses
    incurred in distributing the code, but should not make a profit from this.
    If you discover any bugs in this implementation, or if you have any update
    suggestions, please contact me on peter.johnson@openlink.org.
    Please do modify the code for you own use. I'd like to see any changes you
    make - I could incorporate them into future versions. Please notify me of
    changes on at the above e-mail address.
    This software is provided as is - no warranty is given as to its suitability
    for any purposes to which you may wish to put it.
}


unit iniquick;

interface

uses
  Classes, WinTypes, WinProcs, Forms, IniFiles
  ;

type
  {Abstract base class for components that record window size, position and
  state between program executions}
  TCustomIniquick = class(TComponent)
  private {properties}
    FIgnoreState : Boolean;
    FMoreData : Boolean;
  private
    FWindow : TForm;
      {Instance of window on which to operate}
    FStorageID : string;
      {Identifies storage used for window information - eg ini file name or
      registry sub-key}
    FData : TStrings;
  protected
    procedure ReadStatus(var Left, Top, Width, Height, State : Integer);
      virtual; abstract;
      {Read state of window from storage - user passes default values and method
      returns new values from storage, or defaults if no stored values found.
      Implementation depends on method of storage used by derived classes}
    procedure SaveState(const Left, Top, Width, Height, State : Integer);
      virtual; abstract;
      {Save state of window to storage per given values. Implementation depends
      on method of storage used by derived classes}
    function GetStorageID : string;
      {Returns identification of where information is stored - can be ini file
      name or registry sub-key}
    procedure SetStorageID(AnID : string); virtual;
      {Sets identification of where window information is stored - can be ini
      file name or registry sub-key. Can be overriden to add additional
      processing}
    procedure SaveData; virtual; abstract;
    procedure ReadData; virtual; abstract;
  public
    constructor Create(AOwner: TComponent); override;
      {Class constructor}
    procedure Restore;
      {Read window placement and state from storage and set up the window}
    procedure Save;
      {Save window placement and size to storage}
    property Data : TStrings read FData write FData;
    procedure PutStr(nombre,valor:String);
    function GetStr(nombre:String):String;
    function GetStrD(nombre,defaultS:String):String;
    procedure PutInt(nombre:String;valor:Integer);
    function GetInt(nombre:String):Integer;
    function GetIntD(nombre:String;defaultV:integer):Integer;

  published
    property IgnoreState : Boolean read FIgnoreState write FIgnoreState;
      {When true Restore method ignores the saved state of the window and leaves
      current state unchanged while still setting size and position. When false
      Restore also sets the window state according to the saved state}
    property MoreData : Boolean read FMoreData write FMoreData;
  end;

  {Implements window state storage via ini file}
  TIniQuick = class(TCustomIniquick)
  private {properties}
    FSection : string;
    procedure SetSection(AnID : string); virtual;
  protected
    procedure ReadStatus(var Left, Top, Width, Height, State : Integer);
      override;
      {Reads window state from ini file using given values as defaults}
    procedure SaveState(const Left, Top, Width, Height, State : Integer);
      override;
      {Writes window state to ini file}
    procedure SetStorageID(AnID : string); override;
      {Sets ini file name to given value - or to default name if AnID is false}
    procedure SaveData; override;
    procedure ReadData; override;
  public
    constructor Create(AOwner: TComponent); override;
      {Overridden class constructor sets default section name}
    destructor Destroy; override;
  published
    property IniFileName : string read GetStorageID write SetStorageID;
      {The name of the ini file in which to save window information - uses path
      and name of executable with extension replaced by .ini if set to empty
      string}
    property Section : string read FSection write SetSection;
      {The name of the section in ini file in which to save window information -
      uses "Main Window" if passed emtpy string}
  end;


procedure Register;

implementation

uses
  SysUtils;

constructor TIniQuick.Create(AOwner: TComponent);
  {Overridden class constructor sets default section name}
begin
  inherited Create(AOwner);
  SetSection('');
  FData:=TStringList.Create;
end;

destructor TIniQuick.Destroy;
begin
  FData.Free;
  inherited Destroy;
end;

procedure TIniQuick.ReadStatus(var Left, Top, Width, Height, State : Integer);
  {Reads window state from ini file using given values as defaults}
var
  Ini : TIniFile;             {Instance of ini file class used to read info}
begin
  {Open .ini file and read window info from it}
  Ini := TIniFile.Create(GetStorageID);
  try
    Left := Ini.ReadInteger(Section, 'Left', Left);
    Top := Ini.ReadInteger(Section, 'Top', Top);
    Width := Ini.ReadInteger(Section, 'Width', Width);
    Height := Ini.ReadInteger(Section, 'Height', Height);
    State := Ini.ReadInteger(Section, 'State', State);
  finally
    Ini.Free;
  end;
end;

procedure TIniQuick.ReadData;
var
  Ini : TIniFile;             {Instance of ini file class used to read info}
begin
  {Open .ini file and read window info from it}
  Ini := TIniFile.Create(GetStorageID);
  try
    Ini.ReadSectionValues('General',FData);
  finally
    Ini.Free;
  end;
end;

procedure TIniQuick.SaveState(const Left, Top, Width, Height, State
  : Integer);
  {Writes window state to ini file}
var
  Ini : TIniFile;             {Instance of ini file class used to read info}
begin
  {Open .ini file and write window info to it}
  Ini := TIniFile.Create(GetStorageID);
  try
    Ini.WriteInteger(Section, 'Left', Left);
    Ini.WriteInteger(Section, 'Top', Top);
    Ini.WriteInteger(Section, 'Width', Width);
    Ini.WriteInteger(Section, 'Height', Height);
    Ini.WriteInteger(Section, 'State', State);
  finally
    Ini.Free;
  end;
end;

procedure TIniQuick.SaveData;
var
  Ini : TIniFile;             {Instance of ini file class used to read info}
  i : integer;
begin
  Ini := TIniFile.Create(GetStorageID);
  try
    Ini.EraseSection('General');
  except
  end;
  if FData.Count>0 then
  for i:=0 to FData.Count-1 do begin
    try
      Ini.WriteString('General',FData.Names[i],FData.Values[FData.Names[i]]);
    except
    end;
  end;
  Ini.Free;
end;

procedure TIniQuick.SetStorageID(AnID : string);
  {Sets ini file name to given value - or to default name if AnID is false}
begin
  if (AnID = '') and not (csDesigning in ComponentState) then
    {User provided empty string - set default (but only when we're not
    designing}
    AnID := ChangeFileExt(Application.ExeName, '.ini');
  {Now record adjusted ID}
  inherited SetStorageID(AnID);
end;

procedure TIniQuick.SetSection(AnID : string);
  {Write access method for Section property - records section file name and
  substitutes default value of 'Main Window' if name provided is nul string.
  This substitution doesn't take place when designing the form}
begin
  FSection := AnID;
  if (AnID = '') and not (csDesigning in ComponentState) then
    FSection := 'Main Window';
end;



constructor TCustomIniquick.Create(AOwner: TComponent);
  {Class constructor}
var
  TheForm : TComponent;       {The form that ultimately owns this component}
begin
  {Call inherited constructor}
  inherited Create(AOwner);
  {Check if owner is a form, if not, move up tree of owners until we either find
  a form or a nil reference}
  TheForm := AOwner;
  while (TheForm <> nil) and not (TheForm is TForm) do
    TheForm := TheForm.Owner;
  {Record form window reference appropriately}
  if TheForm <> nil then
    FWindow := TheForm as TForm
  else
    FWindow := nil;
  {Set default idnetifier for where window info is to be kept}
  SetStorageID('');
end;

procedure TCustomIniquick.Restore;
  {Read window placement and state from ini file and set up the window}
var
  Left, Top : Integer;        {Position of window}
  Width, Height : integer;    {Dimensions of window}
  State : TWindowState;       {State of window}
  StateInt : Integer;         {State of window as integer}
begin
  {Check if there is an owning window - get out if not}
  if FWindow = nil then Exit;
  {Read info from storage}
  {set default values in case any of items are not recorded in storage}
  Left := FWindow.Left;
  Top := FWindow.Top;
  Width := FWindow.Width;
  Height := FWindow.Height;
  StateInt := Ord(FWindow.WindowState);
  {read state and size of window from storage - using default set above}
  ReadStatus(Left, Top, Width, Height, StateInt);
  if FMoreData then ReadData;
  State := TWindowState(StateInt);
  {Set window size (normal)}
  FWindow.SetBounds(Left, Top, Width, Height);
  {Now set window state if required}
  if not IgnoreState then
  begin
    {check if window was minimised - we have special processing for minimized
    state since Delphi doesn't minimize windows - it uses application window
    instead}
    if State = wsMinimized then
    begin
      FWindow.Visible := True;
      Application.Minimize;
    end
    else
      FWindow.WindowState := State;
  end;
end;

procedure TCustomIniquick.Save;
  {Save window placement and size to ini file}
var
  Pl : TWindowPlacement;      {Info structure for placement of window}
  R : TRect;                  {Rectangle to hold normal position & size details}
  State : Integer;            {State of window}
begin
  {Check if there is an owning window - get out if not}
  if FWindow = nil then Exit;
  {Calculate window's normal size and position using Windows API call - the
  form's Width, Height, Top and Left properties will give actual window size if
  form is maximised, which is not what we want here}
  Pl.Length := SizeOf(TWindowPlacement);
  GetWindowPlacement(FWindow.Handle, @Pl);
  R := Pl.rcNormalPosition;
  {Record window state (maximised, minimised or normal) - special case when
  minimized since form window is simply hidden when minimised, and application
  window is actually the one minimised - so we check to see if application
  window *is* minimized and act accordingly}
  if IsIconic(Application.Handle) then
    {minimized - write that state}
    State := Ord(wsMinimized)
  else
    {not mimimized - we can rely on window state of form}
    State := Ord(FWindow.WindowState);
  {Save window info}
  SaveState(R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top, State);
  if FMoreData then SaveData;
end;

procedure TCustomIniquick.PutStr(nombre,valor:string);
begin
  try
    FData.Values[nombre]:=valor;
  except
  end;
end;

function TCustomIniquick.GetStr(nombre:string):string;
begin
  try
    result:=FData.Values[nombre];
  except
    result:='';
  end;
end;

function TCustomIniquick.GetStrD(nombre,defaultS:string):string;
begin
  try
    result:=FData.Values[nombre];
  except
    result:=defaultS;
  end;
  if result='' then result:=defaultS;
end;

procedure TCustomIniquick.PutInt(nombre:String;valor:integer);
begin
  try
    FData.Values[nombre]:=inttostr(valor);
  except
  end;
end;

function TCustomIniquick.GetInt(nombre:string):integer;
begin
  try
    result:=strtoint(FData.Values[nombre]);
  except
    result:=0;
  end;
end;

function TCustomIniquick.GetIntD(nombre:string;defaultV:integer):integer;
begin
  try
    result:=strtoint(FData.Values[nombre]);
  except
    result:=defaultV;
  end;
end;

function TCustomIniquick.GetStorageID : string;
  {Returns identification of where information is stored - can be ini file name
  or registry sub-key}
begin
  Result := FStorageID;
end;

procedure TCustomIniquick.SetStorageID(AnID : string);
  {Sets identification of where window information is stored - can be ini file
  name or registry sub-key. Can be overriden to add additional processing}
begin
  FStorageID := AnID;
end;

procedure Register;
begin
  RegisterComponents('Samples', [TIniQuick]);
end;

end.
