Window位置の保存・復元処理

ウィンドウの位置・サイズを保存するとき、Width/Heightをそのまま保存するとウィンドウを最大化してる時に最大化状態のWidth/Heightが保存されてしまうので悲しい状態になります。

そこで、GetWindowPlacementを使うと最大化状態であっても通常状態のウィンドウの位置・サイズを取得出来るのでこれで取得した値を利用するようにすると良いかと。

私は下記のような関数を作ってiniファイルに保存・読込してます。
iniファイルのWindowsセクションにVNameで指定した名前で保存します。

// IniPath: iniファイルのパス
// Form: 位置を読み込むフォーム
// VName: iniファイルから読む時の名前
procedure SaveWindowPosition(IniPath: String; Form: TForm; VName: String);
var
  Strm: TMemoryStream;
  wm: TWindowPlacement;
  ini: TMemInifile;
begin
  wm.length := SizeOf(wm);
  GetWindowPlacement(Form.Handle, @wm);

  Strm := TMemoryStream.Create;
  Strm.Write(wm.rcNormalPosition, SizeOf(TRect));
  Strm.Write(wm.showCmd, SizeOf(UINT));
  Strm.Position := 0;

  ini := TMemIniFile.Create(IniPath);
//  ini := TMemIniFile.Create(IniPath, TEncoding.UTF8); // XEの場合はこちらの方が良いかも?
  ini.WriteBinaryStream('WINDOWS', VName, Strm);
  ini.UpdateFile;

  FreeAndNil(ini);
  FreeAndNil(Strm);
end;

// IniPath: iniファイルのパス
// Form: 位置を読み込むフォーム
// VName: iniファイルから読む時の名前
// TopLeft: 位置のみを復元する場合はTrue
//          位置・サイズ双方を復元する場合はFalse
procedure LoadWindowPosition(IniPath: String; Form: TForm; VName: String;
  TopLeft: Boolean);
var
  Strm: TMemoryStream;
  ini: TMemInifile;
  rc: TRect;
  ShowCmd: UINT;
begin
  Strm := TMemoryStream.Create;
  ini := TMemIniFile.Create(IniPath);

  if ini.ValueExists('WINDOWS', VName) then
  begin
    ini.ReadBinaryStream('WINDOWS', VName, Strm);
    ShowCmd := 0;
    try
      Strm.Position := 0;
      Strm.Read(rc, SizeOf(TRect));
      Strm.Read(ShowCmd, SizeOf(UINT));
    except
    end;
    Form.Top := rc.Top;
    Form.Left := rc.Left;
    if Not TopLeft then
    begin
      Form.Width := rc.Right - rc.Left;
      Form.Height := rc.Bottom - rc.Top;
    end;

    if (ShowCmd = SW_MAXIMIZE) then Form.WindowState := wsMaximized;
  end;
  FreeAndNil(ini);
  FreeAndNil(Strm);
end;