P


©1998-2017 by
Werner Freytag
E-Mail senden



Programmieren unter BeOS

Einführung

Für das BeOS zu Programmieren ist ein wahres Vergnügen. Durch den konsequenten objektorientierten Aufbau sind alle Strukturen schön logisch aufgebaut und man findet sich leicht überall zurecht, hat man erst einmal den Einstieg geschafft.

An dieser Stelle soll kein Basiswissen vermittelt werden. Ein Grundverständnis der C++ Programmierung setze ich voraus. Bitte werft auch einen Blick auf meine Buchempfehlungen

An dieser Stelle möchte ich einen Beispielcode erläutern, und anhand dessen zeigen, wie einfach das Programmieren unter BeOS geht!

Copy Name To Clipboard

Tracker Add-on Hierbei handelt es sich um ein Tracker Add-On, d.h. wenn man im Tracker mit der rechten Maustaste das Context-Menü öffnet, gibt es dort einen Menüpunkt Add-Ons. Hier kann man dann ein Tracker Add-On ausführen.

Copy Name To Clipboard tut genau das, was der Name schon sagt: Es werden die Namen der selektierten Objekte inklusive deren Pfad in die Zwischenablage kopiert und können dann an beliebiger Stelle wieder eingefügt werden.

In diesem Tutorial geht es um zwei spezielle Objekte des BeOS:
  • um Tracker Add-Ons sowie um
  • das Clipboard
Der Quellcode kann hier downgeloadet werden. (6.6kB)

Voraussetzung: Es ist sinnvoll, wenn man sich mit BMessage Objekten einigermaßen auskennt!

Bevor wir loslegen, ein bisschen Vorwissen.

Was ist ein Add-On?

Ein Add-On - oder oft auch Plugin - ist ein Stück Programm, das ein anderes erweitert. Schönstes Beispiel sind in Photoshop (und anderen Grafikprogrammen) die Filter-Plugins: Ein Filter wird in einem bestimmten Verzeichnis abgelegt und erweitert Photoshop um einen zusätzlichen Effekt.

Unter BeOS ist dies nicht viel anders. Allerdings gibt es je nach Add-On unterschiedliche Dinge zu unterscheiden. Es gibt z.B. Tracker Add-Ons, Bildschirmschoner, Deskbar Replikanten oder Add-Ons für ganz "gewöhnliche" Programme.

All diese Add-Ons haben eines gemeinsam: Sie sind (in aller Regel) nicht direkt ausführbar, sondern stattdessen an ein Programm gebunden. Um es genau zu sagen: Ein Add-On wird ein Bestandteil des Programmcodes dieses Programmes.

Dies hat verschiedene Folgen:

  • das Programm und das Add-On können miteinander kommunizieren und Daten untereinander austauschen
  • ein Add-On, das abstürzt, reisst das zugehörige Programm mit sich (und umgekehrt)
  • ein Add-On enthält keine main() Routine
Aus dem letzten Punkt haben wir folgende Konsequenzen zu ziehen:
  1. In den Projekteinstellungen des BeIDE-Projekts muss als Typ Add-On/Shared library gewählt werden
  2. Das Add-On muss irgendwie aufgerufen werden...
Letzterer Punkt sieht im Allgemeinen so aus: Der Programmierer, der die Add-On-Möglichkeit bietet, veröffentlicht eine Schnittstelle, d.h. einen Funktionsaufruf, durch den das Add-On aufgerufen wird.

Konkretes Beispiel: Tracker Add-On

Im Falle des Tracker Add-Ons heisst diese Funktion
void process_refs(entry_ref dir_ref, BMessage *msg, void *)
und wird in "be/add-ons/tracker/TrackerAddOn.h" deklariert.

Die übergebenen Paramter sind:

  • entry_ref dir_ref: Diese entry_ref Struktur sagt uns, in welchem Verzeichnis wir uns befinden
  • BMessage *msg: In dieser Message sind die selektierten Dateien abgelegt, ebenfalls als entry_ref.
  • void *: Dieser Parameter wird momentan nicht verwendet
Was wir also in unserem Add-On machen müssen, ist ganz einfach: Wir müssen eine Funktion genau wie oben beschrieben haben. Diese wird dann vom Tracker aufgerufen und es werden die obengenannten Variablen gefüllt. Damit können wir dann machen, was wir möchten...

Und damit sind wir auch schon beim nächsten Punkt angelangt:

Das Clipboard

So ganz richtig ist diese Überschrift eigentlich gar nicht, da man nicht nur ein Clipboard hat, sondern beliebig viele haben kann. In der Regel wird man jedoch das System-Clipboard verwenden wollen, um die Informationen auch mit anderen Programmen austauschen zu können.

Die grundlegende Funktionsweise des BeOS-Clipboards ist schnell erklärt: Das Clipboard enthält eine BMessage, in der sich die zwischengespeicherte Information befindet. Die Information wird durch MIME-Typen gekennzeichnet abgelegt, so dass ein jedes Programm gleich weiss, ob es die abgelegte Information verwenden kann.

Die Information kann auch in mehreren Typen gleichzeitig abgespeichert sein. Dadurch kann man mehrere Schnittstellen bieten.

Fangen wir endlich an!

Genug der grauen Theorie, stürzen wir uns gleich in die Praxis. An wichtigen Stellen unterbreche ich durch Kommentare...

#include <Clipboard.h>
#include <Entry.h>
#include <Path.h>
#include <InterfaceDefs.h>
#include <String.h>
#include <TrackerAddon.h>

Soweit nichts wirklich Aufregendes. Nun folgt die oben genannte Funktion:

void process_refs(entry_ref dir_ref, BMessage *msg, void *) {

    BString     ClipString;
    BPath       path;

    int         refs;
    entry_ref   file_ref;

    bool        filenameonly = (modifiers() & B_SHIFT_KEY);

...ein paar Variablendeklarationen. Letztere Variable wird auf true gesetzt, wenn eine Shifttaste gedrückt wurde. Im Programm wird dann statt des Dateinamens samt Pfad nur der Name ins Clipboard kopiert.

    for( refs=0; msg->FindRef("refs", refs, &file_ref)==B_NO_ERROR; refs++) { 
        BEntry(&file_ref).GetPath(&path);
		
        if (refs>0) ClipString.Append(" ");

        BString    FileString    = filenameonly ? path.Leaf() : path.Path();
        bool       quote = (FileString.FindFirst(" ") != B_ERROR );

        if (quote) ClipString.Append("\"").Append(FileString).Append("\"");
        else ClipString.Append(FileString);
    }

Wir gehen der Reihe nach unsere BMessage durch und fischen alle entry_refs heraus, d.h. die Verweise auf die Dateien. Mit dem gefundenen entry_ref füllen wir ein Objekt der Klasse BPath namens path.

Die Variable refs (deren Name vielleicht etwas unglücklich gewählt ist) wird bei jedem Schleifendurchlauf um 1 erhöht. Wenn wir mehr als eine Datei gewählt haben, werden die Namen durch ein Leerzeichen zusammengefügt.

Dann extrahieren wir den Dateinamen - je nach Status der Shifttaste inkl. oder exkl. Pfad. Wenn der Name Leerzeichen enthält, müssen wir diesen mit Anführungsstrichen umschließen.

Zuletzt wird der Name an den ClipString angehängt. Nachdem diese Schleife abgearbeitet ist, haben wir in ClipString den String, wie wir ihn in's Clipboard kopieren wollen.

    if (refs != 0) {
        BClipboard    Clipboard("system");
        BMessage      *clip = NULL;
        
        if (Clipboard.Lock()) {

            Clipboard.Clear();
            if ( (clip = Clipboard.Data()) ) {

Wir verwenden das System-Clipboard. Bevor wir darauf zugreiffen dürfen, müssen wir es sperren. Anschließend leeren wir es und besorgen uns die BMessage, die sich darin befindet.

                clip->AddData("text/plain", B_MIME_TYPE, ClipString.String(),
                    ClipString.Length()); 
                Clipboard.Commit();
            }
            Clipboard.Unlock();
        }
    }
}

Nun wird einfach die BMessage mit unseren Daten gefüllt.

Bevor nicht Commit() aufgerufen wurde, können wir das Clipboard einfach wieder freigeben, ohne dass unsere Daten hinzugefügt wurden. Nach dem Entsperren des Clipboards, könnnen andere Tasks darauf zugreifen und unsere abgelegten Daten verwenden. :-)