Vor einer Weile habe ich gesucht, wie ich die Fensterposition unter Windows speichern und wiederherstellen kann. Und zwar so, wie ich es auch von Windows selber gewohnt bin. Ich habe eine ganze Weile gesucht bis ich das richtige gefunden habe. Das alles funktioniert relativ einfach über die beiden Funktionen GetWindowPlacement() und SetWindowPlacement(). Mein Beispiel habe ich wie immer mit dem C++ Builder geschrieben, die Codebeispiele sollten aber leicht in andere Sprachen übertragbar sein.
Die Verwendung von SetWindowPlacement() und GetWindowPlacement() hat einen weiteren Vorteil: Wäre ein Dialog (z. B. aufgrund des Austausches eines Bildschirms auf die andere Seite) im nicht mehr sichtbaren Bereich, wird das automatisch erkannt und er erscheint in dem Eck, dass der letzten Position am nächsten ist.
Fensterposition speichern
Für das Speichern der Fensterposition wird als erstes die Struktur WINDOWPLACEMENT benötigt. Wichtig dabei ist, dass die erstellte Variable mit sizeof(WINDOWPLACEMENT) initialisiert wird. Danach werden die Variablen der Struktur mit der Funktion GetWindowPlacement, der man den Handle des aktuellen Dialogs übergibt, befüllt. In rcNormalPosition befinden sich die Position und die Abmessung der entsprechenden Form, für den WindowState wsNormal. Auch wenn die Form maximiert ist, befinden sich in dieser Variable die Werte für den nicht maximierten Zustand. Hat showCmd den Wert WS_MAXIMIZE, dann ist der Dialog maximiert. Hat man alle benötigten Werte ausgelesen, können diese in einer Ini oder wo auch immer abgespeichert werden. Am besten wird das ganze im FormClose ausgeführt.
// WindowPlacement ueber WinAPI holen WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(this->Handle, &wp); // Die Werte fuer die vom Benutzer eingestellte Fensterposition holen int top = wp.rcNormalPosition.top; int left = wp.rcNormalPosition.left; int bottom = wp.rcNormalPosition.bottom; int right = wp.rcNormalPosition.right; // Pruefen ob das Fenster maximiert ist oder nicht bool maximized = wp.showCmd == SW_MAXIMIZE; // Die Werte in eine Ini schreiben std::auto_ptr<TIniFile> pIniFile(new TIniFile(L".\\Fensterposition.ini")); pIniFile->WriteInteger(this->Name, L"top", top); pIniFile->WriteInteger(this->Name, L"left", left); pIniFile->WriteInteger(this->Name, L"bottom", bottom); pIniFile->WriteInteger(this->Name, L"right", right); pIniFile->WriteBool(this->Name, L"maximized", maximized);
Fensterposition wiederherstellen
Analog zum speichern, wird das wiederherstellen der Fensterposition gemacht. Viel Erklärung braucht es dazu nicht mehr. Das wiederherstellen der Position passiert einfach in umgedrehter Reihenfolge. Am besten ruft man den Code im FormShow auf. DefaultMonitor sollte am besten auf dmDesktop gestellt werden. Beim Standardwert dmActiveForm wird der Dialog auf dem Bildschirm geöffnet, auf dem ein aktives Formular des aktuellen Programms geöffnet ist. Bei dmDesktop hingegen, wird der Dialog auf dem Monitor geöffnet, auf dem er auch zuletzt geschlossen wurde.
// dmDekstop, damit die Form immer auf dem Monitor aufgeht, wo sie auch als // letztes geoeffnet war this->DefaultMonitor = dmDesktop; // Aktuelles WindowPlacement ueber WinAPI holen WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(this->Handle, &wp); // Die frueher gespeicherten Werte aus der Ini holen std::auto_ptr<TIniFile> pIniFile(new TIniFile(L".\\Fensterposition.ini")); int top = pIniFile->ReadInteger(this->Name, L"top", this->Top); int left = pIniFile->ReadInteger(this->Name, L"left", this->Left); int bottom = pIniFile->ReadInteger(this->Name, L"bottom", this->Top + this->Height); int right = pIniFile->ReadInteger(this->Name, L"right", this->Left + this->Width); bool maximized = pIniFile->ReadBool(this->Name, L"maximized", false); // Die Werte setzen wp.rcNormalPosition.top = top; wp.rcNormalPosition.left = left; wp.rcNormalPosition.bottom = bottom; wp.rcNormalPosition.right = right; // Falls das Fenster beim letzten mal maximiert war // -> jetzt auch wieder maximieren if (maximized) wp.showCmd = SW_MAXIMIZE; // Und zum Schluss die WindowsPosition wieder ueber die WinAPI setzen SetWindowPlacement(this->Handle, &wp);
Wenn ihr noch Fragen habt, immer her damit! Ansonsten viel Spaß beim ausprobieren.