Home > Artikel > Ausgabe 1/2017 > Anwendungs-Design mit positionierten Formularen

Anwendungs-Design mit positionierten Formularen

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Wie Sie die Positionen und Abmessungen von Formularen ermitteln oder per VBA setzen können, oder auch die des Access-Rahmenfensters, das erfuhren Sie schon in der letzten Ausgabe von Access Basics. Einige Beispiele, wie Sie solche Routinen gewinnbringend in Ihrer Anwendung einsetzen können, folgen in diesem Beitrag.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1701_AppDesign.accdb.

Access und Monitorauflösungen

Die Auflösung von PC-Monitoren hat eine etwas seltsame Geschichte hinter sich. Es ist noch nicht so lange her, da kamen die ersten Flat-Screen-Monitore in der Größe von 15 bis 19 Zoll auf den Markt. Ihre Auflösung betrug in der Regel 1280 x 1024 Pixel. Dann wurden Multimedia-Anwendungen immer wichtiger, die ein Breitformat erforderten. Inzwischen sind 27-Zoll Monitore fast schon der Standard. Doch an der vertikalen Auflösung hat sich indessen fast nichts geändert. Immer noch sind 1080 Pixel vertikal der weitaus verbreitetste Wert. Besonders gilt das für Laptops, die jedoch immer mehr auch im Büro Einzug halten. Eignet sich diese Auflösung tatsächlich für Datenbankanwendungen?

Bild 1 demonstriert, wie Access 2010 sich unter Windows 7 auf so einem Monitor präsentiert, wenn der Navigationsbereich ausgeblendet ist. Das dürfte nicht selten der Fall sein, da man dem Anwender diesen Bereich eher nicht zur Ansicht bringen will und andere Navigationsmethoden, etwa benutzerdefinierte Ribbons, vorzieht. Da die Taskleiste von Windows die Höhe schmälert, bleiben einer Anwendung in maximiertem Zustand noch 1028 Pixel. Für die Titelleiste von Access gehen davon weitere 24 Pixel ab. Und schließlich nimmt der Ribbon ganze 110 Pixel ein. Somit kann ein maximiertes Formular oder ein Bericht nach Abzug des Rahmens des MDI-Bereichs, also der Arbeitsfläche, höchstens noch die Ausdehnung von 1974 x 864 Pixeln besitzen. Daraus ergibt sich ein Seitenverhältnis von etwa 2,28:1.

Access maximiert auf einem Laptop-Monitor ohne Navigationsbereich

Bild 1: Access maximiert auf einem Laptop-Monitor ohne Navigationsbereich

Unter Excel mag dieses Verhältnis noch einigermaßen sinnvoll sein, da man es hier häufig mit zahlreichen Spalten zu tun hat. Aber Access? Formulare nennen sich nicht zufällig so. Eingabeformulare haben ihr papierenes Vorbild im DIN-A4-Hochformat.

Die Felder sind in der Regel mehr oder weniger untereinander angeordnet. Aber auch Datenblätter lassen sich besser lesen, wenn sie eher vertikal ausgedehnt und mehr Datensätze im Zugriff sind.

Das scheint ein Rückschritt zu sein. Einerseits verbreiterten sich Monitore zunehmend, anderseits leistet der Ribbon gegenüber den früheren Menüleisten zusätzlich seinen Beitrag zu einem unpassenden Design.

Damit taucht die Frage auf, ob solchen Umständen abzuhelfen ist? Das Menüband kann man ausblenden, doch wie realisiert man dann eine Navigation durch die Anwendung?

Eine Möglichkeit wäre ein Switchboard am linken Rand, das den eingebauten Navigationsbereich von Access ersetzte. Dafür käme ein Navigationsformular in Betracht. In der Beispieldatenbank haben wir so etwas entwickelt, ohne den Aufwand zu hoch zu treiben.

Switchboard-Formular

Aussehen soll das Ganze, wie in Bild 2. Der Ribbon ist ausgeblendet und am linken Rand befindet sich das Menü, über das die Elemente der Anwendung aufgerufen werden.

Ohne Ribbon aber mit Switchboard ändert sich die verfügbare Arbeitsfläche

Bild 2: Ohne Ribbon aber mit Switchboard ändert sich die verfügbare Arbeitsfläche

Die Arbeitsfläche vergrößert sich damit vertikal um immerhin 135 Pixel. Dass die horizontale Ausdehnung sich durch das Switchboard verringert, ist zu verschmerzen, denn noch immer haben wir es hier mit einem Breitformat zu tun.

Diese Lösung sieht einfacher aus, als sie es ist. Denn wir haben es mit folgenden Anforderungen zu tun:

  • Das Switchboard-Formular muss links angenagelt bleiben
  • Es sollte sich vertikal den Abmessungen des Access-Rahmenfensters anpassen können
  • Formular und Berichte sollten das Switchboard nicht überdecken können. Das soll auch für maximierte Fenster gelten. Der linke Rand der Anwendungsformulare muss rechts vom Switchboard liegen.

Sowohl das Switchboard-Formular, wie auch die Anwendungsformulare, müssen dazu automatisierten Positionierungsoperationen unterzogen werden. Die Basics dazu erfuhren Sie in der letzten Ausgabe.

Ribbon ausblenden

Das geht mit einer Zeile VBA:

DoCmd.ShowToolbar "Ribbon", acToolbarNo

Lassen Sie diese Zeile beim Start der Anwendung ausführen. Ob dies über ein Startformular geschieht, oder über ein AutoExec-Makro und eine öffentliche Funktion, das bleibt Ihnen überlassen. Einblenden können Sie den Ribbon im Zweifel wieder über den Aufruf der Methode ShowToolbar:

DoCmd.ShowToolbar "Ribbon", acToolbarYes

Navigationselemente

In der Beispieldatenbank nennt sich das Switchboard-Formular frmNavi, im Entwurf in Bild 3 dargestellt. Hier sind ein Label für den Titel und einige Schaltflächen untergebracht, die unterschiedliche Aktionen auslösen. Die Gestaltung ist willkürlich. Passen Sie sie nach ihren Vorstellungen an.

Das Switchboard-Formular frmNavi in der Entwurfsansicht

Bild 3: Das Switchboard-Formular frmNavi in der Entwurfsansicht

Wichtig jedoch ist die Einstellung Ohne für die Eigenschaft Rahmenart des Formulars, damit das Fenster dann nicht über die Titelzeile verschoben werden kann. Zur Sicherheit ist die Eigenschaft Verschiebbar zusätzlich auf Nein eingestellt und MinMaxSchaltflächen auf Keine. Selbstverständlich sind auch Datensatzmarkierer und Navigationsschaltflächen ausgeblendet.

Öffnen Sie dieses Formular direkt, so gibt es keine Möglichkeit, es mit der Maus zu schließen. Nur die Tastenkombination STRG-F4 lässt es wieder verschwinden. Im Prinzip ließe sich auch das verhindern, indem Sie die Eigenschaft Tastenvorschau des Formulars (Tab Ereignis des Eigenschaftenblatts) auf Ja stellten und in die Ereignisprozedur für Bei Taste Ab diese Zeilen schrieben:

Private Sub Form_KeyDown( _

                    KeyCode As Integer, Shift As Integer)

     If KeyCode = 115 And Shift = 2 Then

         KeyCode = 0

     End If

End Sub

Dann hilft nur ein Ausdruck im VBA-Direktfenster weiter:

DoCmd.Close acForm, "frmNavi"

Damit Sie derlei während der Entwicklung nicht bewerkstelligen müssen, ist diese Zeile in das Click-Ereignis des Detailbereichs eingebaut. Klicken Sie also auf den grauen Hintergrund des Formulars, so schließt es sich und außerdem wird der möglicherweise fehlende Ribbon wieder eingeblendet.

In die Click-Prozeduren der Schaltflächen könnten Sie direkt die gewünschten Aktionen programmieren, etwa den Aufruf eines Formulars:

DoCmd.OpenForm "frmAdressen"

Wir wollten jedoch die Navigationsfunktionen an zentraler Stelle verwalten, weshalb im Modul mdlNavigation die Funktion in Listing 1 zu finden ist.

Public Enum eAppFunction

     eAppOpenForm1

     eAppOpenForm2

     eAppOpenForm3

     eAppOpenFormKunden

     eAppOpenDSKunden

     eAppMsg1

     eAppMsg2

     eAppClose

End Enum

Public Function NaviFunction(fu As eAppFunction)

     Select Case fu

     Case eAppOpenForm1

         DoCmd.OpenForm "frmTest1"

     Case eAppOpenForm2

         DoCmd.OpenForm "frmTest2"

     Case eAppOpenForm3

         DoCmd.OpenForm "frmTest3"

     Case eAppOpenFormKunden

         DoCmd.OpenForm "frmAdressen"

     Case eAppOpenDSKunden

         DoCmd.OpenForm "frmAdressenDS", acFormDS

     Case eAppMsg1

         MsgBox "Das ist eine beliebige Meldung", vbInformation

     Case eAppMsg2

         MsgBox "Das ist eine weitere Meldung", vbExclamation

     Case eAppClose

         If MsgBox("Anwendung wirklich schließen?", _

                   vbQuestion Or vbYesNo, _

                  "Bestätigen:") = vbYes Then

             Application.Quit acQuitSaveAll

         End If

     End Select

End Function

Listing 1: Navigationsfunktion

Im Kopf des Moduls stehen Enumerationskonstanten, die die Aktionen versinnbildlichen. eAppOpenFormKunden etwa soll das Kundenformular öffnen, eAppOpenDSKunden das Datenblatt mit Kundenadressen. Diese Konstanten können der Funktion NaviFunction als Parameter übergeben werden. Der Vorteil besteht darin, dass nun IntelliSense bei Schreiben des Funktionsnamens an beliebiger Stelle gleich die Konstanten auflistet. Das Kundenformular rufen Sie also so auf:

NaviFunction eAppOpenFormKunden

Genau diese Zeile steht auch im Click-Ereignis der entsprechenden Schaltfläche des Switchboard-Formulars:

Private Sub cmd4_Click()

     NaviFunction eAppOpenFormKunden

End Sub

Die Funktion ermittelt nun über ein Select-Case-Statement die gewünschte Aktion und übernimmt sie dann im Programmzweig. In jeden Case-Abschnitt können Sie beliebigen VBA-Code unterbringen. Im Beispiel sind das neben dem Öffnen von Formularen etwa noch Meldungen. eAppClose ist eine Aktion, die die Anwendung schließen lassen soll. Das geschieht erst nach Bestätigung eines Nachfragedialogs. Bei Bejahung erfolgt das Application.Quit, welches die Anwendung und Access beendet.

Formulare an den Access-Rahmen anpassen

Wenn Sie das Access-Fenster vergrößern oder verkleinern, dann ändert sich auch die Arbeitsfläche. Da das Switchboard-Formular grundsätzlich den linken Rand einnehmen soll, muss es solchen Größenänderungen folgen. Doch wie kriegt es die mit?

In der letzten Ausgabe wurde erläutert, wie Sie mithilfe einer API-Funktion (GetWindowRect) die Ausdehnung des Access-Fensters zurückbekommen. Diese muss regelmäßig abgefragt werden, da es leider kein Ereignis gibt, welches durch Größenänderung des Access-Fensters hervorgerufen würde. Dafür kommt, wenn man auf komplizierte API-Routinen verzichten möchte, eigentlich nur ein Formular-Timer infrage. Also ist die Eigenschaft Zeitgeberintervall des Formulars frmNavi auf den Wert 300 eingestellt. Etwa drei Mal pro Sekunde ermittelt die Timer-Prozedur dann die Abmessungen des Rahmenfensters, um darauf gegebenenfalls reagieren zu können:

Private Sub Form_Timer()

     AdjustSize

End Sub

Die eigentliche Routine ist in die Prozedur AdjustSize (Listing 2) ausgelagert. Grund dafür ist, dass diese Prozedur als Public deklariert ist, wodurch Sie auch von außen aufgerufen werden könnte:

Public Sub AdjustSize()

     Dim hwndMDI As Long

     Dim RCT As RECT

     hwndMDI = GetParent(Me.hwnd)

     Call GetWindowRect(hwndMDI, RCT)

     MDIHeight = 15 * (RCT.Bottom - RCT.Top - 4)

     MDIWidth = 15 * (RCT.Right - RCT.Left - 6) - Me.InsideWidth

     If Me.InsideHeight <> MDIHeight Then

         Me.SetFocus

         DoCmd.MoveSize 0, 0, , MDIHeight

     End If

End Sub

Listing 2: Anpassen des Switchboards an den Access-MDI-Bereich

Forms!frmNavi.AdjustSize

Nun ist es so, dass das Switchboard ja nicht direkt dem Access-Rahmen folgen soll, sondern der Arbeitsfläche. Auch ohne Größenänderung desselben ändert etwa auch das Ein- und Ausschalten des Ribbon den MDI-Bereich. Deshalb benötigen wird das Fenster-Handle der Arbeitsfläche und nicht das von Access (hwndAccessApp). Von einem Formular heraus ist es zum Glück nicht schwierig, an dieses zu gelangen. Da der Arbeitsbereich immer das Elternfenster eines Formulars darstellt, außer, wenn es im Popup-Modus betrieben wird, muss nur das Elternfenster mit der API-Funktion GetParent ermittelt werden:

hwndMDI = GetParent (Me.hwnd)

Die Deklaration der API-Funktion steht im Modul mdlNavigation:

Public Declare Function GetParent _

     Lib "user32.dll" ( _

ByVal hwnd As Long) As Long

Nun können über GetWindowRect auf die Variable RCT vom API-Typ RECT die Abmessungen und Position des MDI-Bereichs erhalten werden. Breite und Höhe werden in den globalen Variablen MDIWidth und MDIHeight zwischengespeichert. Dabei müssen die Pixel-Angaben erst in Twips umgerechnet werden, was durch Multiplikation mit 15 geschieht. Außerdem ist ein Offset von 4 oder 6 abzuziehen, der dem Rahmen des MDI-Bereichs geschuldet ist.

Nun kommt der Vergleich: Ist der MDI-Bereich (MDIHeight) ungleich der Höhe des Formulars (InsideHeight), so kommt es zur eigentlichen Anpassung über die Methode DoCmd.MoveSize. Hier wird keine API-Funktion benötigt. Die Methode wirkt auf das aktuelle Access-Objekt, weshalb der Fokus zunächst über SetFocus auf das Switchboard-Formular gelegt wird. Die ersten beiden Parameter mit den Werten 0 positionieren das Formular in die linke obere Ecke. Darauf folgt ein leerer Parameter, weil die Breite des Formulars unangetastet bleiben soll. Und schließlich wird seine Höhe über das zwischengespeicherte MDIHeight festgelegt.

Diese Überprüfung findet, wie erwähnt, alle 300 ms statt. Ändern Sie die Größe des Access-Fensters, so verstreicht unter Umständen genau diese Zeit, bis sich das Formular den neuen Bedingungen anpasst. Verringern Sie gegebenenfalls das Zeitgeberintervall, wenn die Anpassung weniger augenscheinlich ausfallen soll.

Warum überhaupt der Vergleich mit der aktuellen Größe des Formulars? Könnte man es nicht einfach regelmäßig dem MDI-Bereich anpassen? Das wäre möglich, hätte aber fatale Folgen: Wäre ein weiteres Formular geöffnet, etwa das Kundenformular, so stiehlt SetFocus auf frmNavi diesem fortwährend den Fokus. Das würde die Arbeit mit dem Kundenformular unmöglich machen und ein dauerndes Flackern zur Folge haben.

Formulare an das Switchboard anpassen

Nun sind die ersten beiden eingangs aufgestellten Forderungen erfüllt. Das Switchboard füllt den linken Rand der Arbeitsfläche aus und passt sich dem Access-Fenster an. Öffnen Sie dann ein weiteres Formular durch Klick auf einen der Navigation-Buttons, so schwebt diese frei im MDI-Bereich und überlagert unter Umständen das Switchboard. Noch unangenehmer wird es, wenn Sie das neue Formular maximieren. Dann wird das Switchboard komplett überlagert.

Deshalb ist weitere Logik erforderlich, um den Formularen ein anderes Verhalten beizubringen. Öffnen Sie das Kundenformular über die Schaltfläche Kundenadressen. Es passt sich automatisch in den verbleibenden MDI-Bereich ein, wie Bild 4 demonstriert.

Das Kundenformular dimensioniert sich automatisch gemäß der verbleibenden Arbeitsfläche und folgt Größenänderungen

Bild 4: Das Kundenformular dimensioniert sich automatisch gemäß der verbleibenden Arbeitsfläche und folgt Größenänderungen

Sie können zur Überprüfung die Anpassungsfunktion über die Checkbox rechts oben (Maximiert) ein- und ausschalten.

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!