Skalieren

Größe und Position von Formen und Steuerelementen
an unterschiedliche Bildschirmauflösungen anpassen.

Hat der Rechner auf dem ein Programm abläuft eine andere Bildschirmauflösung als der Rechner auf dem das Programm erstellt wurde, so werden Formen und Steuerelemente auf den beiden Rechnern unterschiedlich groß dargestellt.

Ein Programm "xyz" wird z.B. auf einem Rechner mit einer aktuellen Bildschirmauflösung von 800 * 600 Pixel erstellt.
Wird dieses Programm jetzt auf einem Rechner mit einer höheren Auflösung (z.B. 1024 * 768) installiert, so werden ohne besondere Vorkehrungen im Programm alle Fenster und Steuerelemente deutlich kleiner als auf dem Entwicklungsrechner dargestellt. Dies könnte in vielen Fällen noch toleriert werden. Unangenehmer wird es aber, wenn der Rechner auf dem das Programm laufen soll eine niedrigere Bildschirmauflösung (z.B. 640 * 480) benutzt. Jetzt werden Fenster und Steuerelemente größer als auf dem Entwicklungsrechner abgebildet. Dies hat zur Folge, dass ein Fenster möglicherweise größer als die tatsächliche Bildschirmfläche wird und einige Steuerelemente der Form gar nicht mehr sichtbar sind. Dies wird sicher kein Anwender tolerieren.

Das Programm sollte also prüfen, mit welcher tatsächlichen Auflösung gearbeitet wird und Grösse und Position von Formen und Steuerelementen entsprechend anpassen.

Die Sub "Skalieren" im folgenden Programmausschnitt sorgt dafür, dass ein Programm unabhängig von der jeweiligen Bildschirmauflösung wird.

Die Werte für die Konstanten
DWidth ( = Screen.Width) und
DHeight ( = Screen.Height)
müssen am Entwicklungsrechner zur Designzeit ermittelt werden.

Beim SSTab gibt es eine Besonderheit.
Für Controls die auf einem momentan nicht sichtbaren Tab liegen wird von der tatsächlichen Left-Eigenschaft ein fester Wert von 75000 (Twips) abgezogen.
D.h. ein Control, das auf einem gerade sichtbaren Tab auf Control.Left = 1000 liegt, erhält in dem Moment in dem das Tab unsichtbar wird (durch Userklick oder durch Code) Control.Left = -74000.
Beim Skalieren muss man also abfragen, ob 1. der Container des Controls ein SSTab ist und ob 2. die Left-Eigenschaft < 0 ist. Sind beide Bedingungen erfüllt, dann muss der Wert für Left entsprechend korrigiert werden.

Ebenso müssen Controls die sich auf einem Toolbarcontrol befinden gesondert behandelt werden. Toolbarcontrols haben feste Werte für z.B. ButtonHeigth, ButtonWidth. Textfelder oder andere Controls, die sich auf einem Toolbarcontrol befinden, werden deshalb sinnvollerweise nach dem Skalieren der Form getrennt an der gewünschten Stelle eingepasst.

Public Sub Skalieren(FRM As Form, ScaleForm As Boolean, ScaleFont As Boolean)
    'Skaliert alle Elemente der übergebenen Form
    'Elemente in Toolbars müssen separat ausgerichtet werden, da Toolbar nicht skaliert wird

    Dim I As Integer
    Dim K As Long
    Dim SFX As Single
    Dim SFY As Single

    Const DWidth = 12000 'Screen.Width zur Designzeit
    Const DHeight = 9000 'Screen.Height zur Designzeit

    SFX = Screen.Width / DWidth 'Skalierfaktor X-Achse
    SFY = Screen.Height / DHeight 'Skalierfaktor Y_Achse

    On Error Resume Next
    If ScaleForm Then
        FRM.Width = FRM.Width * SFX
        FRM.Height = FRM.Height * SFY
        FRM.Left = FRM.Left * SFX
        FRM.Top = FRM.Top * SFY
    End If

    For I = 0 To FRM.Controls.Count - 1
        'nur wenn ein Toolbarcontrol auf der Form ist
        ' If Not TypeOf FRM.Controls(I).Container Is Toolbar Then

            'diese Routine wird nur benötigt, wenn sich auf der Form ein SSTab befindet.
            If TypeOf FRM.Controls(I).Container Is SSTab Then
                If FRM.Controls(I).Left < 0 Then
                    K = 75000
                End If
            End If


            'wenn die vorstehende Routine für SSTab verwendet wird
            FRM.Controls(I).Left = ((FRM.Controls(I).Left + K) * SFX) - K

            'wenn die obige Routine für SSTab nicht verwendet wird
            'FRM.Controls(I).Left = FRM.Controls(I).Left * SFX
           
            FRM.Controls(I).Top = FRM.Controls(I).Top * SFY
            FRM.Controls(I).Width = FRM.Controls(I).Width * SFX
            FRM.Controls(I).Height = FRM.Controls(I).Height * SFY
            If ScaleFont Then
                FRM.Controls(I).Font.Size = FRM.Controls(I).Font.Size * SFY
                FRM.Controls(I).HeadFont.Size = FRM.Controls(I).HeadFont.Size * SFY
            End If

            K = 0

        'nur wenn ein Toolbarcontrol auf der Form ist
        ' End If

    Next I
    On Error GoTo 0
End Sub

Die Sub wird z.B. im Form_Load - Ereignis so aufgerufen

    Skalieren Me, True, True

Der Aufruf bewirkt dass alle Controls auf der Form, die Form selbst und die Fontgrößen skaliert werden.

Wurde die Eigenschaft WindowState der Form zur Designzeit bereits auf vbMaximized eingestellt so ist das Skalieren der Form selbst nicht sinnvoll.
Die Sub wird dann z.B. so aufgerufen:

    Skalieren Me, False, True


Die Einstellung der Werte für .Left, .Top, .Width, .Height kann nicht ohne weiteres in einer "Move Left, Top, Width, Height" - Anweisung zusammengefasst werden. Befinden sich auf der Form Steuerelemente, bei denen eine der Eigenschaften Left, Top, Width oder Height nicht einstellbar ist, so würde wegen "On Error Resume Next" die gesamte Anweisung übergangen. D.h. es würde keine Positionierung bzw. Skalierung für dieses Steuerelement durchgeführt.

Befinden sich auf der Form Liniensteuerelemente (Line) so müssen die jeweiligen X- und Y- Koordinaten ebenfalls in die Skalierung mit einbezogen werden.
Line1.X1 = Line1.X1 * SFX
Line1.X2 = Line1.X2 * SFX
Line1.Y1 = LIne1.Y1 * SFX
Line1.Y2 = LIne1.Y2 * SFY

 

 

  
 

Der vorstehend gezeigte Code sollte nicht als allgemeingültige Lösung für jede Art von Form missverstanden werden. Die Abmessungen vieler Controls sind nicht in allen Achsen beliebig per Code einstellbar. So lässt sich z.B. die Höhe von Toolbars oder Comboboxen nicht ändern, sondern ist vom System vorgegeben. Auch leidet die Optik einer Form oft sehr, wenn Buttons oder Textboxen einfach linear vergrößert oder verkleinert werden. In vielen Fällen ist zum Erreichen einer guten Optik die individuelle Anpassung einzelner Controls sinnvoll. So sollte z.B. in einem benutzerfreundlichen Programm eine Einstellmöglichkeit für Schriftarten und Schriftgrößen vorgesehen sein. Abhängig von einer solchen Benutzereinstellung wird es dann notwendig, z.B. die Höhe von betroffenen Textboxen anzupassen. Der Programmieraufwand für solche individuelle Anpassungen kann im Einzelfall beachtliche Ausmaße annehmen. Das Urteil eines Benutzers, ob er ein Programm gut oder schlecht findet, wird jedoch zu einem nicht geringen Teil von der Optik der einzelnen Forms bestimmt. Es könnte also sehr wohl falsch sein, gerade an dieser Stelle Programmierzeit sparen zu wollen.
 

  
 

Ein  Beispiel für eine von jeglicher Auflösungseinstellung unabhängige Programmoberfläche gibt ADO Demo MU2002.