Session D-HOOKHook mal wieder!Jürgen Wondzinski
|
Build | Damit wird die APP/DLL/EXE neu erstellt. Die diversen Option des Erstellen Dialogs sind als Parameter hier wiederzufinden. |
CleanUp | Führt ein PACK auf die PJX aus. Wenn ein .T. mit übergeben wird, dann werden alle Kompilate mitgelöscht, was ein "Alles neukompilieren" beim nächsten BUILD zwangsweise auslöst. |
Close | Naja... Schliesst das Projekt. |
Refresh | Damit wird das Projekt komplett neu eingelesen, und der Treeview neu aufgebaut. Notwendig nach programmatischem Hinzufügen von Dateien. |
SetMain | Definiert das Hauptprogramm |
Unter den Eigenschaften finden wir alles, was sich irgendwo im Projektfenster, im Versionsdialog oder im Projektinfo-Dialog als Wert eingeben lässt (bis auf die Copyright-Infos,
seltsamerweise)
Eigenschaft |
Zugriff |
Typ |
Bedeutung |
AutoIncrement | S | L | Soll die Versionsnummer hochgezählt werden, wenn EXE oder DLL erstellt wird |
BuildDateTime | L | T | DAtum / Zeit der letzten Erstellung |
Debug | S | L | Debug-Info für jede Datei generieren? |
Encrypted | S | L | Verschlüsseln |
HomeDir | S | C | Ausgangsverzeichnis für die Relativen Pfadangaben bei den Dateien |
Icon | S | C | Icondatei der EXE |
MainClass | L | C | Klassen-Name; nur wenn eine ActiveDoc Klasse als Hauptdatei definiert ist. Wird mit der SETMAIN Methode gesetzt. |
MainFile | L | C | Startprogramm / Startklassenbibliothek. Wird mit der SETMAIN Methode gesetzt. |
Name | L | C | Projektname, incl Pfad |
ProjectHook | S | O | Objektreferenz zum verwendeten ProjectHook. |
ProjectHookClass | S | C | Klassenname des ProjektHooks |
ProjectHookLibrary | S | C | Klassenbibliothek des ProjektHooks. |
SCCProvider | L | C | Name des Quellcodeverwaltungs-Programms |
ServerHelpFile | S | C | Hilfedatei für die Typelib bei COM-Server |
ServerProject | S | C | Linker Teil der , mit der COM-Server in die Registry eingetragen werden. Defaultmässig gleich ProjektName |
TypeLibCLSID | L | C | Die zugewiesene CLSID für die TypeLib. |
TypeLibDesc | S | C | Info für die *.TLB Datei bei COM-Server. |
TypeLibName | L | C | Pfad und Name der TLB Datei |
VersionComments | S | C | VersionInfo: Kommentar |
VersionCompany | S | C | VersionInfo: Firma |
VersionCopyright | S | C | VersionInfo: Copyright |
VersionDescription | S | C | VersionInfo: Beschreibung |
VersionLanguage | S | C | VersionInfo: Sprache |
VersionNumber | S | C | VersionInfo: Nummer; 3x 4Stellen |
VersionProduct | S | C | VersionInfo: Produktname |
VersionTrademarks | S | C | VersionInfo: Warenzeichen |
Visible | S | L | PJ-Manager sichtbar? |
Zugriff: L = Nur lesen, S = Lesen/Schreiben
So, das waren die Methoden und Eigenschaften. Fehlen nur noch die Ereignisse; doch die suchen wir vergebens. Das ist ähnlich dem Problem "Wie kann ich Code zu den _Screen-Ereignissen (zB Resize) zufügen"? Geht nicht, denn der Projektmanager läuft ja schon. Und genau da kommen nun die ProjektHooks ins Spiel! Die ProjektHook Klasse ist nichts anderes als ein Liste aller Projekt-Ereignisse, für die ich nun Code schreiben kann. Durch Zuweisen der Klasse zu einem Projekt wird nun bei jeder Aktion auch der entsprechende Aufruf an das ProjektHook-Objekt weitergereicht, und wir können darauf reagieren
Ausgehend vom Applikationsobjekt, also _VFP, haben wir beliebig viele Projekte (gesammelt als Projects Collection). Diese haben wiederum die Erweiterung durch die Hook-Objekte.
Und dann sehen wir noch zwei weitere Collections pro Projekt: Files und Servers. Über diese kommen Sie dann an die jeweiligen einzelnen Dateien ran, die in jedem Projekt definiert sind.
Die Files und Server Collection sind genaugenommen auch Eigenschaften des Projektobjekts, quasi wie Arrays. Und in diesen Arrays sind nun wieder Verweise (Objektreferenzen) zu den File-Objekten und COM-Server Objekten hinterlegt.
Die Anzahl Dateien ist wieder im COUNT Property der Collection zu finden und um also alle im Projekt verwendeten Dateien aufzulisten, könnten Sie nun schreiben:
Die Files-Collection hat auch noch eine eigene Methode: ADD, mit der sie neue Einträge in der Files-Collection erstellen können. Sie gibt eine Referenz auf das neue File-Objekt zurück. Das File-Objekt kann dann wiederum mit seiner Methode REMOVE (siehe weiter unten) entfernt werden.
Eigenschaft |
Zugriff |
Typ |
Bedeutung |
CodePage | L | N | Codepagenummer, siehe GETCP() |
Description | S | C | Beschreibung |
Exclude | S | L | .T. , wenn Ausgeschlossen |
FileClass | L | C | Bei Forms: Die verwendete Grundklasse |
FileClassLibrary | L | C | Bei Forms: Klassenbibliothek für Grundklasse. |
LastModified | L | T | Datum/Zeit der letzten Änderung. |
Name | L | C | Name, mit vollem Pfad |
ReadOnly | L | L | .T. für schreibgeschützt |
SCCStatus | L | N | Status der Quellcode-Verwaltung. 0: Keine Kontrolle, ansonsten 1-6 diverse Zustände, siehe VFP Hilfe "SCCStatus-Eigenschaft" |
Type | L | C | Datei-Typ; die wichtigsten: V = VCX, P = Programm, R = Report, B = Etikett, K = Form, Q = Abfrage, D = DBF, d = DBC, M = Menü, T = Text, x = sonstiges. |
Aufpassen beim Abfragen der Typ-Eigenschaft: Hier wird sowohl "d" als auch "D" codiert; bei Verwendung von SET COLLATE = "GENERAL" ist ja Klein- gleich
Grossschreibung.daher unbedingt mit Binärvergleich (zwei Gleichheitszeichen) arbeiten! IF oFile.Type == "d"
Das Files-Objekt hat natürlich auch Methoden:
AddToSCC |
Fügt eine Datei in einem Projekt einer Quellcodeverwaltung hinzu. |
CheckIn |
Checkt die Änderungen ein, setzt ReadOnly auf .t. |
CheckOut |
Auschecken aus der Quellcodeverwaltung, dadurch ReadOnly auf .f. |
GetLatestVersion |
Synchronisiert die lokale Kopie mit der Zentralversion, ohne Checkout |
Modify |
Ruft den passenden Editor auf (bei Klassen den Klassennamen mitgeben!) |
Remove |
Entfernt Datei aus FilesCollection, => QueryRemoveFile Event |
RemoveFromSCC |
Aus QuellCodeverwaltung rausnehmen |
Run |
Ausführen (Bei Reports/Etiketten wird Preview gestartet) => QueryRunFile Event |
UndoCheckOut |
Änderungen verwerfen |
Die dabei ausgelösten QueryXXX Ereignisse werden ebenfalls über unseren ProjectHook abgefangen.
Die dritte Collection sind die diversen COM-Server, die wir in einem Projekt definieren können. Hier gibt es nur Eigenschaften:
Eigenschaft |
Zugriff |
Typ |
Beschreibung |
CLSID | L | C | Die CLSID für den Server. |
Description | S | C | dazugehörige Beschreibung in der Registry. |
HelpContextID | S | N | Hilfetext ID. |
Instancing | S | N | Einfach / Mehrfach-Instanziierung: 1 Single, 3 multi-instance. |
| L | C | Die des Servers in der Registry. |
ServerClass | L | C | Klassenname. |
ServerClassLibrary | L | C | Klassenbibliothek. |
So, damit haben wir jetzt direkten Zugriff auf alle Projekt-, Datei- und COMServer Eigenschaften und wir können auch alle vorhanden Methoden aufrufen (und damit ein Projket komplett fernbedienen).
Zum Reagieren auf die Ereignisse müssen wir nun eine ProjektHook Klasse ankoppeln, voraussetzend, dass wir auch schon eine solche Klasse erstellt haben. Dies kann zum einen pro Projekt im jeweiligen Projekt-Info
Dialog definiert werden.Oder aber zentral, für alle zukünftigen Projekte, im Menü unter Extras -> Optionen -> Projekte eingetragen werden. Dies ändert aber nicht mehr schon bestehende Projekte, die sie nun alle einzeln
nachbearbeiten müssen. Wenn sie dem aktuell offenen Projekt die ProjekctHook-Info per Eigenschaft-setzen zuweisen, dann wird das Hookobjekt erst aktiviert, wenn das Projekt das nächste Mal geöffnet wird. Sie können aber auch selbst ein
Hookobjekt instanziieren und dessen Objektreferenz dem Projekt zuweisen:
Dies ist aber nur ein temporärer Vorgang, der nicht dazu führt, dass die Hookinfo dauerhaft im PJX abgelegt wird.
Wenn Sie ein Projket mal ausnahmsweise ohne Hook öffnen wollen, dann verwenden Sie den Zusatz NOPROJEKTHOOK beim MODIFY PROJECT bzw beim CREATE PROJECT. Hier gibt es übrigens auch noch den Zusatz NOSHOW, der das Projekt zwar öffnet, aber den Projektmanager nicht anzeigt (also VISIBLE auf .F. setzt). Das ist der Trick um seinen eigenen Projektmanager anstelle des Standardmanagers anzuzeigen.
Die ProjektHook Klasse hat keine speziellen Eigenschaften und Methoden (ausser den üblichen PEMs, die FoxPro braucht, um die Klassen vom Designer anzusprechen).
Daher sind das einzig Interessante die Ereignisse, die immer aufgerufen werden; egal ob Sie nun interaktiv die Schaltflächen im Projektmanager betätigen, oder programmatisch die zugrundeliegenden Methoden verwenden.
AfterBuild | Aufruf, nachdem das Erstellen fertig ist. |
BeforeBuild | Aufruf, bevor das Projekt erstellen anstartet. Mit NODEFAULT wird der Vorgang abgebrochen. |
OLEDragOver | Wenn eine Datei per Drag'nDrop über den Projektmanager gezogen wird. |
OLEDragDrop | Eine Datei wurde auf den Projektmanager gedroppt. Nach diesem Event kommt dann noch der QueryAddFile |
QueryAddFile | Eine Datei wird dem Projekt zugefügt. NODEFAULT verhindert dies. |
QueryModifyFile | Aufruf, bevor der jeweilige Editor anstartet. NODEFAULT verhindert das Editieren. |
QueryRemoveFile | Aufruf, bevor eine Datei gelöscht wird. NODEFAULT verhindert... |
QueryRunFile | Aufruf vor dem Ausführen. Und natürlich verhindert ein NODEFAULT den Vorgang. |
Aufpassen: Obwohl alle QUERYxxxx Ereignisse mittels NODEFAULT einen Vorgang abbrechen, und folglich VOR der Aktion ablaufen, wird der QueryAddFile erst aufgerufen, wenn der jeweilige Editor geschlossen wurde, und die Datei tatsächlich dem Projekt zugefügt wird. Ich hatte gehofft, auf diese Weise , dem CREATE FORM beizubringen, zuerst nach der zu verwendenden Basisklasse zu fragen, aber funktioniert so nicht. Hier fehlt also noch ein BeforeAddFile Event.
Anhand der nun vollständigen Liste kann man nun seiner Phantasie freien Lauf lassen, und sich entsprechend austoben. Einige Ideen hab ich Ihnen ja schon am Anfang aufgezeigt, schauen Sie sich dazu auch noch die Beispiele zur Session an.
Die aktuellste Version finden Sie bei mir auf der Webseite unter:
Über kurz oder lang werden Sie feststellen, dass man bei verschiedenen Projekten nicht immer die selben Tätigkeiten braucht. Am Anfang wird man möglichereweise mit einigen DO CASE Schleifen das aufkommende Chaos beherrschen können, aber viel besser wäre es, wenn man verschiedene Hook-Klassen angeben könnte. Allerdings kann das Projekt eben nur einen Hook ansteuern. Hier kommt nun die PublicDomain Erweiterung ProjectHookX ins Spiel, die von Mike und Tone Feltman (F1 Technologies) entwickelt wurde. Sie geben die projectHookX Klasse als zentrale Hookklasse an, diese überprüft dann anhand einer speziellen DBF, welche einzelnen "Sub-Hook"-Klassen dann für das jeweilige Objekt mit angesprochen werden. Im Prinzip wird damit also eine Hook-Collection verwaltet. Sehr praktisch!
dFPUG c/o ISYS GmbH Frankfurter Str. 21 b
D-61476 Kronberg |
per Fax an: +49-6173-950903 oder per e-Mail an: |
Texte, Grafiken und Inhalt: ISYS GmbH |