Exkurs: Preview plattformunabhängig

Dies ist die Fortsetzung der «Kurzeinführung Preview». Und jetzt kommt's dicke:

Achtung: alles, was nun folgt, ist keinerlei bewiesen oder von offizieller Seite bestätigt. Es sind allesamt nur Rückschlüsse, die ich aus mir vorliegenden Anwendungen der nicht dokumentierten Befehle gezogen habe! Dieser ganze Abschnitt entbehrt jeglicher Grundlagen. Viel Glück damit ;-)!

GetDialogZoomFactorX/Y() und TwipsPerPixelX/Y()

Will man das Preview-Kontrollfeld unabhängig vom verwendeten System halten, so sind diese zwei undokumentierten Befehle von zentraler Bedeutung. Bereits im Abschnitt zur GUI-unabhängigen Dialog-Erstellung wurde das Problem der Skalierung durch gewisse graphische Benutzeroberflächen angesprochen. Genau diesem Problem widmen sich die hier angesprochenen Befehle. GetDialogZoomFactorX/Y() liefert nämlich den Faktor, um den ein System die Ausgabe skaliert. Was dabei die Basis darstellt ist mir nicht bekannt und auch irrelevant, wenn man sich auf die Verwendung dieser Funktion verlässt. Es ist also wichtig, dass jede Grössenänderung, die im Programm vorgenommen wird und auf Koordinaten und Twips-Massen beruht, mit diesen Faktoren multipliziert wird.

TwipsPerPixelX/Y() scheint dagegen hauptsächlich für die Ausgabe von Bitmaps in einem Preview Anwendung zu finden: es bestimmt, wieviele Twips ein Pixel des Bildes auf dem Bildschirm einnimmt.

Ein Bitmap anzeigen

Lässt man ein geladenes Bitmap einfach mit DrawPicture anzeigen, so wird es bei der Anzeige auf einem anderen System aus erwähnten Gründen im besten Fall etwas falsch plaziert, sehr wahrscheinlich aber auch noch beschnitten oder von einem unschönen Rand versehen (siehe Beispiel in «GUI-unabhängige Dialoge»). In diesem Abschnitt wollen wir schauen, wie sich dies optimieren lässt.

Da die DrawPicture-Methode nicht nur die Koordinaten eines Bildes, sondern auch dessen Ausmasse akzeptiert, können wir hier etwas nachhelfen. Doch: diese Werte werden in Twips erwartet. Dies ist also das Einsatzgebiet der TwipsPerPixelX/Y()-Funktionen. Bevor wir nämlich der Methode die Ausmasse des Bildes übergeben, müssen diese multipliziert werden. Hierfür sollten allerdings die genauen Pixel-Masse bekannt sein. Danach sieht der Aufruf wie folgt aus:

...
myDialog.myPreview.DrawPicture(myPicture, leftX%, topY%, _
   PixelX% * TwipsPerPixelX(), PixelY% * TwipsPerPixelY())
...

Dieser Aufruf sorgt schon mal dafür, dass die Abbildung korrekt skaliert wird. Was aber noch nicht berücksichtigt wurde, ist die Tatsache, dass das Preview selber sehr wahrscheinlich auch nicht mehr den ursprünglichen Ausmassen entspricht. Es ist also unterdessen vielleicht breiter als die Abbildung, ev. auch höher, obwohl beim Entwurf auf dem ursprünglichen System die Ausmasse genau denjenigen des anzuzeigenden Bildes angepasst wurden. Nun sieht das ganz einfach unschön aus, wenn rechts und/oder unten noch ein Rand neben dem Bild sichtbar ist und dieses dafür in der linken oberen Ecke klebt. Wir müssen uns also auch noch darum kümmern. Und hierfür ist GetDialogZoomFactorX/Y() gedacht.

Mit GetDialogZoomFactorX/Y() können wir die reellen Ausmasse unseres Preview-Kontrollfeldes bestimmen, indem wir sowohl Breite (Width) wie auch Höhe (Height) damit multiplizieren:

...
Preview = myDialog.myPreview
PrevHeight% = CInt(myDialog.myPreview.Height * _
   GetDialogZoomFactorY(myDialog.myPreview.Height))
PrevWidth% = CInt(myDialog.myPreview.Width * _
   GetDialogZoomFactorX(myDialog.myPreview.Width))
...

Nun stehen die realen Ausmasse fest. Dies erlaubt es uns, das Bild im Preview zentriert darzustellen, damit allfällige Rahmen mindestens gleichmässig verteilt sind. Hierfür müssen die Startkoordinaten um die Hälfte der Differenz von realer Preview-Breite und Twips-Masse des Bitmaps verschoben werden. Damit ergäbe sich eine Routine, die dies alles übernimmt und in etwa so aussehen könnte:

Sub myDrawPicture(Preview as Object, _
   myPicture as Object, ByVal PixelX%, ByVal PixelY%)

   Dim PrevWidth%, PrevHeight%
   Dim PixWidth%, PixHeight%
   Dim leftX%, topY%

   ' reale Breite und Höhe des Preview bestimmen
   PrevWidth% = CInt(Preview.Width * _ 
      GetDialogZoomFactorX(Preview.Width))
   PrevHeight% = Cint(Preview.Height * _
      GetDialogZoomFactorY(Preview.Height))

   ' reale Breite und Höhe des Bitmaps bestimmen
   PixWidth% = PixelX% * TwipsPerPixelX()
   PixHeight% = PixelHeight% * TwipsPerPixelY()

   ' Startkoordinaten bestimmen
   leftX% = (PrevWidth% - PixWidth%) / 2
   topY% = (PrevHeight% - PixHeight%) / 2

   ' ...und pinseln:
   Preview.DrawPicture(myPicture, leftX%, topY%, _
      leftX% + PixWidth%, topY% + PixHeight%)
End Sub

Als Aufrufparameter werden eine Referenz auf das Preview-Kontrollfeld, ein mit LoadPicture() geladenes Bitmap sowie dessen Ausmasse in Pixeln erwartet.

Dies alles und noch etwas mehr (und verfeinert) tut die in der «tools.sbl» enthaltene Methode PaintPicOnPreview(), die SD selber für die im SO4 enthaltenen AutoPiloten verwendet.

Freies Zeichnen

Etwas einfacher als die Anzeige von Bitmaps gestaltet sich das Zeichnen von freien Elementen mit den Draw*()-Methoden des Preview-Objekts. Diese nehmen wiederum alle Koordinaten und Masse in Twips an. Also reicht es im Grossen und Ganzen, diese Werte mit GetDialogZoomFactorX/Y() zu multiplizieren.

Generell ist es sehr zu empfehlen, ein Programm auf allen möglichen Plattformen, die einem irgendwie zur Verfügung stehen, zu testen.



Letzte Änderung: 24.03.98
Copyright ©1998 by Michael Herger