DocumentTools Library1. Konzeptionelles 1. KonzeptionellesDie DocumentTools Library stellt eine Reihe von Funktionen bereit, die Sie bei der Arbeit mit Dokumenten unterstützen. Dazu gehören zum Beispiel die typischen Dialogboxen zum Öffnen oder Speichern einer Datei. Um die DocumentTools Library nutzen zu können müssen Sie sie ihn Ihr Programm einbinden: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Include "DocumentTools" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Die Routinen der DocumentTools Library arbeiten eng mit einem DocumentGuardian-Objekt zusammen. Damit diese Zusammenarbeit funktioniert müssen die Instancevariablen ConfigData und ButtonHandler des DocumentGuardian Objekts korrekt belegt sein. ConfigData speichert allgemeine Informationen über die vom DocumentGuardian verwalteten Dokumente, z.B. den Dateityp und das Token. Zum Beispiel kommuniziert die Libraryroutine DTOpenDialog direkt mit dem DocumentGuardian-Objekt, so dass sie den FileSelector des "Öffnen"-Dialogs auf den korrekten Pfad, den Dateityp und gegebenenfalls auf das Token der zu öffnenden Datei einstellen kann. Der ButtonHandler wird von der Routine DTShowNewOpenDialog benötigt, damit das BASIC-Programm auf eine Klick auf einen der Buttons in "Neu/Öffnen" Dialog reagieren kann.
Mithilfe der von der DocumentTools Library bereitgestellten Routinen ist es sehr einfach, ein Dokument-Interface mit den üblichen Funktionen zu programmieren. Wie man das macht ist ausführlich im Handbuch "Spezielle Themen", Volume 3, Kapitel 15, beschrieben. Die dort beschrieben Routinen sind dem Beispiel "Dokument Interface" entnommen, das sich im Ordner "R-BASIC\Beispiel\Objekte\ Dateiarbeit" befindet. Zur Vereinfachung kann der gesamte Document-Interface Code über ein R-BASIC Menu in ihr Programm eingebaut werden. Dazu verwenden Sie das Menü "Extras" -> "Code Bausteine" -> "Dokument-Interface". Dort können Sie auch festlegen, welche Teile des Dokumentinterfaces Sie unterstützen wollen, z.B. ob Sie Musterdokumente unterstützen wollen oder nicht. Die von der Library bereitgestellten Routinen kann man grob in drei Gruppen unterteilen:
Routinen, die Dialogboxen bereitstellenDie SUBs DTShowNewOpenDialog und DTCustomNewOpenDialog stellen den typischen "Neu/Öffnen"-Dialog bereit. Mit den Funktionen DTOpenDialog bzw. DTOpenTemplateDialog wird die Dialogbox zum Öffnen eines Dokuments bzw. eines Musterdokuments angezeigt. DTSaveAsDialog bzw. DTSaveAsTemplateDialog stellen die Dialogboxen "Speichern unter" bzw. "Als Muster speichern" bereit. Schließlich stellen die Funktionen DTMoveCopyDialog und DTRenameDialog die Dialogboxen "Kopieren nach", "Verschieben nach" und "Umbenennen" bereit. Weil diese Routinen mit einem DocumentGuardian-Objekt zusammenarbeiten kennen sie selbständig den Dateityp und weitere Eigenschaften der Dokumentendatei, so dass sie z.B. bei der Eingabe eines Dateinamens sicherstellen können, dass die richtige Anzahl und nur gültige Zeichen eingegeben werden können.Routinen, die Änderungen mit oder an Dateien vornehmenDie SUB DTCloneFile legt eine Kopie der aktuell vom DocumentGuardian geöffneten Datei im aktuellen Ordner an. DTCloneAndOpenFile legt eine Kopie an und öffnet sie anschließend. Sie muss mit DTCloseClone wieder geschlossen werden. DTConfirmAndDelete löscht eine vorhandene Datei, fragt aber vorher beim Nutzer nach. Mit der SUB DTChangeUserNotes kann man die Benutzernotizen der vom DocumentGuardian geöffneten Datei ändern. Dazu wird vorher eine entsprechende Dialogbox angezeigt.Sonstige RoutinenDie Funktion DTFindNameForNew findet einen Namen für eine neu anzulegende Datei. Datei greift sie auf die im DocumentGuardian abgelegte Config-Struktur zurück (z.B. Dateimaske, Dateityp). DTCheckFileType prüft, ob eine Datei kompatibel zu den im DocumentGuardian abgelegten Daten (ConfigStruct) ist. DTConfirmClose prüft den Dokumentenstatus des DocumentGuardian-Objekts, ob vor dem Schließen der aktuell geöffneten Datei weitere Aktionen sinnvoll sind (z.B. Speichern der geänderten Daten, Speichern unter neuem Namen bei unbenannten Dateien ...) und fragt beim Nutzer entsprechend nach.Wenn Sie ein Datei-Menü implementieren müssen Sie sicherstellen, dass die Buttons (z.B. Öffnen, Speichern) in bestimmten Situationen enabled sind, in anderen nicht. Die Funktion DTFindEnabled liefert für jeden Button genau diese Information. Welcher Button gemeint ist, wird über eine Identifikationsnummer bestimmt. Dafür sind die folgenden Konstanten definiert:
Jede dieser Konstanten ist auch als actionData-Wert für den entsprechenden Button vorgesehen. Damit können Sie allen Buttons des Datei-Menüs den gleichen ActionHandler geben. Der Handler unterscheidet die Buttons anhand ihres actionData Wertes. Sinnvoller Weise weisen Sie genau diesen Actionhandler auch der Instancevariablen ButtonAction des DocumentGuardian-Objekts zu. Dann behandelt er auch die Klicks auf die Buttons in "Neu/Öffnen" Dialog (Routine DTShowNewOpenDialog). Diese Buttons haben automatisch die korrekten actionData-Werte gesetzt. Fast alle Routinen der DocumentTools Library erwarten als ersten Parameter ein DocumentGuardian-Objekt. Die DocumentTools Library ist mit dem PC/GEOS-SDK (nicht in R-BASIC) geschrieben. Deswegen ist es erforderlich, die Referenz auf das DocumentGuardian-Objekt vor der Übergabe an die Library in eine für das PC/GEOS-SDK lesbare Form zu konvertieren. Dazu wird, wie in den folgenden Beispielen gezeigt, die R-BASIC-Routine ConvertObjForSDK verwendet. ConvertObjForSDK muss bei jedem Aufruf einer Routine aus der DocumentTools Library gerufen werden. Alternativ kann man das Ergebnis der Konvertierung auch in einer eigenen OBJECT-Variablen abspeichern (Beispiel 2). Beispiel 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM ret as DialogReturnStruct ret = DTOpenDialog(ConvertObjForSDK(DocumentObj), "") IF ret.retInfo = DRI_CANCEL THEN RETURN ret = DTRenameDialog(ConvertObjForSDK(DocumentObj), "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Beispiel 2: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM ret as DialogReturnStruct DIM convertedObj as OBJECT convertedObj = ConvertObjForSDK(DocumentObj) ret = DTOpenDialog(convertedObj, "") IF ret.retInfo = DRI_CANCEL THEN RETURN ret = DTRenameDialog(convertedObj, "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^2. DialogboxenAlle Funktionen aus dieser Gruppe liefern eine Struktur zurück, die folgendermaßen definiert ist: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STRUCT DialogReturnStruct fileName$ as String[32] retInfo As Word End Struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Das Feld "fileName$" enthält den vom Nutzer eingegeben bzw. ausgewählten Dateinamen. Das Feld "retInfo" enthält die Information, welchen Button im Dialog der Nutzer gedrückt hat. Dafür dien folgenden Konstanten definiert:
DTShowNewOpenDialog, DTCustomNewOpenDialogDie Routinen zeigen den "Neu/Öffnen" Dialog an. Es wird nicht gewartet bis der Nutzer etwas im Dialog ausgewählt hat. Das ermöglicht das Anzeigen des Dialogs während das Programm startet.Klickt der Nutzer auf einen der Buttons im Dialog so wird der "ButtonHandler" des übergebenen DocumentGuardian-Objekts aufgerufen und der Dialog wird geschlossen. Der actionData-Wert, der dem Handler übergeben wird, beschreibt, welcher Button gedrückt wurde:
Beim Klick auf "Abbrechen" wird der ButtonHandler nicht gerufen, der Dialog wird nur geschlossen. DTCustomNewOpenDialog unterscheidet sich von DTShowNewOpenDialog dadurch, dass die Texte, die neben den Buttons angezeigt werden, geändert werden können. Die Grafiken auf den Buttons können nicht geändert werden.
Das Flag NOF_STARTUP sollte beim Aufruf der Dialogbox am Programmstart gesetzt werden. Dadurch erscheint statt des "Abbrechen" Buttons der Button "Programm beenden", der den actionData-Wert ID_EXIT_PROGRAM hat. Zur Vereinfachung sind außerdem folgenden Konstanten definiert: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CONST NOF_NEW_OPEN = NOF_NEW + NOF_OPEN CONST NOF_NEW_OPEN_TEMPLATE = NOF_NEW + NOF_OPEN + NOF_TEMPLATE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Beispiele: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DTShowNewOpenDialog(ConvertObjForSDK(MYGuardian), NOF_NEW_OPEN + NOF_STARTUP, "") DTShowNewOpenDialog(ConvertObjForSDK(MYGuardian), NOF_NEW_OPEN_TEMPLATE + NOF_IMPORT, "") DTCustomNewOpenDialog(ConvertObjForSDK(MYGuardian), NOF_NEW_OPEN_TEMPLATE, "", "Erstellen.\rEin neues Level für Supergame basteln.", "Bearbeiten\rEin vorhandenes Level für Supergame verändern.", "", "", "") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ein einfacher ButtonHandler des DocumentGuardian-Objekts könnte wie folgt aussehen. Es wird vorausgesetzt, dass die Do~-Routinen irgendwo definiert sind. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BUTTONACTION DocumentAndToolButtonHandler
ON actionData SWITCH
CASE ID_NEW_DOC:
DoCreateNewDoc
END CASE
CASE ID_OPEN_DOC:
DoOpenDoc
END CASE
CASE ID_CLOSE_DOC:
DoCloseDoc
End CASE
CASE ID_EXIT_PROGRAM:
EXIT
END CASE
End SWICTH
END ACTION ' DocumentAndToolButtonHandler
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DTOpenDialogDie Routine zeigt den "Öffnen"-Dialog an, führt aber selbst keine Dateioperationen aus. Wenn der Nutzer "Öffnen" wählt, wechselt die Routine in den vom FileSelector angezeigten Ordner.Der Fileselektor in der Dialogbox wird entsprechend den Instancevariablen des übergebenen DocumentGuardian-Objekts initialisiert. Die Routine gibt eine Variable vom Typ DialogReturnStruct (siehe vorn) zurück. Die Felder haben folgende Bedeutung:
Beispiel: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM ret as DialogReturnStruct DIM fh as FILE ret = DTOpenDialog(ConvertObjForSDK(MYGuardian), "") IF ret.retInfo = DRI_CANCEL THEN RETURN fh = FileOpen ( ret.fileName$ ) ... FileClose (fh) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DTSaveAsDialogDie Routine zeigt den "Speichern unter"-Dialog an, führt aber selbst keine Dateioperationen aus. Wenn der Nutzer "Speichern" wählt, wechselt die Routine in den vom FileSelector angezeigten Ordner.Der Fileselektor in der Dialogbox und das Textobjekt für den neuen Namen werden entsprechend den Instancevariablen des übergebenen DocumentGuardian-Objekts initialisiert (Pfad, Name der zu speichernden Datei usw.). Es werden also nur die Dateien angezeigt, die auch zum "Öffnen" angeboten werden. Die Routine gibt eine Variable vom Typ DialogReturnStruct (siehe vorn) zurück. Die Felder haben folgende Bedeutung:
Deklaration:
DTOpenTemplateDialogDie Routine zeigt den "Muster Öffnen"-Dialog an, führt aber selbst keine Dateioperationen aus. Wenn der Nutzer "Öffnen" wählt, wechselt die Routine in den vom FileSelector angezeigten Ordner.Konzeptionell ist die Routine gleichwertig zu DTOpenDialog, alle dort gemachten Ausführungen gelten auch für DTOpenTemplateDialog. DTOpenTemplateDialog startet aber immer im Template-Ordner.
DTSaveAsTemplateDialogDie Routine zeigt den "Speichern als Muster"-Dialog an, führt aber selbst keine Dateioperationen aus. Wenn der Nutzer "Als Muster speichern" wählt, wechselt die Routine in den vom FileSelector angezeigten Ordner.Konzeptionell ist die Routine gleichwertig zu DTSaveAsDialog, alle dort gemachten Ausführungen gelten auch für DTSaveAsTemplateDialog. DTSaveAsTemplateDialog startet aber immer im Template-Ordner.
DTMoveCopyDialogDie Routine zeigt den Dialog zum Verschieben oder Kopieren des vom DocumentGuardian geöffneten Dokuments an, führt aber selbst keine Dateioperationen aus. Wenn der Nutzer "Verschieben" bzw. "Kopieren" wählt, wechselt die Routine in den vom FileSelector angezeigten Ordner.Der Fileselektor in der Dialogbox wird entsprechend den Instancevariablen des übergebenen DocumentGuardian-Objekts initialisiert. Die Routine gibt eine Variable vom Typ DialogReturnStruct (siehe vorn) zurück. Die Felder haben folgende Bedeutung:
Deklaration
DTRenameDialogDie Routine zeigt den Dialog zum Umbenennen der vom DocumentGuardian-Objekt geöffneten Datei an, führt aber selbst keine Dateioperationen aus.Die Routine gibt eine Variable vom Typ DialogReturnStruct (siehe vorn) zurück. Die Felder haben folgende Bedeutung:
Deklaration
^3. Bearbeiten von DateienDTConfirmAndDeleteDie Routine prüft ob die übergebene Datei im aktuellen Ordner existiert, fragt beim Nutzer nach, ob die Datei gelöscht werden soll und löscht die auf Anforderung. Tritt dabei ein Fehler auf gibt es eine Fehlermeldung und die globale Variable fileError wird auf den entsprechenden Fehlerwert gesetzt.
Deklaration
DTCloneFileDie Routine dupliziert die die aktuell vom DocumentGuardian Objekt geöffnete Datei im aktuellen Ordner mit dem angegebenen Namen. Die Datei darf im aktuellen Ordner noch nicht existieren! Existiert die Datei oder tritt ein anderer Fehler auf gibt es eine entsprechende Fehlermeldung.DTCloneFile setzt die globale Variable fileError (Null oder Fehlerwert).
DTCloneAndOpenFile, DTCloseCloneDie Routine DTCloneAndOpenFile dupliziert die die aktuell vom DocumentGuardian Objekt geöffnete Datei im aktuellen Ordner mit dem angegebenen Namen und öffnet sie anschließend. Die Datei darf im aktuellen Ordner noch nicht existieren! Existiert die Datei oder tritt ein anderer Fehler auf gibt es eine entsprechende Fehlermeldung.DTCloseClone schließt eine mit DTCloneAndOpenFile geöffnete Datei. Beide Routinen die globale Variable fileError (Null oder Fehlerwert).
DTChangeUserNotesDTChangeUserNotes erlaubt das Ändern der Dokumentnotizen des aktuell vom DocumentGuardian-Objekt geöffneten Dokuments. Dazu zeigt die Routine eine Dialogbox an, die das Ändern der Dokumentnotizen zulässt und ändert sie dann.
^4. Sonstige ToolsDTFindNameForNewDTFindNameForNew findet einen Dateinamen, der zu den Instancedaten des DocumentGuardian-Objekts passt und der im aktuellen Ordner noch nicht existiert.
DTCheckFileTypeDie Routine prüft, ob eine Datei kompatibel zum Dateityp des DocumentGuardian-Objekts ist. Sie vergleicht zunächst den Dateityp (DOS-, GEOS oder VM-File). Für GEOS und VM-Dateien werden zusätzlich das Token und das CreatorToken verglichen, für DOS-Dateien wird stattdessen die Dateierweiterung verglichen.DTCheckFileType liefert Null (FALSE) wenn die Datei kompatibel ist, andernfalls liefert sie einen Fehlerwert z.B. ERROR_FILE_FORMAT_MISMATCH.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM err, fileName$
fileName$ = FileFindNext$( ... )
err = DTCheckFileType(ConvertObjForSDK(MyDocGuardian),
fileName$, "*")
IF err THEN MsgBox "Nicht kompatibel: "+ErrorText$(err)
err = DTCheckFileType(ConvertObjForSDK(MyDocGuardian),
fileName$, "HTM")
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DTConfirmCloseDie Funktion DTConfirmClose prüft die Instancevariable "documentState" des übergebenen DocumentGuardian-Objekts, ob das vom DocumentGuardian-Objekt geöffnete Dokument einfach geschlossen werden kann oder ob weitere Aktionen nötig sind. Im Zweifelsfall wird der Nutzer durch eine Dialogbox gefragt, wie weiter zu verfahren ist. DTConfirmClose handelt alle denkbaren Fälle und liefert einen der folgenden Werte zurück:
Folgende Situationen sind möglich:
Deklaration
DTFindEnabledWenn Sie ein Datei-Menü implementieren müssen Sie sicherstellen, dass die Buttons (z.B. Öffnen, Speichern) in bestimmten Situationen enabled sind, in anderen nicht. Die Funktion DTFindEnabled liefert für jeden Button genau diese Information. Welcher Button gemeint ist, wird über eine Identifikationsnummer bestimmt. Eine Liste der dafür definierten Konstanten finden Sie vor, im Abschnitt 1.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MenuOpenButton.enabled = DTFindEnabled
(ConvertObjForSDK(MyDocGuardian), ID_OPEN_DOC)
ToolsTemplateButton.enabled = DTFindEnabled
(ConvertObjForSDK(MyDocGuardian), ID_OPEN_TEMPLATE)
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^ |