Montag, 4. Februar 2008

Bilder zur Laufzeit in einem Form bewegen / Moving images in a form at runtime

Zu o.a. Thema gibt es diverse, ziemlich aufwendige Codebeispiele. Je nach Aufgabenstellung macht es auch durchaus Sinn, einen etwas komplexeren Ansatz zu wählen. Wenn wir jedoch mit möglichst geringem Aufwand bspw. ein Image-Objekt zur Laufzeit bewegen möchten, dann läßt sich das auch mit wenig Code realisieren.

Für die Umsetzung benötigen wir jeweils eine Property für die X- und die Y-Achse, sprich image.Top und image.Left.

Der notwendige Code für die Repositionierung wird in der Methode image.MouseMove hinterlegt.

Im INIT-Ereignis des image-Objektes hinterlegen wir den folgenden Code:

WITH This

    .AddProperty([nxlast],0)
    .AddProperty([nylast],0)

    .Anchor = 0
    .Top    = 1
    .Left   = 1
    .Width  = .Parent.Width
    .Height = .Parent.Height
    .Anchor = 15
 
ENDWITH

Über die Funktion .AddProperty erzeugen wir die beiden notwendigen Eigenschaften für .Top und .Left. Die Folgezeilen stellen sicher, dass unser image korekt im übergeordneten Container positioniert wird.

An dieser Stelle noch eine kurze Bemerkung zur Anchor-Eigenschaft.

Wird die Position eines Objektes zur Laufzeit verändert und anschliessend die Form in ihrer Größe verändert, dann erfolgt der Resize auf Basis der ursprünglichen Position. Um dies zu vermeiden ist es zwingend notwendig, die Anchor-Eigenschaft des bewegten Objektes auf 0 zu setzen (dies initialisiert den Anchor-Speicher), anschliessend das Objekt neu zu positionieren und zum Schluss den Anchor-Wert wiederherzustellen.

Nun zurück zum eigentlichen Thema.

Nachdem die Init-Methode mit dem o.a. Code besetzt ist wenden wir uns dem Ereignis MouseMove zu. Eine 'Bewegungsaktion' macht hier nur dann Sinn, wenn die dargestellte Grafik auch größer als der übergeordnete Container ist. Befindet sich das image.Objekt jedoch im Modus 'Stretch = 1' dann erfolgt die Anzeige isometrisch angepasst auf die Abmessungen des übergeordneten Containers. Mit anderen Worten: Nur wenn sich das image-Objekt im Clip- oder im Stretch-Modus befindet (image.stretch = 0 -> Clip, 2 -> Stretch) erfolgt eine Neupositionierung des Objektes.

Wie dies vor sich geht zeigt der im folgenden angezeigte Code:

LPARAMETERS nButton, nShift, nXCoord, nYCoord

WITH This
    IF .Stretch = 0 ;
    OR (.Stretch = 2 AND (.Width > .Parent.Width OR .Height > .Parent.Height))
        IF m.nButton = 1
            IF .nxLast <> 0 AND .nyLast <> 0
                .Top = .Top - (.nyLast - (m.nYCoord))
                IF .Parent.Height - .Height > .Top
                    .Top = .Parent.Height - .Height
                ENDIF
                IF .Top > 1
                    .Top = 1
                ENDIF
              
                .Left = .Left - (.nxLast - (m.nXCoord))
                IF .Parent.Width - .Width > .Left
                    .Left = .Parent.Width - .Width
                ENDIF
                IF .Left > 1
                    .Left = 1
                ENDIF
            ENDIF
            .nxLast = m.nXCoord
            .nyLast = m.nYCoord
        ELSE
            .nxLast = 0
            .nyLast = 0
        ENDIF
    ENDIF
ENDWITH

Für die weitere Vorgehensweise erscheint es angeraten, als Parent-Objekt einen einfachen Container einzusetzen. Diesem können dann problemlos weitere Funktionen bzgl. der image-Handlings hinzugefügt werden. Möglich wären bspw. die Anzeige von Bildinformationen, Umschaltung zwischen .stretch = 0 und 1, eine Zoomfunktion über .stretch = 2 usw.

Im Zusammenspiel mit Craig Boyds scrollbarer Containerklasse macht das Ganze dann so richtig Spass.

Keine Kommentare:

Kommentar veröffentlichen