[Back to DELPHI SWAG index] [Back to Main SWAG index] [Original]
A: Here is WindowRestorer - a window size and state restorer DESCRIPTION:
Ever notice how professional programs seem to remember in what condition
and location you left them and their child windows? Ever notice how most
RAD apps don't? You can take that ragged edge off your program with this
unit. It Allows apps to save the location, size, and state of windows so
that when the user reopens them, they will look as the user left them.
USE: Put WINRSTOR in the uses of clause of your main form and any forms
that will be saving or restoring their own state, size, or location. (If
you will be doing all the saving and restoring using WinSaveChildren and
WinRestoreChildren from the main form, you only need reference it in the
main form's uses clause.)
In MainForm.Create, initialize the global WinRestorer object as follows
(it's already declared in this file, but needs to be allocated):
--------------------------------------------------------------------------------
GlobalWinRestorer := TWinRestorer.create( Application, TRUE, WHATSAVE_ALL);
--------------------------------------------------------------------------------
Which is the same as:
--------------------------------------------------------------------------------
GlobalWinRestorer := TWinRestorer.create( Application, TRUE, [location, size, state]);
--------------------------------------------------------------------------------
Then, in MainForm.Destroy, deallocate the global WinRestorer object as
follows:
--------------------------------------------------------------------------------
GlobalWinRestorer.free;
--------------------------------------------------------------------------------
A good place to save a form's status is in the queryclose event or else
attached to a button or menu item. I usually create an item in the File
Menu captioned 'Save &Workspace' which does:
--------------------------------------------------------------------------------
GlobalWinRestorer.SaveChildren(Self, [default]);
--------------------------------------------------------------------------------
And under main form's Close event I put:
--------------------------------------------------------------------------------
GlobalWinRestorer.SaveWin(Self, [WHATSAVE_ALL]);
--------------------------------------------------------------------------------
I have tended to restore the children's status in their own show events
like this:
--------------------------------------------------------------------------------
GlobalWinRestorer.RestoreWin(Self, [default]);
--------------------------------------------------------------------------------
though I am moving toward putting in the main form's show event:
--------------------------------------------------------------------------------
GlobalWinRestorer.RestoreWin(Self, [default]);
GlobalWinRestorer.RestoreChildren(Self, [default]);
--------------------------------------------------------------------------------
HINTS: If you set TForm.Position to poScreenCenter or anything fancy, this
unit won't do what you expect. poDesigned seems to work fairly well. I
could have raised an exception if you try to set top and left of a
poScreenCentere'd form, but then you have to be careful using
WinRestoreChildren. I opted not to check the position property and leave
that up to individual developers.
--------------------------------------------------------------------------------
unit WinRstor;
INTERFACE
USES SysUtils, Forms;
TYPE {=============================================================}
{------------------------------------------------------------------
Windows restorer object class and related types.
-------------------------------------------------------------------}
EWinRestorer = class( Exception);
TWhatSave = (default, size, location, state);
STWhatSave = set of TWhatSave;
TWinRestorer = class(TObject)
protected
mIniFile: string;
mIniSect: string[80];
mIsInitialized: boolean;
mDefaultWhat: STWhatSave;
public
constructor Create( TheApp: TApplication;
LocalDir: boolean; DefaultWhatSave: STWhatSave);
{If localDir is true, ini dir is the app dir. Else, ini dir is the windows dir.}
procedure SaveWin(TheForm: TForm; What: STWhatSave);
procedure SaveChildren(TheMDIForm: TForm; What: STWhatSave);
procedure RestoreWin( TheForm: TForm; What: STWhatSave);
procedure RestoreChildren(TheMDIForm: TForm; What: STWhatSave);
property IniFileName: string read mIniFile;
end;
CONST
WHATSAVE_ALL = [size, location, state];
VAR
GlobalWinRestorer: TWinRestorer;
IMPLEMENTATION
Uses IniFiles;
constructor TWinRestorer.create;
var fname, path: string[100];
begin
inherited create;
{Calculate ini file name}
if default in DefaultWhatSave then
raise EWinRestorer.create(
'Attempt to initialize default window position paramaters with set ' +
' containing [default] item. ' +
'Default params may contain only members of [size, location, state]. ')
else mDefaultWhat := DefaultWhatSave;
fname := ChangeFileExt( ExtractFileName( TheApp.exeName), '.INI');
if LocalDir then begin {parse out path and add to file name}
path := ExtractFilePath(TheApp.exeName);
if path[length(path)] <> '\' then
path := path + '\';
fname := path + fname;
end;
{fill object fields}
mIniFile := fname;
mIniSect := 'WindowsRestorer';
{It'd be nice to write some notes to a section called [WinRestorer Notes]}
end;
procedure TWinRestorer.RestoreWin;
var FormNm, SectionNm: string[80]; ini: TIniFile;
n,l,t,w,h: integer; {Left, Top Width, Height}
begin
ini := TIniFile.create( mIniFile);
TRY
SectionNm := mIniSect;
FormNm := TheForm.classname;
if default in What then What := mDefaultWhat;
{Update Window State if Necessary}
if state in What then
n := ini.ReadInteger( SectionNm, FormNm + '_WindowState', 0);
case n of
1: TheForm.WindowState := wsMinimized;
2: TheForm.WindowState := wsNormal;
3: TheForm.WindowState := wsMaximized;
end;
{Update Size and Location if necessary.}
with TheForm do begin l:=left; t:=top; h:=height; w:=width; end; {Save current vals.}
if size in What then begin
w := ini.ReadInteger( SectionNm, FormNm + '_Width', w);
h := ini.ReadInteger( SectionNm, FormNm + '_Height', h);
end;
if location in What then begin
t := ini.ReadInteger( SectionNm, FormNm + '_Top', t);
l := ini.ReadInteger( SectionNm, FormNm + '_Left', l);
end;
TheForm.SetBounds(l,t,w,h);
FINALLY
ini.free;
END;
end;
procedure TWinRestorer.RestoreChildren;
var i: integer;
begin
if TheMDIForm.formstyle <> fsMDIForm then
raise EWinRestorer.create('Attempting to save window sizes of children for a non MDI parent window.')
else
for i := 0 to TheMDIForm.MDIChildCount - 1 do
RestoreWin( TheMDIForm.MDIChildren[i], what);
end;
procedure TWinRestorer.SaveWin;
var FormNm, SectionNm: string[80]; w : STWhatsave; ini: TIniFile;
begin
ini := TIniFile.create( mIniFile);
TRY
SectionNm := mIniSect;
FormNm := TheForm.ClassName;
if default in What then w := mDefaultWhat else w := mDefaultWhat;
if size in w then begin
ini.WriteInteger( SectionNm, FormNm + '_Width', TheForm.Width);
ini.WriteInteger( SectionNm, FormNm + '_Height', TheForm.Height);
end;
if location in w then begin
ini.WriteInteger( SectionNm, FormNm + '_Top', TheForm.Top);
ini.WriteInteger( SectionNm, FormNm + '_Left', TheForm.Left);
end;
if state in w then
case TheForm.WindowState of
wsMinimized: ini.WriteInteger( SectionNm, FormNm + '_WindowState', 1);
wsNormal: ini.WriteInteger( SectionNm, FormNm + '_WindowState', 2);
wsMaximized: ini.WriteInteger( SectionNm, FormNm + '_WindowState', 3);
end;
FINALLY
ini.free;
END;
end;
procedure TWinRestorer.SaveChildren;
var i: integer;
begin
if TheMDIForm.formstyle <> fsMDIForm then
raise EWinRestorer.create('Attempting to restore window sizes of children for a non MDI parent window.')
else
for i := 0 to TheMDIForm.MDIChildCount - 1 do
SaveWin( TheMDIForm.MDIChildren[i], what);
end;
INITIALIZATION
END.
[Back to DELPHI SWAG index] [Back to Main SWAG index] [Original]