home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 June / Chip_2002-06_cd1.bin / zkuste / delphi / kolekce / d6 / rxlibsetup.exe / {app} / units / Placemnt.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-02-19  |  35.7 KB  |  1,269 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 2001,2002 SGB Software          }
  6. {         Copyright (c) 1997, 1998 Fedor Koshevnikov,   }
  7. {                        Igor Pavluk and Serge Korolev  }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11.  
  12. unit Placemnt;
  13.  
  14. {$I RX.INC}
  15.  
  16. interface
  17.  
  18. uses RTLConsts, Variants, Windows, Registry, Controls, Messages, Classes, Forms, IniFiles, Dialogs, VclUtils, RxHook;
  19.  
  20. type
  21.   TPlacementOption = (fpState, fpPosition, fpActiveControl);
  22.   TPlacementOptions = set of TPlacementOption;
  23.   TPlacementOperation = (poSave, poRestore);
  24. {$IFDEF WIN32}
  25.   TPlacementRegRoot = (prCurrentUser, prLocalMachine, prCurrentConfig,
  26.     prClassesRoot, prUsers, prDynData);
  27. {$ENDIF}
  28.  
  29.   TIniLink = class;
  30.  
  31. { TWinMinMaxInfo }
  32.  
  33.   TFormPlacement = class;
  34.  
  35.   TWinMinMaxInfo = class(TPersistent)
  36.   private
  37.     FOwner: TFormPlacement;
  38.     FMinMaxInfo: TMinMaxInfo;
  39.     function GetMinMaxInfo(Index: Integer): Integer;
  40.     procedure SetMinMaxInfo(Index: Integer; Value: Integer);
  41.   public
  42.     function DefaultMinMaxInfo: Boolean;
  43.     procedure Assign(Source: TPersistent); override;
  44.   published
  45.     property MaxPosLeft: Integer index 0 read GetMinMaxInfo write SetMinMaxInfo default 0;
  46.     property MaxPosTop: Integer index 1 read GetMinMaxInfo write SetMinMaxInfo default 0;
  47.     property MaxSizeHeight: Integer index 2 read GetMinMaxInfo write SetMinMaxInfo default 0;
  48.     property MaxSizeWidth: Integer index 3 read GetMinMaxInfo write SetMinMaxInfo default 0;
  49.     property MaxTrackHeight: Integer index 4 read GetMinMaxInfo write SetMinMaxInfo default 0;
  50.     property MaxTrackWidth: Integer index 5 read GetMinMaxInfo write SetMinMaxInfo default 0;
  51.     property MinTrackHeight: Integer index 6 read GetMinMaxInfo write SetMinMaxInfo default 0;
  52.     property MinTrackWidth: Integer index 7 read GetMinMaxInfo write SetMinMaxInfo default 0;
  53.   end;
  54.  
  55. { TFormPlacement }
  56.  
  57.   TFormPlacement = class(TComponent)
  58.   private
  59.     FActive: Boolean;
  60.     FIniFileName: String;
  61.     FIniSection: String;
  62.     FIniFile: TIniFile;
  63.     FUseRegistry: Boolean;
  64. {$IFDEF WIN32}
  65.     FRegIniFile: TRegIniFile;
  66.     FRegistryRoot: TPlacementRegRoot;
  67. {$ENDIF WIN32}
  68.     FLinks: TList;
  69.     FOptions: TPlacementOptions;
  70.     FVersion: Integer;
  71.     FSaved: Boolean;
  72.     FRestored: Boolean;
  73.     FDestroying: Boolean;
  74.     FPreventResize: Boolean;
  75.     FWinMinMaxInfo: TWinMinMaxInfo;
  76.     FDefMaximize: Boolean;
  77.     FWinHook: TRxWindowHook;
  78.     FSaveFormShow: TNotifyEvent;
  79.     FSaveFormDestroy: TNotifyEvent;
  80.     FSaveFormCloseQuery: TCloseQueryEvent;
  81.     FOnSavePlacement: TNotifyEvent;
  82.     FOnRestorePlacement: TNotifyEvent;
  83.     procedure SetEvents;
  84.     procedure RestoreEvents;
  85.     procedure SetHook;
  86.     procedure ReleaseHook;
  87.     procedure CheckToggleHook;
  88.     function CheckMinMaxInfo: Boolean;
  89.     procedure MinMaxInfoModified;
  90.     procedure SetWinMinMaxInfo(Value: TWinMinMaxInfo);
  91.     function GetIniSection: string;
  92.     procedure SetIniSection(const Value: string);
  93.     function GetIniFileName: string;
  94.     procedure SetIniFileName(const Value: string);
  95.     function GetIniFile: TObject;
  96.     procedure SetPreventResize(Value: Boolean);
  97.     procedure UpdatePreventResize;
  98.     procedure UpdatePlacement;
  99.     procedure IniNeeded(ReadOnly: Boolean);
  100.     procedure IniFree;
  101.     procedure AddLink(ALink: TIniLink);
  102.     procedure NotifyLinks(Operation: TPlacementOperation);
  103.     procedure RemoveLink(ALink: TIniLink);
  104.     procedure WndMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
  105.     procedure FormShow(Sender: TObject);
  106.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  107.     procedure FormDestroy(Sender: TObject);
  108.     function GetForm: TForm;
  109.   protected
  110.     procedure Loaded; override;
  111.     procedure Save; dynamic;
  112.     procedure Restore; dynamic;
  113.     procedure SavePlacement; virtual;
  114.     procedure RestorePlacement; virtual;
  115.     function DoReadString(const Section, Ident, Default: string): string; virtual;
  116.     procedure DoWriteString(const Section, Ident, Value: string); virtual;
  117.     property Form: TForm read GetForm;
  118.   public
  119.     constructor Create(AOwner: TComponent); override;
  120.     destructor Destroy; override;
  121.     procedure SaveFormPlacement;
  122.     procedure RestoreFormPlacement;
  123.     function ReadString(const Ident, Default: string): string;
  124.     procedure WriteString(const Ident, Value: string);
  125.     function ReadInteger(const Ident: string; Default: Longint): Longint;
  126.     procedure WriteInteger(const Ident: string; Value: Longint);
  127.     procedure EraseSections;
  128.     property IniFileObject: TObject read GetIniFile;
  129.     property IniFile: TIniFile read FIniFile;
  130. {$IFDEF WIN32}
  131.     property RegIniFile: TRegIniFile read FRegIniFile;
  132. {$ENDIF WIN32}
  133.   published
  134.     property Active: Boolean read FActive write FActive default True;
  135.     property IniFileName: string read GetIniFileName write SetIniFileName;
  136.     property IniSection: string read GetIniSection write SetIniSection;
  137.     property MinMaxInfo: TWinMinMaxInfo read FWinMinMaxInfo write SetWinMinMaxInfo;
  138.     property Options: TPlacementOptions read FOptions write FOptions default [fpState, fpPosition];
  139.     property PreventResize: Boolean read FPreventResize write SetPreventResize default False;
  140. {$IFDEF WIN32}
  141.     property RegistryRoot: TPlacementRegRoot read FRegistryRoot write FRegistryRoot default prCurrentUser;
  142. {$ENDIF WIN32}
  143.     property UseRegistry: Boolean read FUseRegistry write FUseRegistry default False;
  144.     property Version: Integer read FVersion write FVersion default 0;
  145.     property OnSavePlacement: TNotifyEvent read FOnSavePlacement
  146.       write FOnSavePlacement;
  147.     property OnRestorePlacement: TNotifyEvent read FOnRestorePlacement
  148.       write FOnRestorePlacement;
  149.   end;
  150.  
  151. { TFormStorage }
  152.  
  153. {$IFDEF RX_D3}
  154.   TStoredValues = class;
  155.   TStoredValue = class;
  156. {$ENDIF RX_D3}
  157.  
  158.   TFormStorage = class(TFormPlacement)
  159.   private
  160.     FStoredProps: TStrings;
  161. {$IFDEF RX_D3}
  162.     FStoredValues: TStoredValues;
  163. {$ENDIF RX_D3}
  164.     procedure SetStoredProps(Value: TStrings);
  165. {$IFDEF RX_D3}
  166.     procedure SetStoredValues(Value: TStoredValues);
  167.     function GetStoredValue(const Name: string): Variant;
  168.     procedure SetStoredValue(const Name: string; Value: Variant);
  169. {$ENDIF RX_D3}
  170.   protected
  171.     procedure Loaded; override;
  172.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  173.     procedure SavePlacement; override;
  174.     procedure RestorePlacement; override;
  175.     procedure SaveProperties; virtual;
  176.     procedure RestoreProperties; virtual;
  177.     procedure WriteState(Writer: TWriter); override;
  178.   public
  179.     constructor Create(AOwner: TComponent); override;
  180.     destructor Destroy; override;
  181. {$IFDEF WIN32}
  182.     procedure SetNotification;
  183. {$ENDIF WIN32}
  184. {$IFDEF RX_D3}
  185.     property StoredValue[const Name: string]: Variant read GetStoredValue write SetStoredValue;
  186. {$ENDIF RX_D3}
  187.   published
  188.     property StoredProps: TStrings read FStoredProps write SetStoredProps;
  189. {$IFDEF RX_D3}
  190.     property StoredValues: TStoredValues read FStoredValues write SetStoredValues;
  191. {$ENDIF RX_D3}
  192.   end;
  193.  
  194. { TIniLink }
  195.  
  196.   TIniLink = class(TPersistent)
  197.   private
  198.     FStorage: TFormPlacement;
  199.     FOnSave: TNotifyEvent;
  200.     FOnLoad: TNotifyEvent;
  201.     function GetIniObject: TObject;
  202.     function GetRootSection: string;
  203.     procedure SetStorage(Value: TFormPlacement);
  204.   protected
  205.     procedure SaveToIni; virtual;
  206.     procedure LoadFromIni; virtual;
  207.   public
  208.     destructor Destroy; override;
  209.     property IniObject: TObject read GetIniObject;
  210.     property Storage: TFormPlacement read FStorage write SetStorage;
  211.     property RootSection: string read GetRootSection;
  212.     property OnSave: TNotifyEvent read FOnSave write FOnSave;
  213.     property OnLoad: TNotifyEvent read FOnLoad write FOnLoad;
  214.   end;
  215.  
  216. {$IFDEF RX_D3}
  217.  
  218. { TStoredValue }
  219.  
  220.   TStoredValueEvent = procedure(Sender: TStoredValue; var Value: Variant) of object;
  221.  
  222.   TStoredValue = class(TCollectionItem)
  223.   private
  224.     FName: string;
  225.     FValue: Variant;
  226.     FKeyString: string;
  227.     FOnSave: TStoredValueEvent;
  228.     FOnRestore: TStoredValueEvent;
  229.     function IsValueStored: Boolean;
  230.     function GetStoredValues: TStoredValues;
  231.   protected
  232.     function GetDisplayName: string; override;
  233.     procedure SetDisplayName(const Value: string); override;
  234.   public
  235.     constructor Create(Collection: TCollection); override;
  236.     procedure Assign(Source: TPersistent); override;
  237.     procedure Clear;
  238.     procedure Save; virtual;
  239.     procedure Restore; virtual;
  240.     property StoredValues: TStoredValues read GetStoredValues;
  241.   published
  242.     property Name: string read FName write SetDisplayName;
  243.     property Value: Variant read FValue write FValue stored IsValueStored;
  244.     property KeyString: string read FKeyString write FKeyString;
  245.     property OnSave: TStoredValueEvent read FOnSave write FOnSave;
  246.     property OnRestore: TStoredValueEvent read FOnRestore write FOnRestore;
  247.   end;
  248.  
  249. { TStoredValues }
  250.  
  251.   TStoredValues = class({$IFDEF RX_D4}TOwnedCollection{$ELSE}TCollection{$ENDIF})
  252.   private
  253.     FStorage: TFormPlacement;
  254.     function GetValue(const Name: string): TStoredValue;
  255.     procedure SetValue(const Name: string; StoredValue: TStoredValue);
  256.     function GetStoredValue(const Name: string): Variant;
  257.     procedure SetStoredValue(const Name: string; Value: Variant);
  258.     function GetItem(Index: Integer): TStoredValue;
  259.     procedure SetItem(Index: Integer; StoredValue: TStoredValue);
  260.   public
  261. {$IFDEF RX_D4}
  262.     constructor Create(AOwner: TPersistent);
  263. {$ELSE}
  264.     constructor Create;
  265. {$ENDIF}
  266.     function IndexOf(const Name: string): Integer;
  267.     procedure SaveValues; virtual;
  268.     procedure RestoreValues; virtual;
  269.     property Storage: TFormPlacement read FStorage write FStorage;
  270.     property Items[Index: Integer]: TStoredValue read GetItem write SetItem; default;
  271.     property Values[const Name: string]: TStoredValue read GetValue write SetValue;
  272.     property StoredValue[const Name: string]: Variant read GetStoredValue write SetStoredValue;
  273.   end;
  274.  
  275. {$ENDIF RX_D3}
  276.  
  277. implementation
  278.  
  279. uses SysUtils,
  280. {$IFDEF RX_D3}
  281.   Consts,
  282. {$ENDIF RX_D3}
  283.   AppUtils, rxStrUtils, RxProps;
  284.  
  285. const
  286. { The following string should not be localized }
  287.   siActiveCtrl = 'ActiveControl';
  288.   siVisible = 'Visible';
  289.   siVersion = 'FormVersion';
  290.  
  291. { TFormPlacement }
  292.  
  293. constructor TFormPlacement.Create(AOwner: TComponent);
  294. begin
  295.   inherited Create(AOwner);
  296.   FIniFileName := EmptyStr;
  297.   FIniSection := EmptyStr;
  298.   FActive := True;
  299.   if AOwner is TForm then FOptions := [fpState, fpPosition]
  300.   else FOptions := [];
  301.   FWinHook := TRxWindowHook.Create(Self);
  302.   FWinHook.AfterMessage := WndMessage;
  303.   FWinMinMaxInfo := TWinMinMaxInfo.Create;
  304.   FWinMinMaxInfo.FOwner := Self;
  305.   FLinks := TList.Create;
  306. end;
  307.  
  308. destructor TFormPlacement.Destroy;
  309. begin
  310.   IniFree;
  311.   while FLinks.Count > 0 do RemoveLink(FLinks.Last);
  312.   FLinks.Free;
  313.   if not (csDesigning in ComponentState) then begin
  314.     ReleaseHook;
  315.     RestoreEvents;
  316.   end;
  317.   //DisposeStr(FIniFileName);
  318.   //DisposeStr(FIniSection);
  319.   FWinMinMaxInfo.Free;
  320.   inherited Destroy;
  321. end;
  322.  
  323. procedure TFormPlacement.Loaded;
  324. var
  325.   Loading: Boolean;
  326. begin
  327.   Loading := csLoading in ComponentState;
  328.   inherited Loaded;
  329.   if not (csDesigning in ComponentState) then begin
  330.     if Loading then SetEvents;
  331.     CheckToggleHook;
  332.   end;
  333. end;
  334.  
  335. procedure TFormPlacement.AddLink(ALink: TIniLink);
  336. begin
  337.   FLinks.Add(ALink);
  338.   ALink.FStorage := Self;
  339. end;
  340.  
  341. procedure TFormPlacement.NotifyLinks(Operation: TPlacementOperation);
  342. var
  343.   I: Integer;
  344. begin
  345.   for I := 0 to FLinks.Count - 1 do
  346.     with TIniLink(FLinks[I]) do
  347.       case Operation of
  348.         poSave: SaveToIni;
  349.         poRestore: LoadFromIni;
  350.       end;
  351. end;
  352.  
  353. procedure TFormPlacement.RemoveLink(ALink: TIniLink);
  354. begin
  355.   ALink.FStorage := nil;
  356.   FLinks.Remove(ALink);
  357. end;
  358.  
  359. function TFormPlacement.GetForm: TForm;
  360. begin
  361.   if Owner is TCustomForm then Result := TForm(Owner as TCustomForm)
  362.   else Result := nil;
  363. end;
  364.  
  365. procedure TFormPlacement.SetEvents;
  366. begin
  367.   if Owner is TCustomForm then begin
  368.     with TForm(Form) do begin
  369.       FSaveFormShow := OnShow;
  370.       OnShow := FormShow;
  371.       FSaveFormCloseQuery := OnCloseQuery;
  372.       OnCloseQuery := FormCloseQuery;
  373.       FSaveFormDestroy := OnDestroy;
  374.       OnDestroy := FormDestroy;
  375.       FDefMaximize := (biMaximize in BorderIcons);
  376.     end;
  377.     if FPreventResize then UpdatePreventResize;
  378.   end;
  379. end;
  380.  
  381. procedure TFormPlacement.RestoreEvents;
  382. begin
  383.   if (Owner <> nil) and (Owner is TCustomForm) then
  384.     with TForm(Form) do begin
  385.       OnShow := FSaveFormShow;
  386.       OnCloseQuery := FSaveFormCloseQuery;
  387.       OnDestroy := FSaveFormDestroy;
  388.     end;
  389. end;
  390.  
  391. procedure TFormPlacement.SetHook;
  392. begin
  393.   if not (csDesigning in ComponentState) and (Owner <> nil) and
  394.     (Owner is TCustomForm) then
  395.     FWinHook.WinControl := Form;
  396. end;
  397.  
  398. procedure TFormPlacement.ReleaseHook;
  399. begin
  400.   FWinHook.WinControl := nil;
  401. end;
  402.  
  403. procedure TFormPlacement.CheckToggleHook;
  404. begin
  405.   if CheckMinMaxInfo or PreventResize then SetHook else ReleaseHook;
  406. end;
  407.  
  408. function TFormPlacement.CheckMinMaxInfo: Boolean;
  409. begin
  410.   Result := not FWinMinMaxInfo.DefaultMinMaxInfo;
  411. end;
  412.  
  413. procedure TFormPlacement.MinMaxInfoModified;
  414. begin
  415.   UpdatePlacement;
  416.   if not (csLoading in ComponentState) then CheckToggleHook;
  417. end;
  418.  
  419. procedure TFormPlacement.SetWinMinMaxInfo(Value: TWinMinMaxInfo);
  420. begin
  421.   FWinMinMaxInfo.Assign(Value);
  422. end;
  423.  
  424. procedure TFormPlacement.WndMessage(Sender: TObject; var Msg: TMessage;
  425.   var Handled: Boolean);
  426. begin
  427.   if FPreventResize and (Owner is TCustomForm) then begin
  428.     case Msg.Msg of
  429.       WM_GETMINMAXINFO:
  430.         if Form.HandleAllocated and IsWindowVisible(Form.Handle) then begin
  431.           with TWMGetMinMaxInfo(Msg).MinMaxInfo^ do begin
  432.             ptMinTrackSize := Point(Form.Width, Form.Height);
  433.             ptMaxTrackSize := Point(Form.Width, Form.Height);
  434.           end;
  435.           Msg.Result := 1;
  436.         end;
  437.       WM_INITMENUPOPUP:
  438.         if TWMInitMenuPopup(Msg).SystemMenu then begin
  439.           if Form.Menu <> nil then
  440.             Form.Menu.DispatchPopup(TWMInitMenuPopup(Msg).MenuPopup);
  441.           EnableMenuItem(TWMInitMenuPopup(Msg).MenuPopup, SC_SIZE,
  442.             MF_BYCOMMAND or MF_GRAYED);
  443.           EnableMenuItem(TWMInitMenuPopup(Msg).MenuPopup, SC_MAXIMIZE,
  444.             MF_BYCOMMAND or MF_GRAYED);
  445.           Msg.Result := 1;
  446.         end;
  447.       WM_NCHITTEST:
  448.         begin
  449.           if Msg.Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT,
  450.             HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT]
  451.           then Msg.Result := HTNOWHERE;
  452.         end;
  453.     end;
  454.   end
  455.   else if (Msg.Msg = WM_GETMINMAXINFO) then begin
  456.     if CheckMinMaxInfo then begin
  457.       with TWMGetMinMaxInfo(Msg).MinMaxInfo^ do begin
  458.          if FWinMinMaxInfo.MinTrackWidth <> 0 then
  459.            ptMinTrackSize.X := FWinMinMaxInfo.MinTrackWidth;
  460.          if FWinMinMaxInfo.MinTrackHeight <> 0 then
  461.            ptMinTrackSize.Y := FWinMinMaxInfo.MinTrackHeight;
  462.          if FWinMinMaxInfo.MaxTrackWidth <> 0 then
  463.            ptMaxTrackSize.X := FWinMinMaxInfo.MaxTrackWidth;
  464.          if FWinMinMaxInfo.MaxTrackHeight <> 0 then
  465.            ptMaxTrackSize.Y := FWinMinMaxInfo.MaxTrackHeight;
  466.          if FWinMinMaxInfo.MaxSizeWidth <> 0 then
  467.            ptMaxSize.X := FWinMinMaxInfo.MaxSizeWidth;
  468.          if FWinMinMaxInfo.MaxSizeHeight <> 0 then
  469.            ptMaxSize.Y := FWinMinMaxInfo.MaxSizeHeight;
  470.          if FWinMinMaxInfo.MaxPosLeft <> 0 then
  471.            ptMaxPosition.X := FWinMinMaxInfo.MaxPosLeft;
  472.          if FWinMinMaxInfo.MaxPosTop <> 0 then
  473.            ptMaxPosition.Y := FWinMinMaxInfo.MaxPosTop;
  474.       end;
  475.     end
  476.     else begin
  477.       TWMGetMinMaxInfo(Msg).MinMaxInfo^.ptMaxPosition.X := 0;
  478.       TWMGetMinMaxInfo(Msg).MinMaxInfo^.ptMaxPosition.Y := 0;
  479.     end;
  480.     Msg.Result := 1;
  481.   end;
  482. end;
  483.  
  484. procedure TFormPlacement.FormShow(Sender: TObject);
  485. begin
  486.   if Active then
  487.     try
  488.       RestoreFormPlacement;
  489.     except
  490.       Application.HandleException(Self);
  491.     end;
  492.   if Assigned(FSaveFormShow) then FSaveFormShow(Sender);
  493. end;
  494.  
  495. procedure TFormPlacement.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  496. begin
  497.   if Assigned(FSaveFormCloseQuery) then
  498.     FSaveFormCloseQuery(Sender, CanClose);
  499.   if CanClose and Active and (Owner is TCustomForm) and (Form.Handle <> 0) then
  500.     try
  501.       SaveFormPlacement;
  502.     except
  503.       Application.HandleException(Self);
  504.     end;
  505. end;
  506.  
  507. procedure TFormPlacement.FormDestroy(Sender: TObject);
  508. begin
  509.   if Active and not FSaved then begin
  510.     FDestroying := True;
  511.     try
  512.       SaveFormPlacement;
  513.     except
  514.       Application.HandleException(Self);
  515.     end;
  516.     FDestroying := False;
  517.   end;
  518.   if Assigned(FSaveFormDestroy) then FSaveFormDestroy(Sender);
  519. end;
  520.  
  521. procedure TFormPlacement.UpdatePlacement;
  522. const
  523. {$IFDEF WIN32}
  524.   Metrics: array[bsSingle..bsSizeToolWin] of Word =
  525.     (SM_CXBORDER, SM_CXFRAME, SM_CXDLGFRAME, SM_CXBORDER, SM_CXFRAME);
  526. {$ELSE}
  527.   Metrics: array[bsSingle..bsDialog] of Word =
  528.     (SM_CXBORDER, SM_CXFRAME, SM_CXDLGFRAME);
  529. {$ENDIF}
  530. var
  531.   Placement: TWindowPlacement;
  532. begin
  533.   if (Owner <> nil) and (Owner is TCustomForm) and Form.HandleAllocated and
  534.   not (csLoading in ComponentState) then
  535.     if not (FPreventResize or CheckMinMaxInfo) then begin
  536.       Placement.Length := SizeOf(TWindowPlacement);
  537.       GetWindowPlacement(Form.Handle, @Placement);
  538.       if not IsWindowVisible(Form.Handle) then
  539.         Placement.ShowCmd := SW_HIDE;
  540.       if Form.BorderStyle <> bsNone then begin
  541.         Placement.ptMaxPosition.X := -GetSystemMetrics(Metrics[Form.BorderStyle]);
  542.         Placement.ptMaxPosition.Y := -GetSystemMetrics(Metrics[Form.BorderStyle] + 1);
  543.       end
  544.       else Placement.ptMaxPosition := Point(0, 0);
  545.       SetWindowPlacement(Form.Handle, @Placement);
  546.     end;
  547. end;
  548.  
  549. procedure TFormPlacement.UpdatePreventResize;
  550. var
  551.   IsActive: Boolean;
  552. begin
  553.   if not (csDesigning in ComponentState) and (Owner is TCustomForm) then
  554.   begin
  555.     if FPreventResize then
  556.       FDefMaximize := (biMaximize in Form.BorderIcons);
  557.     IsActive := Active;
  558.     Active := False;
  559.     try
  560.       if (not FPreventResize) and FDefMaximize and
  561.         (Form.BorderStyle <> bsDialog) then
  562.         Form.BorderIcons := Form.BorderIcons + [biMaximize]
  563.       else Form.BorderIcons := Form.BorderIcons - [biMaximize];
  564.     finally
  565.       Active := IsActive;
  566.     end;
  567.     if not (csLoading in ComponentState) then CheckToggleHook;
  568.   end;
  569. end;
  570.  
  571. procedure TFormPlacement.SetPreventResize(Value: Boolean);
  572. begin
  573.   if (Form <> nil) and (FPreventResize <> Value) then begin
  574.     FPreventResize := Value;
  575.     UpdatePlacement;
  576.     UpdatePreventResize;
  577.   end;
  578. end;
  579.  
  580. function TFormPlacement.GetIniFile: TObject;
  581. begin
  582. {$IFDEF WIN32}
  583.   if UseRegistry then Result := FRegIniFile
  584.   else Result := FIniFile;
  585. {$ELSE}
  586.   Result := FIniFile;
  587. {$ENDIF WIN32}
  588. end;
  589.  
  590. function TFormPlacement.GetIniFileName: string;
  591. begin
  592.   Result := FIniFileName;
  593.   if (Result = '') and not (csDesigning in ComponentState) then begin
  594. {$IFDEF WIN32}
  595.     if UseRegistry then Result := GetDefaultIniRegKey
  596.     else Result := GetDefaultIniName;
  597. {$ELSE}
  598.     Result := GetDefaultIniName;
  599. {$ENDIF}
  600.   end;
  601. end;
  602.  
  603. procedure TFormPlacement.SetIniFileName(const Value: string);
  604. begin
  605.   FIniFileName := Value;
  606. end;
  607.  
  608. function TFormPlacement.GetIniSection: string;
  609. begin
  610.   Result := FIniSection;
  611.   if (Result = '') and not (csDesigning in ComponentState) then
  612.     Result := GetDefaultSection(Owner);
  613. end;
  614.  
  615. procedure TFormPlacement.SetIniSection(const Value: string);
  616. begin
  617.   FIniSection := Value;
  618. end;
  619.  
  620. procedure TFormPlacement.Save;
  621. begin
  622.   if Assigned(FOnSavePlacement) then FOnSavePlacement(Self);
  623. end;
  624.  
  625. procedure TFormPlacement.Restore;
  626. begin
  627.   if Assigned(FOnRestorePlacement) then FOnRestorePlacement(Self);
  628. end;
  629.  
  630. procedure TFormPlacement.SavePlacement;
  631. begin
  632.   if Owner is TCustomForm then begin
  633. {$IFDEF WIN32}
  634.     if UseRegistry then begin
  635.       if (Options * [fpState, fpPosition] <> []) then begin
  636.         WriteFormPlacementReg(Form, FRegIniFile, IniSection);
  637.         FRegIniFile.WriteBool(IniSection, siVisible, FDestroying);
  638.       end;
  639.       if (fpActiveControl in Options) and (Form.ActiveControl <> nil) then
  640.         FRegIniFile.WriteString(IniSection, siActiveCtrl, Form.ActiveControl.Name);
  641.     end
  642.     else begin
  643.       if (Options * [fpState, fpPosition] <> []) then begin
  644.         WriteFormPlacement(Form, FIniFile, IniSection);
  645.         FIniFile.WriteBool(IniSection, siVisible, FDestroying);
  646.       end;
  647.       if (fpActiveControl in Options) and (Form.ActiveControl <> nil) then
  648.         FIniFile.WriteString(IniSection, siActiveCtrl, Form.ActiveControl.Name);
  649.     end;
  650. {$ELSE}
  651.     if (Options * [fpState, fpPosition] <> []) then begin
  652.       WriteFormPlacement(Form, FIniFile, IniSection);
  653.       FIniFile.WriteBool(IniSection, siVisible, FDestroying);
  654.     end;
  655.     if (fpActiveControl in Options) and (Form.ActiveControl <> nil) then
  656.       FIniFile.WriteString(IniSection, siActiveCtrl, Form.ActiveControl.Name);
  657. {$ENDIF}
  658.   end;
  659.   NotifyLinks(poSave);
  660. end;
  661.  
  662. procedure TFormPlacement.RestorePlacement;
  663. begin
  664.   if Owner is TCustomForm then begin
  665. {$IFDEF WIN32}
  666.     if UseRegistry then
  667.       ReadFormPlacementReg(Form, FRegIniFile, IniSection, fpState in Options,
  668.         fpPosition in Options)
  669.     else
  670. {$ENDIF}
  671.       ReadFormPlacement(Form, FIniFile, IniSection, fpState in Options,
  672.         fpPosition in Options);
  673.   end;
  674.   NotifyLinks(poRestore);
  675. end;
  676.  
  677. procedure TFormPlacement.IniNeeded(ReadOnly: Boolean);
  678. begin
  679.   if IniFileObject = nil then begin
  680. {$IFDEF WIN32}
  681.     if UseRegistry then begin
  682.       FRegIniFile := TRegIniFile.Create(IniFileName);
  683. {$IFDEF RX_D5}
  684.       if ReadOnly then FRegIniFile.Access := KEY_READ;
  685. {$ENDIF}
  686.       case FRegistryRoot of
  687.         prLocalMachine:
  688.           FRegIniFile.RootKey := HKEY_LOCAL_MACHINE;
  689.         prClassesRoot: 
  690.           FRegIniFile.RootKey := HKEY_CLASSES_ROOT;
  691.         prCurrentConfig: 
  692.           FRegIniFile.RootKey := HKEY_CURRENT_CONFIG;
  693.         prUsers: 
  694.           FRegIniFile.RootKey := HKEY_USERS;
  695.         prDynData:
  696.           FRegIniFile.RootKey := HKEY_DYN_DATA;
  697.       end;
  698.       if FRegIniFile.RootKey <> HKEY_CURRENT_USER then
  699.         FRegIniFile.OpenKey(FRegIniFile.FileName, not ReadOnly);
  700.     end
  701.     else
  702. {$ENDIF}
  703.     FIniFile := TIniFile.Create(IniFileName);
  704.   end;
  705. end;
  706.  
  707. procedure TFormPlacement.IniFree;
  708. begin
  709.   if IniFileObject <> nil then begin
  710.     IniFileObject.Free;
  711.     FIniFile := nil;
  712. {$IFDEF WIN32}
  713.     FRegIniFile := nil;
  714. {$ENDIF}
  715.   end;
  716. end;
  717.  
  718. function TFormPlacement.DoReadString(const Section, Ident,
  719.   Default: string): string;
  720. begin
  721.   if IniFileObject <> nil then
  722.     Result := IniReadString(IniFileObject, Section, Ident, Default)
  723.   else begin
  724.     IniNeeded(True);
  725.     try
  726.       Result := IniReadString(IniFileObject, Section, Ident, Default);
  727.     finally
  728.       IniFree;
  729.     end;
  730.   end;
  731. end;
  732.  
  733. function TFormPlacement.ReadString(const Ident, Default: string): string;
  734. begin
  735.   Result := DoReadString(IniSection, Ident, Default);
  736. end;
  737.  
  738. procedure TFormPlacement.DoWriteString(const Section, Ident, Value: string);
  739. begin
  740.   if IniFileObject <> nil then
  741.     IniWriteString(IniFileObject, Section, Ident, Value)
  742.   else begin
  743.     IniNeeded(False);
  744.     try
  745.       IniWriteString(IniFileObject, Section, Ident, Value);
  746.     finally
  747.       IniFree;
  748.     end;
  749.   end;
  750. end;
  751.  
  752. procedure TFormPlacement.WriteString(const Ident, Value: string);
  753. begin
  754.   DoWriteString(IniSection, Ident, Value);
  755. end;
  756.  
  757. function TFormPlacement.ReadInteger(const Ident: string; Default: Longint): Longint;
  758. begin
  759.   if IniFileObject <> nil then
  760.     Result := IniReadInteger(IniFileObject, IniSection, Ident, Default)
  761.   else begin
  762.     IniNeeded(True);
  763.     try
  764.       Result := IniReadInteger(IniFileObject, IniSection, Ident, Default);
  765.     finally
  766.       IniFree;
  767.     end;
  768.   end;
  769. end;
  770.  
  771. procedure TFormPlacement.WriteInteger(const Ident: string; Value: Longint);
  772. begin
  773.   if IniFileObject <> nil then
  774.     IniWriteInteger(IniFileObject, IniSection, Ident, Value)
  775.   else begin
  776.     IniNeeded(False);
  777.     try
  778.       IniWriteInteger(IniFileObject, IniSection, Ident, Value);
  779.     finally
  780.       IniFree;
  781.     end;
  782.   end;
  783. end;
  784.  
  785. procedure TFormPlacement.EraseSections;
  786. var
  787.   Lines: TStrings;
  788.   I: Integer;
  789. begin
  790.   if IniFileObject = nil then begin
  791.     IniNeeded(False);
  792.     try
  793.       Lines := TStringList.Create;
  794.       try
  795.         IniReadSections(IniFileObject, Lines);
  796.         for I := 0 to Lines.Count - 1 do begin
  797.           if (Lines[I] = IniSection) or
  798.             (IsWild(Lines[I], IniSection + '.*', False) or
  799.             IsWild(Lines[I], IniSection + '\*', False)) then
  800.             IniEraseSection(IniFileObject, Lines[I]);
  801.         end;
  802.       finally
  803.         Lines.Free;
  804.       end;
  805.     finally
  806.       IniFree;
  807.     end;
  808.   end;
  809. end;
  810.  
  811. procedure TFormPlacement.SaveFormPlacement;
  812. begin
  813.   if FRestored or not Active then begin
  814.     IniNeeded(False);
  815.     try
  816.       WriteInteger(siVersion, FVersion);
  817.       SavePlacement;
  818.       Save;
  819.       FSaved := True;
  820.     finally
  821.       IniFree;
  822.     end;
  823.   end;
  824. end;
  825.  
  826. procedure TFormPlacement.RestoreFormPlacement;
  827. var
  828.   cActive: TComponent;
  829. begin
  830.   FSaved := False;
  831.   IniNeeded(True);
  832.   try
  833.     if ReadInteger(siVersion, 0) >= FVersion then begin
  834.       RestorePlacement;
  835.       FRestored := True;
  836.       Restore;
  837.       if (fpActiveControl in Options) and (Owner is TCustomForm) then begin
  838.         cActive := Form.FindComponent(IniReadString(IniFileObject,
  839.           IniSection, siActiveCtrl, ''));
  840.         if (cActive <> nil) and (cActive is TWinControl) and
  841.           TWinControl(cActive).CanFocus then
  842.             Form.ActiveControl := TWinControl(cActive);
  843.       end;
  844.     end;
  845.     FRestored := True;
  846.   finally
  847.     IniFree;
  848.   end;
  849.   UpdatePlacement;
  850. end;
  851.  
  852. { TWinMinMaxInfo }
  853.  
  854. procedure TWinMinMaxInfo.Assign(Source: TPersistent);
  855. begin
  856.   if Source is TWinMinMaxInfo then begin
  857.     FMinMaxInfo := TWinMinMaxInfo(Source).FMinMaxInfo;
  858.     if FOwner <> nil then FOwner.MinMaxInfoModified;
  859.   end
  860.   else inherited Assign(Source);
  861. end;
  862.  
  863. function TWinMinMaxInfo.GetMinMaxInfo(Index: Integer): Integer;
  864. begin
  865.   with FMinMaxInfo do begin
  866.     case Index of
  867.       0: Result := ptMaxPosition.X;
  868.       1: Result := ptMaxPosition.Y;
  869.       2: Result := ptMaxSize.Y;
  870.       3: Result := ptMaxSize.X;
  871.       4: Result := ptMaxTrackSize.Y;
  872.       5: Result := ptMaxTrackSize.X;
  873.       6: Result := ptMinTrackSize.Y;
  874.       7: Result := ptMinTrackSize.X;
  875.       else Result := 0;
  876.     end;
  877.   end;
  878. end;
  879.  
  880. procedure TWinMinMaxInfo.SetMinMaxInfo(Index: Integer; Value: Integer);
  881. begin
  882.   if GetMinMaxInfo(Index) <> Value then begin
  883.     with FMinMaxInfo do begin
  884.       case Index of
  885.         0: ptMaxPosition.X := Value;
  886.         1: ptMaxPosition.Y := Value;
  887.         2: ptMaxSize.Y := Value;
  888.         3: ptMaxSize.X := Value;
  889.         4: ptMaxTrackSize.Y := Value;
  890.         5: ptMaxTrackSize.X := Value;
  891.         6: ptMinTrackSize.Y := Value;
  892.         7: ptMinTrackSize.X := Value;
  893.       end;
  894.     end;
  895.     if FOwner <> nil then FOwner.MinMaxInfoModified;
  896.   end;
  897. end;
  898.  
  899. function TWinMinMaxInfo.DefaultMinMaxInfo: Boolean;
  900. begin
  901.   with FMinMaxInfo do begin
  902.     Result := not ((ptMinTrackSize.X <> 0) or (ptMinTrackSize.Y <> 0) or
  903.       (ptMaxTrackSize.X <> 0) or (ptMaxTrackSize.Y <> 0) or
  904.       (ptMaxSize.X <> 0) or (ptMaxSize.Y <> 0) or
  905.       (ptMaxPosition.X <> 0) or (ptMaxPosition.Y <> 0));
  906.   end;
  907. end;
  908.  
  909. { TFormStorage }
  910.  
  911. constructor TFormStorage.Create(AOwner: TComponent);
  912. begin
  913.   inherited Create(AOwner);
  914.   FStoredProps := TStringList.Create;
  915. {$IFDEF RX_D3}
  916.   FStoredValues := TStoredValues.Create{$IFDEF RX_D4}(Self){$ENDIF RX_D4};
  917.   FStoredValues.Storage := Self;
  918. {$ENDIF RX_D3}
  919. end;
  920.  
  921. destructor TFormStorage.Destroy;
  922. begin
  923.   FStoredProps.Free;
  924.   FStoredProps := nil;
  925. {$IFDEF RX_D3}
  926.   FStoredValues.Free;
  927.   FStoredValues := nil;
  928. {$ENDIF RX_D3}
  929.   inherited Destroy;
  930. end;
  931.  
  932. {$IFDEF WIN32}
  933. procedure TFormStorage.SetNotification;
  934. var
  935.   I: Integer;
  936.   Component: TComponent;
  937. begin
  938.   for I := FStoredProps.Count - 1 downto 0 do begin
  939.     Component := TComponent(FStoredProps.Objects[I]);
  940.     if Component <> nil then Component.FreeNotification(Self);
  941.   end;
  942. end;
  943. {$ENDIF WIN32}
  944.  
  945. procedure TFormStorage.SetStoredProps(Value: TStrings);
  946. begin
  947.   FStoredProps.Assign(Value);
  948. {$IFDEF WIN32}
  949.   SetNotification;
  950. {$ENDIF}
  951. end;
  952.  
  953. {$IFDEF RX_D3}
  954. procedure TFormStorage.SetStoredValues(Value: TStoredValues);
  955. begin
  956.   FStoredValues.Assign(Value);
  957. end;
  958.  
  959. function TFormStorage.GetStoredValue(const Name: string): Variant;
  960. begin
  961.   Result := StoredValues.StoredValue[Name];
  962. end;
  963.  
  964. procedure TFormStorage.SetStoredValue(const Name: string; Value: Variant);
  965. begin
  966.   StoredValues.StoredValue[Name] := Value;
  967. end;
  968.  
  969. {$ENDIF RX_D3}
  970.  
  971. procedure TFormStorage.Loaded;
  972. begin
  973.   inherited Loaded;
  974.   UpdateStoredList(Owner, FStoredProps, True);
  975. end;
  976.  
  977. procedure TFormStorage.WriteState(Writer: TWriter);
  978. begin
  979.   UpdateStoredList(Owner, FStoredProps, False);
  980.   inherited WriteState(Writer);
  981. end;
  982.  
  983. procedure TFormStorage.Notification(AComponent: TComponent; Operation: TOperation);
  984. var
  985.   I: Integer;
  986.   Component: TComponent;
  987. begin
  988.   inherited Notification(AComponent, Operation);
  989.   if not (csDestroying in ComponentState) and (Operation = opRemove) and
  990.     (FStoredProps <> nil) then
  991.     for I := FStoredProps.Count - 1 downto 0 do begin
  992.       Component := TComponent(FStoredProps.Objects[I]);
  993.       if Component = AComponent then FStoredProps.Delete(I);
  994.     end;
  995. end;
  996.  
  997. procedure TFormStorage.SaveProperties;
  998. begin
  999.   with TPropsStorage.Create do
  1000.   try
  1001.     Section := IniSection;
  1002.     OnWriteString := DoWriteString;
  1003. {$IFDEF WIN32}
  1004.     if UseRegistry then OnEraseSection := FRegIniFile.EraseSection
  1005.     else OnEraseSection := FIniFile.EraseSection;
  1006. {$ELSE}
  1007.     OnEraseSection := FIniFile.EraseSection;
  1008. {$ENDIF WIN32}
  1009.     StoreObjectsProps(Owner, FStoredProps);
  1010.   finally
  1011.     Free;
  1012.   end;
  1013. end;
  1014.  
  1015. procedure TFormStorage.RestoreProperties;
  1016. begin
  1017.   with TPropsStorage.Create do
  1018.   try
  1019.     Section := IniSection;
  1020.     OnReadString := DoReadString;
  1021.     try
  1022.       LoadObjectsProps(Owner, FStoredProps);
  1023.     except
  1024.       { ignore any exceptions }
  1025.     end;
  1026.   finally
  1027.     Free;
  1028.   end;
  1029. end;
  1030.  
  1031. procedure TFormStorage.SavePlacement;
  1032. begin
  1033.   inherited SavePlacement;
  1034.   SaveProperties;
  1035. {$IFDEF RX_D3}
  1036.   StoredValues.SaveValues;
  1037. {$ENDIF}
  1038. end;
  1039.  
  1040. procedure TFormStorage.RestorePlacement;
  1041. begin
  1042.   inherited RestorePlacement;
  1043.   FRestored := True;
  1044.   RestoreProperties;
  1045. {$IFDEF RX_D3}
  1046.   StoredValues.RestoreValues;
  1047. {$ENDIF}
  1048. end;
  1049.  
  1050. { TIniLink }
  1051.  
  1052. destructor TIniLink.Destroy;
  1053. begin
  1054.   FOnSave := nil;
  1055.   FOnLoad := nil;
  1056.   SetStorage(nil);
  1057.   inherited Destroy;
  1058. end;
  1059.  
  1060. function TIniLink.GetIniObject: TObject;
  1061. begin
  1062.   if Assigned(FStorage) then Result := FStorage.IniFileObject
  1063.   else Result := nil;
  1064. end;
  1065.  
  1066. function TIniLink.GetRootSection: string;
  1067. begin
  1068.   if Assigned(FStorage) then Result := FStorage.FIniSection else Result := '';
  1069.   if Result <> '' then Result := Result + '\';
  1070. end;
  1071.  
  1072. procedure TIniLink.SetStorage(Value: TFormPlacement);
  1073. begin
  1074.   if FStorage <> Value then begin
  1075.     if FStorage <> nil then FStorage.RemoveLink(Self);
  1076.     if Value <> nil then Value.AddLink(Self);
  1077.   end;
  1078. end;
  1079.  
  1080. procedure TIniLink.SaveToIni;
  1081. begin
  1082.   if Assigned(FOnSave) then FOnSave(Self);
  1083. end;
  1084.  
  1085. procedure TIniLink.LoadFromIni;
  1086. begin
  1087.   if Assigned(FOnLoad) then FOnLoad(Self);
  1088. end;
  1089.  
  1090. {$IFDEF RX_D3}
  1091.  
  1092. { TStoredValue }
  1093.  
  1094. constructor TStoredValue.Create(Collection: TCollection);
  1095. begin
  1096.   inherited Create(Collection);
  1097.   FValue := Unassigned;
  1098. end;
  1099.  
  1100. procedure TStoredValue.Assign(Source: TPersistent);
  1101. begin
  1102.   if (Source is TStoredValue) and (Source <> nil) then begin
  1103.     if VarIsEmpty(TStoredValue(Source).FValue) then
  1104.       Clear
  1105.     else
  1106.       Value := TStoredValue(Source).FValue;
  1107.     Name := TStoredValue(Source).Name;
  1108.     KeyString := TStoredValue(Source).KeyString;
  1109.   end;
  1110. end;
  1111.  
  1112. function TStoredValue.GetDisplayName: string;
  1113. begin
  1114.   if FName = '' then
  1115.     Result := inherited GetDisplayName
  1116.   else
  1117.     Result := FName;
  1118. end;
  1119.  
  1120. procedure TStoredValue.SetDisplayName(const Value: string);
  1121. begin
  1122.   if (Value <> '') and (AnsiCompareText(Value, FName) <> 0) and
  1123.     (Collection is TStoredValues) and (TStoredValues(Collection).IndexOf(Value) >= 0) then
  1124.     raise Exception.Create(SDuplicateString);
  1125.   FName := Value;
  1126.   inherited;
  1127. end;
  1128.  
  1129. function TStoredValue.GetStoredValues: TStoredValues;
  1130. begin
  1131.   if Collection is TStoredValues then
  1132.     Result := TStoredValues(Collection)
  1133.   else
  1134.     Result := nil;
  1135. end;
  1136.  
  1137. procedure TStoredValue.Clear;
  1138. begin
  1139.   FValue := Unassigned;
  1140. end;
  1141.  
  1142. function TStoredValue.IsValueStored: Boolean;
  1143. begin
  1144.   Result := not VarIsEmpty(FValue);
  1145. end;
  1146.  
  1147. procedure TStoredValue.Save;
  1148. var
  1149.   SaveValue: Variant;
  1150.   SaveStrValue: string;
  1151. begin
  1152.   SaveValue := Value;
  1153.   if Assigned(FOnSave) then
  1154.     FOnSave(Self, SaveValue);
  1155.   SaveStrValue := VarToStr(SaveValue);
  1156.   if KeyString <> '' then
  1157.     SaveStrValue := XorEncode(KeyString, SaveStrValue);
  1158.   StoredValues.Storage.WriteString(Name, SaveStrValue);
  1159. end;
  1160.  
  1161. procedure TStoredValue.Restore;
  1162. var
  1163.   RestoreValue: Variant;
  1164.   RestoreStrValue, DefaultStrValue: string;
  1165. begin
  1166.   DefaultStrValue := VarToStr(Value);
  1167.   if KeyString <> '' then
  1168.     DefaultStrValue := XorEncode(KeyString, DefaultStrValue);
  1169.   RestoreStrValue := StoredValues.Storage.ReadString(Name, DefaultStrValue);
  1170.   if KeyString <> '' then
  1171.     RestoreStrValue := XorDecode(KeyString, RestoreStrValue);
  1172.   RestoreValue := RestoreStrValue;
  1173.   if Assigned(FOnRestore) then
  1174.     FOnRestore(Self, RestoreValue);
  1175.   Value := RestoreValue;  
  1176. end;
  1177.  
  1178. { TStoredValues }
  1179.  
  1180. {$IFDEF RX_D4}
  1181. constructor TStoredValues.Create(AOwner: TPersistent);
  1182. begin
  1183.   inherited Create(AOwner, TStoredValue);
  1184. end;
  1185. {$ELSE}
  1186. constructor TStoredValues.Create;
  1187. begin
  1188.   inherited Create(TStoredValue);
  1189. end;
  1190. {$ENDIF}
  1191.  
  1192. function TStoredValues.IndexOf(const Name: string): Integer;
  1193. begin
  1194.   for Result := 0 to Count - 1 do
  1195.     if AnsiCompareText(Items[Result].Name, Name) = 0 then Exit;
  1196.   Result := -1;
  1197. end;
  1198.  
  1199. function TStoredValues.GetItem(Index: Integer): TStoredValue;
  1200. begin
  1201.   Result := TStoredValue(inherited Items[Index]);
  1202. end;
  1203.  
  1204. procedure TStoredValues.SetItem(Index: Integer; StoredValue: TStoredValue);
  1205. begin
  1206.   inherited SetItem(Index, TCollectionItem(StoredValue));
  1207. end;
  1208.  
  1209. function TStoredValues.GetStoredValue(const Name: string): Variant;
  1210. var
  1211.   StoredValue: TStoredValue;
  1212. begin
  1213.   StoredValue := GetValue(Name);
  1214.   if StoredValue = nil then Result := Null
  1215.   else Result := StoredValue.Value;
  1216. end;
  1217.  
  1218. procedure TStoredValues.SetStoredValue(const Name: string; Value: Variant);
  1219. var
  1220.   StoredValue: TStoredValue;
  1221. begin
  1222.   StoredValue := GetValue(Name);
  1223.   if StoredValue = nil then begin
  1224.     StoredValue := TStoredValue(Add);
  1225.     StoredValue.Name := Name; 
  1226.     StoredValue.Value := Value;
  1227.   end
  1228.   else StoredValue.Value := Value;
  1229. end;
  1230.  
  1231. function TStoredValues.GetValue(const Name: string): TStoredValue;
  1232. var
  1233.   I: Integer;
  1234. begin
  1235.   I := IndexOf(Name);
  1236.   if I < 0 then
  1237.     Result := nil
  1238.   else
  1239.     Result := Items[I];
  1240. end;
  1241.  
  1242. procedure TStoredValues.SetValue(const Name: string; StoredValue: TStoredValue);
  1243. var
  1244.   I: Integer;
  1245. begin
  1246.   I := IndexOf(Name);
  1247.   if I >= 0 then
  1248.     Items[I].Assign(StoredValue);
  1249. end;
  1250.  
  1251. procedure TStoredValues.SaveValues;
  1252. var
  1253.   I: Integer;
  1254. begin
  1255.   for I := 0 to Count - 1 do
  1256.     Items[I].Save;
  1257. end;
  1258.  
  1259. procedure TStoredValues.RestoreValues;
  1260. var
  1261.   I: Integer;
  1262. begin
  1263.   for I := 0 to Count - 1 do
  1264.     Items[I].Restore;
  1265. end;
  1266.  
  1267. {$ENDIF RX_D3}
  1268.  
  1269. end.