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:
/@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:
- eine separate Zeile im Fenster reservieren, in der der Hilfetext
angezeigt wird (z.B. mittels Text() oder besser in einem String- oder
ReadOnly-Button-Gadget, das sich dann auch um das Clipping kümmert)
- die Screenzeile benutzen, um den Hilfetext anzuzeigen
- einen EasyRequester mit dem Hilfetext anzeigen
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>
|