Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Fensterposition persistent machen (https://www.delphipraxis.net/195841-fensterposition-persistent-machen.html)

Codehunter 30. Mär 2018 18:12

Fensterposition persistent machen
 
Hallo!

Ich habe grad sowas wie ein Anfängerproblem bzw. steh wohl auf dem Schlauch ^^

Ich möchte die Größe, Position und WindowState eines Forms in einer Ini speichern und beim Programmstart wiederherstellen. Das Speichern klappt wunderbar, nur beim Wiederherstellen gibts Probleme. Zwar kann ich die gespeicherten Werte korrekt auslesen. Das mache ich im OnCreate des MainForm. BoundsRect und WindowState lassen sich hier problemlos setzen, aber nicht Left und Top. Die werden ignoriert und im Anschluss durch die Werte überschrieben, die in der DFM hinterlegt sind bzw. falls Position = poScreenCenter eingestellt ist, dann wird das Fenster zentriert.

Eigentlich müsste ja schon das Zuweisen vom BoundsRect die Position verändern, aber auch da wird Left und Top ignoriert und wieder überschrieben. Selbst wenn ich das Zuweisen von Left und Top später mache, z.B. in einem OnShow/WM_AFTERSHOW-Konstrukt, ändert sich an dem Problem nichts. Wie lässt sich das lösen?

Grüße
Cody

hoika 30. Mär 2018 18:24

AW: Fensterposition persistent machen
 
Hallo,
Formactivate?

Der schöne Günther 30. Mär 2018 18:24

AW: Fensterposition persistent machen
 
Ohne es ausprobiert zu haben: Versuche doch als letztes noch einmal
Delphi-Quellcode:
OnActivate
statt
Delphi-Quellcode:
OnShow
.

Codehunter 30. Mär 2018 18:37

AW: Fensterposition persistent machen
 
Doppelt hält in dem Fall auch nicht besser. Wird dort genauso wieder überschrieben. Wenn ich ein ShowMessage an der Stelle einbaue, so rein zu Testzwecken WANN das Ereignis kommt, dann erscheint das Meldungsfenster immer noch bevor das Hauptfenster erscheint. Daher vermute ich, dass es auf die Zuweisung von Left und Top immer noch nicht spät genug erfolgt.

Delphi.Narium 30. Mär 2018 18:45

AW: Fensterposition persistent machen
 
Das funtioniert nur, wenn Position auf poDesigned steht.

Dann werden die von Dir gewünschten Werte genommen, andernfalls, die jeweils entsprechend zu berechnenden Werte.

ScreenCenter widerspricht (in der Regel) nun mal Top 47 und Left 11.

Was sollte bei der Einstellung poScreenCenter denn dann genommen werden: Die Bildschirmmitte oder 47 und 11?

himitsu 30. Mär 2018 18:54

AW: Fensterposition persistent machen
 
Zitat:

Die werden ignoriert und im Anschluss durch die Werte überschrieben, die in der DFM hinterlegt sind bzw. falls Position = poScreenCenter eingestellt ist
Nein, wenn du etwas nach dem Auslesen der DFM überschreibst , dan ist es überschrieben,

ABER ja nach Position wird das zu unterschiedlichen Zeitpunkten ausgewertet ... Top/Left hier und Width/Height dort/dann.
Probier da mal bissl rum (hab's jetzt nicht im Kopf), aber einige der Position werden "komplett" vor dem OnShow behandelt und schon kannst du alles im OnShow überschreiben.

Codehunter 30. Mär 2018 19:09

AW: Fensterposition persistent machen
 
Zitat:

Zitat von himitsu (Beitrag 1397687)
ABER ja nach Position wird das zu unterschiedlichen Zeitpunkten ausgewertet ... Top/Left hier und Width/Height dort/dann.
Probier da mal bissl rum (hab's jetzt nicht im Kopf), aber einige der Position werden "komplett" vor dem OnShow behandelt und schon kannst du alles im OnShow überschreiben.

Ich habe schon jede erdenkliche Kombination von Position und OnCreate/OnShow/WM_AFTERSHOW/OnActivate durch. Das Resultat ist immer das selbe. Die persistente Position wird korrekt aus der Ini gelesen und Left/Top zugewiesen, doch anschließend "irgendwo" wieder übersteuert.

Delphi.Narium 30. Mär 2018 19:25

AW: Fensterposition persistent machen
 
In meinen Programmen speichere ich schon seit Jahren die Position, Breite und Höhe (und vieles andere) in der Registry. Das geht analog auch in 'ner INI.

Es funktioniert nur, wenn Position auf poDesigned steht.

Alles andere ist dauerhaft, über die Jahre und Delphiversionen, gescheitert.

Wenn Du die Position selbst bestimmen willst, ist es doch nicht erforderlich die Position automatisch bestimmen zu lassen und dann nach irgend 'nem Weg zu suchen, der die eigene Bestimmung der Position doch noch ermöglicht.

Und wenn im Objektinspektor schon unbeding Position auf poScreenCenter stehen muss, dann versuch' doch mal, ob (sinngemäß) sowas funktioniert:
Delphi-Quellcode:
  // Irgendwo 'ner Prozedur vom Formular.
  Self.Position := poDesigned;
  Self.Left := ini.ReadInteger('Left',Self.Name,Self.Left);
  Self.Top := ini.ReadInteger('Top',Self.Name,Self.Top);
  ...
  Self.Position := poScreenCenter;

Sailor 30. Mär 2018 19:28

AW: Fensterposition persistent machen
 
Setze die MainForm.Position auf einen der Defaultwerte (poDefault,..). Im erstmaligen Aufruf von FormShow werden Top, Left, Width und Height auf die Werte aus der Ini-Datei gesetzt und dann eventuell noch korrigiert, also Anpassen an Bildschirmgröße etc. Anschließend setze ich WindowState auf den gespeicherten Wert. Klappt einwandfrei mit Delphi2010 auf allen Windows-Systemen.

ghubi01 30. Mär 2018 20:23

AW: Fensterposition persistent machen
 
Hallo,

ich würde die Daten im initialization Abschnitt aus der ini-Datei oder Registry einlesen und in globalen Variablen speichern.
Danach im FormCreate-Ereignis setzen.

Ich hab folgendes ausprobiert und es funktioniert:
Delphi-Quellcode:
var
  Form1: TForm1;
  x1,y1: integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Top:=x1;
  Left:=y1;
end;

initialization
// Das Einlesen aus der INI oder Registry habe ich mir hier gespart
// Die eingelesen Werte werden hier den globalen Variablen übergeben
  x1:=30;
  y1:=100;

end.

EWeiss 30. Mär 2018 20:31

AW: Fensterposition persistent machen
 
Zitat:

ich würde die Daten im initialization Abschnitt aus der ini-Datei oder Registry einlesen und in globalen Variablen speichern.
Ich glaube einige Leute schreiben nur um des schreiben willens und lesen tun sie auch nicht.

Er hat doch geschrieben das er die werte speichert darum geht es doch gar nicht.
Sondern darum das die eingelesenen werte beim setzen in OnShow ignoriert werden und Delphi tut was es will.

gruss

himitsu 30. Mär 2018 20:33

AW: Fensterposition persistent machen
 
Neee, erstmal ist es egal wann die Daten gelesen werden, denn es hängt beim Zuweisen und nicht beim Auslesen.
Und nein, es funktioniert nicht immer.

Je nach TForm.Position werden Monitor, Größe und Top/Left zu unterschiedlichen Zeitpunkten von der VCL gesetzt.
Wenn man also seine Zuweisung macht und anschließend die VCL das wieder überschreibt, dann hat man ein Problemchen.

Einiges wird z.B. schon im Constructor ausgeführt, Anderes im OnShow (aber noch bevor das eigene Event behandelt wird) und wieder Anderes erst danach.
Und wann OnCreate ausgeführt wird, dass kann sich auch noch entscheidend auswirken. (Delphi-Referenz durchsuchenOldCreateOrder)

EWeiss 30. Mär 2018 20:38

AW: Fensterposition persistent machen
 
werfe die VCL weg und mache es von Hand.

Delphi-Quellcode:
    SetRect(rc, 0, 0, XMIN_SIZE, YMIN_SIZE);
    AdjustWindowRectEx(rc, dwStyle, False, dwExStyle);

    X := MAX((GetSystemMetrics(SM_CXSCREEN) - rc.Right - rc.Left) div 2, 0);
    Y := MAX((GetSystemMetrics(SM_CYSCREEN) - rc.Bottom - rc.top) div 2, 0);

    MainHandle := CreateWindowEx(dwExStyle, myClass, myTitle, dwStyle, X, Y, rc.Right - rc.Left,
      rc.Bottom - rc.top, 0, 0, wc.hInstance, nil);
gruss

ghubi01 30. Mär 2018 20:53

AW: Fensterposition persistent machen
 
Zitat:

Zitat von EWeiss (Beitrag 1397695)
Ich glaube einige Leute schreiben nur um des schreiben willens und lesen tun sie auch nicht.

Er hat doch geschrieben das er die werte speichert darum geht es doch gar nicht.
Sondern darum das die eingelesenen werte beim setzen in OnShow ignoriert werden und Delphi tut was es will.

gruss

Danke gleichfalls.

Ich bin davon ausgegangen, dass man anhand des Beispiels erkennt welchen Weg man zur Lösung des Problems noch gehen könnte.
Dabei sollte die Positionszuweisung (Top und Left) in OnCreate der eigentliche Hinweis sein.

bernau 30. Mär 2018 21:01

AW: Fensterposition persistent machen
 
Zitat:

Zitat von ghubi01 (Beitrag 1397702)
Dabei sollte die Positionszuweisung (Top und Left) in OnCreate der eigentliche Hinweis sein.

Und eben das funktioniert ja nicht bei Ihm. Hat er ja im ersten Post geschrieben.

ghubi01 30. Mär 2018 21:03

AW: Fensterposition persistent machen
 
Zitat:

Zitat von himitsu (Beitrag 1397696)
Neee, erstmal ist es egal wann die Daten gelesen werden, denn es hängt beim Zuweisen und nicht beim Auslesen.
Und nein, es funktioniert nicht immer.

Je nach TForm.Position werden Monitor, Größe und Top/Left zu unterschiedlichen Zeitpunkten von der VCL gesetzt.
Wenn man also seine Zuweisung macht und anschließend die VCL das wieder überschreibt, dann hat man ein Problemchen.

Einiges wird z.B. schon im Constructor ausgeführt, Anderes im OnShow (aber noch bevor das eigene Event behandelt wird) und wieder Anderes erst danach.
Und wann OnCreate ausgeführt wird, dass kann sich auch noch entscheidend auswirken. (Delphi-Referenz durchsuchenOldCreateOrder)

OK. Wann die Daten eingelesen werden ist wirklich egal.

Zu deiner zweiten Aussage: Lässt sich das irgendwie reproduzieren?

EWeiss 30. Mär 2018 21:05

AW: Fensterposition persistent machen
 
Zitat:

Je nach TForm.Position werden Monitor, Größe und Top/Left zu unterschiedlichen Zeitpunkten von der VCL gesetzt.
Ich sag doch wirf sie weg ;)

Zitat:

Danke gleichfalls.
In wie fern?

Ich habe keine Probleme bei allen meinen Anwendungen die x, y Position zu setzen.
Das tue ich schon da existiert noch gar kein Window .. und bevor es angezeigt wird.

Nebenbei sag mir was du testen willst.. ich brauche keine VCL.
Um den Shot klein zu halten NUR 6 meiner Programme.
Und wunder sie sitzen da wo sie sitzen sollen.

gruss

ghubi01 30. Mär 2018 21:08

AW: Fensterposition persistent machen
 
Zitat:

Zitat von bernau (Beitrag 1397704)
Und eben das funktioniert ja nicht bei Ihm. Hat er ja im ersten Post geschrieben.

Stimmt. Sorry hatte ich falsch gelesen. :oops:

bernau 30. Mär 2018 21:16

AW: Fensterposition persistent machen
 
Zitat:

Zitat von ghubi01 (Beitrag 1397694)
ich würde die Daten im initialization Abschnitt aus der ini-Datei oder Registry einlesen und in globalen Variablen speichern.
Danach im FormCreate-Ereignis setzen.

Jetzt muss ich mal blöd fragen. Was hast du davon? Im OnCreate wird die Fensterposition benötigt. Dann lese ich die dort auch aus und nicht vorher in der Initialization.

Würde bei der Mainform keinen Unterschied machen. Aber in einem weiteren erzeugte Fenster (FormB) passt das irgenwie gar nicht. Du liest die Position beim Programmstart ein. Dann öffnest du das FormB schiebst es an eine andere Position und schliesst es wieder. Dann erwarte ich eigentlich, dass dieses FormB bei erneutem Aufruf an der zuletzt geschlossenen Position wieder erscheint. Wird es aber nicht, weil die Position im Initialization beim Start des Programms eingelesen wurde. Hhhmm?

ghubi01 30. Mär 2018 21:22

AW: Fensterposition persistent machen
 
Zitat:

Zitat von bernau (Beitrag 1397708)
Würde bei der Mainform keinen Unterschied machen. Aber in einem weiteren erzeugte Fenster (FormB) passt das irgenwie gar nicht. Du liest die Position beim Programmstart ein. Dann öffnest du das FormB schiebst es an eine andere Position und schliesst es wieder. Dann erwarte ich eigentlich, dass dieses FormB bei erneutem Aufruf an der zuletzt geschlossenen Position wieder erscheint. Wird es aber nicht, weil die Position im Initialization beim Start des Programms eingelesen wurde. Hhhmm?

Für ein weiteres erzeugtes Fenster würde ich das auch so nicht machen. Das Beispiel sollte auch nur für die Mainform gelten.

KodeZwerg 30. Mär 2018 22:55

AW: Fensterposition persistent machen
 
Wenn du Deine Werte aus der Ini/Registry einliest und verarbeitest, ist dann da das Fenster bereits wenigstens einmal "gezeichnet" worden?
Wenn du spassenshalber mal einen Knopf raufpappst mit der "Lade Ini, Setze Werte" funktionalität ausstattest, klappt es dann?

Codehunter 31. Mär 2018 00:12

AW: Fensterposition persistent machen
 
So, Problem gefunden. Ganz was blödes :twisted:

Ich hatte die Message WM_AFTERSHOW im OnShow per Perform() abgesetzt. Verwende ich stattdessen PostMessage() funktioniert es einwandfrei. Damit bekomme ich die AfterShow-Procedure wirklich erst ganz zum Schluss wenn alles auf den Bildschirm gepinselt ist. Scheinbar reiht Perform() die Message früher in den Queue ein. Da muss man auch erst mal drauf kommen ^^

Danke allen die helfen wollten :-D Das Ergebnis könnt ihr hier herunter laden. Viel Spaß damit :-)

himitsu 31. Mär 2018 00:23

AW: Fensterposition persistent machen
 
Perform = SendMessage

Wenn es also sowieso "sofort" ausgeführt wird, ist es egal, ob hier oder woanders. :stupid:

Codehunter 31. Mär 2018 00:26

AW: Fensterposition persistent machen
 
Fängt beides mit P an :oops: Da kann man ja mal durcheinander kommen...

Guts Nächtle und frohe Ostern!


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:46 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