• Offizieller Beitrag

    Bitnugger hatte in diesem Thread die Funktion _WinAPI_GetWindowPlacement() vorgeschlagen, um die Positionsdaten eines Fensters bei Programmende zu speichern.

    Tatsächlich ist diese WinApi-Funktion sehr gut dafür geeignet. Vor allem, weil man damit auf einen Schlag alle Fensterdaten abspeichern kann. Also auch, ob maximiert/minimiert.

    So habe ich mir gedacht: Am besten beim Programmende gleich die ganze Struktur speichern und beim nächsten Programmstart wiederherstellen.

    Dafür habe ich hier mal eine kleine UDF geschrieben, die diese beiden Funktionen ("_LoadWindowPlacement" und "_SaveWindowPlacement") zur Verfügung stellt.

    Außerdem gibt es noch eine Funktion, um sicherzustellen, dass sich das Fenster auf dem Desktop befindet. Benutzer von mehreren Bildschirmen werden das nachvollziehen können: Wenn man ein Fenster auf dem zweiten Bildschirm positioniert hat und dieser zweite Bildschirm beim nächsten Programmstart gerade nicht aktiviert ist. Dann wird das Fenster an einer Position geöffnet, die man nicht erreichen kann. In dem Fall hilft meine Funktion "_WindowOnDesktop". Sie verschiebt das Fenster dann auf den sichtbaren Desktop.

    Beispiel:

    Edit 13.04.18 Neue Version 1.1:

    - Man kann jetzt die Daten von mehreren Fenstern (GUIs) in einer einzelnen Datei speichern (pro Fenster 44 Bytes = 1 Block).

    - Die Funktion "_WindowOnDesktop" noch etwas angepasst. Danke Bitnugger!

  • Sehr schön! ;)

    Ich setze es in meinen Scripts allerdings ein wenig anders um und speichere die Strukturen in einem IniFile...

    1. Weil ich die gespeicherte WindowPlacement-Struktur bei Bedarf einlesen möchte, bevor das Fenster erstellt wurde.
    2. Weil ich nicht für jedes Fenster (in einem Projekt) eine separate Datei zum Speichern der Strukturen haben möchte.

    Z.B.: _SaveWindowPlacement($sIniFile, $hWnd, $sWndName)

    [MainGUI]

    WindowPlacement=44|0|1|-1,-1|-1,-1|0,1035,808,1669

    Alternativ ließen sich die Strukturen sicher auch mit SQLite als BLOB speichern...

    Funktion _WindowOnDesktop (s.u.): Die For-Schleife (Zeile 77-79) und die beiden DllStructSetData (Zeile 82, 83) kannst du dir sparen:

    Code
    $tDesktopRect = DllStructCreate($tagRECT, DllStructGetPtr($tDesktopInfo, 'rWindow'))
    Code
    $tWindowPoint = DllStructCreate($tagPOINT, DllStructGetPtr($tWindowPlacement, 'rcNormalPosition'))

    _WinAPI_GetDesktopWindow liefert bei mir nur die Koordinaten des primären Monitors (Monitor 1)...

    $tDesktopInfo = _WinAPI_GetWindowInfo(_WinAPI_GetDesktopWindow()) ; 0, 0, 1920, 1080

    Deshalb evtl. besser so... damit bekomme ich die von allen (erweiterten) Monitoren (1+2)

    $tDesktopInfo = _WinAPI_GetWindowInfo(WinGetHandle('[CLASS:Progman]')) ; -1920, 0, 3840, 1080

    Dadurch landen die Fenster in den sichtbaren Bereich des Monitors, auf dem sich der größte Teil des Fensters befindet, oder auf dem, der den Koordinaten am nähesten ist. Bei einem größeren/kleineren Monitor könnte man optional noch die Position und Größe anpassen.

    • Offizieller Beitrag

    Ich habe meine Funktionen jetzt noch um die Möglichkeit erweitert, die Positionsdaten von mehreren Fenstern in einer einzelnen Datei zu speichern. Dazu muss man lediglich den Block (je 44 Bytes / Strukturgröße) angeben.

    Die Funktion "_WindowOnDesktop" habe ich auch noch etwas angepasst. Danke Bitnugger!

    Neue Version der UDF in Post#1.

  • Die Funktion _WindowOnDesktop verschiebt Fenster, wenn die linke obere Ecke auf dem Desktop nicht sichtbar ist, auf den primären Monitor. In einigen Fällen wäre es mir aber lieber, dass sie auf den Monitor landen, der den Koordinaten am nähesten ist, von denen aus sie verschoben werden sollen.

    Im Anhang mal ein erster Ansatz... mit dieser Funktion kann man selbst bestimmen, wohin verschoben wird und ob das Fenster sichtbar, minimiert, maximiert und/oder die Größe angepasst werden soll.

    PS: Das Arbeitsbereich-Rechteck verringert sich nicht nur durch den Platz, den die Taskleiste benötigt, wenn diese nicht automatisch ausgeblendet wird, denn andere Anwendungen können sich auch Platz reservieren. Bei mir ist dies auf dem primären Monitor z.B. das Shelf von Winstep.

  • AutoIt
    Global $ret = _LoadWindowPlacement($hGui, $sPlacementFile, 0) ; die Positionsdaten aus Block 1 laden und fuer Fenster 1 setzen
    If @error Then GUISetState(@SW_SHOW, $hGui)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : LoadWindowPlacement1 = ' & $ret & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

    Das Thema ist aus meiner Sicht nicht veraltet, die UDF funktioniert einwandfrei, hat mir heute gut weitergeholfen.
    Nur zum Verständnis: wieso wird GUISetState nur im Errorfall aufgerufen? Muss das nicht immer passieren?

    :)