Formularpositionen merken und wiederherstellen

15.10.2006 von Helma  Spona
Formulare werden in aller Regel von Access automatisch positioniert und in der Größe angezeigt, in der das Formular zuletzt in der Entwurfsansicht gespeichert wurde. Beides ist nicht immer von Vorteil. Mit wenig Aufwand und ein paar API-Funktionen lässt sich das aber ändern.

Wünschenswert wäre es, dass Formulare beim nächsten Aufruf dort positioniert werden, wo sie sich beim letzten Schließen befanden, und auch ihre Größe beibehalten wird. Das Problem dabei ist, dass Access keine Eigenschaften für ein Formular zur Verfügung stellt, über die Sie die aktuelle Position zur Laufzeit abfragen und/oder setzen können. Auch eine Methode zum Verschieben des Fensters fehlt. Beides müssen Sie durch entsprechende API-Deklarationen ersetzen.

Notwendige Prozeduren und Funktionen

Als Erstes deklarieren Sie die notwendigen APIFunktionen (Listing 1). Diese Deklarationen ergänzt um einen benutzerdefinierten Datentyp erstellen Sie in einem normalen Modul. Dort können Sie auch die Hilfsfunktionen aus Listing 2 einfügen.

Declare Function MoveWindow Lib "user32.dll" (ByVal hwnd As Long, _
ByVal x As Long, _
ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, _
lpRect As RECT) As Long
Public Declare Function GetParent Lib "user32" (ByVal _
hwnd As Long) As Long
Type RECT
left As Long
top As Long
right As Long
bottom As Long
End Type

Hilfsfunktionen einfügen

Const AppName = "Tipps"
Function Verschieben(ByVal lngLeft As Long, ByVal lngTop As Long, _
ByVal lngWidth As Long, ByVal lngHeight As Long, objForm As Form)
Dim typRect2 As RECT
GetWindowRect GetParent(objForm.hwnd), typRect2
MoveWindow objForm.hwnd, lngLeft, lngTop - typRect2.top, lngWidth, lngHeight,
True
End Function
Function links(objForm As Form) As Long
Dim typRect As RECT
If GetWindowRect(objForm.hwnd, typRect) = 1 Then
links = typRect.left
End If
End Function
Function oben(objForm As Form) As Long
Dim typRect As RECT
If GetWindowRect(objForm.hwnd, typRect) = 1 Then
oben = typRect.top
End If
End Function
Function breite(objForm As Form) As Long
Dim typRect As RECT
If GetWindowRect(objForm.hwnd, typRect) = 1 Then
breite = typRect.right - typRect.left
End If
End Function
Function hoehe(objForm As Form) As Long
Dim typRect As RECT
If GetWindowRect(objForm.hwnd, typRect) = 1 Then
hoehe = typRect.bottom - typRect.top
End If
End Function
Sub speichern(objForm As Form)
SaveSetting AppName, objForm.Name, "Breite", breite(objForm)
SaveSetting AppName, objForm.Name, "Hoehe", hoehe(objForm)
SaveSetting AppName, objForm.Name, "Links", links(objForm)
SaveSetting AppName, objForm.Name, "Oben", oben(objForm)
End Sub
Sub laden(objForm As Form)
Dim lngLinks As Long
Dim lngOben As Long
Dim lngBreite As Long
Dim lngHoehe As Long
lngBreite = GetSetting(AppName, objForm.Name, "Breite", 0)
If lngBreite <> 0 Then
lngHoehe = GetSetting(AppName, objForm.Name, "Hoehe", 0)
lngLinks = GetSetting(AppName, objForm.Name, "Links", 0)
lngOben = GetSetting(AppName, objForm.Name, "Oben", 0)
Verschieben lngLinks, lngOben, lngBreite, lngHoehe, objForm
End If
End Sub

Die Funktion MoveWindow verschiebt ein Fenster an die angegebene Position. Die Zielposition und Zielgröße legen Sie über die Parameter der Funktion fest. Der erste Parameter definiert das Fenster, das verschoben beziehungsweise vergrößert werden soll, indem Sie dessen Fenster-Handle übergeben. Die Funktion gibt 1 (True) zurück, wenn sie fehlerfrei ausgeführt werden konnte.

Mit der Funktion GetWindowRect ermitteln Sie die Fläche, die ein Fenster einnimmt. Damit können Sie also Größe und Position festlegen. Die Funktion gibt diese Informationen als RECTStruktur zurück, deren Werte left, top, right, bottom die Position des Bereichs von links, oben, rechts und unten darstellen, bezogen auf das umgebende Fenster. Um die Werte zu ermitteln, übergeben Sie eine Variable des Typs RECT als Parameter. Nach Aufruf der Funktion enthält diese Variable die gewünschten Werte. Über den Rückgabewert der Funktion können Sie ermitteln, ob die Funktion fehlerfrei aufgerufen werden konnte.

Auch an diese Funktion übergeben Sie wieder das Fenster-Handle des Fensters, dessen Position ermittelt werden soll. Die Funktion GetParent gibt das Fenster-Handle des übergeordneten Fensters, hier des Access-Fensters zurück.

Die Hilfsfunktionen

Neben den API-Funktionen benötigen Sie noch weitere Hilfsfunktionen. Die Funktion Verschieben verschiebt das Formularfenster und ändert gegebenenfalls seine Größe. Sie ruft nichts weiter als die API-Funktion GetWindowsRect auf, um den Bereich des Access-Fensters zu ermitteln, und übergibt dann die Parameter der Funktion mit korrigierter oberer Position des Access-Fensters an die Funktion MoveWindows.

An die Funktion Verschieben übergeben Sie neben der Position des Fensters und dessen Größe auch das Formular als Form-Objekt. Darüber hinaus benötigen Sie zur Ermittlung der linken und oberen Position des Fensters und zu dessen Größe je eine Funktion. Die Funktionen links, oben, breite und hoehe tun dabei nichts weiter, als die GetWindowRect-Funktion aufzurufen und den entsprechenden Wert aus der Struktur zurückzugeben.

Damit haben Sie den gesamten Code erstellt, um die notwendigen Daten zu ermitteln und zu verschieben. Möchten Sie aber ein Fenster immer an der Stelle öffnen, an der es zuletzt geöffnet war, und auch dessen Größe wieder herstellen, müssen Sie natürlich auch die ermittelten Daten speichern. Dazu eignet sich die Registry. Am einfachsten nutzen Sie die SaveSetting-Anweisung und die GetSetting-Funktion, um die Daten zu speichern und zu lesen. Den eigentlichen Lese- und Schreibvorgang übernehmen dann die Prozeduren speichern und laden. Beiden übergeben Sie das Formular als Parameter. Die Prozedur speichern ermittelt dann Position und Größe des Formulars und speichert diese in der Registry unter einem Schlüssel, der dem Namen des Formulars entspricht. Beim Lesen der Daten in der Prozedur laden wird zunächst nur die Breite gelesen. Falls dafür der Wert 0 aus der Registry zurückgegeben wird, wurden noch keine Daten für das Formular gespeichert. In diesem Fall sollten die Daten natürlich nicht zugewiesen werden, weil sonst das Formular bei einer Größe von 0 nicht sichtbar wäre.

Daher werden die anderen Daten nur dann ermittelt, wenn die Breite ungleich 0 ist, und auch nur dann wird die Funktion Verschieben aufgerufen.

Einbinden in die Formulare

In alle Formulare, deren Position und Größe Sie speichern und laden möchten, müssen Sie nun noch den entsprechenden Code einbinden. Beim Öffnen des Formulars müssen Sie die Prozedur laden aufrufen, beim Schließen die Prozedur speichern. Dazu erstellen Sie Ereignisprozedur für die Ereignisse Beim Öffnen (Form_Open) und Beim Schließen (Form_Close).

Private Sub Form_Close()
speichern Me
End Sub
Private Sub Form_Open(Cancel As Integer)
laden Me
End Sub