ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 07.01.2000

Diese Seite wurde zuletzt aktualisiert am 07.01.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicAddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für IE, Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zur AVB-Web-Site, Kontakt und Impressum

Zurück...

Zurück...

(-hg) mailto:hg_storescalemode@aboutvb.de

Es ist nicht nur ein guter Programmierstil, veränderte Zustände nach getaner Arbeit wieder zurückzusetzen, sondern vielmehr eine wichtige Maßnahme zur Verhinderung von Fehlern. Wenn Sie beispielsweise bei einem Objekt (Form, PictureBox, Printer, UserControl usw.) vorübergehen während einer Operation einen anderen MSDN Library - VB ScaleModeScaleMode einstellen, sollten Sie nach Abschluß dieser Operation die ursprünglich angetroffene Einstellung wiederherstellen, damit andere Operationen nicht unvermuteterweise auf eine andere Einstellung als erwartet treffen und fehlerhaft funktionieren.

Auf den ersten Blick scheint das eine banale Angelegenheit zu sein. Im Prinzip müsste es ja genügen, den ScaleMode des betreffenden Objekts zu Beginn der Operation in einer lokalen Variablen zwischenzuspeichern und in nach Abschluß der Operation wieder der ScaleMode-Eigenschaft des Objekts zuzuweisen:

Dim nOldScaleMode As ScaleModeConstants

' ...
nOldScaleMode = Object.ScaleMode
' ... Operation(en)
Object.ScaleMode = nScaleMode

In der Regel reicht dies auch, wenn Sie lediglich zwischen den "festen" ScaleMode-Einstellungen hin und her schalten. Falls es jedoch vorkommen kann, dass benutzerdefinierte ScaleMode-Eigenschaften zu sichern und wiederherzustellen sind, reicht dieses Verfahren nicht aus. Benutzerdefinierte ScaleMode-Eigenschaften bedeuten, dass mindestens eine der weiteren Scale...-Eigenschaften (MSDN Library - VB ScaleLeft/ScaleTopScaleLeft und ScaleTop oder MSDN Library - VB ScaleHeight/ScaleWidthScaleWidth und ScaleHeight) verändert worden sind. Visual Basic setzt dann nämlich den ScaleMode auf 0 (vbUser). Wenn Sie danach den ScaleMode ändern, etwa in vbTwips, und in wieder auf vbUser zurücksetzen würden, gehen die ursprünglichen Scale...-Werte verloren. Statt dessen bleiben die letzten Scale..-Werte (hier vbTwips entsprechend) zurück.

Treffen Sie also vor Beginn Ihrer Operation(en) auf den ScaleMode vbUser, müssen Sie auch alle übrigen Scale...-Eigenschaften (da Sie ja nicht wissen können, welche von diesen verändert wurden) sichern und anschließend wiederherstellen:

Dim nOldScaleMode As ScaleModeConstants
Dim nOldScaleLeft as Single
Dim nOldScaleTop as Single
Dim nOldScaleWidth as Single
Dim nOldScaleHeight as Single

'...
With Object
  nOldScaleMode = .ScaleMode
  If nOldScaleMode = vbUser Then
    nOldScaleLeft = .ScaleLeft
    nOldScaleTop = .ScaleTop
    nOldScaleWidth = .ScaleWidth
    nOldScaleHeight = .ScaleHeight
  End If
End With

'... Ihre Operation(en)

With Object
  .OldScaleMode = nScaleMode
  If nOldScaleMode = vbUser Then
    .OldScaleLeft = nScaleLeft
    .OldScaleTop = nScaleTop
    .OldScaleWidth = nScaleWidth
    .nOldScaleHeight = nScaleHeight
  End If
End With

Das sieht nach mühseliger Tipperei aus, nicht wahr? Und Performance kostet das auch, vor allem, wenn die benutzerdefinierten Scale...-Einstellungen nur einmal gesetzt wurden (etwa zur Entwicklungszeit) und später dann eigentlich nur jeweils wiederhergestellt zu werden bräuchten.

Zur Tipperei sparenden und gegebenenfalls die Performance steigernden Lösung dieser Aufgabe bietet sich die Verwendung einer Klasse an, die den notwendigen Code enthält - die Klasse clsStoreScaleMode.

Der Methode Store der Klasse übergeben Sie einfach das Objekt, dessen Scale-Eigenschaften gesichert werden sollen und zum Wiederherstellen der Einstellungen rufen Sie die Restore-Methode der Klasse auf. Da eine Instanz dieser Klasse zur Sicherung meistens nur lokal in einer Prozedur verwendet wird (andere Verwendungsmöglichkeiten werde ich Ihnen noch später in diesem Artikel zeigen), können Sie die Instanzvariable sogar ausnahmsweise als "As New" deklarieren. Dann können Sie die Objektinstanz ohne ausdrückliche Instanzierung verwenden. Seine Lebensdauer ist automatisch auf die jeweilige Prozedur beschränkt. Konkret sieht die Verwendung zum Beispiel so aus:

Sub Irgendwas()
  Dim nStoreScaleMode As New clsStoreScaleMode

  ' z.B. Form1.ScaleWidth ist 100
  nStoreScaleMode.Store Form1
  ' z.B. für API-Operationen:
  ' Form1.ScaleMode = vbPixels
  ' ... Ihre Operation(en) ...
  nStoreScaleMode.Restore
  ' Form1.ScaleWidth ist wieder 100
End Sub

Das sieht doch schon viel handlicher aus, oder? Nun noch ein Beispiel zur ständigen Wiederherstellung von voreingestellten Scale...-Werten. Angenommen, Sie hätten die ScaleHeight- und ScaleWidth-Eigenschaft eines Forms zur Entwicklungszeit individuell eingestellt, beispielsweise auf ein bestimmtes Papierformat für eine Druckvorschau. Dann speichern Sie den Scale-Zustand ein einziges Mal in einer Objektinstanz der Klasse clsStoreScaleMode und restaurieren ihn nur noch jedes Mal nach jeder Veränderung - wenn Sie etwa die reale Größe des Forms auf dem Bildschirm geändert haben. Zugegeben, das ist kein besonders glückliches Beispiel, da dann die Größenänderung des Forms proportional erfolgen sollte, damit die Darstellung nicht in der Breite oder in der Höhe verzerrt wird. Aber ich denke, Sie werden das Prinzip verstehen und das Problem der proportionalen Größenänderung des Forms selbst zu lösen wissen. Das betreffende Form-Modul würde nun folgenden Code enthalten:

Private mStoreScaleMode As clsStoreScaleMode

Private Sub Form_Load()
  Set mStoreScaleMode = New clsStoreScaleMode
  mStoreScaleMode.Store Me
End Sub

Private Sub Form_Resize()
  If Me.WindowState = vbNormal Then
    mStoreScaleMode.Restore
  End If
End Sub

Schauen wir uns nun einmal die beiden Methoden der Klasse näher an. Die modulweiten Deklarationen und ihr Code lautet:

Public Enum ssmErrorConstants
  ssmErrNoScaleModeProperty = vbObjectError + 10001
  ssmErrNoScaleProperties = vbObjectError + 10002
  ssmErrNoObject = vbObjectError + 10003
  ssmErrUnknown = vbObjectError + 10010
End Enum

Private pObject As Object
Private pScaleHeight As Single
Private pScaleLeft As Single
Private pScaleMode As ScaleModeConstants
Private pScaleTop As Single
Private pScaleWidth As Single

Public Sub Store(Optional Object As Object, _
 Optional ByVal StoreObject As Boolean = True)

  Dim nObject As Object
  
  If StoreObject Then
    Set pObject = Object
    Set nObject = pObject
  Else
    If Object Is Nothing Then
      Set nObject = pObject
    Else
      Set nObject = Object
    End If
  End If
  If nObject Is Nothing Then
    Err.Raise ssmErrNoObject, "clsStoreScaleMode.Store", _
     "Kein Objekt."
  Else
    With nObject
      On Error Resume Next
      pScaleMode = .ScaleMode
      Select Case Err.Number
        Case 0
          pScaleLeft = .ScaleLeft
          pScaleTop = .ScaleTop
          pScaleHeight = .ScaleHeight
          pScaleWidth = .ScaleWidth
          Select Case Err.Number
            Case 438
              Err.Raise ssmErrNoScaleProperties, _
               "clsStoreScaleMode.Store", _
               "Objekt verfügt nicht über Scale-Eigenschaften."
            Case Else
              Err.Raise ssmErrUnknown, _
               "clsStoresScaleMode.Store", _
               "Objekt-Fehler Nr. " & Err.Number
          End Select
        Case 438
          Err.Raise ssmErrNoScaleModeProperty, _
           "clsStoreScaleMode.Store", _
           "Objekt verfügt nicht über ScaleMode-Eigenschaft."
        Case Else
          Err.Raise ssmErrUnknown, _
           "clsStoresScaleMode.Store", _
           "Objekt-Fehler Nr. " & Err.Number
      End Select
    End With
  End With
End Sub

Public Sub Restore(Optional Object As Object)
  Dim nObject As Object
  
  If Object Is Nothing Then
    Set nObject = pObject
  Else
    Set nObject = Object
  End If
  If nObject Is Nothing Then
    Err.Raise ssmErrNoObject, "clsStoreScaleMode.Restore", _
     "Kein Objekt."
  Else
    With Object
      On Error Resume Next
      .ScaleMode = pScaleMode
      Select Case Err.Number
        Case 0
          If pScaleMode = vbUser Then
            .ScaleLeft = pScaleLeft
            .ScaleTop = pScaleTop
            .ScaleHeight = pScaleHeight
            .ScaleWidth = pScaleWidth
            Select Case Err.Number
              Case 438
                Err.Raise ssmErrNoScaleProperties, _
                 "clsStoreScaleMode.Restore", _
                 "Objekt verfügt nicht über Scale-Eigenschaften."
              Case Else
                Err.Raise ssmErrUnknown, _
                 "clsStoresScaleMode.Restore", _
                 "Objekt-Fehler Nr. " & Err.Number
            End Select
          End If
        Case 438
          Err.Raise ssmErrNoScaleModeProperty, _
           "clsStoreScaleMode.Restore", _
           "Objekt verfügt nicht über ScaleMode-Eigenschaft."
        Case Else
          Err.Raise ssmErrUnknown, _
           "clsStoresScaleMode.Restore", _
           "Objekt-Fehler Nr. " & Err.Number
      End Select
    End With
  End With
End Sub

Sie sehen, dass da einiges gegenüber dem oben gezeigten, jedes Mal erneut einzugebenden lokalen Code hinzugekommen ist. Diese Erweiterungen haben jedoch ihren Sinn (als ob ich Ihnen sinnlosen Code verkaufen täte...).

Da ist etwa der optionale Parameter StoreObject der Store-Methode. Er ist auf True voreingestellt. Wie das zuvor gezeigte zweite Verwendungsbeispiel zeigt, ist es dafür notwendig, das Objekt zu speichern. Allerdings kann es eventuell notwendig sein, auf die Zwischenspeicherung zu verzichten, damit nicht irgendwelche Objektreferenzen "irgendwo in der Landschaft herumstehen", die ein sauberes Terminieren des betreffenden Objekts verhindern könnten. Das ist auch der erste Grund für den optionalen Parameter Object der Restore-Methode. Sie können also das Objekt, falls es nicht gespeichert werden sollte, ausdrücklich übergeben.

Die ersten Code-Zeilen der beiden Methoden dienen zur Feststellung, ob ein Objekt übergeben worden ist und auf welches Objekt der eigentliche Code der Methode angewendet werden soll. Denn auch bei der Store-Methode ist der Object-Parameter optional, so dass Sie sich nach einer erstmaligen Übergabe des betreffenden Objekts im weiteren die Übergabe sogar sparen können. Wurde kein Objekt übergeben, wird die intern in der Variablen pObject abgelegte Objektreferenz verwendet. Stellt sich nun heraus, dass gar kein Objekt vorhanden ist, wird die Bearbeitung der Methoden mit der Fehlermeldung ssmErrNoObject (aus der Enumeration ssmErrorConstants) beendet.

Da wir den Objekt-Parameter unverbindlich als "As Object" deklariert haben (späte Bindung - Sie können natürlich die Klasse auch für einen bestimmten Objekt-Typ, etwa für Forms spezialiseren, indem Sie den Object-Parameter als "As Form" deklarieren), könnte es ja vorkommen, dass versehentlich ein Objekt übergeben worden ist, dass nicht über eine ScaleMode-Eigenschaft verfügt, oder nicht über die übrigen Scale...-Eigenschaften. Wir schalten daher eine einfache Fehlerbehandlung mit On Error Resume Next ein, die wir entsprechend auswerten und im Fehlerfalle einen Laufzeitfehler (Err.Raise ...) mit der passenden Fehlernummer (wieder aus ssmErrorConstants) auslösen.

Im übrigen entspricht der Code dem Eingangs angeführten Code-Beispiel.

Der Ordnung halber geben wir in jedem Fall das in pObject gegebenenfalls gespeicherte Objekt im Terminate-Ereignis der Klasse wieder frei:

Private Sub Class_Terminate()
  Set pObject = Nothing
End Sub

Kommen wir nun zu den weiteren Verwendungmöglichkeiten der Klasse clsStoreScaleMode.

Der tieferen Sinn des Spielchens mit den optionalen Object-Parametern und der Speicherung der Objektreferenz wird Ihnen aufgehen, wenn Sie erst einmal auf die Idee kommen, dass Sie durchaus verschiedene Objekte ins Spiel bringen können.

So können Sie die Scale...-Einstellungen eines Forms ohne Probleme an ein anderes Form weitergeben, indem Sie der Store-Methode das erste Form übergeben, der Restore-Methode jedoch ein anderes Form. Aufgrund der Deklarationen "As Object" können Sie sogar so weit gehen, mit verschiedenen Objekttypen zu hantieren. Die Übergabe der Scale...-Einstellungen einer PictureBox (oder eines hochspezialisierten UserControls oder OCXes) an das Printer-Objekt ist nur eine von vielen Möglichkeiten.

Sie können auch für ein und dasselbe Objekt mehrere benutzerdefinierte Scale...-Einstellungen speichern, indem Sie das Objekt im jeweiligen Zustand einer gesonderten Instanz der clsStoreScaleMode-Klasse übergeben. Quasi wie bei der Verwendung von Formatvorlagen in einer Textverarbeitung können Sie so ohne Umstände jederzeit verschiedene Scale...-Einstellungen abrufen - stecken Sie diese "Vorlagen"-Instanzen unter einem Vorlagennamen in eine Collection und... alles klar? Genauso können Sie auch verschiedene Zustände in einer Collection stapeln, um eine Undo-Funktion zu ermöglichen.

Weiteren Komfort gerade im Hinblick auf die zuletzt angeführten Verwendungsmöglichkeiten bietet die naheliegende Offenlegung der internen Variablen zur Speicherung der Scale...-Eigenschaften über Eigenschaften-Prozeduren. Wie auch VB es handhabt, wird hier der interne Wert pScaleMode auf vbUser gesetzt, sobald eine der Eigenschaften ScaleLeft, ScaleTop, ScaleWidth oder ScaleHeight geändert wird.

Public Property Get Object() As Object
  Set Object = pObject
End Property

Public Property Set Object(New_Object As Object)
  Set pObject = New_Object
End Property

Public Property Get ScaleHeight() As Single
  ScaleHeight = pScaleHeight
End Property

Public Property Let ScaleHeight(ByVal New_ScaleHeight As Single)
  pScaleHeight = New_ScaleHeight
  pScaleMode = vbUser
End Property

Public Property Get ScaleLeft() As Single
  ScaleLeft = pScaleLeft
End Property

Public Property Let ScaleLeft(ByVal New_ScaleLeft As Single)
  pScaleLeft = New_ScaleLeft
  pScaleMode = vbUser
End Property

Public Property Get ScaleMode() As ScaleModeConstants
  ScaleMode = pScaleMode
End Property

Public Property Let ScaleMode(ByVal New_ScaleMode _
 As ScaleModeConstants)
  pScaleMode = New_ScaleMode
End Property

Public Property Get ScaleTop() As Single
  ScaleTop = pScaleTop
End Property

Public Property Let ScaleTop(ByVal New_ScaleTop As Single)
  pScaleTop = New_ScaleTop
  pScaleMode = vbUser
End Property

Public Property Get ScaleWidth() As Single
  ScaleWidth = pScaleWidth
End Property

Public Property Let ScaleWidth(ByVal New_ScaleWidth As Single)
  pScaleWidth = New_ScaleWidth
  pScaleMode = vbUser
End Property


Kompletter Code der Klasse clsStoreScaleMode Kompletter Code der Klasse clsStoreScaleMode

Die Klasse clsStoreScaleMode (clsStoreScaleMode.zip - ca. 5,3 KB)



Komponenten-Übersicht

Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...