1480 lines
44 KiB
ObjectPascal
1480 lines
44 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvPlacemnt.PAS, released on 2002-07-04.
|
|
|
|
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
|
|
Copyright (c) 2001,2002 SGB Software
|
|
All Rights Reserved.
|
|
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvFormPlacement.pas 11277 2007-05-07 23:10:58Z jfudickar $
|
|
|
|
unit JvFormPlacement;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$IFDEF HAS_UNIT_VARIANTS}
|
|
Variants,
|
|
{$ENDIF HAS_UNIT_VARIANTS}
|
|
{$IFDEF HAS_UNIT_TYPES}
|
|
Types,
|
|
{$ENDIF HAS_UNIT_TYPES}
|
|
{$IFDEF HAS_UNIT_RTLCONSTS}
|
|
RTLConsts,
|
|
{$ENDIF HAS_UNIT_RTLCONSTS}
|
|
SysUtils, Classes, Windows, Messages, Controls, Forms,
|
|
{$IFDEF VCL}
|
|
JvWndProcHook,
|
|
{$ENDIF VCL}
|
|
JvAppStorage, JvComponentBase, JvJVCLUtils, JvTypes, JvConsts;
|
|
|
|
type
|
|
TJvIniLink = class;
|
|
|
|
TJvFormPlacement = class;
|
|
|
|
TJvWinMinMaxInfo = class(TPersistent)
|
|
private
|
|
FOwner: TJvFormPlacement;
|
|
FMinMaxInfo: TMinMaxInfo;
|
|
function GetMinMaxInfo(Index: Integer): Integer;
|
|
procedure SetMinMaxInfo(Index: Integer; AValue: Integer);
|
|
public
|
|
function DefaultMinMaxInfo: Boolean;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property MaxPosLeft: Integer index 0 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MaxPosTop: Integer index 1 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MaxSizeHeight: Integer index 2 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MaxSizeWidth: Integer index 3 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MaxTrackHeight: Integer index 4 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MaxTrackWidth: Integer index 5 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MinTrackHeight: Integer index 6 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
property MinTrackWidth: Integer index 7 read GetMinMaxInfo write SetMinMaxInfo default 0;
|
|
end;
|
|
|
|
TJvFormPlacementVersionCheck = (fpvcNocheck, fpvcCheckGreaterEqual, fpvcCheckEqual);
|
|
|
|
TJvFormPlacement = class(TJvComponent)
|
|
private
|
|
FActive: Boolean;
|
|
FAppStorage: TJvCustomAppStorage;
|
|
FAppStoragePath: string;
|
|
FLinks: TList;
|
|
FOptions: TPlacementOptions;
|
|
FVersion: Integer;
|
|
FVersionCheck: TJvFormPlacementVersionCheck;
|
|
FSaved: Boolean;
|
|
FRestored: Boolean;
|
|
FDestroying: Boolean;
|
|
FPreventResize: Boolean;
|
|
FWinMinMaxInfo: TJvWinMinMaxInfo;
|
|
FDefMaximize: Boolean;
|
|
{$IFDEF VCL}
|
|
FWinHook: TJvWindowHook;
|
|
{$ENDIF VCL}
|
|
FSaveFormShow: TNotifyEvent;
|
|
FSaveFormDestroy: TNotifyEvent;
|
|
FSaveFormCloseQuery: TCloseQueryEvent;
|
|
{$IFDEF VisualCLX}
|
|
FSaveFormConstrainedResize: TConstrainedResizeEvent;
|
|
{$ENDIF VisualCLX}
|
|
FOnSavePlacement: TNotifyEvent;
|
|
FOnRestorePlacement: TNotifyEvent;
|
|
FBeforeSavePlacement: TNotifyEvent;
|
|
FAfterSavePlacement: TNotifyEvent;
|
|
FBeforeRestorePlacement: TNotifyEvent;
|
|
FAfterRestorePlacement: TNotifyEvent;
|
|
procedure SetAppStoragePath(const AValue: string);
|
|
procedure SetEvents;
|
|
procedure RestoreEvents;
|
|
{$IFDEF VCL}
|
|
procedure SetHook;
|
|
procedure ReleaseHook;
|
|
procedure CheckToggleHook;
|
|
procedure WndMessage(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
|
|
{$ENDIF VCL}
|
|
function CheckMinMaxInfo: Boolean;
|
|
procedure MinMaxInfoModified;
|
|
procedure SetWinMinMaxInfo(AValue: TJvWinMinMaxInfo);
|
|
procedure SetPreventResize(AValue: Boolean);
|
|
procedure UpdatePreventResize;
|
|
procedure UpdatePlacement;
|
|
procedure AddLink(ALink: TJvIniLink);
|
|
procedure NotifyLinks(Operation: TPlacementOperation);
|
|
procedure RemoveLink(ALink: TJvIniLink);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
|
|
procedure FormDestroy(Sender: TObject);
|
|
{$IFDEF VisualCLX}
|
|
procedure FormConstrainedResize(Sender: TObject; var MinWidth, MinHeight,
|
|
MaxWidth, MaxHeight: Integer);
|
|
{$ENDIF VisualCLX}
|
|
function GetForm: TForm;
|
|
protected
|
|
procedure ResolveAppStoragePath;
|
|
procedure Loaded; override;
|
|
procedure Save; dynamic;
|
|
procedure Restore; dynamic;
|
|
procedure SavePlacement; virtual;
|
|
procedure RestorePlacement; virtual;
|
|
property Form: TForm read GetForm;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
function ConcatPaths(const Paths: array of string): string;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function IsActive: Boolean;
|
|
procedure SaveFormPlacement;
|
|
procedure RestoreFormPlacement;
|
|
function ReadString(const Ident: string; const Default: string = ''): string;
|
|
procedure WriteString(const Ident: string; const AValue: string);
|
|
function ReadBoolean(const Ident: string; Default: Boolean): Boolean;
|
|
procedure WriteBoolean(const Ident: string; AValue: Boolean);
|
|
function ReadFloat(const Ident: string; Default: Double = 0): Double;
|
|
procedure WriteFloat(const Ident: string; AValue: Double);
|
|
function ReadInteger(const Ident: string; Default: Longint = 0): Longint;
|
|
procedure WriteInteger(const Ident: string; AValue: Longint);
|
|
function ReadDateTime(const Ident: string; Default: TDateTime = 0): TDateTime;
|
|
procedure WriteDateTime(const Ident: string; AValue: TDateTime);
|
|
procedure EraseSections;
|
|
published
|
|
property Active: Boolean read FActive write FActive default True;
|
|
property AppStorage: TJvCustomAppStorage read FAppStorage write FAppStorage;
|
|
property AppStoragePath: string read FAppStoragePath write SetAppStoragePath;
|
|
property MinMaxInfo: TJvWinMinMaxInfo read FWinMinMaxInfo write SetWinMinMaxInfo;
|
|
property Options: TPlacementOptions read FOptions write FOptions default [fpState, fpSize, fpLocation];
|
|
property PreventResize: Boolean read FPreventResize write SetPreventResize default False;
|
|
property Version: Integer read FVersion write FVersion default 0;
|
|
property VersionCheck: TJvFormPlacementVersionCheck read FVersionCheck write FVersionCheck default fpvcCheckGreaterEqual;
|
|
property BeforeSavePlacement: TNotifyEvent read FBeforeSavePlacement write
|
|
FBeforeSavePlacement;
|
|
property OnSavePlacement: TNotifyEvent read FOnSavePlacement write FOnSavePlacement;
|
|
property AfterSavePlacement: TNotifyEvent read FAfterSavePlacement write
|
|
FAfterSavePlacement;
|
|
property BeforeRestorePlacement: TNotifyEvent read FBeforeRestorePlacement
|
|
write FBeforeRestorePlacement;
|
|
property OnRestorePlacement: TNotifyEvent read FOnRestorePlacement write FOnRestorePlacement;
|
|
property AfterRestorePlacement: TNotifyEvent read FAfterRestorePlacement write
|
|
FAfterRestorePlacement;
|
|
end;
|
|
|
|
TJvStoredValues = class;
|
|
TJvStoredValue = class;
|
|
TJvFormStorageStringList = class;
|
|
|
|
TJvFormStorage = class(TJvFormPlacement)
|
|
private
|
|
FStoredProps: TJvFormStorageStringList;
|
|
FStoredValues: TJvStoredValues;
|
|
FStoredPropsPath: string;
|
|
function GetStoredProps: TStrings;
|
|
procedure SetStoredProps(AValue: TStrings);
|
|
procedure SetStoredValues(AValue: TJvStoredValues);
|
|
function GetStoredValue(const Name: string): Variant;
|
|
procedure SetStoredValue(const Name: string; AValue: Variant);
|
|
function GetDefaultStoredValue(const Name: string; DefValue: Variant): Variant;
|
|
procedure SetDefaultStoredValue(const Name: string; DefValue: Variant; const AValue: Variant);
|
|
function GetStoredValuesPath: string;
|
|
procedure SetStoredValuesPath(const AValue: string);
|
|
protected
|
|
procedure Loaded; override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure SavePlacement; override;
|
|
procedure RestorePlacement; override;
|
|
procedure SaveProperties; virtual;
|
|
procedure RestoreProperties; virtual;
|
|
procedure WriteState(Writer: TWriter); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure SetNotification;
|
|
property StoredValue[const Name: string]: Variant read GetStoredValue write SetStoredValue;
|
|
property DefaultValue[const Name: string; DefValue: Variant]: Variant read GetDefaultStoredValue write SetDefaultStoredValue;
|
|
published
|
|
property StoredProps: TStrings read GetStoredProps write SetStoredProps;
|
|
property StoredValues: TJvStoredValues read FStoredValues write SetStoredValues;
|
|
property StoredPropsPath: string read FStoredPropsPath write FStoredPropsPath;
|
|
property StoredValuesPath: string read GetStoredValuesPath write SetStoredValuesPath;
|
|
end;
|
|
|
|
TJvFormStorageStringList = class(TStringList)
|
|
private
|
|
FFormStorage: TJvFormStorage;
|
|
public
|
|
constructor Create(AFormStorage: TJvFormStorage);
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure LoadFromStream(Stream: TStream); override;
|
|
end;
|
|
|
|
TJvIniLink = class(TPersistent)
|
|
private
|
|
FStorage: TJvFormPlacement;
|
|
FOnSave: TNotifyEvent;
|
|
FOnLoad: TNotifyEvent;
|
|
procedure SetStorage(AValue: TJvFormPlacement);
|
|
protected
|
|
procedure SaveToIni; virtual;
|
|
procedure LoadFromIni; virtual;
|
|
public
|
|
destructor Destroy; override;
|
|
property Storage: TJvFormPlacement read FStorage write SetStorage;
|
|
property OnSave: TNotifyEvent read FOnSave write FOnSave;
|
|
property OnLoad: TNotifyEvent read FOnLoad write FOnLoad;
|
|
end;
|
|
|
|
TJvStoredValueEvent = procedure(Sender: TJvStoredValue; var AValue: Variant) of object;
|
|
|
|
TJvStoredValue = class(TCollectionItem)
|
|
private
|
|
FName: string;
|
|
FValue: Variant;
|
|
FKeyString: string;
|
|
FOnSave: TJvStoredValueEvent;
|
|
FOnRestore: TJvStoredValueEvent;
|
|
function IsValueStored: Boolean;
|
|
function GetStoredValues: TJvStoredValues;
|
|
protected
|
|
function GetDisplayName: string; override;
|
|
procedure SetDisplayName(const AValue: string); override;
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure Clear;
|
|
procedure Save; virtual;
|
|
procedure Restore; virtual;
|
|
property StoredValues: TJvStoredValues read GetStoredValues;
|
|
published
|
|
property Name: string read FName write SetDisplayName;
|
|
property Value: Variant read FValue write FValue stored IsValueStored;
|
|
property KeyString: string read FKeyString write FKeyString;
|
|
property OnSave: TJvStoredValueEvent read FOnSave write FOnSave;
|
|
property OnRestore: TJvStoredValueEvent read FOnRestore write FOnRestore;
|
|
end;
|
|
|
|
TJvStoredValues = class(TOwnedCollection)
|
|
private
|
|
FStorage: TJvFormPlacement;
|
|
FPath: string;
|
|
function GetValue(const Name: string): TJvStoredValue;
|
|
procedure SetValue(const Name: string; StoredValue: TJvStoredValue);
|
|
function GetStoredValue(const Name: string): Variant;
|
|
procedure SetStoredValue(const Name: string; AValue: Variant);
|
|
function GetItem(Index: Integer): TJvStoredValue;
|
|
procedure SetItem(Index: Integer; StoredValue: TJvStoredValue);
|
|
public
|
|
constructor Create(AOwner: TPersistent);
|
|
function IndexOf(const Name: string): Integer;
|
|
procedure SaveValues; virtual;
|
|
procedure RestoreValues; virtual;
|
|
|
|
property Path: string read FPath write FPath;
|
|
property Storage: TJvFormPlacement read FStorage write FStorage;
|
|
property Items[Index: Integer]: TJvStoredValue read GetItem write SetItem; default;
|
|
property Values[const Name: string]: TJvStoredValue read GetValue write SetValue;
|
|
property StoredValue[const Name: string]: Variant read GetStoredValue write SetStoredValue;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvFormPlacement.pas $';
|
|
Revision: '$Revision: 11277 $';
|
|
Date: '$Date: 2007-05-08 01:10:58 +0200 (mar., 08 mai 2007) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
Consts,
|
|
JclStrings,
|
|
JvJCLUtils, JvPropertyStorage;
|
|
|
|
const
|
|
siActiveCtrl = 'ActiveControl'; // do not localize
|
|
siVersion = 'FormVersion'; // do not localize
|
|
cFormNameMask = '%FORM_NAME%'; // do not localize
|
|
|
|
//=== { TJvFormPlacement } ===================================================
|
|
|
|
constructor TJvFormPlacement.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FActive := True;
|
|
if AOwner is TForm then
|
|
FOptions := [fpState, fpSize, fpLocation]
|
|
else
|
|
FOptions := [];
|
|
{$IFDEF VCL}
|
|
FWinHook := TJvWindowHook.Create(Self);
|
|
FWinHook.AfterMessage := WndMessage;
|
|
{$ENDIF VCL}
|
|
FWinMinMaxInfo := TJvWinMinMaxInfo.Create;
|
|
FWinMinMaxInfo.FOwner := Self;
|
|
FLinks := TList.Create;
|
|
FVersion := 0;
|
|
FVersionCheck := fpvcCheckGreaterEqual;
|
|
FAppStoragePath := cFormNameMask;
|
|
FSaved := False;
|
|
FRestored := False;
|
|
FDestroying := False;
|
|
end;
|
|
|
|
destructor TJvFormPlacement.Destroy;
|
|
begin
|
|
while FLinks.Count > 0 do
|
|
RemoveLink(TJvIniLink(FLinks.Last));
|
|
FLinks.Free;
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
{$IFDEF VCL}
|
|
ReleaseHook;
|
|
{$ENDIF VCL}
|
|
RestoreEvents;
|
|
end;
|
|
FWinMinMaxInfo.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.Loaded;
|
|
var
|
|
Loading: Boolean;
|
|
begin
|
|
// Mantis 3190: Only resolve when we are loaded so that we get the correct
|
|
// form name if it's a form inheriting from another one.
|
|
ResolveAppStoragePath;
|
|
Loading := csLoading in ComponentState;
|
|
inherited Loaded;
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
if Loading then
|
|
SetEvents;
|
|
{$IFDEF VCL}
|
|
CheckToggleHook;
|
|
{$ENDIF VCL}
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.AddLink(ALink: TJvIniLink);
|
|
begin
|
|
FLinks.Add(ALink);
|
|
ALink.FStorage := Self;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.NotifyLinks(Operation: TPlacementOperation);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FLinks.Count - 1 do
|
|
with TJvIniLink(FLinks[I]) do
|
|
case Operation of
|
|
poSave:
|
|
SaveToIni;
|
|
poRestore:
|
|
LoadFromIni;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.RemoveLink(ALink: TJvIniLink);
|
|
begin
|
|
ALink.FStorage := nil;
|
|
FLinks.Remove(ALink);
|
|
end;
|
|
|
|
function TJvFormPlacement.GetForm: TForm;
|
|
begin
|
|
if Owner is TCustomForm then
|
|
Result := TForm(Owner as TCustomForm)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SetAppStoragePath(const AValue: string);
|
|
begin
|
|
if (AValue <> '') and (AnsiLastChar(AValue) <> '\') then
|
|
FAppStoragePath := AValue + '\'
|
|
else
|
|
FAppStoragePath := AValue;
|
|
|
|
// Mantis 3190: Do not resolve if we are loding, this is way too early to
|
|
// get a valid form name if this form is inheriting from another one.
|
|
if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then
|
|
begin
|
|
ResolveAppStoragePath;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SetEvents;
|
|
begin
|
|
if Owner is TCustomForm then
|
|
begin
|
|
with TForm(Form) do
|
|
begin
|
|
FSaveFormShow := OnShow;
|
|
OnShow := FormShow;
|
|
FSaveFormCloseQuery := OnCloseQuery;
|
|
OnCloseQuery := FormCloseQuery;
|
|
FSaveFormDestroy := OnDestroy;
|
|
OnDestroy := FormDestroy;
|
|
{$IFDEF VisualCLX}
|
|
FSaveFormConstrainedResize := OnConstrainedResize;
|
|
OnConstrainedResize := FormConstrainedResize;
|
|
{$ENDIF VisualCLX}
|
|
FDefMaximize := (biMaximize in BorderIcons);
|
|
end;
|
|
if FPreventResize then
|
|
UpdatePreventResize;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.RestoreEvents;
|
|
begin
|
|
if (Owner <> nil) and (Owner is TCustomForm) then
|
|
with TForm(Form) do
|
|
begin
|
|
OnShow := FSaveFormShow;
|
|
OnCloseQuery := FSaveFormCloseQuery;
|
|
OnDestroy := FSaveFormDestroy;
|
|
{$IFDEF VisualCLX}
|
|
OnConstrainedResize := FSaveFormConstrainedResize;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvFormPlacement.SetHook;
|
|
begin
|
|
if not (csDesigning in ComponentState) and (Owner <> nil) and
|
|
(Owner is TCustomForm) then
|
|
FWinHook.Control := Form;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.ReleaseHook;
|
|
begin
|
|
FWinHook.Control := nil;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.CheckToggleHook;
|
|
begin
|
|
if CheckMinMaxInfo or PreventResize then
|
|
SetHook
|
|
else
|
|
ReleaseHook;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
function TJvFormPlacement.CheckMinMaxInfo: Boolean;
|
|
begin
|
|
Result := not FWinMinMaxInfo.DefaultMinMaxInfo;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.MinMaxInfoModified;
|
|
begin
|
|
UpdatePlacement;
|
|
{$IFDEF VCL}
|
|
if not (csLoading in ComponentState) then
|
|
CheckToggleHook;
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SetWinMinMaxInfo(AValue: TJvWinMinMaxInfo);
|
|
begin
|
|
FWinMinMaxInfo.Assign(AValue);
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
procedure TJvFormPlacement.WndMessage(Sender: TObject; var Msg: TMessage;
|
|
var Handled: Boolean);
|
|
{$IFDEF CLR}
|
|
var
|
|
MinMax: TMinMaxInfo;
|
|
InitMenuPopup: TWMInitMenuPopup;
|
|
{$ELSE}
|
|
type
|
|
PWMInitMenuPopup = ^TWMInitMenuPopup;
|
|
var
|
|
MinMax: PMinMaxInfo;
|
|
InitMenuPopup: PWMInitMenuPopup;
|
|
{$ENDIF CLR}
|
|
begin
|
|
if FPreventResize and (Owner is TCustomForm) then
|
|
begin
|
|
case Msg.Msg of
|
|
WM_GETMINMAXINFO:
|
|
if Form.HandleAllocated and IsWindowVisible(Form.Handle) then
|
|
begin
|
|
{$IFDEF CLR}
|
|
MinMax := TWMGetMinMaxInfo.Create(Msg).MinMaxInfo;
|
|
{$ELSE}
|
|
MinMax := TWMGetMinMaxInfo(Msg).MinMaxInfo;
|
|
{$ENDIF CLR}
|
|
MinMax.ptMinTrackSize := Point(Form.Width, Form.Height);
|
|
MinMax.ptMaxTrackSize := Point(Form.Width, Form.Height);
|
|
{$IFDEF CLR}
|
|
TWMGetMinMaxInfo.Create(Msg).MinMaxInfo := MinMax;
|
|
{$ENDIF CLR}
|
|
Msg.Result := 1;
|
|
end;
|
|
WM_INITMENUPOPUP:
|
|
begin
|
|
{$IFDEF CLR}
|
|
InitMenuPopup := TWMInitMenuPopup.Create(Msg);
|
|
{$ELSE}
|
|
InitMenuPopup := PWMInitMenuPopup(@Msg);
|
|
{$ENDIF CLR}
|
|
if InitMenuPopup.SystemMenu then
|
|
begin
|
|
if Form.Menu <> nil then
|
|
Form.Menu.DispatchPopup(InitMenuPopup.MenuPopup);
|
|
EnableMenuItem(InitMenuPopup.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED);
|
|
EnableMenuItem(InitMenuPopup.MenuPopup, SC_MAXIMIZE, MF_BYCOMMAND or MF_GRAYED);
|
|
Msg.Result := 1;
|
|
end;
|
|
end;
|
|
WM_NCHITTEST:
|
|
begin
|
|
if Msg.Result in [HTLEFT, HTRIGHT, HTBOTTOM, HTBOTTOMRIGHT,
|
|
HTBOTTOMLEFT, HTTOP, HTTOPRIGHT, HTTOPLEFT]
|
|
then
|
|
Msg.Result := HTNOWHERE;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
if Msg.Msg = WM_GETMINMAXINFO then
|
|
begin
|
|
{$IFDEF CLR}
|
|
MinMax := TWMGetMinMaxInfo.Create(Msg).MinMaxInfo;
|
|
{$ELSE}
|
|
MinMax := TWMGetMinMaxInfo(Msg).MinMaxInfo;
|
|
{$ENDIF CLR}
|
|
if CheckMinMaxInfo then
|
|
begin
|
|
with MinMax{$IFNDEF CLR}^{$ENDIF} do
|
|
begin
|
|
if FWinMinMaxInfo.MinTrackWidth <> 0 then
|
|
ptMinTrackSize.X := FWinMinMaxInfo.MinTrackWidth;
|
|
if FWinMinMaxInfo.MinTrackHeight <> 0 then
|
|
ptMinTrackSize.Y := FWinMinMaxInfo.MinTrackHeight;
|
|
if FWinMinMaxInfo.MaxTrackWidth <> 0 then
|
|
ptMaxTrackSize.X := FWinMinMaxInfo.MaxTrackWidth;
|
|
if FWinMinMaxInfo.MaxTrackHeight <> 0 then
|
|
ptMaxTrackSize.Y := FWinMinMaxInfo.MaxTrackHeight;
|
|
if FWinMinMaxInfo.MaxSizeWidth <> 0 then
|
|
ptMaxSize.X := FWinMinMaxInfo.MaxSizeWidth;
|
|
if FWinMinMaxInfo.MaxSizeHeight <> 0 then
|
|
ptMaxSize.Y := FWinMinMaxInfo.MaxSizeHeight;
|
|
if FWinMinMaxInfo.MaxPosLeft <> 0 then
|
|
ptMaxPosition.X := FWinMinMaxInfo.MaxPosLeft;
|
|
if FWinMinMaxInfo.MaxPosTop <> 0 then
|
|
ptMaxPosition.Y := FWinMinMaxInfo.MaxPosTop;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
MinMax.ptMaxPosition.X := 0;
|
|
MinMax.ptMaxPosition.Y := 0;
|
|
end;
|
|
{$IFDEF CLR}
|
|
TWMGetMinMaxInfo.Create(Msg).MinMaxInfo := MinMax;
|
|
{$ENDIF CLR}
|
|
Msg.Result := 1;
|
|
end;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvFormPlacement.FormShow(Sender: TObject);
|
|
begin
|
|
if IsActive and not FRestored then
|
|
try
|
|
RestoreFormPlacement;
|
|
except
|
|
Application.HandleException(Self);
|
|
end;
|
|
if Assigned(FSaveFormShow) then
|
|
FSaveFormShow(Sender);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
|
|
begin
|
|
if Assigned(FSaveFormCloseQuery) then
|
|
FSaveFormCloseQuery(Sender, CanClose);
|
|
if CanClose and IsActive and (Owner is TCustomForm) and (Form.Handle <> NullHandle) then
|
|
try
|
|
SaveFormPlacement;
|
|
except
|
|
Application.HandleException(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.FormDestroy(Sender: TObject);
|
|
begin
|
|
if IsActive and not FSaved then
|
|
begin
|
|
FDestroying := True;
|
|
try
|
|
SaveFormPlacement;
|
|
except
|
|
Application.HandleException(Self);
|
|
end;
|
|
FDestroying := False;
|
|
end;
|
|
if Assigned(FSaveFormDestroy) then
|
|
FSaveFormDestroy(Sender);
|
|
end;
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvFormPlacement.FormConstrainedResize(Sender: TObject; var MinWidth, MinHeight,
|
|
MaxWidth, MaxHeight: Integer);
|
|
begin
|
|
if FPreventResize and (Owner is TCustomForm) then
|
|
begin
|
|
if FWinMinMaxInfo.MinTrackWidth <> 0 then
|
|
MinWidth := FWinMinMaxInfo.MinTrackWidth;
|
|
if FWinMinMaxInfo.MinTrackHeight <> 0 then
|
|
MinHeight := FWinMinMaxInfo.MinTrackHeight;
|
|
{
|
|
if FWinMinMaxInfo.MaxTrackWidth <> 0 then
|
|
ptMaxTrackSize.X := FWinMinMaxInfo.MaxTrackWidth;
|
|
if FWinMinMaxInfo.MaxTrackHeight <> 0 then
|
|
ptMaxTrackSize.Y := FWinMinMaxInfo.MaxTrackHeight;
|
|
}
|
|
|
|
if FWinMinMaxInfo.MaxSizeWidth <> 0 then
|
|
MaxWidth := FWinMinMaxInfo.MaxSizeWidth;
|
|
if FWinMinMaxInfo.MaxSizeHeight <> 0 then
|
|
MaxHeight := FWinMinMaxInfo.MaxSizeHeight;
|
|
|
|
if FWinMinMaxInfo.MaxPosLeft <> 0 then
|
|
if TCustomForm(Owner).Left > FWinMinMaxInfo.MaxPosLeft then
|
|
TCustomForm(Owner).Left := FWinMinMaxInfo.MaxPosLeft;
|
|
if FWinMinMaxInfo.MaxPosTop <> 0 then
|
|
if TCustomForm(Owner).Top > FWinMinMaxInfo.MaxPosTop then
|
|
TCustomForm(Owner).Top := FWinMinMaxInfo.MaxPosTop;
|
|
end;
|
|
if Assigned(FSaveFormConstrainedResize) then
|
|
FSaveFormConstrainedResize(Sender, MinWidth, MinHeight, MaxWidth, MaxHeight);
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvFormPlacement.UpdatePlacement;
|
|
const
|
|
{$IFDEF VCL}
|
|
Metrics: array [bsSingle..bsSizeToolWin] of Word =
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
Metrics: array [fbsSingle..fbsSizeToolWin] of TSysMetrics =
|
|
{$ENDIF VisualCLX}
|
|
(SM_CXBORDER, SM_CXFRAME, SM_CXDLGFRAME, SM_CXBORDER, SM_CXFRAME);
|
|
var
|
|
Placement: TWindowPlacement;
|
|
begin
|
|
if (Owner <> nil) and (Owner is TCustomForm) and Form.HandleAllocated and
|
|
not (csLoading in ComponentState) then
|
|
if not (FPreventResize or CheckMinMaxInfo) then
|
|
begin
|
|
Placement.Length := SizeOf(TWindowPlacement);
|
|
GetWindowPlacement(Form.Handle, {$IFNDEF CLR}@{$ENDIF} Placement);
|
|
if not IsWindowVisible(Form.Handle) then
|
|
Placement.ShowCmd := SW_HIDE;
|
|
if Form.BorderStyle <> fbsNone then
|
|
begin
|
|
Placement.ptMaxPosition.X := -GetSystemMetrics(Metrics[Form.BorderStyle]);
|
|
Placement.ptMaxPosition.Y := -GetSystemMetrics(Succ(Metrics[Form.BorderStyle]));
|
|
end
|
|
else
|
|
Placement.ptMaxPosition := Point(0, 0);
|
|
SetWindowPlacement(Form.Handle, {$IFNDEF CLR}@{$ENDIF} Placement);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.UpdatePreventResize;
|
|
var
|
|
IsActive: Boolean;
|
|
begin
|
|
if not (csDesigning in ComponentState) and (Owner is TCustomForm) then
|
|
begin
|
|
if FPreventResize then
|
|
FDefMaximize := (biMaximize in Form.BorderIcons);
|
|
IsActive := Active;
|
|
Active := False;
|
|
try
|
|
if (not FPreventResize) and FDefMaximize and
|
|
(Form.BorderStyle <> fbsDialog) then
|
|
Form.BorderIcons := Form.BorderIcons + [biMaximize]
|
|
else
|
|
Form.BorderIcons := Form.BorderIcons - [biMaximize];
|
|
finally
|
|
Active := IsActive;
|
|
end;
|
|
{$IFDEF VCL}
|
|
if not (csLoading in ComponentState) then
|
|
CheckToggleHook;
|
|
{$ENDIF VCL}
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SetPreventResize(AValue: Boolean);
|
|
begin
|
|
if (Form <> nil) and (FPreventResize <> AValue) then
|
|
begin
|
|
FPreventResize := AValue;
|
|
UpdatePlacement;
|
|
UpdatePreventResize;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.Save;
|
|
begin
|
|
if Assigned(FOnSavePlacement) then
|
|
FOnSavePlacement(Self);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.Restore;
|
|
begin
|
|
if Assigned(FOnRestorePlacement) then
|
|
FOnRestorePlacement(Self);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SavePlacement;
|
|
begin
|
|
if Owner is TCustomForm then
|
|
begin
|
|
if Options <> [fpActiveControl] then
|
|
begin
|
|
InternalSaveFormPlacement(Form, AppStorage, AppStoragePath, Options);
|
|
if (fpActiveControl in Options) and (Form.ActiveControl <> nil) then
|
|
AppStorage.WriteString(AppStoragePath + siActiveCtrl, Form.ActiveControl.Name);
|
|
end;
|
|
end;
|
|
NotifyLinks(poSave);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.RestorePlacement;
|
|
begin
|
|
if Owner is TCustomForm then
|
|
InternalRestoreFormPlacement(Form, AppStorage, AppStoragePath, Options);
|
|
NotifyLinks(poRestore);
|
|
end;
|
|
|
|
function TJvFormPlacement.ConcatPaths(const Paths: array of string): string;
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
Result := AppStorage.ConcatPaths(Paths)
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TJvFormPlacement.ReadString(const Ident: string; const Default: string = ''): string;
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
Result := ReadString(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.WriteString(const Ident, AValue: string);
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
WriteString(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, False)]), AValue);
|
|
end;
|
|
|
|
function TJvFormPlacement.ReadBoolean(const Ident: string; Default: Boolean): Boolean;
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
Result := ReadBoolean(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.WriteBoolean(const Ident: string; AValue: Boolean);
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
WriteBoolean(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, False)]), AValue);
|
|
end;
|
|
|
|
function TJvFormPlacement.ReadFloat(const Ident: string; Default: Double = 0): Double;
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
Result := ReadFloat(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.WriteFloat(const Ident: string; AValue: Double);
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
WriteFloat(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, False)]), AValue);
|
|
end;
|
|
|
|
function TJvFormPlacement.ReadInteger(const Ident: string; Default: Longint = 0): Longint;
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
Result := ReadInteger(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.WriteInteger(const Ident: string; AValue: Longint);
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
WriteInteger(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, False)]), AValue);
|
|
end;
|
|
|
|
function TJvFormPlacement.ReadDateTime(const Ident: string; Default: TDateTime = 0): TDateTime;
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
Result := ReadDateTime(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, True)]), Default)
|
|
else
|
|
Result := Default;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.WriteDateTime(const Ident: string; AValue: TDateTime);
|
|
begin
|
|
if Assigned(AppStorage) and (Ident <> '') then
|
|
with AppStorage do
|
|
WriteDateTime(ConcatPaths([AppStoragePath, TranslatePropertyName(Self, Ident, False)]), AValue);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.EraseSections;
|
|
begin
|
|
AppStorage.DeleteSubTree(AppStoragePath);
|
|
end;
|
|
|
|
function TJvFormPlacement.IsActive: Boolean;
|
|
begin
|
|
Result := Active and (AppStorage <> nil);
|
|
end;
|
|
|
|
procedure TJvFormPlacement.SaveFormPlacement;
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
begin
|
|
if Assigned(FBeforeSavePlacement) then
|
|
FBeforeSavePlacement(Self);
|
|
if VersionCheck <> fpvcNocheck then
|
|
WriteInteger(siVersion, FVersion);
|
|
Save;
|
|
SavePlacement;
|
|
if Assigned(FAfterSavePlacement) then
|
|
FAfterSavePlacement(Self);
|
|
FSaved := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.RestoreFormPlacement;
|
|
var
|
|
ActiveCtl: TComponent;
|
|
ReadVersion: Integer;
|
|
ContinueRestore: Boolean;
|
|
begin
|
|
if Assigned(AppStorage) then
|
|
begin
|
|
FSaved := False;
|
|
ReadVersion := ReadInteger(siVersion, 0);
|
|
case VersionCheck of
|
|
fpvcNocheck:
|
|
ContinueRestore := True;
|
|
fpvcCheckGreaterEqual:
|
|
ContinueRestore := ReadVersion >= FVersion;
|
|
fpvcCheckEqual:
|
|
ContinueRestore := ReadVersion = FVersion;
|
|
else
|
|
ContinueRestore := False;
|
|
end;
|
|
if ContinueRestore then
|
|
begin
|
|
if Assigned(FBeforeRestorePlacement) then
|
|
FBeforeRestorePlacement(Self);
|
|
RestorePlacement;
|
|
FRestored := True;
|
|
Restore;
|
|
if (fpActiveControl in Options) and (Owner is TCustomForm) then
|
|
begin
|
|
ActiveCtl := Form.FindComponent(AppStorage.ReadString(AppStorage.ConcatPaths([AppStoragePath, siActiveCtrl]), ''));
|
|
if (ActiveCtl <> nil) and (ActiveCtl is TWinControl) and
|
|
TWinControl(ActiveCtl).CanFocus then
|
|
Form.ActiveControl := TWinControl(ActiveCtl);
|
|
end;
|
|
if Assigned(FAfterRestorePlacement) then
|
|
FAfterRestorePlacement(Self);
|
|
end;
|
|
FRestored := True;
|
|
end;
|
|
UpdatePlacement;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if (Operation = opRemove) and (AComponent = AppStorage) then
|
|
AppStorage := nil;
|
|
end;
|
|
|
|
//=== { TJvWinMinMaxInfo } ===================================================
|
|
|
|
procedure TJvWinMinMaxInfo.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TJvWinMinMaxInfo then
|
|
begin
|
|
FMinMaxInfo := TJvWinMinMaxInfo(Source).FMinMaxInfo;
|
|
if FOwner <> nil then
|
|
FOwner.MinMaxInfoModified;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TJvWinMinMaxInfo.GetMinMaxInfo(Index: Integer): Integer;
|
|
begin
|
|
with FMinMaxInfo do
|
|
begin
|
|
case Index of
|
|
0:
|
|
Result := ptMaxPosition.X;
|
|
1:
|
|
Result := ptMaxPosition.Y;
|
|
2:
|
|
Result := ptMaxSize.Y;
|
|
3:
|
|
Result := ptMaxSize.X;
|
|
4:
|
|
Result := ptMaxTrackSize.Y;
|
|
5:
|
|
Result := ptMaxTrackSize.X;
|
|
6:
|
|
Result := ptMinTrackSize.Y;
|
|
7:
|
|
Result := ptMinTrackSize.X;
|
|
else
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvWinMinMaxInfo.SetMinMaxInfo(Index: Integer; AValue: Integer);
|
|
begin
|
|
if GetMinMaxInfo(Index) <> AValue then
|
|
begin
|
|
with FMinMaxInfo do
|
|
begin
|
|
case Index of
|
|
0:
|
|
ptMaxPosition.X := AValue;
|
|
1:
|
|
ptMaxPosition.Y := AValue;
|
|
2:
|
|
ptMaxSize.Y := AValue;
|
|
3:
|
|
ptMaxSize.X := AValue;
|
|
4:
|
|
ptMaxTrackSize.Y := AValue;
|
|
5:
|
|
ptMaxTrackSize.X := AValue;
|
|
6:
|
|
ptMinTrackSize.Y := AValue;
|
|
7:
|
|
ptMinTrackSize.X := AValue;
|
|
end;
|
|
end;
|
|
if FOwner <> nil then
|
|
FOwner.MinMaxInfoModified;
|
|
end;
|
|
end;
|
|
|
|
function TJvWinMinMaxInfo.DefaultMinMaxInfo: Boolean;
|
|
begin
|
|
with FMinMaxInfo do
|
|
begin
|
|
Result := not ((ptMinTrackSize.X <> 0) or (ptMinTrackSize.Y <> 0) or
|
|
(ptMaxTrackSize.X <> 0) or (ptMaxTrackSize.Y <> 0) or
|
|
(ptMaxSize.X <> 0) or (ptMaxSize.Y <> 0) or
|
|
(ptMaxPosition.X <> 0) or (ptMaxPosition.Y <> 0));
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvFormStorage } =====================================================
|
|
|
|
constructor TJvFormStorage.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FStoredProps := TJvFormStorageStringList.Create(Self);
|
|
FStoredValues := TJvStoredValues.Create(Self);
|
|
FStoredValues.Storage := Self;
|
|
end;
|
|
|
|
destructor TJvFormStorage.Destroy;
|
|
begin
|
|
FStoredProps.Free;
|
|
FStoredProps := nil;
|
|
FStoredValues.Free;
|
|
FStoredValues := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetNotification;
|
|
var
|
|
I: Integer;
|
|
Component: TComponent;
|
|
begin
|
|
for I := StoredProps.Count - 1 downto 0 do
|
|
begin
|
|
Component := TComponent(StoredProps.Objects[I]);
|
|
if Component <> nil then
|
|
Component.FreeNotification(Self);
|
|
end;
|
|
end;
|
|
|
|
function TJvFormStorage.GetStoredProps: TStrings;
|
|
begin
|
|
Result := FStoredProps;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetStoredProps(AValue: TStrings);
|
|
begin
|
|
FStoredProps.Assign(AValue);
|
|
SetNotification;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetStoredValues(AValue: TJvStoredValues);
|
|
begin
|
|
FStoredValues.Assign(AValue);
|
|
end;
|
|
|
|
function TJvFormStorage.GetStoredValue(const Name: string): Variant;
|
|
begin
|
|
Result := StoredValues.StoredValue[Name];
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetStoredValue(const Name: string; AValue: Variant);
|
|
begin
|
|
StoredValues.StoredValue[Name] := AValue;
|
|
end;
|
|
|
|
procedure TJvFormStorage.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
UpdateStoredList(Owner, FStoredProps, True);
|
|
end;
|
|
|
|
procedure TJvFormStorage.WriteState(Writer: TWriter);
|
|
begin
|
|
UpdateStoredList(Owner, FStoredProps, False);
|
|
inherited WriteState(Writer);
|
|
end;
|
|
|
|
procedure TJvFormStorage.Notification(AComponent: TComponent; Operation: TOperation);
|
|
var
|
|
I: Integer;
|
|
Component: TComponent;
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if not (csDestroying in ComponentState) and (Operation = opRemove) and
|
|
(FStoredProps <> nil) then
|
|
for I := FStoredProps.Count - 1 downto 0 do
|
|
begin
|
|
Component := TComponent(FStoredProps.Objects[I]);
|
|
if Component = AComponent then
|
|
FStoredProps.Delete(I);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SaveProperties;
|
|
begin
|
|
with TJvPropertyStorage.Create do
|
|
try
|
|
AppStoragePath := ConcatPaths ([Self.AppStoragePath, StoredPropsPath]);
|
|
AppStorage := Self.AppStorage;
|
|
StoreObjectsProps(Owner, FStoredProps);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormStorage.RestoreProperties;
|
|
begin
|
|
with TJvPropertyStorage.Create do
|
|
try
|
|
AppStoragePath := ConcatPaths ([Self.AppStoragePath, StoredPropsPath]);
|
|
AppStorage := Self.AppStorage;
|
|
try
|
|
LoadObjectsProps(Owner, FStoredProps);
|
|
except
|
|
{ ignore any exceptions }
|
|
end;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SavePlacement;
|
|
Var
|
|
JvAppStorageHandler: IJvAppStorageHandler;
|
|
begin
|
|
inherited SavePlacement;
|
|
if Supports(Owner, IJvAppStorageHandler, JvAppStorageHandler)then
|
|
JvAppStorageHandler.WriteToAppStorage(AppStorage, AppStoragePath);
|
|
SaveProperties;
|
|
StoredValues.SaveValues;
|
|
end;
|
|
|
|
procedure TJvFormStorage.RestorePlacement;
|
|
Var
|
|
JvAppStorageHandler: IJvAppStorageHandler;
|
|
begin
|
|
inherited RestorePlacement;
|
|
FRestored := True;
|
|
if Supports(Owner, IJvAppStorageHandler, JvAppStorageHandler)then
|
|
JvAppStorageHandler.ReadFromAppStorage(AppStorage, AppStoragePath);
|
|
RestoreProperties;
|
|
StoredValues.RestoreValues;
|
|
end;
|
|
|
|
//=== { TJvIniLink } =========================================================
|
|
|
|
destructor TJvIniLink.Destroy;
|
|
begin
|
|
FOnSave := nil;
|
|
FOnLoad := nil;
|
|
SetStorage(nil);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvIniLink.SetStorage(AValue: TJvFormPlacement);
|
|
begin
|
|
if FStorage <> AValue then
|
|
begin
|
|
if FStorage <> nil then
|
|
FStorage.RemoveLink(Self);
|
|
if AValue <> nil then
|
|
AValue.AddLink(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvIniLink.SaveToIni;
|
|
begin
|
|
if Assigned(FOnSave) then
|
|
FOnSave(Self);
|
|
end;
|
|
|
|
procedure TJvIniLink.LoadFromIni;
|
|
begin
|
|
if Assigned(FOnLoad) then
|
|
FOnLoad(Self);
|
|
end;
|
|
|
|
//=== { TJvStoredValue } =====================================================
|
|
|
|
constructor TJvStoredValue.Create(Collection: TCollection);
|
|
begin
|
|
inherited Create(Collection);
|
|
FValue := Unassigned;
|
|
end;
|
|
|
|
procedure TJvStoredValue.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TJvStoredValue then
|
|
begin
|
|
if VarIsEmpty(TJvStoredValue(Source).Value) then
|
|
Clear
|
|
else
|
|
Value := TJvStoredValue(Source).Value;
|
|
Name := TJvStoredValue(Source).Name;
|
|
KeyString := TJvStoredValue(Source).KeyString;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TJvStoredValue.GetDisplayName: string;
|
|
begin
|
|
if FName = '' then
|
|
Result := inherited GetDisplayName
|
|
else
|
|
Result := FName;
|
|
end;
|
|
|
|
procedure TJvStoredValue.SetDisplayName(const AValue: string);
|
|
begin
|
|
if (AValue <> '') and (AnsiCompareText(AValue, FName) <> 0) and
|
|
(Collection is TJvStoredValues) and (TJvStoredValues(Collection).IndexOf(AValue) >= 0) then
|
|
{$IFDEF CLR}
|
|
raise EJVCLException.Create(SDuplicateString);
|
|
{$ELSE}
|
|
raise EJVCLException.CreateRes(@SDuplicateString);
|
|
{$ENDIF CLR}
|
|
FName := AValue;
|
|
inherited SetDisplayName(AValue);
|
|
end;
|
|
|
|
function TJvStoredValue.GetStoredValues: TJvStoredValues;
|
|
begin
|
|
if Collection is TJvStoredValues then
|
|
Result := TJvStoredValues(Collection)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TJvStoredValue.Clear;
|
|
begin
|
|
FValue := Unassigned;
|
|
end;
|
|
|
|
function TJvStoredValue.IsValueStored: Boolean;
|
|
begin
|
|
Result := not VarIsEmpty(FValue);
|
|
end;
|
|
|
|
procedure TJvStoredValue.Save;
|
|
var
|
|
SaveValue: Variant;
|
|
SaveStrValue: string;
|
|
PathName: string;
|
|
begin
|
|
PathName := StoredValues.Storage.ConcatPaths([StoredValues.Path, Name]);
|
|
SaveValue := Value;
|
|
if Assigned(FOnSave) then
|
|
FOnSave(Self, SaveValue);
|
|
if KeyString <> '' then
|
|
begin
|
|
SaveStrValue := VarToStr(SaveValue);
|
|
SaveStrValue := XorEncode(KeyString, SaveStrValue);
|
|
StoredValues.Storage.WriteString(PathName, SaveStrValue);
|
|
end
|
|
else
|
|
if VarIsInt(SaveValue) then
|
|
StoredValues.Storage.WriteInteger(PathName, SaveValue)
|
|
else
|
|
if VarType(SaveValue) in [varSingle, varDouble, varCurrency] then
|
|
StoredValues.Storage.WriteFloat(PathName, SaveValue)
|
|
else
|
|
if VarType(SaveValue) in [varDate] then
|
|
StoredValues.Storage.WriteDateTime(PathName, SaveValue)
|
|
else
|
|
if VarType(SaveValue) in [varBoolean] then
|
|
StoredValues.Storage.WriteBoolean(PathName, SaveValue)
|
|
else
|
|
StoredValues.Storage.WriteString(PathName, SaveValue);
|
|
end;
|
|
|
|
procedure TJvStoredValue.Restore;
|
|
var
|
|
RestoreValue: Variant;
|
|
RestoreStrValue, DefaultStrValue: string;
|
|
PathName: string;
|
|
begin
|
|
PathName := StoredValues.Storage.ConcatPaths([StoredValues.Path, Name]);
|
|
if KeyString <> '' then
|
|
begin
|
|
DefaultStrValue := VarToStr(Value);
|
|
DefaultStrValue := XorEncode(KeyString, DefaultStrValue);
|
|
RestoreStrValue := StoredValues.Storage.ReadString(PathName, DefaultStrValue);
|
|
RestoreStrValue := XorDecode(KeyString, RestoreStrValue);
|
|
RestoreValue := RestoreStrValue;
|
|
end
|
|
else
|
|
if VarIsInt(Value) then
|
|
RestoreValue := StoredValues.Storage.ReadInteger(PathName, Value)
|
|
else
|
|
if VarType(Value) in [varSingle, varDouble, varCurrency] then
|
|
RestoreValue := StoredValues.Storage.ReadFloat(PathName, Value)
|
|
else
|
|
if VarType(Value) in [varDate] then
|
|
RestoreValue := StoredValues.Storage.ReadDateTime(PathName, Value)
|
|
else
|
|
if VarType(Value) in [varBoolean] then
|
|
RestoreValue := StoredValues.Storage.ReadBoolean(PathName, Value)
|
|
else
|
|
RestoreValue := StoredValues.Storage.ReadString(PathName, Value);
|
|
if Assigned(FOnRestore) then
|
|
FOnRestore(Self, RestoreValue);
|
|
Value := RestoreValue;
|
|
end;
|
|
|
|
//=== { TJvStoredValues } ====================================================
|
|
|
|
constructor TJvStoredValues.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner, TJvStoredValue);
|
|
end;
|
|
|
|
function TJvStoredValues.IndexOf(const Name: string): Integer;
|
|
begin
|
|
for Result := 0 to Count - 1 do
|
|
if AnsiCompareText(Items[Result].Name, Name) = 0 then
|
|
Exit;
|
|
Result := -1;
|
|
end;
|
|
|
|
function TJvStoredValues.GetItem(Index: Integer): TJvStoredValue;
|
|
begin
|
|
Result := TJvStoredValue(inherited Items[Index]);
|
|
end;
|
|
|
|
procedure TJvStoredValues.SetItem(Index: Integer; StoredValue: TJvStoredValue);
|
|
begin
|
|
inherited SetItem(Index, TCollectionItem(StoredValue));
|
|
end;
|
|
|
|
function TJvStoredValues.GetStoredValue(const Name: string): Variant;
|
|
var
|
|
StoredValue: TJvStoredValue;
|
|
begin
|
|
StoredValue := GetValue(Name);
|
|
if StoredValue = nil then
|
|
Result := Null
|
|
else
|
|
Result := StoredValue.Value;
|
|
end;
|
|
|
|
procedure TJvStoredValues.SetStoredValue(const Name: string; AValue: Variant);
|
|
var
|
|
StoredValue: TJvStoredValue;
|
|
begin
|
|
StoredValue := GetValue(Name);
|
|
if StoredValue = nil then
|
|
begin
|
|
StoredValue := TJvStoredValue(Add);
|
|
StoredValue.Name := Name;
|
|
StoredValue.Value := AValue;
|
|
end
|
|
else
|
|
StoredValue.Value := AValue;
|
|
end;
|
|
|
|
function TJvStoredValues.GetValue(const Name: string): TJvStoredValue;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := IndexOf(Name);
|
|
if I < 0 then
|
|
Result := nil
|
|
else
|
|
Result := Items[I];
|
|
end;
|
|
|
|
procedure TJvStoredValues.SetValue(const Name: string; StoredValue: TJvStoredValue);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := IndexOf(Name);
|
|
if I >= 0 then
|
|
Items[I].Assign(StoredValue);
|
|
end;
|
|
|
|
procedure TJvStoredValues.SaveValues;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
Items[I].Save;
|
|
end;
|
|
|
|
procedure TJvStoredValues.RestoreValues;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
Items[I].Restore;
|
|
end;
|
|
|
|
function TJvFormStorage.GetDefaultStoredValue(const Name: string; DefValue: Variant): Variant;
|
|
begin
|
|
Result := StoredValue[Name];
|
|
if Result = Null then
|
|
Result := DefValue;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetDefaultStoredValue(const Name: string;
|
|
DefValue: Variant; const AValue: Variant);
|
|
begin
|
|
if AValue = Null then
|
|
StoredValue[Name] := DefValue
|
|
else
|
|
StoredValue[Name] := AValue;
|
|
end;
|
|
|
|
function TJvFormStorage.GetStoredValuesPath: string;
|
|
begin
|
|
Result := FStoredValues.Path;
|
|
end;
|
|
|
|
procedure TJvFormStorage.SetStoredValuesPath(const AValue: string);
|
|
begin
|
|
FStoredValues.Path := AValue;
|
|
end;
|
|
|
|
procedure TJvFormPlacement.ResolveAppStoragePath;
|
|
begin
|
|
if (StrFind(cFormNameMask, FAppStoragePath) <> 0) and
|
|
Assigned(Owner) and (Owner is TCustomForm) then
|
|
StrReplace(FAppStoragePath, cFormNameMask, Owner.Name, [rfIgnoreCase]);
|
|
end;
|
|
|
|
{ TJvFormStorageStringList }
|
|
|
|
procedure TJvFormStorageStringList.Assign(Source: TPersistent);
|
|
begin
|
|
inherited;
|
|
if not (csLoading in FFormStorage.ComponentState) then
|
|
UpdateStoredList(FFormStorage.Owner, Self, True);
|
|
end;
|
|
|
|
constructor TJvFormStorageStringList.Create(AFormStorage: TJvFormStorage);
|
|
begin
|
|
inherited Create;
|
|
FFormStorage := AFormStorage;
|
|
end;
|
|
|
|
procedure TJvFormStorageStringList.LoadFromStream(Stream: TStream);
|
|
begin
|
|
inherited;
|
|
if not (csLoading in FFormStorage.ComponentState) then
|
|
UpdateStoredList(FFormStorage.Owner, Self, True);
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|
|
|