Deklaration der Abhängigkeit

Ich habe ja schon an anderer Stelle auf die MacOSControls hingewiesen, von denen ich einige mit dem Erscheinen (oder kurz danach, je nachdem, was sich noch ändern mag) von Xojo 2014r3 (im übrigen kostenlos) veröffentlichen werde. Aber die beste Hilfe ist immer noch die zur Selbsthilfe. Was also tun, wenn das Betriebssystem eigentlich eine benötigte Funktion zur Verfügung stellt, diese aber nicht zum Lieferumfang von Xojo gehört?

Gehen wir mal in die Praxis. Ich entwickle ja wie gesagt am liebsten für den Mac und habe in die anderen Systeme wenig hineingeschaut. Wenn Sie die API-Aufrufe für Windows & Linux kennen, teilen Sie sie mir gerne mit, dann ergänze ich dieses Beispiel entsprechend. Es ist aber auch jetzt schon in vielerlei Hinsicht übertragbar.

Wenn Sie in einem Xojo-Desktop-Projekt ein neues Fenster anlegen und mit

Window1.show

(oder wie auch immer Ihr Fenster heißt) auf den Bildschirm bringen, klebt es in der Regel links oben. Das ist nicht immer die bevorzugte Position, um nicht zu sagen, eigentlich so gut wie nie. Normalerweise möchte man ein neues Fenster in den Blickpunkt des Benutzers rücken, und der ist eher in der Mitte des Bildschirms angesiedelt.

Jetzt können Sie mittels Window1.Left und Window1.Top und Vergleich mit den Werten der Screen-Methode auslesen, auf welchem Bildschirm das Fenster überhaupt angezeigt wird, die Dimensionen des Bildschirms bestimmen, Fensterbreite und -höhe halbieren, von der Hälfte der Bildschirmdimensionen abziehen und die erhaltenen Werte wieder in Window1.Left und Window1.Top zurückschreiben, wobei Sie für die Höhe evtl. noch die Höhe der Menüzeile abziehen, zumindest auf dem Mac, und nach Goldenem Schnitt das Ganze ein wenig nach oben setzen. Nichts verkehrt daran, und das Schöne: Das funktioniert dann auf jedem System.

Aber irgendwie auch eine Menge Rechnerei, die das Betriebssystem viel schneller und eleganter zur Verfügung stellt. Die Apple-Entwicklerunterlagen bieten die kompletten OS X-Funktionsbeschreibungen (wenn Sie nicht online gehen wollen: In XCode finden Sie die Bibliothek auch offline im Hilfe-Menü). Wir suchen eine Fensterfunktion, benutzen natürlich das Cocoa-Framework und fahnden deshalb nach der NSWindow-Klasse (die meisten Objekte in Cocoa beginnen mit „NS“ und einem meistens geläufigen Objektnamen, also „NSWindow, NSButton, NSString …“).  Und dort finden wir auch eine Center-Methode, die folgendermaßen beschrieben wird (falls Sie sie eben nicht finden, sondern Apple erst mal einen Identitätsnachweis verlangt: Sie bekommen Zugriff auf die Entwicklerressourcen durch die kostenlose Entwicklermitgliedschaft):

center

Sets the window’s location to the center of the screen.

– (void)center

Die Funktionsbeschreibung klingt also ganz richtig, aber wie liest man jetzt den Rest?

Sehen Sie das Minus am Anfang der Objective C-Zeile? Das gibt uns den Hinweis darauf, dass diese Methode eine Instanzmethode ist – sie wird also auf eine Instanz der Klasse NSWindow angewandt. Ist ja auch ganz logisch; es würde wenig helfen, diese Methode klassenweit anzuwenden – wenn alle Fenster sich in der Mitte stapeln, erhöht das auch nicht gerade die Übersicht.

In der nachfolgenden Klammer sehen Sie den Rückgabeparameter. Der ist void, also nüschte – wir haben hier eine, ja nach Sprechpräferenz, Subroutine oder Methode ohne Rückgabeparameter vor uns, keine Funktion.

Und dann folgt schon der Aufruf. OS X lässt Betriebssystemaufrufe durch einen Namens-Identifikator zu. Die Schreibung ist hier enorm wichtig, auch was Groß- und Kleinbuchstaben angeht. Die Funktion hört also auf den Namen „center“.

 

Setzen wir das Ganze mal um. Sie können ein Modul erstellen, das die Funktion allen Xojo-Windows zur Verfügung stellt, eine Methode in eine Fenster-Instanz einfügen oder eine eigene Window-Subklasse erstellen, sodass Sie die Funktion in allen Fenstern nutzen können, denen Sie diese Klasse zuweisen. Ich finde Subklassen bei allen visuell verfügbaren Steuerelementen am schönsten – so haben Sie auch die Möglichkeit, über Inspector behavior und eine Open-Routine viele Funktionen und Eigenschaften im Inspector verwendbar zu machen. Ich wähle hier aber die zweite Methode, um das Beispiel nicht unnötig aufzublähen.

Wählen Sie also Ihr Fenster im Layout-Editor oder Navigator  an und fügen Sie eine Methode hinzu, die Sie Center nennen. Sie bekommt keine Funktions- und keine Rückgabeparameter; lassen Sie die Felder Parameters und Return Type also frei. Achten Sie darauf, dass der Scope der Methode auf Public gestellt ist, damit Sie sie auch von außen, also z. B. aus dem App-Modul heraus ansprechen können.

Geben Sie nun im Code-Editor folgendes für die Methode ein:

#if TargetMacOS
Declare Sub center Lib "Cocoa.framework" _
Selector "center" (Id as Integer)
center handle
#endif

Was heißt das alles?

Zunächst haben wir eine ungewohnte Bedingung: #If mit einer Raute, abgeschlossen von einem #Endif (ebenso mit Raute).

Das ist eine Pragma-Direktive, eine Anweisung an den Compiler. Lesen Sie sie so:
„Wenn du für MacOS kompilierst, dann nimm das Folgende“. 
Wir wollen ja nicht, dass dieser Funktionsaufruf in Mac OS X hinein in einem Windows-Programm vorkommt. Und ebenso können wir bei Kenntnis über die APIs der anderen Systeme hier später mit #Else TargetWindows etc. auch deren Methoden ergänzen.

Sub = Jetzt folgt eine Methode ohne Rückgabeparameter

center = Der Name, unter dem wir diese Funktion innerhalb dieser Methode deklarieren. Den können Sie ganz frei wählen.

Lib = benutze das folgende Framework. Die NSWindow-Klasse gehört wie gesagt zum Cocoa-Framework, und dessen Namen habe ich hier eingetragen. Wenn Sie mehrere verschiedene Funktionsaufrufe in ein Framework innerhalb eines Projekts realisieren wollen, lohnt es sich, ihn eher als globale String-Konstante anzulegen, um das Projekt nicht unnötig aufzublähen. Hier aber mal im Klartext.

Selector = Benutze die Funktion, die du unter diesem Namen findest (hier ist wie gesagt sogar Groß-/Kleinschreibung zu beachten).

Id = Die Speicheradresse der Instanz, auf die der Methodenaufruf anzuwenden ist (Sie erinnern sich an das Minus am Anfang der Beschreibung?). Das ist eigentlich ein Pointer, ein Zeiger auf einen Speicherbereich. Xojo kennt hier eigentlich die Klasse Ptr. Es würde mich nicht wundern, wenn dies irgendwann auch konsequent so gehandhabt wird. Momentan gibt Xojo allerdings die Pointer als Integer heraus.

Wenn Sie in der Xojo-Sprachreferenz die Window-Klasse nachschlagen, finden Sie diese Eigenschaft unter Handle.

 

In der nächsten Zeile dann nur der Funktionsaufruf mit dem Handle des Fensters als Eingabeparameter.

Das war’s auch schon. Um die Funktion zu testen, fügen Sie zu Ihrem Fenster noch einen Open-Eventhandler hinzu und rufen Sie dort einfach die Methode auf:

center

Lassen Sie das Projekt jetzt laufen. Wenn Sie alles richtig abgetippt haben, wird das neue Fenster nun in der optischen Mitte Ihres Bildschirms geöffnet.
Falls Sie eine Fehlermeldung erhalten: Kontrollieren Sie genau die Schreibung und beachten Sie bitte, dass die Zeile Selector Center … noch zur oberen Zeile Declare Sub … dazugehört. Ich habe Sie hier aus optischen Gründen abgesetzt (auch wenn ich mich ärgere, dass die Einrückungen durch WordPress immer wieder rausgelöscht werden) und ans Ende der ersten Zeile mit einem Abstand von einem Leerzeichen einen Unterstrich gesetzt – das bedeutet in Xojo „die folgende Zeile gehört dazu, wurde mir aber optisch zu lang“).
Insgesamt gar nicht mal so schwer, oder?

 

Wenn es Sie interessiert, wie Sie mit Rückgabeparametern umgehen, eine Klassenmethode aufrufen oder das Inspector Behavior ergänzen können, sodass Sie einen Schieberegler „Center“ für alle Fenster haben können, lassen Sie es mich doch gerne wissen.

Ein herzlicher Dank geht an Jim McKay, der die Mac-API-Aufrufe im Xojo-Forum eingehend erläutert und auf seiner Site zur Referenz aufgelistet hat.

Weitere Informationen finden Sie auch hier. Und das Beispiel als Xojo-Projekt ist hier.

 

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s