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.
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.
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.