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.