<< Inhalt >> Workshops Inhalt

4. Hintergrund: Das Handbuch - diesmal online (von Michael Christoph)

Wurde im letzten Teil besonderes Augenmerk auf das gedruckte Handbuch und dessen Anforderungen gelegt, soll diesmal eine weitere Art der Anleitung genauer unter die Lupe genommen werden: die Online-Hilfe. Dieser Teil zeigt zwar im besonderen die Programmierumsetzung, liefert aber auch für jeden Interessierten etwas.

Unter der Online-Hilfe versteht man die Hilfe, die direkt vom Programm aus aufgerufen werden kann. Sie sollte ebenso Standard sein, wie ein normales Handbuch (egal ob gedruckt oder digital) und auch die im letzten Teil angesprochenen Punkte erfüllen.

Die Hilfe sollte idealerweise sofort zur Textstelle verzweigen, an der die Informationen zum aktuellen Kontext zu finden sind. Nur dann ist diese Art der Hilfe überhaupt sinnvoll. Sowohl AmigaGuide als auch HTML unterstützen das gezielte Anzeigen einer Passage und sollen daher nachfolgend genauer betrachtet werden. Mittels des HTML-Datatypes ist außerdem kein extra Browser notwendig (auch wenn seit AmigaOS 3.5 AWeb bereits im Betriebssystem vorhanden ist). Solange HTML nur nach seiner ursprünglichen Konzeption eingesetzt wird, ist dieser Datatype völlig ausreichend.

Man kann die normale Anleitung so gestalten, dass sie direkt im Programm auch als Hilfe eingebunden werden kann, oder man erstellt eine zusätzliche Datei. Wichtig dabei ist nur, dass sofort der Text zum aktuellen Kontext angezeigt wird. Diese Hilfe kann man beispielsweise grob auf die einzelnen Fenster gliedern oder sehr fein auf die einzelnen Gadgets.

Wenden wir uns daher dem Aufbau der Online-Hilfe zu.

Im AmigaGuide-Format sollte jedes Kapitel und auch die Unterkapitel in einem eigenen Node vorliegen. Und so wie das Inhaltsverzeichnis auf jeden Node verweist, kann auch von jeder anderen Stelle im Text darauf verwiesen werden. Der Node-Verweis kann noch mittels einer optionalen Zeilennummer genauer innerhalb des Kapitels platziert werden.


AmigaGuide - Vorteil : Amiga-eigenes Format, Datatype-Unterstützung 
 Nachteil: keine direkte Bildereinbindung, 
  geringe Layoutmöglichkeiten 
   

Bei HTML gliedert man allgemein nur die oberen Kapitel in einzelne Dateien. In diesem Fall ist es hilfreich, wenn zu Beginn der HTML-Datei die einzelnen Unterkapitel aufgezählt werden, so dass durch einen einfachen Klick dorthin gesprungen werden kann. Natürlich ist das Inhaltsverzeichnis mit allen Kapiteln zu verwenden, wobei die Unterkapitel direkt an die entsprechenden Stellen in der HTML-Datei zeigen sollten.


HTML - Vorteil : direkte Bilderunterstützung, Layoutmöglichkeiten 
 Nachteil: extra Browser oder HTML-Datatype notwendig 
  

Besonders wichtig ist auch eine Indexseite, auf der die wichtigsten Begriffe rund um das Programm aufgeführt sind und die direkt auf die entsprechenden Zeilen in den Beschreibungstexten verweisen.

Da es allerdings auch Konvertierungsprogramme gibt, die AmigaGuide- Anleitungen in eine HTML-Datei umwandeln können, spricht nichts dagegen, beide Arten von Online-Hilfe mitzuliefern. Dadurch kann der Leser selbst entscheiden, welche Art der Hilfe er bevorzugt.


Ein Grundgerüst für eine AmigaGuide-Datei hat den folgenden Aufbau (bitte einen Textanzeiger oder -editor zur Ansicht verwenden):

@DATABASE "Anleitung.guide"
@INDEX "INDEX"

@NODE "MAIN" "Inhaltsverzeichnis"
@{"Kapitel 1"     LINK "Kapitel1"}
@{"  Kapitel 1.1" LINK "Kapitel1_1"}
@{"  Kapitel 1.2" LINK "Kapitel1_2"}
@ENDNODE

@NODE "Kapitel1" "Kapitel 1"
Einleitungstext ...
@ENDNODE

@NODE "Kapitel1_1" "Kapitel 1.1"
Text ...
@ENDNODE

@NODE "Kapitel1_2" "Kapitel 1.2"
Text ...
@ENDNODE

@NODE "INDEX" "Index"
@{"Schlüsselwort" LINK "Verweisziel"}
@ENDNODE

Ein Grundgerüst für eine HTML-Datei hat den folgenden Aufbau:

<HTML>
<HEAD>
<TITLE>Anleitung zu ...</TITLE>
</HEAD>
<BODY>
<P>
<H1>Kapitel 1</H1>
<UL>
  <LI><A HREF="#kapitel1_1">Kapitel 1.1</A></LI>
  <LI><A HREF="#kapitel1_2">Kapitel 1.2</A></LI>
</UL>
Einleitungstext ...
</P>

<P>
<A NAME="kapitel1_1"><H1>Kapitel 1.1</H1></A>
Text ...
</P>

<P>
<A NAME="kapitel1_2"><H1>Kapitel 1.2</H1></A>
Text ...
</P>
</BODY>
</HTML>

Die einfachste Art, die Anleitung anzuzeigen, ist der direkte Aufruf von MultiView. Das nachfolgende Beispiel zeigt die vollständige Funktion, die sehr flexibel ist. So wird neben MultiView auch die ältere Ausgabe AmigaGuide gesucht, und es wird auch überprüft, ob die Anleitung im aktuellen oder im System-Hilfe-Verzeichnis vorhanden ist. Im Fehlerfall wird ein entsprechender Text ausgegeben (z.B. mittels EasyRequest() in einer normalen GUI-Anwendung). Ansonsten wird der gefundene Anzeiger mittels Execute() (oder alternativ mittels SystemTagList()) gestartet. Das Programm hat keine Kontrolle über die Anzeige, läuft aber parallel zum Anzeigefenster weiter, da es mittels "run" als Hintergrundprozess gestartet wird. Allerdings fehlt auch die Möglichkeit, sofort eine bestimmte Sektion der Datei anzuzeigen. Daher eignet sich diese Art der Hilfe eher zum Anzeigen des normalen Handbuches.

BOOL ZeigeAnleitung(const STRPTR guide)
{
  BOOL res = FALSE;

  UBYTE kommand[80] = "";
  UBYTE guidefile[50];
  BPTR lock;

  /* prüfen, ob die Anleitung vorhanden ist */
  strcpy(guidefile,guide);
  if((lock = Lock(guidefile,SHARED_LOCK)))
  {
    UnLock(lock);
  }
  else
  {
    sprintf(guidefile,"LOCALE:Help/%s",guide);
    if((lock = Lock(guidefile,SHARED_LOCK)))
    {
      UnLock(lock);
    }
    else guidefile[0]='\0';
  }

  if(guidefile[0])
  {
    /* prüfen, ob ein Anzeigeprogramm vorhanden ist */
    if((lock = Lock("SYS:Utilities/MultiView",SHARED_LOCK)))
    {
      UnLock(lock);
      sprintf(kommand,"RUN >NIL: SYS:Utilities/MultiView %s",guidefile);
    }
    else if((lock = Lock("SYS:Utilities/AmigaGuide",SHARED_LOCK)))
    {
      UnLock(lock);
      sprintf(kommand,"RUN >NIL: SYS:Utilities/AmigaGuide %s",guidefile);
    }

    if(kommand[0])
    {
      Execute(kommand,NULL,NULL);
      res = TRUE;
    }
    else printf("Fehler\n"
                "Guide-Anzeiger sind nicht vorhanden;\n"
                "SYS:Utilities/MultiView oder\nSYS:Utilities/AmigaGuide.\n");
  }
  else printf("Fehler\n"
              "Anleitung '%s'\n"
              "ist nicht (im aktuellen Verzeichnis) vorhanden.\n",guide);

  return( res );
}

Das nächste Beispiel zeigt die Benutzung der amigaguide.library, wie sie seit AmigaOS 2.x existiert. Dabei wird nur die einfache, blockierende Anwendung vorgestellt. Das heißt, die Hilfe muss erst geschlossen werden, damit das Programm fortgesetzt wird. Man hat allerdings genaue Kontrolle über die Anzeige. Über den nichtblockierenden Aufruf OpenAmigaGuideAsync() kann das Programm ganz normal parallel zur Hilfe weiterlaufen. Es besteht dann jederzeit die Möglichkeit, die Hilfe wieder nach vorn zu holen oder eine andere Stelle anzuzeigen. Über den Eintrag nag_Node der NewAmigaGuide- Struktur kann direkt die anzuzeigende Seite (Default Main) vorgegeben werden.

struct Library *AmigaGuideBase;

BOOL ZeigeAnleitung(const STRPTR guide)
{
  BOOL res = FALSE;
  struct NewAmigaGuide nag = { NULL };
  AMIGAGUIDECONTEXT handle;
  BPTR lock;

  if((AmigaGuideBase = OpenLibrary("amigaguide.library",33)))
  {
    if((lock = Lock((UBYTE*)guide,SHARED_LOCK)))
    {
      UnLock(lock);

      if((handle = OpenAmigaGuide(&nag,NULL)))
      {
        /* synchrone Verarbeitung; */
        /* kehrt erst nach Beenden von AmigaGuide zurück */

        CloseAmigaGuide(handle);
        res = TRUE;
      }
      else printf("Anzeige durch AmigaGuide fehlgeschlagen.\n");
    }
    else printf("Guide-Datei '%s' fehlt.\n",guide);

    CloseLibrary(AmigaGuideBase);
  }
  else printf("amigaguide.library V33 fehlt.\n");

  return( res );
}

Mittels NewDTObject() kann jeder Amiga-Programmierer die Hilfe direkt per Datatype in sein Programm einbinden. Dabei ist man vom Format her am flexibelsten, da lediglich ein passender Datatype vorhanden sein muss. Allerdings hat man auch hierbei wieder keine Möglichkeit, direkt eine Stelle in der Anleitung anzuzeigen.

Das folgende Gerüst zeigt, wie der Datentyp ermittelt werden kann und die Datei eingelesen wird. Die Weiterverarbeitung als Gadget wird allerdings nicht mehr ausgeführt. Diese Art ist wieder nichtblockierend.

struct Library *DataTypesBase;

BOOL ZeigeAnleitung(const STRPTR guide)
{
  BOOL res = FALSE;
  struct DataType       *dtn;
  struct DataTypeHeader *dth;
  Object                *obj;
  BPTR                   lock;

  if((DataTypesBase = OpenLibrary("datatypes.library",39)))
  {

    /* existiert die angegebene Datei überhaupt */
    if((lock = Lock((UBYTE*)guide,SHARED_LOCK)))
    {
      /* Dateityp ermitteln */
      if((dtn = ObtainDataTypeA(DTST_FILE,(APTR)lock,NULL)))
      {
        dth = dtn->dtn_Header;

        if(dth->dth_GroupID == GID_DOCUMENT ||  /* = AmigaGuide */
           dth->dth_GroupID == GID_TEXT)        /* = HTML */
        {
          res = TRUE;
        }
        else printf("Falscher Dateityp der Anleitung.\n");

        ReleaseDataType(dtn);
      }


      if(res)
      {
        /* Datei einlesen */
        if((obj = NewDTObject((APTR) guide,
                               DTA_SourceType, DTST_FILE,
                               /* DTA_GroupID, GID_xxx, */
                               /* wenn ein bestimmter Typ gefordert wird */
                               TAG_DONE)))
        {
          /* ... Datatype-Objekt mittels Gadget zur Anzeige verwenden */

          DisposeDTObject(obj);
        }
        else printf("Kein passender Datatype zur Anzeige vorhanden.\n");
      }

      UnLock(lock);
    }
    else printf("Anleitungsdatei '%s' fehlt.\n",guide);

    CloseLibrary(DataTypesBase);
  }
  else printf("datatype.library V39 fehlt.\n");

  return( res );
}

Eine ganz andere Richtung soll noch kurz angesprochen werden.

Seit OS 3.0 (V39) unterstützen die Boopsi-Gadgets die GM_HELPTEST-Methode, um dem Programm mitzuteilen, zu welchem Gadget der Benutzer eine Hilfe wünscht. Window-bezogen sind die Tags WA_HelpGroup und WA_HelpGroupWindow dafür zuständig, dass eine Nachricht der Art IDCMP_GADGETHELP versandt wird. Wie allerdings der fromme Wunsch des Benutzers nach einer Hilfe vom Programm letztendlich umgesetzt wird, dafür hatte Commodore keine Lösung mehr parat. Hier drei sehr einfache Möglichkeiten:


In allen drei Fällen kann in Verbindung mit einem Timer die Anzeige 
auch zeitlich beschränkt werden (BuildEasyRequest() + FreeSysRequest() 
im dritten Fall). 
 

Diese Art eignet sich natürlich besonders gut, um eine Kurzhilfe zum aktuellen Gadget oder Fenster anzuzeigen. Allerdings ist es wirklich nur eine Kurzhilfe, da platzbedingt meist sehr wenig Raum zur Verfügung steht. Des weiteren muss diese Hilfe direkt im Programm eingebaut werden oder besser in einer externen Catalog-Datei untergebracht werden.

Alle Varianten haben ihre Vor- und Nachteile. So setzt die Datatypes- Methode voraus, dass das Programm unter OS 3.x läuft, was allerdings heute wohl der Standard sein dürfte. Die Execute-Methode ist zwar sehr einfach und robust, erlaubt allerdings keine Kontrolle über die Anzeige und eignet sich eher zum Anzeigen der normalen Anleitung.

Letztendlich muss der Programmierer anhand der Zielgruppe und OS-Version abschätzen, welche Lösung die für seinen Fall passendste ist.

Mit diesen Worten soll die kleine dreiteilige Geschichte zum Handbuch abgeschlossen werden.

Michael Christoph <michael@meicky-soft.de>

<< >>