MagnaMedia · AMIGA-Magazin · Intuition-Programmierung unter pOS, Folge 1

Aktuelles Heft 7/97

Intuitive Benutzeroberfl�chen

Zwar kann die pOS-Oberfl�che �u�erlich das gleiche Look-and-Feel wie vergleichbare Amiga-Software vermitteln, allerdings m�ssen diese Features v�llig anders programmiert werden. Heute lernen Sie das pIntui-Konzept kennen und entwerfen mit uns ein Beispielsprogramm. Wer das mit Kickstart 2.0 eingef�hrte BOOPSI-Konzept kennt, wird sich auch in der objektorientierten Gadgetprogrammierung unter pOS schnell zurechtfinden.

# von Michael Christoph

Mit Kickstart 2.0 wurde beim Amiga die m�chtige DOS-Funktion ReadArgs() eingef�hrt. Dadurch sollten alle Programme eine Standardschnittstelle f�r den Programmstart erhalten. Ein vergleichbares Konzept kann pOS ebenfalls bieten -- aber in erheblich erweiterter Funktionalit�t. Die Funktion �pOS_ReadDosArgs()� bekommt �ber Tags neben dem Template weitere Angaben f�r Hilfstexte (ARGTAG_HelpText) zu den Parametern und den Versionsstring (ARGTAG_PrgVerText). �ber ARGTAG_VarName k�nnen Sie auch einen ENV-Variablennamen angeben, aus dem die Vorgaben ermittelt werden. Weitere Tags finden Sie in der Include-Datei �pDOS/ArgTags.h�. Es lassen sich aber nicht nur Argumente �bergeben, sondern �ber �pOS_WriteDosArgs()� die Argumente auch in eine Datei schreiben. Alle pOS-Preferences-Einsteller verwenden diese M�glichkeit. Die Argumente werden im lesbaren Format als ASCII-Text-Datei gespeichert (z.B. �ENV:sys/serial.prefs�). Dazu enth�lt die Datei eine Marke (Serial z.B. �#SerialDefPrefs�), nach der die Argumente inklusive Keywort stehen. Abgeschlossen wird der Block mit dem Zeichen �#�. F�r unser Beispiel w�rde der ReadArgs-Befehl so aussehen:


struct pOS_DosArgs *rda=pOS_ReadDosArgs(gb_PrgTemplate,args,sizeof(args)/sizeof(ULONG),
	 ARGTAG_PrgHeaderText, gb_PrgHeader,    /* kurze Programm-Beschreibung */
	 ARGTAG_HelpText,      gb_PrgHelpText,  /* Hilfe-Text zu den Parametern */
	 ARGTAG_PrgVerText,    gb_PrgVersion,   /* Versions-String */
       TAG_END);

Die eingesetzen Variablen haben folgendes Format bzw. Inhalt:


const CHAR *gb_PrgHelpText = "$H(PUBSCREEN/K)Name of the pubscreen we visite";
const CHAR *gb_PrgHeader   = PROGNAME" - Example with gadgets, menus, message-handling";
const CHAR *gb_PrgVersion  = "$VER: "PROGNAME" "VERSIONR" ("PROGDATE") ("COPYRIGT")";
const CHAR *gb_PrgTemplate = "PUBSCREEN/K";
enum { ARG_pubscreen, ARG_MAX };
ULONG args[ARG_MAX]={ 0 };

F�r die Hilfstexte gilt diese Syntax:



$H(keyword)hilfetext

F�r jeden Parameter ist der Zusatz �$H� zu definieren. Ein Zeilenvorschub am Ende ist nicht notwendig, da pOS automatisch nach jeder Parameterhilfe die Zeile abschlie�t. Es ist nat�rlich m�glich, mehrzeilige Texte mit �\n� zu trennen.

Intuition mit dem neuen Betriebssystem pOS: Dieses Beispielprogramm finden Sie auf unserer n�chsten Amiga-CD

Den Hilfstext bekommen Sie, wenn Sie das Programm aus der Shellumgebung mit dem Argument �??� (z.B. �IntuiDemo_1 ??�) starten. Sind mehrere Argumente vorhanden, k�nnen gezielte Informationen �ber �?? keyword� (z.B. �IntuiDemo_1 ?? PUBSCREEN�) abgefragt werden. Das Template k�nnen Sie ebenfalls erfragen, dann gibt man allerdings nur ein Fragezeichen an (z.B. �IntuiDemo_1 ?�).

Der Parameter �numresult� von p.OS_ReadDosArgs() bedeutet: per �sizeof(args)/sizeof(ULONG)� �berlassen wir es dem Compiler, die korrekte Anzahl der ULONG-Platzhalter zu berechnen. In der pOS-Entwickler-Version wird Fehlermeldung ausgegeben, falls diese Angabe nicht mit der Anzahl der Template-Keyw�rter �bereinstimmt.

Wenn p.OS_ReadDosArgs() fehlschl�gt (Returnwert NULL-Zeiger), m�ssen Sie keine Fehlerausgabe definieren, da dies bereits vom Betriebssystem erledigt wurde. Dadurch wird kein allgemeiner Fehlertext ausgegeben, sondern genau gezeigt, welcher Parameter nicht korrekt war, bzw. welche Angaben evtl. fehlen.

Im Normalfall erhalten Sie einen Zeiger, den Sie am Programmende mit p.OS_DeleteDosArgs() wieder freigegeben m�ssen.

Achtung: Anschlie�end d�rfen Sie auf keine Variablen mehr zur�ckgreifen, da z.B. Multi-String-Arrays nicht mehr existieren. W�hrend das Programm aber l�uft ist es erlaubt, das eigene ULONG-Array beliebig zu ver�ndern.

pOS bietet die bekannten Templateargumente:


Optional:

Es ist auch m�glich, nur das Keywort vorzugeben (z.B. �prompt PROMPT�).

Hierbei wird der erste String PROMPT (CHAR*) zugewiesen. Bei Bedarf sollte nur das erste Keywort ohne weitere Angaben definiert sein, da es sonst zu �unsicheren� Zuweisungen kommen kann. Besser ist, immer die Angabe mit Keywort (/K), wobei Abk�rzungen die Eingabe erleichtern (z.B. �list MA=MultiAssign/S�). Sie k�nnen dann wahlweise die Abk�rzung (MA) oder das ganze Keywort (MultiAssign) angeben.

Unter pOS lassen sich Keyw�rter beliebig gro� und klein schreiben werden. Auch die Trennung mit zus�tzlichen Leerzeichen ist m�glich (z.B. �ARG1/S, Arg2/S, arg3/S�).

Eine genaue Beschreibung der Programmauswertung finden Sie in den Autodocs zu pDOS oder im Programmbeispiel �ReadArgsTest.c� aus dem Entwicklerpaket.

Nun wollen wir die ben�tigten Libraries per pOS_OpenLibrary() �ffnen. Am Programmende m�ssen wieder alle offenen Bibliotheken mit pOS_CloseLibrary() geschlossen werden. Der neue StormC-Compiler von Haage&Partner l�st das komfortabel, da nur der Basiszeiger angegeben wird und das �ffnen/Schlie�en automatisch geschieht. Die Versionsnummer richtet sich momentan nach der aktuellen Revisionsnummer von p.OS (25).

pOS kann auch Devices als Libraries �ffnen. Wer bereits einmal das timer.device verwendet hat, um die aktuelle Systemzeit zu ermitteln, wei� wieviel Aufwand an (unbenutzen) Device-IOs notwendig ist. Diese M�glichkeit bieten aber nicht alle Devices und es lassen sich nur die Library- Funktionen verwenden. Intuition, ebenso wie die Workbench, sind intern als Device aufgebaut (siehe Basiszeiger pOS_IntuiDevice). Als Programmierer k�nnen Sie aber einfach �ber pOS_OpenLibrary() das Device �ffnen und benutzen. F�r unser Programmbeispiel brauchen wir die pIntui-, pGraphics- und pUtility.library.

Beispielprogramm compilieren

Das Programm ist mit jedem beliebigen C/C++-Compiler �bersetzbar.

Spezielle Compileroptionen werden nicht gebraucht. Beachten Sie jedoch, da� statt des normalen Amiga-Startupcode, der spezielle p.OS-Startupcode zu verwenden ist. Dazu mu� die Datei �p:pLib/StartCode.o� oder �p:pLib/MainCode.o� (damit argc/argv- Argumente gesetzt werden) als erste Datei gelinkt werden.

Verwenden Sie einen C++-Compiler, m�ssen Sie die xxxCPP-Dateien benutzen, damit auch Konstruktoren/Destruktoren aufgerufen werden. Zus�tzlich ben�tigt man die Linklibraries �pOSStub.lib� und �pOS.lib�.

Verwenden Sie ANSI-File-Funktionen, m�ssen Sie zus�tzlich �StdIO.lib� einsetzen.

�berpr�fen Sie unbedingt, da� ja blo� keine Amiga-Funktionen eingebunden werden: Viele ANSI-Funktionen (z.B. aus �time.h�) st�tzen sich n�mlich unsichtbar auf Amiga-Funktionen und f�hren beim Einsatz unter pOS unweigerlich zu Programmfehlern. Der neue StormC-Compiler bietet neben speziellen pOS-Amiga-Cross-Libraries auch ANSI-Libraries an, die sich problemlos mit pOS einsetzen lassen.

Aus R�cksicht auf �ltere Compiler wurde bei den Variablen auf �enums� verzichtet, da diese Software nicht all e als Datentyp verarbeiten kann. �bersetzen mit:

MaxonC:

mcpp:mcppc3 -gs -o IntuiDemo_1 p:pLib/StartCode.o
  IntuiDemo_1.c -l pOSStub -l pOS -i p: -j plib:

StormC:

stormc:stormsys/stormc IntuiDemo_1.c -i p:
stormc:stormsys/stormlink p:pLib/StartCode.o IntuiDemo_1.c
  LIB pOSStub LIB pOS LIBPATH plib: LIB stormc:lib/strom.lib
  TO IntuiDemo_1

SAS-C:

sc NOLINK DATA=FAR CODE=FAR NOSTACKCHECK INCLUDEDIR=p:
  OBJECTNAME IntuiDemo_1.o IntuiDemo_1.c
slink p:pLib/StartCode.o IntuiDemo_1.o to
  IntuiDemo_1 LIB plib:pOSStub.lib plib:pOS.lib
  SMALLDATA SMALLCODE

wobei �p:� ein Assign aufs pOS-Include-Verzeichnis und �plib:� ein Assign aufs pOSLib-Verzeichnis ist. Sie k�nnen die Programme auch mit den jeweiligen Oberfl�chen �bersetzen, wobei ebenfalls die Include/Libraries-Pfade angepa�t werden m�ssen. Der Linkmodus ist auf �Linken ohne Startupcode� einzustellen und das Datenmodell mu� durchgehend auf �gro߫ gesetzt werden.

Weitere wichtige Libraries:

Alle ge�ffneten Libraries und Devices lassen sich �ber das Shell-Kommando �control� erfragen, wobei �LIBLIST� die Libraries und �DEVLIST� die Devices zeigt.

Nach dem optionalen pOS_LockPubScreen() erfolgt dann bereits das �ffnen des Fensters. pOS_LockPubScreen() erwartet als Parameter den Namen eines Bildschirms oder einen NULL-Zeiger f�r den Vorgabe-Bildschirm. In der aktuellen pOS-Version (R25) ist nur ein Screen (�Workbench�) vorhanden. Das sollte Sie aber nicht davon abhalten, Ihre Programme zukunfsbereit per Keywort �PUBSCREEN/K� auszustatten. Dies geschieht �ber die Anweisungen:

struct pOS_Screen *scr=pOS_LockPubScreen((CHAR*)args[ARG_pubscreen]);

So l��t sich ohne Unterscheidung jeder Bildschirm ermitteln. Sie k�nnen zwar auch �ber SCRTAG_PubName beim �ffnen des Fensters den Namen angeben, sobald Sie aber Gadgets oder Men�s vor dem �ffnen des Fenster erzeugen wollen, brauchen Sie die DrawInfo-Daten aus dem Screen. Au�erdem kann man so auch zwischen fehlendem Screen und fehlerbehafteten Fenster�ffnen unterscheiden. Mit pOS_OpenWindow() �ffnen Sie das Fenster durch Angabe einer Tagliste. Die einzelnen Tags stehen in der Include-Datei �pScreen/ScrTags.h�. Dabei sind die meisten Tags f�r pOS_OpenScreen() und pOS_OpenWindow() g�ltig.

EPOS -- Entwicklerprogramm f�r p.OS

Sollten Sie nun auch durch diesen Kurs Interesse an der Entwicklung von pOS-Software bekommen haben, bietet proDAD den Entwicklerservice �EpOS� an, der allerdings ab bestimmten kommerziellen Entwicklerkategorien Kosten mit sich bringt. PD/Shareware-Entwickler zahlen dagegen keine Beitr�ge.

Eine spezielle, aber nicht mehr ganz aktuelle Entwickler-Version (R24) ohne Workbench, daf�r aber mit Entwicklertools und -dokumentationen gibt es auf der �Geek Gadgets Vol. 2� von Fred Fish. Sogar die Linux-Emulation und der GCC sind bereits integriert.

Neuere Entwicklerversionen, Updates und Dokumentationen erhalten eingetragene Entwickler ab sofort per FTP direkt bei proDAD.

Ab Mitte Juli 1997 ist ein PreRelease (Vorabversion) inkl. Workbench, diversen Demos und komfortablen Features f�r 49 Mark erh�ltlich -- auch f�r Anwender. Schon mit dieser Version l��t sich viel �ber das neue OS in Erfahrung bringen. Diese Version ist auf upgradef�hig auf die Final Release, damit entsteht finanziell kein zus�tzlicher Aufwand.

Beide Versionen sind erh�ltlich bei:

Stefan Ossowskis Schatztruhe,
Veronikastr. 33,
45131 Essen,
Tel. (02 01) 78 87 78,
Fax: (02 01)79 84 47,
WWW: http://www.schatztruhe.de
E-Mail: stefano@schatztruhe.de

Wenn Sie den Tag SCRTAG_UnderMouse auf TRUE setzen, �ffnet sich das Fenster automatisch unterhalb des Mauszeigers. Vor allem bei Benutzung �bergro�er Bildschirme ist es l�stig, wenn das Fenster in sch�ner Regelm��igkeit links oben aufgeht. SCRTAG_AutoAdjust sollte ebenfalls nicht fehlen. Damit erlauben Sie dem Betriebssystem, das Fenster notfalls zu verkleinern und/oder zu verschieben, damit es sich �ffnen l��t.
Mit dem Tag SCRTAG_IGfxType k�nnen Sie den Typ des Fensters definieren: derzeit existieren die Typen Standard, Application und Requester (zu finden in �p:pIntui/ITypes.h�). F�r Standard-, Application- und Requester-Fenster k�nnen Sie ein Hintergrundmuster definieren (Prefs-Modul: Background), das dann automatisch verwendet wird. Ohne Tag bekommt das Fenster keinen Hintergrund. Der Standard-Typ kann f�r Unterfenster einer Applikation oder f�r kleinere Tool-Programme verwendet werden. Beachten Sie, da� Sie bei aktivem Hintergrund nicht �ber pOS_DrawRectFill() mit der Hintergrundfarbe zeichnen d�rfen, sondern per pOS_EraseRect() den gew�nschten Teil "l�schen" m�ssen.

Wichtig ist auch, da� Sie momentan selbst f�r das Neuzeichnen der Fensterinhalte (au�er Gadgets) verantwortlich sind. �ber den Tag WINFLGF_SimpleRefresh (zu setzen bei SCRTAG_Flags) signalisiert man die Bereitschaft dazu.
Die zweite M�glichkeit von Fenstertypen sind die SuperBitmap-Fenster (WINFLGF_SuperBitmap). Sie erzeugen dann wiederum eine Bitmap (pOS_AllocGfxMap()/pOS_FreeGfxMap()), bzw. laden per Datatypes eine Grafik in die Bitmap (pOS_CreateFHDTObject()/pOS_DeleteDTObject()). In diesem Fall �bernimmt das OS die Restaurierung des Inhalts. SuperBitmap-Fenster bieten dar�berhinaus die M�glichkeit, nur einen Teil daraus sichtbar zu machen. Den Rest k�nnten Sie scrollen lassen, z.B. �ber Schieber im Fensterrahmen.
Unter p.OS ist es sogar m�glich, Gadgets mit der SuperBitmap zu verschieben. Die korrekte Auswertung der (verschobenen) Gadgets �bernimmt weiterhin das OS f�r Sie.

Die Philosophie von pOS sieht vor, da� ein Fenster nur noch Gadgets enth�lt, die sich jederzeit selbst�ndig zeichnen und clippen. Dadurch braucht sich das Programm nicht mehr um Fensterrestaurierungen zu k�mmern, sondern kann (zeitgleich) andere Aufgaben erledigen. Auf diese M�glichkeiten kommen wir aber erst in der n�chsten Folge zur�ck.
Anmerkung zum Thema �Slider im Fensterrahmen�: Unter pOS ist das ebenfalls sehr einfach zu realisieren. �ber pOS_GetWindowBorder() k�nnen Sie die Gr��e f�r den (k�nftigen) Fensterrahmen ermitteln. Mit diesen Werten erzeugen Sie dann den Schieber (oder andere Border-Gadgets). Beachten Sie, da� diese Funktion ebenfalls verwendet werden mu�, wenn Sie die H�he der Titelzeile ben�tigen. Diese darf auf keinen Fall, wie beim Amiga vorgeschrieben, aus der Fonth�he ermittelt werden! Wenn Sie die H�he nicht selbst ben�tigen, k�nnen Sie beim Fenster�ffnen �ber die Tags SCRTAG_InnerWidth/SCRTAG_InnerHeight die Gr��e des Fensters ohne Au�enr�nder vorgeben.

Kurs�bersicht

Dieser dreiteilige Programmierkurs soll die Konzepte zur Entwicklung von GUIs (Graphical User Interfaces = Grafische Benutzeroberfl�chen) unter pOS vorstellen. Begleitend wird stufenweise ein einfaches Programm entwickelt, um auch die praktische Seite nicht zu vernachl�ssigen.

Folge 1: Beschreibung des pIntui-Konzepts, Beispielprogramm mit Fenster �ffnen und leerem Messageloop Am Ende dieses ersten Teils haben Sie ein Programmger�st, das die �bergebenen Argumente parsen kann, ein Fenster �ffnet und auf das Anklicken des Schlie�-Symbols wartet. Dieses Programmger�st k�nnen Sie als Ausgangsbasis f�r jedes neue Programm verwenden.

Folge 2: Beschreibung von Gadget/IObject-Konzept von pOS und BubbleHelp, Beispielprogramm erweitert um Gadgets und Messageloop. Im zweiten Kursteil wird das Fenster lebendig, d.h. wir werden es mit vielen verschiedenen Gadgettypen f�llen. Dazu wird das Gadgetkonzept von pOS n�her beleuchtet, die einzelnen Gadget-Tags vorgestellt und der Messageloop um die Gadgetinterkommunikation erweitert.

Folge 3: Beschreibung von Men�aufbau/auswertung und Requestern Beispielprogramm erweitert um Men�s, EasyRequester und Messageloop Im dritten und letzten Kursteil erh�lt das Fenster noch ein Men� spendiert und nat�rlich wird der Messageloop nochmals um die Men�verwaltung erweitert. Zus�tzlich wird ein Easy-Requester f�r die Programminformation erg�nzt.

pOS verwendet die bekannten FIFO-Message-Ports (First in -- first out) f�r den Nachrichtenaustausch mit den Fenstern (win->win_UserPort). �ber welche Aktionen Sie informiert werden wollen, geben Sie per SCRTAG_IDCMP beim �ffnen des Fensters an. Die gebr�uchlichsten Aktionen sind in IDCMP_StdSysMsg (z.B. Gadgets, Tasten) zusammengefa�t. Weniger wichtige Aktionen, wie Fensterschlie�en und Men�auswahl, m�ssen Sie zus�tzlich �ORen� (�ber den Bit-Operator �|�).
Falls mehrere Fenster gleichzeitig ge�ffnet bleiben sollen (z.B. f�r verschiedene Parametereinsteller), bekommen Sie irgendwann das Problem, da� max. 16 User-Signal-Bits (die 16 anderen sind vom OS reserviert) zur Verf�gung stehen. F�r diesen Zweck bietet pOS sogennante Shared-UserPorts; d.h. mehrere Fenster k�nnen sich denselben Message-Port f�r die Kommunikation teilen. Dazu �ffnen Sie das erste Fenster wie gewohnt und bei jedem weiteren geben Sie per SCRTAG_SharedUserPort den existierenden Port weiter. Beim Schlie�en der Fenster brauchen Sie sich nicht um ausstehende Nachrichten zu k�mmern (wie es beim Amiga notwendig w�re).
Wenn Sie weitere Message-Ports ben�tigen (z.B. f�r einen ARexx-Port zur Au�enwelt), k�nnen Sie diesen �ber pOS_CreatePort() erzeugen und per pOS_DeletePort() wieder entfernen. Ein �ffentlicher Port l��t sich anhand seines Namen �ber pOS_FindPort() suchen. Die Funktion liefert die Adresse des existierenden Message-Ports oder NULL (wenn er ganz fehlt).

Nachdem nun die Voraussetzungen geschaffen sind und das Fenster offen ist, wollen wir uns mit der Ermittlung und Behandlung der Benutzeraktionen besch�ftigen.
Mit pOS_WaitSignal() teilen Sie dem OS mit, da� es auf Aktionen warten soll. Anzugeben sind dabei die Signal-Bits aller Ports, auf deren Signale man warten will.
Zus�tzlich sollte immer DOSSIGF_CTRL_C angegeben werden, damit sich das Programm jederzeit von au�en durch die Tastenkombination CTRL+C abbrechen l��t.
W�hrend der Wartezeit beansprucht das Programm keinerlei Rechenzeit. Dadurch l��t sich im Multitaskingbetrieb optimale Performance erzielen.
Sobald ein Signal eintrifft, kehrt pOS_WaitSignal() damit zur�ck. Dabei k�nnen im Multitaskingbetrieb auch mehrere Signale gleichzeitig eintreffen! Falls es sich um eine �Fenster-Nachricht� handelt, k�nnen Sie diese per pOS_GetMsg() aus dem Message-Port lesen. Verwenden Sie SharedPorts, l��t sich �ber msg->im_Window das ausl�sende Fenster ermitteln. Die Nachricht m�ssen Sie als erstes �ber pOS_SysIMessage() dem Betriebssystem zum Vorverdauen �bergeben. Falls die Nachricht bereits verarbeitet werden konnte, kehrt die Funktion mit TRUE zur�ck. Dann d�rfen Sie auf keinen Fall Zeiger aus der Nachricht lesen, denn diese wurde bereits beantwortet (d.h. zur�ckgesandt). Ansonsten bietet sich eine �Switch-case�-Konstellation zur Aufgabenverteilung an.

Uns interessiert im Augenblick nur das Anklicken des Fenster-Schlie�-Symbols. Dies wird uns �ber den msg->im_Class-Eintrag IDCMP_CloseWindow mitgeteilt. Dann verlassen wir den Nachrichtenloop und Beenden das Programm. Vorher senden wir aber noch die ausgelesene Nachricht �ber pOS_ReplyMsg() ans OS zur�ck. Eventuelle weitere Nachrichten in unserem Messageport werden beim Fensterschlie�en automatisch vom OS freigegeben.
Am Programmende m�ssen Sie, wie im Fehlerfall auch, s�mtliche angeforderten Resourcen wieder ans Betriebssystem zur�ckgeben: zu jedem Openxxx() mu� also auch ein Closexxx() existieren, das aufzurufen ist. F�r einige Strukturen bietet p.OS auch Constructxxx()-Funktionen an, die die Struktur mit g�ltigen Werten vorbelegt. Dann existiert wieder eine Destructxxx()-Gegenfunktion. Den Source-Code in C finden Sie auf der n�chsten Amiga-Magazin-CD und hier auf dieserWebseite.

bl

� C-Source 1
� C-Source 2
� Source-Codes und lauffähige Programme als LHA-Archive

proDAD,
Feldelestr. 24,
78194 Immendingen,
Tel: (0 74 62) 91 13 4,
Fax: (0 74 62) 74 35
WWW:http://www.prodad.de
E-Mail: adver@prodad.de


MagnaMedia Hauptseite

� Copyright by MagnaMedia Verlag AG, Haar bei M�nchen
Ver�ffentlichung und Vervielf�ltigung nur mit schriftlicher Genehmigung des Verlags


Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 10.Juni 1997.