tags:

views:

615

answers:

4

This question seems easy but for some reason I have trouble finding the answer.

I have an application that saves the form's size and position on an INI file. That's all an well, however when you close the application when maximized it will save the size and position of the form maximized but not its state.

What I mean is that on the next run the form would appear maximized when in fact it's "restored" but covering the whole desktop.

Is there a way to save the form size previous to the maximize event, then save the fact that the form is maximized. The on the read from the INI file create the form in a maximized state and set its "restore" size to the one before the maximize event?

thanks!

+7  A: 

Use the Windows API function GetWindowPlacement(), like so:

procedure TForm1.WriteSettings(AUserSettings: TIniFile);
var
  Wp: TWindowPlacement;
begin
  Assert(AUserSettings <> nil);

  if HandleAllocated then begin
    Wp.length := SizeOf(TWindowPlacement);
    GetWindowPlacement(Handle, Wp);

    AUserSettings.WriteInteger(SektionMainForm, KeyFormLeft,
      Wp.rcNormalPosition.Left);
    AUserSettings.WriteInteger(SektionMainForm, KeyFormTop,
      Wp.rcNormalPosition.Top);
    AUserSettings.WriteInteger(SektionMainForm, KeyFormWidth,
      Wp.rcNormalPosition.Right - Wp.rcNormalPosition.Left);
    AUserSettings.WriteInteger(SektionMainForm, KeyFormHeight,
      Wp.rcNormalPosition.Bottom - Wp.rcNormalPosition.Top);
    AUserSettings.WriteBool(SektionMainForm, KeyFormMaximized,
      WindowState = wsMaximized);
  end;
end;
mghie
Thanks. How do I call this function? What is IPersistentSettingsWriter?
wonderer
@wonderer -- This example shows usage example of the GetWindowPlacement API function. You would have to modify this example for your own project... and change the AUserSettings calls to something like an INI file, or user registry settings.
skamradt
@skamradt: Indeed, +1. I just copied it from my current project. @wonderer: IPersistentSettingsWriter is in its simplest form a wrapper for TIniFile, you can see that the WriteXXX() methods have the same name and parameters. Simply replace as skamradt suggested.
mghie
Edited, hopefully it's clearer now. In my defense, I consider programming against interfaces instead of classes a very good thing. My settings interface can easily be implemented in terms of INI file, registry or even database table storage, and the code using it doesn't have to be changed one bit. Also, I have distinct *IPersistentSettingsReader* and *IPersistentSettingsWriter* interfaces, so it's impossible to accidently write to an INI file that is in a read-only directory if the code is given only a reader interface.
mghie
I understand, thank you.I get the following error:[Error] main.pas(1150): Incompatible types: 'tagWINDOWPLACEMENT' and 'PWindowPlacement'on GetWindowPlacement(Handle, Wp);
wonderer
got it. thanks for the help!
wonderer
+2  A: 

Try the Form.WindowState property. By reading this, you can write it to the ini file, then read back from the ini to re-set the state in the form.show method. You might want to re-cast it to an integer as the WindowState is an enumerated type (TWindowState).

Tom
A: 

DelphiDabbler has some nice window state components. You just drop one on your form and it will save the state to an ini file or the registry on form destroy and load it on form create.

BJ Miller
+1  A: 

Tom's answer should work nicely. Here is some Pseudo-Code to clarify a little:

procedure TfrmDatenMonitor.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  inherited;
  //*** Save the WindowState in every case
  aIniFile.WriteInteger(Name, 'State', Integer(WindowState));

  if WindowState = wsNormal then begin
    //*** Save Position and Size, too...
    aIniFile.WriteInteger(Name, 'Top',    Top);
    aIniFile.WriteInteger(Name, 'Left',   Left);
    aIniFile.WriteInteger(Name, 'Height', Height);
    aIniFile.WriteInteger(Name, 'Width',  Width);
  end;
end;

when reading the settings set Size and Position first. Then read the WindowState and assign it with a typecast:

WindowState := TWindowState(aIniFile.ReadInteger(Name, 'State', Integer(wsNormal)));
Andreas Wieland