|
|
|
|
|
Windows-typische Koordinatensysteme haben die Eigenart, nach
rechts unten hin ausgerichtet zu sein. Das bedeutet, dass der
Ursprung des Koordinatensystems links oben liegt und der positive
Zuwachs der Y-Koordinate nach unten hin erfolgt. Beim mathematischen
Standard-Koordinatensystem ("Kartesisches
Koordinatensystem") ist die Y-Richtung umgekehrt ausgerichtet,
von unten nach oben zeigend. Außerdem liegt der Ursprung logisch
gesehen in der Mitte, so dass sowohl für X- als auch Y-Koordinaten
positive und negative dargestellt werden können.
Zwar können Sie über API-Funktionen das Koordinatensystem eines
Fensters (eines Forms, einer PictureBox usw.) entsprechend
umorientieren und den Ursprung positionieren. Doch geraten damit die
gewohnten ScaleMode-Eigenschaften (ScaleLeft, ScaleTop, ScaleWidth,
ScaleHeight, ScaleX und ScaleY) ziemlich durcheinander. Und eine
Größenänderung bei Beibehaltung des ScaleMode-Maßstabs ist auch
nicht so einfach nachzuhalten.
Einfacher ist die Aufgabe mit ein paar wenigen Modifikationen in
reinem Visual Basic zu bewerkstelligen. Um negative Koordinaten zu
erhalten, müssen Sie lediglich einen negativen Wert für ScaleLeft
(X-Achse) bzw. ScaleTop (Y-Achse) angeben, um den Nullpunkt einer
Achse in Richtung Flächenmitte zu verschieben. Geben Sie die volle
Breite bzw. die volle Höhe als negativen Wert an, liegt der
jeweilige Achsen-Nullpunkt rechts bzw. unten, und Sie erhalten für
die betreffende Achse nur noch negative Werte.
Dabei müssen Sie allerdings beachten, dass Sie alle Y-Werte zur
Auswertung in den Mausereignissen oder bei der sonstigen Verwendung,
etwa beim Zeichnen, mit minus 1 multiplizieren. Wenn
der Ursprung nach einer Größenänderung der Fläche an der im
Verhältnis gleichen Stelle liegen soll (etwa weiterhin rechts
unten), sind die Eigenschaften ScaleLeft und ScaleTop entsprechend
neu zu setzen.
Die hier vorgestellte Klasse CartesianScaleMode automatisiert das
Verfahren für Standard-Positionen des Ursprungs: für oben links,
oben mittig, oben rechts, links mittig, rechts mittig, unten links,
unten mittig, unten rechts und in der Fläche zentriert. Sie
übergeben der Methode Init ein Flächen-Objekt (ein Form oder eine
PictureBox) und setzen im optionalen Parameter InitOrigin eine der
Positionsangaben aus der Enumeration OriginConstants. Die
Voreinstellung csoDefault (= 0) sorgt dafür, dass sich das Objekt
dem Windows-Standard entsprechend verhält. Bei einer angegebenen
Position merkt sich die Klasse die zunächst angetroffenen
ScaleMode-Einstellungen unabhängig davon, ob ein Standard-ScaleMode
(etwa vbTwips oder vbPixels) eingestellt ist, oder ob Sie eine der
Eigenschaften benutzerdefiniert geändert haben. Die Eigenschaft
Origin können Sie nachträglich jederzeit ändern (siehe
herunterladbares Beispiel-Projekt).
In der Klasse wird eine Ereignis-Referenz auf das übergebene
Objekt gesetzt. Die Klasse reagiert nun eigenständig auf
Größenänderungen des Objekts (Resize-Ereignis) und auf dessen
Mausereignisse. Letztere werden von einem klasseneigenen Ereignis
durchgereicht, wobei die Y-Koordinate automatisch umgekehrt wird.
Wie bereits erwähnt, brauchen Sie nun nur noch beim Zeichnen die
Y-Koordinate mit minus 1 zu multiplizieren, wenn in der
Eigenschaft Origin ein anderer Wert als csoDefault eingestellt ist.
Private mDefScaleMode As Integer
Private mDefScaleLeft As Single
Private mDefScaleTop As Single
Private mDefScaleWidth As Single
Private mDefScaleHeight As Single
Private WithEvents eForm As Form
Private WithEvents ePictureBox As PictureBox
Public Enum OriginConstants
csoDefault
csoLeftTop
csoLeftBottom
csoRightBottom
csoRightTop
csoCenterTop
csoCenterBottom
csoCenterLeft
csoCenterRight
csoCenter
End Enum
Public Event MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Public Event MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Public Event MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Private pOrigin As OriginConstants
Public Property Get Object() As Object
If Not (eForm Is Nothing) Then
Set Object = eForm
ElseIf Not (ePictureBox Is Nothing) Then
Set Object = ePictureBox
End If
End Property
Public Property Get Origin() As OriginConstants
Origin = pOrigin
End Property
Public Property Let Origin(ByVal New_Origin As OriginConstants)
pOrigin = New_Origin
If Not (eForm Is Nothing) Then
eForm_Resize
ElseIf Not (ePictureBox Is Nothing) Then
ePictureBox_Resize
End If
End Property
Public Sub Init(Object As Object, _
Optional ByVal InitOrigin As OriginConstants = csoDefault)
If Not (eForm Is Nothing) Then
zResetFormScaleMode
Set eForm = Nothing
End If
If Not (ePictureBox Is Nothing) Then
zResetPictureBoxScaleMode
Set ePictureBox = Nothing
End If
pOrigin = InitOrigin
If TypeOf Object Is Form Then
Set eForm = Object
With eForm
mDefScaleMode = .ScaleMode
If mDefScaleMode = vbUser Then
mDefScaleLeft = .ScaleLeft
mDefScaleTop = .ScaleTop
mDefScaleWidth = .ScaleWidth
mDefScaleHeight = .ScaleHeight
End If
End With
eForm_Resize
ElseIf TypeOf Object Is PictureBox Then
Set ePictureBox = Object
With ePictureBox
mDefScaleMode = .ScaleMode
If mDefScaleMode = vbUser Then
mDefScaleLeft = .ScaleLeft
mDefScaleTop = .ScaleTop
mDefScaleWidth = .ScaleWidth
mDefScaleHeight = .ScaleHeight
End If
End With
ePictureBox_Resize
End If
End Sub
Public Sub Destroy()
Class_Terminate
End Sub
Private Sub Class_Terminate()
Set eForm = Nothing
Set ePictureBox = Nothing
End Sub
Private Sub eForm_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseDown(Button, Shift, X, Y)
End Sub
Private Sub eForm_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseMove(Button, Shift, X, Y)
End Sub
Private Sub eForm_MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseUp(Button, Shift, X, Y)
End Sub
Private Sub eForm_Resize()
With eForm
If .WindowState <> vbMinimized Then
zResetFormScaleMode
Select Case pOrigin
Case csoDefault
Case csoLeftTop
Case csoLeftBottom
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoRightBottom
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoRightTop
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
Case csoCenterTop
.ScaleLeft = -(.ScaleWidth / 2) + _
.ScaleX(0.5, vbPixels, .ScaleMode)
Case csoCenterBottom
.ScaleLeft = -(.ScaleWidth / 2) + _
.ScaleX(0.5, vbPixels, .ScaleMode)
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoCenterLeft
.ScaleTop = -(.ScaleHeight / 2) + _
.ScaleY(0.5, vbPixels, .ScaleMode)
Case csoCenterRight
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
.ScaleTop = -(.ScaleHeight / 2) + _
.ScaleY(0.5, vbPixels, .ScaleMode)
Case csoCenter
.ScaleLeft = -(.ScaleWidth / 2) + _
.ScaleX(0.5, vbPixels, .ScaleMode)
.ScaleTop = -(.ScaleHeight / 2) + _
.ScaleY(0.5, vbPixels, .ScaleMode)
End Select
End If
End With
End Sub
Private Sub ePictureBox_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseDown(Button, Shift, X, Y)
End Sub
Private Sub ePictureBox_MouseMove(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseMove(Button, Shift, X, Y)
End Sub
Private Sub ePictureBox_MouseUp(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
If pOrigin Then
Y = -Y
End If
RaiseEvent MouseUp(Button, Shift, X, Y)
End Sub
Private Sub ePictureBox_Resize()
With ePictureBox
zResetPictureBoxScaleMode
Select Case pOrigin
Case csoDefault
Case csoLeftTop
Case csoLeftBottom
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoRightBottom
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoRightTop
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
Case csoCenterTop
.ScaleLeft = -(.ScaleWidth / 2) + .ScaleX(0.5, vbPixels, _
.ScaleMode)
Case csoCenterBottom
.ScaleLeft = -(.ScaleWidth / 2) + .ScaleX(0.5, vbPixels, _
.ScaleMode)
.ScaleTop = -.ScaleHeight + .ScaleY(1, vbPixels, .ScaleMode)
Case csoCenterLeft
.ScaleTop = -(.ScaleHeight / 2) + .ScaleY(0.5, vbPixels, _
.ScaleMode)
Case csoCenterRight
.ScaleLeft = -.ScaleWidth + .ScaleX(1, vbPixels, .ScaleMode)
.ScaleTop = -(.ScaleHeight / 2) + .ScaleY(0.5, vbPixels, _
.ScaleMode)
Case csoCenter
.ScaleLeft = -(.ScaleWidth / 2) + .ScaleX(0.5, vbPixels, _
.ScaleMode)
.ScaleTop = -(.ScaleHeight / 2) + .ScaleY(0.5, vbPixels, _
.ScaleMode)
End Select
End With
End Sub
Private Sub zResetFormScaleMode()
With eForm
.ScaleMode = mDefScaleMode
If mDefScaleMode = vbUser Then
.ScaleLeft = mDefScaleLeft
.ScaleTop = mDefScaleTop
.ScaleWidth = mDefScaleWidth
.ScaleHeight = mDefScaleHeight
End If
End With
End Sub
Private Sub zResetPictureBoxScaleMode()
With ePictureBox
.ScaleMode = mDefScaleMode
If mDefScaleMode = vbUser Then
.ScaleLeft = mDefScaleLeft
.ScaleTop = mDefScaleTop
.ScaleWidth = mDefScaleWidth
.ScaleHeight = mDefScaleHeight
End If
End With
End Sub

|
|
|