Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Formular Position speichern (https://www.delphipraxis.net/186030-formular-position-speichern.html)

Sugar 28. Jul 2015 19:26

Formular Position speichern
 
Hallo,

ich arbeite daran die Positionen der Formulre meiner Anwendung zu speichern und auch wieder zu lesen.

Im Prinzip ist mein Problem:

Ich speichere den Namen (und weitere Daten) des Formulares in einer Tabelle. Das Feld in dem der Name des Formulares steht ist ein VarChar, also String.

Nun muss ich beim Öffnn der Formulare dieses String in ein TForm (o.ä.) umwandeln um dann Width, Top etc zuzuweisen. Ich scheitere aber daran, den ausgelesenen String in ein TForm umzuwandeln.


Kann mir jemand helfen?

Sir Rufo 28. Jul 2015 20:24

AW: Formular Position speichern
 
Und warum lässt du die Form die Werte nicht selber speichern und laden?

Der Form sollte ihr Name doch bekannt sein

Luckie 28. Jul 2015 21:49

AW: Formular Position speichern
 
Stichwort: Ini-Datei, Registry. Im OnClose speichern und beim OnCreate wieder lesen.

hoika 28. Jul 2015 22:13

AW: Formular Position speichern
 
Sugar,
ein bisschen mehr Infos bitte.

ÄHeiko

Perlsau 28. Jul 2015 22:51

AW: Formular Position speichern
 
Zitat:

Zitat von Sugar (Beitrag 1310061)
Ich speichere den Namen (und weitere Daten) des Formulares in einer Tabelle. Das Feld in dem der Name des Formulares steht ist ein VarChar, also String. Nun muss ich beim Öffnn der Formulare dieses String in ein TForm (o.ä.) umwandeln um dann Width, Top etc zuzuweisen. Ich scheitere aber daran, den ausgelesenen String in ein TForm umzuwandeln. Kann mir jemand helfen?

Mir ist ebenfalls nicht so recht klar, was dein eigentliches Problem ist. Meinst du wirklich das Property Name, wenn du davon schreibst, den Namen des Formulars speichern und lesen zu wollen? Oder meinst du – was weitaus wahrscheinlicher wäre – das Property Caption, das den Text enthält, der in der Titelleiste eines Formulars angezeigt wird? Wie oben schon festgestellt wurde, ist der Name eines Formulars beim dessen Erzeugung bereits bekannt. Andernfalls könntest du das Formular gar nicht erst erzeugen. Irgendwo hast du da offenbar was vollkommen falsch verstanden, aber was das sein könnte, entzieht sich meiner Kenntnis.

hathor 28. Jul 2015 23:03

AW: Formular Position speichern
 
http://www.torry.net/pages.php?id=96

Sugar 29. Jul 2015 05:44

AW: Formular Position speichern
 
Hallo Forum,

habe ich mich wirklich so unverständlich ausgedrückt? Entschuldigung.

Also, mal weiter ausgeholt:

Ich erweitere eine ältere interne Anwendung über die unsere User sich schon immer beschwert haben, weil die Fensterpositionen nicht gespeichert werden und man nicht die Möglichkeit hat sich auf den Bildschirmen zurecht gerückten Formulare, dessen Größe und Position zu "merken". Hintergrund: Kommt ein Anruf in der Zentrale an zeigt das Hauptformular den Stammsatz des Anrufers an, soweit erkennbar.

Der User muss dann weitere Fenster "manuell" öffnen um bspw. Historie, Rechnungen etc. im Blick zu haben.

Ich möchte nun, dass der User sich seine drei, vier Fenster öffnen und auf den Bildschirmen platzieren kann UND diese "Ansicht" als Szenario speichern. Öffnet der User dann das Programm, lese ich in der Datenbank was er als Szenario gespeichert hat und öffne und platziere diese Fenster. So die Idee...

Ich dachte mir nun, ich speichere in einer Tabelle den Usernamen, den Namen der Form (Ja, die Eigenschaft NAME),Top, Height, Width, left und ein bit ob das Fenster beim Start sichtbar sein soll.

Was ich nun nicht weiß wie man es umsetzt ist: Ich hole mir den Namen der Form als String, nur wie wandele ich diesen String um, so dass ich damit die Form mit diesem Namen anzeigen kann?

Kurzes "Nebenproblem" noch dazu: Gibt es eine Möglichkeit alle offenen Formulare der Anwendung zu ermitteln?

Also, nochmal Sorry für die vielleicht verwirrende Anfrage. Ich hoffe es ist nun klarer was ich vorhabe.

Danke für die bisherige Hilfe

Gruß
Sugar

[edit]ps. @hathor: Dein Link ist nicht verfügbar

[edit2]:

Zu dem Ermitteln der offenen Formulare habe ich etwas gefunden:

Delphi-Quellcode:
For i:=0 to Screen.FormCount-1 do
   begin
    Screen.Forms[i].Name
Wenn in Name etwas steht ist es eine geöffnete Form meiner App.

bcvs 29. Jul 2015 07:33

AW: Formular Position speichern
 
Zitat:

Zitat von Sugar (Beitrag 1310077)
Was ich nun nicht weiß wie man es umsetzt ist: Ich hole mir den Namen der Form als String, nur wie wandele ich diesen String um, so dass ich damit die Form mit diesem Namen anzeigen kann?

Schreib dir halt eine Funktion, die abhängig vom Namen die richtige Form erzeugt und anzeigt. z.B. ganz einfach so

Delphi-Quellcode:
if FormName='MyForm' then
begin
  MyForm:=TMyForm.Create(Application);
  MyForm.Show;
end;

Sugar 29. Jul 2015 07:58

AW: Formular Position speichern
 
@bcvs

Ich dachte halt es geht eleganter. So muss ich bei jeder neu hinzukommenden Form auch die Abfrage anpassen... das wollte ich umgehen

Lemmy 29. Jul 2015 08:19

AW: Formular Position speichern
 
Zitat:

Zitat von Sugar (Beitrag 1310081)
@bcvs

Ich dachte halt es geht eleganter. So muss ich bei jeder neu hinzukommenden Form auch die Abfrage anpassen... das wollte ich umgehen

dann nimm eine TClassLIst (aus contnrs) und fülle die beim Programmstart mit allen relevanten Formularen

Delphi-Quellcode:
Liste := TClassList;
Liste.Add(TFormXYZ);
-...

wenn Du nun ein bestimmtes Formular suchst:

Delphi-Quellcode:
function FOrmErzeugen(AFormularName: String): TForm;
var
  FormClass: TFormClass;
  idxForm: Integer;
begin
  FormClass := nil;
  for idxForm := 0 to Liste.Count -1 do
  begin
    if Liste.Item[idxForm].ClassName = AFormularName then
      FormClass := Liste.Item[idxForm]
  end;
  if Assigned(FOrmClass) then
    result := FormClass.Create(Application)
  else
    ....

Und wenn dir das ständige Durchlaufen der ClassList zu langsam ist, dann sortiere die Liste nach den Namen, dann kannst Du schneller suchen....

Nachtrag: Wenn Du ein aktuelleres Delphi hast, kannst Du hier auch mit einer generischen Liste arbeiten....

hathor 29. Jul 2015 08:25

AW: Formular Position speichern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Vielleicht ist FormPersist für Dich geeignet.
Von hier: http://www.torry.net/vcl/forms/savers/FormPersist.zip
Getestet mit WIN8.1, XE7
Im Anhang EXE.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, FormPersist;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin //
//  SaveForms();
  SaveAllForms;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin //
//  LoadForms();
  LoadAllForms;
end;

end.

//-----------------------------------------------------------------
//(c) Alex Mitev, alexmi@abv.bg, February 2005
//You can use this unit freely, but please let me know if you make any improvements in it.


// a conditional symbol for saving the settigns file in text format, without archiving
//{$DEFINE DEBUG}

unit FormPersist;

interface

uses
  System.Classes, System.SysUtils, Vcl.Forms, System.ZLib, System.TypInfo,
  Winapi.Windows, Vcl.Dialogs;

type
  TSectionFile = class(TObject)
  private
    FSections: TStringList;
    function AddSection(const Section: string): TStrings;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Clear;
    function SectionExists(const Section: string): Boolean;
    procedure ReadSection(const Section: string; Strings: TStrings); overload;
    function ReadSection(const Section: string): String; overload;
    procedure EraseSection(const Section: string);
    procedure WriteSection(const Section: string; Strings: TStrings); overload;
    procedure WriteSection(const Section: string; const Str: String); overload;
    function ReadSections(Strings: TStrings): Boolean;

    procedure GetStrings(List: TStrings);
    procedure SetStrings(List: TStrings);

    procedure LoadFromFile(const FileName: string);
    procedure LoadFromStream(Stream: TStream);
    procedure SaveToFile(const FileName: string);
    procedure SaveToStream(Stream: TStream);
  end;

    {
    Loads all forms' settigns, specified by the AForms parameter.
    The best place put this function is before Application.Run in
    the project file or in the form's OnCreate() method
    Avoid calling this procedure mulpiple times in a for loop, because for
    each call the settings file is decompressed and read in memory. Instead,
    create an array of TForm, fill it with data and then call the procedure.
    }
  procedure LoadForms(AForms: array of TForm);
    {
    Saves all forms' settigns, specified by the AForms parameter.
    The best place put this function is after Application.Run in
    the project file or in the form's OnDestroy() method
    Avoid calling this procedure mulpiple times in a for loop, because for
    each call the settings file is decompressed and then compressed again. Instead,
    create an array of TForm, fill it with data and then call the procedure.
    }
  procedure SaveForms(AForms: array of TForm);
    // the same as LoadForms, but loads all screen forms
  procedure LoadAllForms;
    // the same as SaveForms, but saves all screen forms
  procedure SaveAllForms;

 
implementation

type
    {
    The original idea for this class was taken from the class AsInheritedReader
    in the Demos\RichEdit demo (which shows how to reload a form from a resource
    at run-time), but was developed further. Now the only common thing between
    the two classes is the ReadPrefix() procedure.
    }
  TFormSettingsReader = class(TReader)
  private
    procedure ErrorEvent(Reader: TReader; const Message: string; var Handled: Boolean);
  public
    constructor Create(Stream: TStream; BufSize: Integer);
    procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer); override;
  end;

  TFormSettingsWriter = class(TWriter)
  public
    procedure DefineBinaryProperty(const Name: string;
      ReadData, WriteData: TStreamProc;
      HasData: Boolean); override;
  end;


{ TFormSettingsReader }

constructor TFormSettingsReader.Create(Stream: TStream; BufSize: Integer);
begin
  inherited;
  OnError := ErrorEvent;
end;

procedure TFormSettingsReader.ErrorEvent(Reader: TReader; const Message: string;
  var Handled: Boolean);
begin
    {
    EClassNotFound is raised if a class name that has not been linked
    into the current application is encountered when reading a component from a stream,
    i.e. the user has deleted all components from a given class since the last save

    EReadError is raised if a property can't be read while creating a form,
    i.e. the user has deleted a component (and thus its associated published field) since the last save
    }
  if (ExceptObject is EClassNotFound) or (ExceptObject is EReadError) then
    Handled := True;
end;

procedure TFormSettingsReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
begin
  inherited ReadPrefix(Flags, AChildPos);
    // when Flags contains ffInherited, TReader.ReadComponent will find
    // the existing component instead of creating a new one
  Include(Flags, ffInherited);
end;


{ TFormSettingsWriter }

procedure TFormSettingsWriter.DefineBinaryProperty(const Name: string;
  ReadData, WriteData: TStreamProc; HasData: Boolean);
begin
  // Don't save binary properties.
  // If you want to enable saving of binary properties, call
  // inherited;
  // This will have a very negative impact on the size of the settigns file.
end;

procedure PatchIsDefaultPropertyValue;
type
  T3Bytes = array[0..2] of Byte;
  T4Bytes = array[0..3] of Byte;

  // there is no standart type with size 3 bytes that we can use to compare
  // 3 bytes, wo we write a custom function
function Compare3Bytes(const Val1, Val2: T3Bytes): Boolean;
begin
  Result := (Val1[0] = Val2[0])
        and (Val1[1] = Val2[1])
        and (Val1[2] = Val2[2]);
end;

const
  EndOfFunc: T4Bytes = (
    $5D,        // pop ebp
    $C2,$08,$00  // ret $0008
  );
    // The release and debug versions of Classes.pas compile to different machine code,
    // so we need 2 different patches depending on which version of Classes.pas
    // the program is linked in
  ReleaseBytes: T3Bytes = (
    $8B,$C3,    // mov eax, ebx
    $5B         // pop ebx
  );
  ReleasePatch: T3Bytes = (
    $33,$C0,    // xor eax, eax
    $5B         // pop ebx
  );
  DebugBytes: T3Bytes = (
    $8A,$45,$E3  // mov al, [ebp-$1d]
  );
  DebugPatch: T3Bytes = (
    $33,$C0,    // xor eax, eax
    $90          // nop
  );
var
  PBytes, PPatch: Pointer;
  WrittenBytes: SIZE_T; //Cardinal;
begin
  PBytes := @System.Classes.IsDefaultPropertyValue;

  while Integer(PBytes^) <> Integer(EndOfFunc) do
    Integer(PBytes) := Integer(PBytes) + 1;

  Integer(PBytes) := Integer(PBytes) - 5;

  PPatch := nil;
  if Compare3Bytes(T3Bytes(PBytes^), ReleaseBytes) then
      // the program is linked to the release version of Classes.pas
    PPatch := @ReleasePatch
  else if Compare3Bytes(T3Bytes(PBytes^), DebugBytes) then
      // the program is linked to the debug version of Classes.pas
    PPatch := @DebugPatch;

  if PPatch <> nil then
    WriteProcessMemory(GetCurrentProcess, PBytes, PPatch, SizeOf(T3Bytes), WrittenBytes);
end;

// A general procedure for compressing a stream
procedure CompressStream(ASource, ATarget: TStream);
begin
  with TCompressionStream.Create(clDefault, ATarget) do
    try
      CopyFrom(ASource, ASource.Size);
    finally
      Free;
    end;
end;

// A general procedure for decompressing a stream
procedure DecompressStream(ASource, ATarget: TStream);
var
  Buf: array[0..1023] of Byte;
  nRead: Integer;
begin
  with TDecompressionStream.Create(ASource) do
    try
        // ATarget.CopyFrom(DecompStream, 0) won't work, because CopyFrom requests the
        // size of the stream when the Count parameter is 0, and TDecompressionStream
        // doesn't support requesting the size of thå stream
      repeat
        nRead := Read(Buf, 1024);
        ATarget.Write(Buf, nRead);
      until nRead = 0;
    finally
      Free;
    end;
end;

function LoadSettingsFile(ASectionFile: TSectionFile): Boolean;
var
  msCompFile, msDecompFile: TMemoryStream;
  SettingsFileName: String;
begin
  Result := False;

  msCompFile := TMemoryStream.Create;
  msDecompFile := TMemoryStream.Create;
  try
    SettingsFileName := ChangeFileExt(Application.ExeName, '.ini');
    if FileExists(SettingsFileName) then
    begin
      msCompFile.LoadFromFile(SettingsFileName);
      msCompFile.Position := 0;
      DecompressStream(msCompFile, msDecompFile);
      msDecompFile.Position := 0;
      ASectionFile.LoadFromStream(msDecompFile);
      Result := True;
    end;
  except
    {$IFDEF DEBUG}
    on E: EZlibError do //ECompressionError do
      try
        msCompFile.Position := 0;    
        ASectionFile.LoadFromStream(msCompFile);
        Result := True;
      except
      end;
    {$ENDIF}
  end;
  msCompFile.Free;
  msDecompFile.Free;
end;

function SaveSettingsFile(ASectionFile: TSectionFile): Boolean;
var
  msCompFile, msDecompFile: TMemoryStream;
  SettingsFileName: String;
begin
  Result := False;

  msCompFile := TMemoryStream.Create;
  msDecompFile := TMemoryStream.Create;
  try
    SettingsFileName := ChangeFileExt(Application.ExeName, '.ini');
    ASectionFile.SaveToStream(msDecompFile);
    msDecompFile.Position := 0;
    {$IFNDEF DEBUG}
      CompressStream(msDecompFile, msCompFile);
    {$ELSE}
      msCompFile.CopyFrom(msDecompFile, 0);
    {$ENDIF}
    msCompFile.Position := 0;
    msCompFile.SaveToFile(SettingsFileName);
    Result := True;
  except
  end;
  msCompFile.Free;
  msDecompFile.Free;
end;


procedure LoadForms(AForms: array of TForm);
  procedure LoadFormFromStream(AForm: TForm; AStream: TStream);
  var
    OrigName: String;
  begin
    with TFormSettingsReader.Create(AStream, 4096) do
      try
        OrigName := AForm.Name;
        AForm := ReadRootComponent(AForm) as TForm;
          // By default, the streaming system changes the name of the form,
          // because a form with the same name already exists.
          // It is safe to restore the original name after the streaming process is done.
        AForm.Name := OrigName;
      finally
        Free;
      end;
  end;
var
  SectionFile: TSectionFile;
  msBinary, msText: TMemoryStream;
  Strings: TStringList;
  I: Integer;
begin
  SectionFile := TSectionFile.Create;
  msBinary := TMemoryStream.Create;
  msText := TMemoryStream.Create;
  Strings := TStringList.Create;
  try
    if not LoadSettingsFile(SectionFile) then Exit;

    for I := Low(AForms) to High(AForms) do
    begin
      SectionFile.ReadSection(AForms[I].Name, Strings);
      if Strings.Count > 0 then
      begin
        msText.Position := 0;
        Strings.SaveToStream(msText);
        msText.Position := 0;
        msBinary.Position := 0;
        ObjectTextToBinary(msText, msBinary);
        msBinary.Position := 0;
        LoadFormFromStream(AForms[I], msBinary);
      end;
    end;
  finally
    SectionFile.Free;
    msBinary.Free;
    msText.Free;
    Strings.Free;
  end;
end;

procedure SaveForms(AForms: array of TForm);
  procedure SaveFormToStream(AForm: TForm; AStream: TStream);
  begin
    with TFormSettingsWriter.Create(AStream, 4096) do
      try
        WriteDescendent(AForm, nil);
      finally
        Free;
      end;
  end;
var
  SectionFile: TSectionFile;
  msBinary, msText: TMemoryStream;
  Strings: TStringList;
  I: Integer;
begin
  SectionFile := TSectionFile.Create;
  msBinary := TMemoryStream.Create;
  msText := TMemoryStream.Create;
  Strings := TStringList.Create;
  try
    LoadSettingsFile(SectionFile);

    for I := Low(AForms) to High(AForms) do
    begin
      msBinary.Position := 0;
      SaveFormToStream(AForms[I], msBinary);
      msBinary.Position := 0;
      msText.Position := 0;
      ObjectBinaryToText(msBinary, msText);
      msText.Position := 0;
      Strings.LoadFromStream(msText);
      SectionFile.WriteSection(AForms[I].Name, Strings);
    end;

    SaveSettingsFile(SectionFile);
  finally
    SectionFile.Free;
    msBinary.Free;
    msText.Free;
    Strings.Free;
  end;
end;

procedure LoadAllForms;
var
  FormsArr: array of TForm;
  I: Integer;
begin
  SetLength(FormsArr, Screen.FormCount);
  for I := 0 to Screen.FormCount - 1 do
    FormsArr[I] := Screen.Forms[I];
  LoadForms(FormsArr);
end;

procedure SaveAllForms;
var
  FormsArr: array of TForm;
  I: Integer;
begin
  SetLength(FormsArr, Screen.FormCount);
  for I := 0 to Screen.FormCount - 1 do
    FormsArr[I] := Screen.Forms[I];
  SaveForms(FormsArr);
end;


{ TSectionFile }

constructor TSectionFile.Create;
begin
  inherited;
  FSections := TStringList.Create;
end;

destructor TSectionFile.Destroy;
begin
  if FSections <> nil then
    Clear;
  FSections.Free;

  inherited;
end;

function TSectionFile.AddSection(const Section: string): TStrings;
begin
  Result := TStringList.Create;
  try
    FSections.AddObject(Section, Result);
  except
    Result.Free;
    raise;
  end;
end;

procedure TSectionFile.Clear;
var
  I: Integer;
begin
  for I := 0 to FSections.Count - 1 do
    TObject(FSections.Objects[I]).Free;
  FSections.Clear;
end;

function TSectionFile.SectionExists(const Section: string): Boolean;
begin
    // if the section name exists, then the section is non-empty
  Result := FSections.IndexOf(Section) >= 0;
end;

procedure TSectionFile.ReadSection(const Section: string;
  Strings: TStrings);
var
  I: Integer;
begin
  Strings.Clear;
  I := FSections.IndexOf(Section);
  if I >= 0 then
    Strings.Assign(TStrings(FSections.Objects[I]));
end;

function TSectionFile.ReadSection(const Section: string): String;
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    ReadSection(Section, Strings);
    if Strings.Count > 0 then
      Result := Strings[0]
    else
      Result := '';
  finally
    Strings.Free;
  end;
end;

procedure TSectionFile.WriteSection(const Section: string;
  Strings: TStrings);
var
  I: Integer;
  Str: TStrings;
begin
  if Assigned(Strings) and (Strings.Count > 0) then
  begin
    I := FSections.IndexOf(Section);
    if I >= 0 then
      Str := TStrings(FSections.Objects[I])
    else
      Str := AddSection(Section);

    Str.Assign(Strings);
  end
  else
    EraseSection(Section);
end;

procedure TSectionFile.WriteSection(const Section: string; const Str: String);
var
  Strings: TStringList;
begin
  Strings := nil;
  try
    if Str <> '' then
    begin
      Strings := TStringList.Create;
      Strings.Append(Str);
    end;

    WriteSection(Section, Strings);
  finally
    if Assigned(Strings) then Strings.Free;
  end;
end;

function TSectionFile.ReadSections(Strings: TStrings): Boolean;
begin
  Strings.Assign(FSections);
  Result := Strings.Count > 0;
end;

procedure TSectionFile.EraseSection(const Section: string);
var
  I: Integer;
begin
  I := FSections.IndexOf(Section);

  if I >= 0 then
  begin
    TStrings(FSections.Objects[I]).Free;
    FSections.Delete(I);
  end;
end;

procedure TSectionFile.GetStrings(List: TStrings);
var
  I, J: Integer;
  Strings: TStrings;
begin
  List.BeginUpdate;
  try
    for I := 0 to FSections.Count - 1 do
    begin
      List.Add('[' + FSections[I] + ']');
      Strings := TStrings(FSections.Objects[I]);
      for J := 0 to Strings.Count - 1 do
        List.Add(Strings[J]);
    end;
  finally
    List.EndUpdate;
  end;
end;

procedure TSectionFile.SetStrings(List: TStrings);
var
  I: Integer;
  S: string;
  Strings: TStrings;
begin
  Clear;
  Strings := nil;
  for I := 0 to List.Count - 1 do
  begin
    S := List[I];

                     // the line is not a cooment
    if (S <> '') and (S[1] <> ';') then
      if (S[1] = '[') and (S[Length(S)] = ']') then // a section
      begin
        Delete(S, 1, 1);
        SetLength(S, Length(S)-1);
        Strings := AddSection(Trim(S));
      end
      else
        if Strings <> nil then
          Strings.Add(S);
  end;
end;

procedure TSectionFile.LoadFromFile(const FileName: string);
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);
    SetStrings(Strings);
  finally
    Strings.Free;
  end;
end;

procedure TSectionFile.LoadFromStream(Stream: TStream);
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    Strings.LoadFromStream(Stream);
    SetStrings(Strings);
  finally
    Strings.Free;
  end;
end;

procedure TSectionFile.SaveToFile(const FileName: string);
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    GetStrings(Strings);
    Strings.SaveToFile(FileName);
  finally
    Strings.Free;
  end;
end;

procedure TSectionFile.SaveToStream(Stream: TStream);
var
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  try
    GetStrings(Strings);
    Strings.SaveToStream(Stream);
  finally
    Strings.Free;
  end;
end;

initialization
  PatchIsDefaultPropertyValue;

end.

Jasocul 29. Jul 2015 08:31

AW: Formular Position speichern
 
Nimm doch einfach die Jedi-Komponente TJvFormStorage (Zu finden in der Gruppe JV Persistence).
Oder musst du das zwingend in der Datenbank speichern?

Luckie 29. Jul 2015 10:13

AW: Formular Position speichern
 
Also, ich weiß ja nicht, was ihr hier für Klimmzüge veranstaltet. 500 Zeilen Code? :shock:

Delphi-Quellcode:
unit Unit6;

interface

uses
  Windows, SysUtils, IniFiles;

type
  TFoobar = class(TObject)
  private
    FFormName: AnsiString;
    FLeft: Integer;
    FTop: Integer;
    FWidth: Integer;
    FHeight: Integer;
  public
    constructor Create(FormName: AnsiString; Left, Top, Width, Height: Integer);
    procedure SaveSizePos;
end;

implementation

{ TFoobar }

constructor TFoobar.Create(FormName: AnsiString; Left, Top, Width, Height: Integer);
begin
  inherited Create;
  FFormName := FormName;
  Fleft := Left;
  FTop := Top;
  FWidth := Width;
  FHeight := Height;
end;

procedure TFoobar.SaveSizePos;
var
  Ini: TIniFile;
begin
  Ini := TIniFile.Create('Z:\test.ini');
  try
    Ini.WriteInteger(FFormName, 'left', Fleft);
    Ini.WriteInteger(FFormName, 'top', FTop);
    Ini.WriteInteger(FFormName, 'width', FWidth);
    Ini.WriteInteger(FFormName, 'height', FHeight);
  finally
    Ini.Free;
  end;
end;

end.
Die Routine zum laden habe ich mir mal gespart. In OnClose der Formulare dann:

Delphi-Quellcode:
procedure TForm5.FormClose(Sender: TObject; var Action: TCloseAction);
var
  SizePos: TFoobar;
begin
  SizePos := TFoobar.Create(Self.Name, Self.Left, Self.Top, Self.Width, Self.Height);
  try
    SizePos.SaveSizePos;
  finally
    SizePos.Free;
  end;
end;
Sieht dann so aus:
Code:
[Form5]
left=98
top=327
width=349
height=280
[Form1]
left=879
top=206
width=651
height=338

bcvs 29. Jul 2015 10:26

AW: Formular Position speichern
 
So wie ich den OP verstanden habe, geht es nicht darum, dass ein Form seine eigene Position speichern und lesen kann, sondern es liegt in einer DB eine Liste von Formnamen mit zugehörigen Positionen vor und nur diese Forms sollen erzeugt und angezeigt werden.

Man braucht also eine irgendwie geartete Zuordnung FormName -> FormKlasse um eine Instanz der entsprechenden Klasse zu erzeugen. Vorschläge dazu wurden in #8 und #10 gemacht.

Wenn die Form dann erst einmal erzeugt ist, kann sie sich die Position ja wieder selbst aus der DB oder sonst woher auslesen.

bernau 29. Jul 2015 10:36

AW: Formular Position speichern
 
@Luckie:

Wie ich es sehe, geht es Ihm nicht primär darum, die Position zu lesen und zu speichern. Vielmehr speichert er beim Verlassen des Programms die Positionen UND den Namen der Fenster. Anhand des Namen soll nun beim Starten die entsprechenden Forms instanziert werden, um alle Fenster, die er vor beenden des Programms offen hatte, wieder zu öffnen.

EDIT: da war bcvs wohl schneller.

Sir Rufo 29. Jul 2015 10:38

AW: Formular Position speichern
 
Die Anzahl der Zeilen ist doch nicht entscheidend (auch wenn einige hier im Forum das meinen), solange es DRY ist und die geforderte Aufgabe löst.

Wird die Aufgabe damit nicht gelöst, dann ist auch eine Zeile Code schon zu viel.

Luckie 29. Jul 2015 10:41

AW: Formular Position speichern
 
Ok, es sollen also automatisch die Formulare geöffnet werden, die beim letzten mal geöffnet waren?

Beim Start der Anwendung:
wenn in Ini Section FormA existiert, dann FormA.Show
wenn in Ini Section FormB existiert, dann FormB.Show

@Sir Rufo: Das mag sein. Aber ich küsse lieber. ;) -> KISS Prinzip. Und damit ich mich nicht wiederhole, habe ich den Code in eine Klasse ausgelagert.

bernau 29. Jul 2015 10:43

AW: Formular Position speichern
 
@Sugar: Schaum mal hier. Beitrag #6

http://www.delphipraxis.net/46874-an...ten-forms.html

Perlsau 29. Jul 2015 12:49

AW: Formular Position speichern
 
Bei mir hat sich folgende Vorgehensweise bestens bewährt:

In meinen Datenbanken gibt es gewöhnlich eine Tabelle BENUTZER, die für Single-User-Anwendungen nur einen Datensatz enthält, bei Multi-User-Anwendungen für jeden registrierten Benutzer einen weiteren Datensatz. Dort steht dann z.B. in den Spalten MAIN_LEFT, MAIN_TOP, MAIN_WIDTH, MAIN_HEIGHT, MAIN_MAX, wo das Fenster mit welcher Größe positioniert werden und ob es maximiert angezeigt werden soll. Jedes Formular, dessen Fensterparameter gespeichert werden sollen, erhält zwei private Methoden: Einstellungen_Lesen und Einstellungen_Speichern, die beim OnShow bzw. beim OnClose aufgerufen werden. Darin steht dann folgender Code:

Delphi-Quellcode:
Procedure TFormMain.Einstellungen_Lesen;
begin
  Self.Left          := DatMod.Qset_Benutzer.FieldByName('MAIN_LEFT').AsInteger;
  Self.Top           := DatMod.Qset_Benutzer.FieldByName('MAIN_TOP').AsInteger;
  Self.Width         := DatMod.Qset_Benutzer.FieldByName('MAIN_WIDTH').AsInteger;
  Self.Height        := DatMod.Qset_Benutzer.FieldByName('MAIN_HEIGHT').AsInteger;
  IF DatMod.Qset_Benutzer.FieldByName('MAIN_MAX').AsBoolean THEN
     Self.WindowState := wsMaximized                       ELSE
     Self.WindowState := wsNormal;
end;

Procedure TFormMain.Einstellungen_Speichern;
Var
  Maxi : Boolean;

begin
  Maxi := Self.WindowState = wsMaximized;
  Self.WindowState       := wsNormal;

  DatMod.Qset_Benutzer.Edit;
  DatMod.Qset_Benutzer.FieldByName('MAIN_LEFT').AsInteger   := Self.Left;
  DatMod.Qset_Benutzer.FieldByName('MAIN_TOP').AsInteger    := Self.Top;
  DatMod.Qset_Benutzer.FieldByName('MAIN_WIDTH').AsInteger  := Self.Width;
  DatMod.Qset_Benutzer.FieldByName('MAIN_HEIGHT').AsInteger := Self.Height;
  DatMod.Qset_Benutzer.FieldByName('MAIN_MAX').AsBoolean    := Maxi;
  DatMod.Qset_Benutzer.Post;
end;
Eine Kennzeichnung der Spalten für die verschiedenen Formulare benötigst du im Grunde nur deswwegen, damit du dich selbst nicht unnötig in Verwirrung stürzt. Dafür kannst du ja den Namen des Formulars verwenden, gefolgt von einem Unterstrich und den jeweiligen Bezeichnungen für Left, Top usw. Jedes Formular richtet sich dann beim Erscheinen vollkommen selbständig aus und speichert seine Parameter beim Schließen ebenso automatisch, so daß du dich nicht weiter darum kümmern mußt. Diese Methoden mußt du nur einmal schreiben und kannst sie dann einfach in das neue Formular kopieren, wobei du natürlich die Spaltenbezeichner anpassen mußt. Wenn du das eine Weile so gehandhabt hast, machst du das praktisch im Schlaf und hast das sozusagen in Nullkommanix erledigt.

Eine weitere Tabelle verwende ich z.B. für Spaltenbreiten von Grids, die ebenfalls für jeden Benutzer gesondert abgespeichert werden. Sonstige Einstellungen wie Farben usw. werden ebenfalls in der Benutzertabelle gespeichert, die bei umfangreichen Anwendungen auch mal um die 100 Spalten beherbergt.

Diese Vorgehensweise hat sich im Laufe der Jahre so weit entwickelt, daß ich damit vollkommen zufrieden bin und mich weder um Registry-Einträge noch um User-Verzeichnisse kümmern muß.

Mavarik 29. Jul 2015 13:04

AW: Formular Position speichern
 
Es Fehlt dann nur noch die Überprüfung ob der Monitor noch existiert...

Besonders Interessant, wenn der User per Datensicherung die Daten auf einen anderen PC/Laptop übertragen will...

Sollten die Daten 1. Computernamen bezogen gespeichert werden und bei laden getestet werden ob es die Top/Left Positions auf dem aktuellen Computer gibt...

Mavarik

Perlsau 29. Jul 2015 13:10

AW: Formular Position speichern
 
Zitat:

Zitat von Mavarik (Beitrag 1310139)
Sollten die Daten 1. Computernamen bezogen gespeichert werden und bei laden getestet werden ob es die Top/Left Positions auf dem aktuellen Computer gibt...

Eine vortreffliche Ergänzung, die mir bislang nicht in den Sinn gekommen ist. Dafür danke ich dir herzlich :thumb:

In der Tat hatte ich gelegentlich Rückfragen von Kunden zu bearbeiten, die sich darüber beschwerten, daß ein Formular, das sie zur Anzeige gewählt hatten, nicht sichtbar sei. Ich habe dann natürlich jedesmal erklärt, daß das Formular nur deshalb nicht zu sehen sei, weil es sich außerhalb des Bildschirms befände und anschließend erläutert, wie man dieses Formular via Tastatur wieder in den sichtbaren Bereich herüberziehen kann. Diese Problematik hat sich mit deiner Hilfe nun endgültig erledigt :thumb:

Mavarik 29. Jul 2015 13:16

AW: Formular Position speichern
 
Zitat:

Zitat von Perlsau (Beitrag 1310143)
Dafür danke ich dir herzlich :thumb:

Danke... Kurze Ergänzung:

Ein Formular kann schon über den Bildschirmrand hinaus gehen... Man sollte testen ob die Titelleiste
per Maus greifbar ist, damit der Kunde nicht die F10 usw... Tastaturbedienung zum Fensterverschieben lernen muss...

Bedeutet bei "links raus" die Weite der minimize,maximize und close Schaltflächen abzuziehen...

Es hat sich auch bewährt im Menue neben der Window-Liste einen Reset-Positionsaufruf ins Mainmenue zu übernehmen...

Perlsau 29. Jul 2015 13:30

AW: Formular Position speichern
 
Im Grunde sollte es genügen zu überprüfen, ob der Left-Wert größer ist als ScreenMax. Ist noch was vom Fenster zu sehen, kann der Anwender sich in der Regel selbst behelfen. Oder man prüft gleich in Einstellungen_Lesen, ob der Left-Wert plus Fensterbreite größer ist als ScreenMax und korrigiert dann sofort. Das werde ich demnächst mal genauer ausbaldowern müssen. Das Formular kann ja auch in Minusbereich des Screens (unsichtbar) "erscheinen", je nachdem, wie die Anordnung der verschiedenen Bildschirme zuvor aussah. Bei Releases hab ich immer darauf geachtet, daß die mitgelieferte Datenbank keine Formulare auf möglicherweise unsichtbaren Screens öffnet, indem ich die Positionen entweder von Hand in der DB geändert habe oder beim letzten Test vor dem Versenden die entsprechenden Formulare einfach richtig positionierte. Das ist natürlich umständlich, was sich mit deinem Vorschlag jetzt erledigt hat.

Dejan Vu 29. Jul 2015 14:32

AW: Formular Position speichern
 
Hmmm..

Delphi-Quellcode:
Function TMyFormDataModule.LoadFormPos (Form : TForm);
Begin
  // Damit die Position nur 1x gesetzt wird.
  If Form.Tag=1 then Exit;
  Form.Tag := 1;

  FormPosition.Active := False;
  // FormPosition.SQL := 'select * from FormPositionen '
  //                    +'where UserName = :UserName and FormName = :FormName';

  FormPosition.Parameters.ParamByName['UserName'] := Self.TheUserName;
  FormPosition.Parameters.ParamByName['FormName'] := Form.Name;
  FormPosition.Open;

  If FormPosition.IsEmpty then Exit;

  Form.Left := FormPosition['Left'];
  Form.Top := FormPosition['Top'];
  Form.Width := FormPosition['Width'];
  Form.Height := FormPosition['Height'];
  DemandFormOnScreen(Form); // Stellt sicher, das das Formular sichtbar ist.
End;
Abspeichern geht dann analog.

In jedem Formular...

Delphi-Quellcode:
Procedure TMyForm.FormActivate(Sender : TObject);
Begin
  MyFormDataModule.LoadFormPos (Self);
End;
Getippt und nicht getestet, sollte aber so oder ähnlich laufen.

bernau 29. Jul 2015 15:00

AW: Formular Position speichern
 
Zitat:

Zitat von Dejan Vu (Beitrag 1310172)
Hmmm..

Delphi-Quellcode:
Function TMyFormDataModule.LoadFormPos (Form : TForm);
Begin
  // Damit die Position nur 1x gesetzt wird.
  If Form.Tag=1 then Exit;
  Form.Tag := 1;

  FormPosition.Active := False;
  // FormPosition.SQL := 'select * from FormPositionen '
  //                    +'where UserName = :UserName and FormName = :FormName';

  FormPosition.Parameters.ParamByName['UserName'] := Self.TheUserName;
  FormPosition.Parameters.ParamByName['FormName'] := Form.Name;
  FormPosition.Open;

  If FormPosition.IsEmpty then Exit;

  Form.Left := FormPosition['Left'];
  Form.Top := FormPosition['Top'];
  Form.Width := FormPosition['Width'];
  Form.Height := FormPosition['Height'];
  DemandFormOnScreen(Form); // Stellt sicher, das das Formular sichtbar ist.
End;
Abspeichern geht dann analog.

Das sind aber geringfügig mehr als die max. 7-10 Zeilen in einer Procedure wie du im deinem Post aus dem anderen Thread behauptest.

SCNR :lol:

Sir Rufo 29. Jul 2015 15:45

AW: Formular Position speichern
 
Zitat:

Zitat von bernau (Beitrag 1310184)
Das sind aber geringfügig mehr als die max. 7-10 Zeilen in einer Procedure wie du im deinem Post aus dem anderen Thread behauptest.

SCNR :lol:

Ich sehe hier aber auch in keinster Weise irgendwo Clean Code, sondern wie angekündigt einfach nur mal so schnell getippt für einen ungefähren Anhaltspunkt.

Clean Code wäre eher etwas in dieser Richtung:
Delphi-Quellcode:
unit Services;

interface

uses
  System.Classes;

type
  IFormSettingsService = interface
    [ '{37C1665C-8C12-4430-9820-83D82DB76366}' ]
    function GetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
    function SetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
  end;

implementation

end.
Delphi-Quellcode:
unit Services.Impl;

interface

uses
  System.Classes,
  Services;

type
  TIniFormSettingsService = class( TInterfacedObject, IFormSettingsService )
  private
    FFileName: string;
    FSection: string;
  public
    constructor Create( const AFileName, ASection: string );
    function GetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
    function SetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
  end;

implementation

uses
  System.IniFiles;

{ TIniFormSettingsService }

constructor TIniFormSettingsService.Create( const AFileName, ASection: string );
begin
  inherited Create;
  FFileName := AFileName;
  FSection := ASection;
end;

function TIniFormSettingsService.GetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
var
  LIniFile: TIniFile;
begin
  LIniFile := TIniFile.Create( FFileName );
  try
    if LIniFile.SectionExists( FSection ) and LIniFile.ValueExists( FSection, BlockName ) then
    begin
      LIniFile.ReadBinaryStream( FSection, BlockName, ABlockData );
      Result := True;
    end
    else
      Result := False;
  finally
    LIniFile.Free;
  end;
end;

function TIniFormSettingsService.SetBlock( const BlockName: string; const ABlockData: TStream ): Boolean;
var
  LIniFile: TIniFile;
begin
  LIniFile := TIniFile.Create( FFileName );
  try
    ABlockData.Seek( 0, soFromBeginning );
    LIniFile.WriteBinaryStream( FSection, BlockName, ABlockData );
    Result := True;
  finally
    LIniFile.Free;
  end;
end;

end.
Delphi-Quellcode:
unit Configuration;

interface

implementation

uses
  FMX.Platform,
  Services,
  Services.Impl;

initialization

TPlatformServices.Current.AddPlatformService( IFormSettingsService, TIniFormSettingsService.Create( '.\foo.ini', 'forms' ) ); // ja, ja, das ist ein Unding mit dem relativen Pfad :o)

end.
Delphi-Quellcode:
unit Form.BaseForm;

interface

uses
  Services,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TBaseForm = class( TForm )
  private
    FLoaded: Boolean;
    procedure InternalLoadSettings( Service: IFormSettingsService );
    procedure InternalStoreSettings( Service: IFormSettingsService );
  protected
    function GetBlockName: string; virtual;
    procedure DoClose( var Action: TCloseAction ); override;
    procedure DoShow; override;
    procedure DoLoadSettings( Settings: TBinaryReader ); virtual;
    procedure DoStoreSettings( Settings: TBinaryWriter ); virtual;
  public
    procedure LoadSettings;
    procedure StoreSettings;
  end;

var
  BaseForm: TBaseForm;

implementation

{$R *.dfm}

uses
  FMX.Platform;

{ TBaseForm }

procedure TBaseForm.DoClose( var Action: TCloseAction );
var
  LService: IFormSettingsService;
begin
  inherited;
end;

procedure TBaseForm.DoLoadSettings( Settings: TBinaryReader );
begin
end;

procedure TBaseForm.DoShow;
begin
  if not FLoaded then
    LoadSettings;
  FLoaded := True;
  inherited;
end;

procedure TBaseForm.DoStoreSettings( Settings: TBinaryWriter );
begin

end;

function TBaseForm.GetBlockName: string;
begin
  Result := Self.ClassName;
end;

procedure TBaseForm.InternalLoadSettings( Service: IFormSettingsService );
var
  LBlockData: TMemoryStream;
  LReader: TBinaryReader;
begin
  LBlockData := TMemoryStream.Create;
  try
    if Service.GetBlock( GetBlockName, LBlockData ) then
    begin
      LBlockData.Seek( 0, soFromBeginning );
      LReader := TBinaryReader.Create( LBlockData );
      try
        DoLoadSettings( LReader );
      finally
        LReader.Free;
      end;
    end;
  finally
    LBlockData.Free;
  end;
end;

procedure TBaseForm.InternalStoreSettings( Service: IFormSettingsService );
var
  LBlockData: TMemoryStream;
  LWriter: TBinaryWriter;
begin
  LBlockData := TMemoryStream.Create;
  try
    LWriter := TBinaryWriter.Create( LBlockData );
    try
      DoStoreSettings( LWriter );
    finally
      LWriter.Free;
    end;
    LBlockData.Seek( 0, soFromBeginning );
    Service.SetBlock( GetBlockName, LBlockData );
  finally
    LBlockData.Free;
  end;
end;

procedure TBaseForm.LoadSettings;
var
  LService: IFormSettingsService;
begin
  if TPlatformServices.Current.SupportsPlatformService( IFormSettingsService, LService ) then
    InternalLoadSettings( LService );
end;

procedure TBaseForm.StoreSettings;
var
  LService: IFormSettingsService;
begin
  if TPlatformServices.Current.SupportsPlatformService( IFormSettingsService, LService ) then
    InternalStoreSettings( LService );
end;

end.
Delphi-Quellcode:
unit Form.MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Form.BaseForm, Vcl.StdCtrls;

type
  TMainForm = class( TBaseForm )
    Edit1: TEdit;
  private
  protected
    procedure DoLoadSettings( Settings: TBinaryReader ); override;
    procedure DoStoreSettings( Settings: TBinaryWriter ); override;
  public

  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}
{ TMainForm }

procedure TMainForm.DoLoadSettings( Settings: TBinaryReader );
begin
  inherited;
  Top := Settings.ReadInteger;
  Left := Settings.ReadInteger;
  Height := Settings.ReadInteger;
  Width := Settings.ReadInteger;
  Edit1.Text := Settings.ReadString;
end;

procedure TMainForm.DoStoreSettings( Settings: TBinaryWriter );
begin
  inherited;
  Settings.Write( Top );
  Settings.Write( Left );
  Settings.Write( Height );
  Settings.Write( Width );
  Settings.Write( Edit1.Text );
end;

end.
Aber so schön Clean das auch ist, es löst nicht das eigentliche Problem!

Ein Anfang ist es aber schon mal ;)

bernau 29. Jul 2015 16:02

AW: Formular Position speichern
 
Rofl

uligerhardt 29. Jul 2015 16:05

AW: Formular Position speichern
 
Zitat:

Zitat von Mavarik (Beitrag 1310139)
Es Fehlt dann nur noch die Überprüfung ob der Monitor noch existiert...

Besonders Interessant, wenn der User per Datensicherung die Daten auf einen anderen PC/Laptop übertragen will...

Sollten die Daten 1. Computernamen bezogen gespeichert werden und bei laden getestet werden ob es die Top/Left Positions auf dem aktuellen Computer gibt...

Dafür gibt's unter Windows MSDN-Library durchsuchenGetWindowPlacement/MSDN-Library durchsuchenSetWindowPlacement.

Mikkey 29. Jul 2015 16:23

AW: Formular Position speichern
 
Zitat:

Zitat von Sir Rufo (Beitrag 1310201)
Aber so schön Clean das auch ist, es löst nicht das eigentliche Problem!

Auch darin lassen sich bis zu 15 Codezeilen zählen.

SCNRT

Mavarik 29. Jul 2015 16:38

AW: Formular Position speichern
 
Zitat:

Zitat von uligerhardt (Beitrag 1310203)
Zitat:

Zitat von Mavarik (Beitrag 1310139)
Es Fehlt dann nur noch die Überprüfung ob der Monitor noch existiert...

Besonders Interessant, wenn der User per Datensicherung die Daten auf einen anderen PC/Laptop übertragen will...

Sollten die Daten 1. Computernamen bezogen gespeichert werden und bei laden getestet werden ob es die Top/Left Positions auf dem aktuellen Computer gibt...

Dafür gibt's unter Windows MSDN-Library durchsuchenGetWindowPlacement/MSDN-Library durchsuchenSetWindowPlacement.

Und was soll das bringen?

Sir Rufo 29. Jul 2015 16:40

AW: Formular Position speichern
 
Zitat:

Zitat von Mikkey (Beitrag 1310204)
Zitat:

Zitat von Sir Rufo (Beitrag 1310201)
Aber so schön Clean das auch ist, es löst nicht das eigentliche Problem!

Auch darin lassen sich bis zu 15 Codezeilen zählen.

SCNRT

Logisch, aber eine Variante in C# - die exakt das Gleiche macht - hätte hier keinem etwas gebracht, wäre dafür aber in jeder Methode unter 10 Zeilen geblieben.

Die sprachbedingten Boilerplates werden eigentlich nicht mitgezählt.
Delphi-Quellcode:
{1} LFoo := TFoo.Create();
{-} try
{2}   LFoo.DoBar();
{-} finally
{-}  LFoo.Free;
{-} end;
denn mit ARC sieht der Code mit gleicher Funktionalität so aus
Delphi-Quellcode:
{1} LFoo := TFoo.Create();
{2} LFoo.DoBar();

Luckie 29. Jul 2015 20:07

AW: Formular Position speichern
 
Ihr kommt vom Thema ab.

Mikkey 29. Jul 2015 20:32

AW: Formular Position speichern
 
Ein Vorschlag für die Ausgangsfrage:
Du hast in der Datenbank stehen, dass Formular "Form4711" an Position (x,y) Größe (w,h) steht.

Jede Form-Klasse kennt nun ihren Namen. Beim Einlesen der Informationen aus der Datenbank wird nun einer dafür vorgesehenen Klassenmethode jeder(!) dieser Klassen übergeben. Die Klasse, die eine Übereinstimmung ihres Namens mit dem übergebenen Namen feststellt, öffnet ihr Form entsprechend den weiteren Parametern.

Diese Methode kann auf verschiedene Arten angelegt werden.

Perlsau 29. Jul 2015 22:22

AW: Formular Position speichern
 
Zitat:

Zitat von Luckie (Beitrag 1310227)
Ihr kommt vom Thema ab.

Offenbar lösen sinnvolle Lösungsvorschläge häufig einen Streit darum aus, wer "den Längeren" hat :twisted:

Sir Rufo 29. Jul 2015 22:33

AW: Formular Position speichern
 
Es geht darum nicht einfach und lapidar die Position der Formulare zu speichern (dafür haben wir hier einige Lösungen gesehen), sondern darum, dass es unterschiedliche Szenarien gibt.

Im Szenario S1 sollen 3 Formulare angezeigt werden (F1, F2, F3). Jedes dieser Formulare hat in diesem Szenario einen bestimmten Platz.
Im Szenario S2 sollen 4 Formulare angezeigt werden (F3, F4, F5, F6). In diesem Szenario hat z.B. das Formular F2 aber eine ganz andere Position.

Die eigentliche Frage bezieht sich jetzt darauf, wie man für die beiden Szenarien S1 und S2 die Formulare erzeugt und platziert. Weiterhin kommt hinzu, dass die Szenarien nicht fest sind, sondern die Anzahl der Formulare kann wechseln.

Darum steht unter meinem Code auch der Hinweis, dass dieser nicht das eigentliche Problem löst!


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz