[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]