Session D-TREE

Das Treeview-Control im Einsatz

Norbert Abb
Wizards & Builders GmbH


Einleitung

Das Treeview Control ist ein ActiveX Steuerelement (OCX) zur Darstellung von hierarchischen Strukturen. Das Control ist der Darstellung im Explorer ähnlich. Man kann also mit diesem Control Oberflächen aufbauen, die sich in hervorragend in das Betriebssystem einfügen.

Ein weiterer Vorteil ist, daß das Control zu den ‚Common Controls‘ gehört, die von Microsoft bei Visual FoxPro (und anderen Visual Studio Produkten) mitgeliefert wird und deshalb ohne weitere Lizenzgebühren verteilt werden darf.

Im Folgenden soll gezeigt werden, wie das Control mit VFP eingesetzt werden kann.

Überblick

Herkunft und Versionen

In diesem Kapitel wird erläutert, wo das Control zu finden ist, und in welchen Versionen es ausgeliefert wurde. Diese Informationen sind deshalb wichtig, da zwar ein Abwärtskompatibilität besteht, aber keine Aufwärtskompatibilität.

Arbeiten mit ActiveX Controls

Es werden Grundlagen zum Einsatz von ActiveX Controls in VFP vermittelt.

Objektmodell und ImageList

Der Aufbau des Treeview Controls wird erläutert. Methoden und Properties werden vorgestellt. Außerdem wird das ImageList Control vorgestellt. Mit Hilfe dieses Controls können graphische Symbole in der Darstellung des Treeviews verwendet werden.

Beispiele

Es wird an einfachen Beispielen gezeigt wie ein Treeview Objekt in einer Maske unter VFP gefüllt werden kann. In komplexeren Beispielen werden weitere Möglichkeiten des Treeviews gezeigt.

Tips und Tricks

Als Abschluß werden einige Tips und Tricks aufgezeigt, die für die Arbeit mit dem Treeview Control wertvoll sind.

Herkunft und Versionen

Woher bekommt man das Treeview Control?

Das Control wird mit VFP ausgeliefert und gehört zu den ‚Common Controls‘. Das bedeutet, es verbirgt sich in einer Datei im Windows System Verzeichnis mit dem Namen ComCtl32.OCX. In dieser Datei befinden sich noch weitere Controls auf die hier nicht weiter eingegangen wird. Die Datei wird bei den Programmen des Microsoft Developer Studios mitgeliefert. Das bedeutet: Es kann auch sein, daß andere Anwendungen diese Controls verwenden. Deshalb ist es besonders wichtig bei der Installation darauf zu achten, daß keine ältere Version installiert wird. Programme, die mit einer neueren Version entwickelt wurden laufen sonst nicht mehr!

Welche Versionen gibt es?

Hier sollen nur die ‘neueren’ (1997) Versionen der ComCtl32.OCX behandelt werden. Mit der Version 5.0a von VFP wurde der Build 3714 ausgeliefert. Da in dieser Versionen noch einige Bugs vorhanden waren wurde bald darauf eine neue Version auf dem Internet bereitgestellt (und auch mit dem SP1 zum Visual Studio ausgeliefert und mit VB installiert).

Die neueste Version ist der Build 4319. Diese Version wird mit dem Service Pack 2 des Visual Studios ausgeliefert. Sie wird allerdings nicht mit dem VFP Update installiert, sondern mit VB. Das heißt, es ist nicht sicher, daß die neuste Version der Controls auf der Maschine installiert ist, wenn VFP 5.0b installiert ist.

Um die Build Nr. der Controls festzustellen klickt man im Windows\System Verzeichnis mit der rechten Maustaste auf die Datei ComCtl32.OCX wählt dann zunächst ‘Eigenschaften’ und dann die ‘Version’ Seite.

Probleme mit Versionen

Warum sind die Versionsnummern so wichtig? Nun, wenn eine Anwendung mit einer älteren Version des Treeviews erstellt wurde als das auf der Maschine installiert ist, so gibt es keine Probleme. Wenn aber die beim Erstellen der Applikation verwendete Version neuer ist, als die auf der Maschine installierte Version, dann läuft das Treeview nicht. Dies gilt auch für die Entwicklungs-umgebung. Dadurch kann es sehr schnell zu einem Versionskonflikt kommen, wenn man mit mehreren Entwicklern arbeitet. Wenn einer der Entwickler eine neue Version des Treviews bekommen hat (durch welche Installation auch immer) und dann eine Maske bearbeitet in der das Treeview verwendet wird, dann werden danach alle Maschinen mit einer älteren Version der Controls die Maske (oder Klasse) nicht mehr fehlerfrei öffnen können.

Hilfe

Woher bekommt man Hilfe zum Treeview Control? Es gibt eine Hilfedatei im Windows\System Verzeichnis. Diese Hilfedatei ist allerdings schlecht strukturiert und man findet sich schlecht zurecht. Der einzige Vorteil dieser Hilfedatei ist, daß sie dort auch in der lokalisierten Version vorhanden ist (deutsch).

Eine besser strukturierte Hilfedatei wurde mit VFP ausgeliefert. Diese Hilfedatei befindet sich im Verzeichnis CtrlHelp im VFP Verzeichnis (CtrlRef.hlp). Die Hilfedatei ist ein Subset aus der Visual Basic Hilfe und die Beispiele darin sind ebenfalls in Visual Basic, aber trozdem einfach zu übertragen nach VFP.

Die Datei wird seit der Version 5.0a von VFP nicht mehr mitgeliefert.

Arbeiten mit ActiveX Controls

Einige grundsätzliche Bemerkungen zum Arbeiten mit ActiveX Controls in VFP:

Die Controls wurden früher auch OCXe genannt nach ihrer Dateikennung (*.OCX). Die Begriffe OCX, OCX Controls und ActiveX Controls sind deshalb als Synonyme zu sehen.

Registrieren

Um ActiveX Controls auf einer Maschine einsetzen zu können müssen sie registriert werden. Das bedeutet, es reicht nicht die OCX Dateien auf einen PC zu kopieren, sondern sie müssen dem System auch noch bekannt gemacht werden. Dies geschieht durch das ‚Registrieren‘. Manuell kann man das Registrieren am einfachsten dadurch erledigen, daß man die fragliche OCX Datei mit der Maus auf das Programm RegSrv32.EXE (im Windows System Verzeichnis) zieht und dort ‚fallen läßt‘. Man bekommt dann die Meldung, daß das OCX nun registriert ist. Programmatisch kann auch das RegSrv32 Programm mit der OCX Datei als Parameter aufgerufen werden.

Bei VFP anmelden

Wenn man Controls in VFP verwenden möchte, und sie aus dem Toolbar holen möchte, muß man sie als Controls in den ‚Optionen‘, ‚Steuerelemente‘ aktivieren. Nur die dort aktivierten ActiveX Controls werden im Designer Toolbar angezeigt. Wenn bereits bestehende Klassen, oder Masken ein Control verwenden, so reicht es aus wenn das Control auf der Maschine installiert und registriert ist.

Subclassing von ActiveX Controls

VFP ist das einzige Microsoft Produkt, das im Moment ActiveX Controls Subclassen kann. Das heißt, es kann eine Klasse erstellt werden. die zusätzlich zu den Eigenschaften und Methoden des Controls noch selbstdefinierte Eigenschaften und Methoden enthält. Wenn man mit solchen Klassen arbeitet, hat man den Vorteil, daß die Objekthierarchie einfacher wird: Man braucht keinen zusätzlichen Container. Wenn man sich aber entschließt das Control ‚as is‘ zu verwenden und die zusätzlichen Eigenschaften und Methoden in einen Container um das Control herum zu verlagern, kann man das Control einfacher austauschen. Dies kann dann sowohl eine andere Version sein, als auch evtl. ein anderes Control, das sich ähnlich verhält.

Nachbemerkung zu ActiveX Controls

Nicht alle auf dem Markt erhältlichen Controls lassen sich ohne Probleme mit VFP einsetzen. Das liegt daran, daß sie oft nur für VB erstellt und getestet werden. Visual Basic arbeitet aber bei der Einbindung von ActiveX Controls nicht korrekt (VTable Binding). Da VFP in dieser Hinsicht sich genauer an die von Microsoft definierte Schnittstelle hält, kann es zu Problemen mit Controls kommen. Deshalb hat VFP seit der Version 5.0a die Möglichkeit das VTable Binding mit der SYS Funktion 2333 abzuschalten. Wenn sich also ein Control nicht mit VFP verwenden läßt (fällt bereits in der Entwicklungsumgebung auf), dann sollte man sich die Hilfe zur Funktion SYS(2333) ansehen.

Objektmodell und Imagelist

Das Objektmodell

Das Treeview Control hat Eigenschaften und Methoden wie ‚normale‘ VFP Objekte. Die eigentlich interessanten Objekte mit ihren Eigenschaften, sind jedoch zum Entwurfszeitpunkt nicht zu sehen: Die ‚Knoten‘ des Baumes.

Mit einem Rechtsklick auf das Control bekommt man die Möglichkeit einen speziellen Eigenschaften-Dialog für das Control aufzurufen.

In diesem Dialog kann das Aussehen des Treeviews bestimmt werden: Style legt das grundsätzliche Aussehen der Linien und Symbole fest. Beschreibungen zu den Eigenschaften sind in der Hilfe Datei zu finden.

In der Hilfe Datei findet man auch Beschreibungen zu der ‚Nodes Collection‘ und den ‚Nodes‘. Die Nodes oder Knoten sind die Teile des Treeview Objektes, die zur Laufzeit die Daten enthalten. Eine ‚Collection‘ ist zu sehen wie ein Array in VFP. Die einzelnen Elemente der Nodes Collection (die Nodes) können auch über den Index des Knoten angesprochen werden. Es gibt Methoden und Eigenschaften für die gesamte Collection (alle Knoten), wie z.B. oTree.Nodes.add() für das Hinzufügen eines Knoten und Methoden und Eigenschaften für einzelne Elemente wie oTree.Nodes(1).expanded.

Informationen über die Methoden, Eigenschaften und Ereignisse, für das Treeview Control finden sich in der Hilfe Datei.

ActiveX Controls haben eine ‚object‘ Eigenschaft in VFP. Dies ist eine Referenz auf das eigentliche Objekt normalerweise werden Aufrufe an das Objekt automatisch durchgereicht bei Methoden und Eigenschaften. Daß aber das ‚object‘ etwas anderes ist als das VFP Objekt wird gleich noch beim ImageList Control erläutert.

Mit den Eigenschaften, die das Aussehen des Controls beeinflussen sollte man etwas experimentieren, um das passende Aussehen zu finden.

Achtung: Die LabelEdit Eigenschaft des Controls steht per Default auf ‚automatic‘ das bedeutet, daß der Anwender wenn er in den Text zu einem Knoten Klickt diesen Text editieren kann (aus dem Explorer bekannt). Da dies jedoch meist nicht gewünscht wird sollte man diese Eigenschaft auf ‚manual‘ setzen.

Das ImageList Control

Das ImageList Control ist ebenfalls in den ‚Common Controls‘ enthalten. Es dient dazu um im Treeview oder im Listview die Einträge mit Grafiken (Icons) zu versehen.

Das Control ist einfach zu verwenden:

Nachdem es im Designer auf die Maske oder Klasse gelegt wurde, können Grafiken (*.bmps) hinzugefügt werden indem die Eigenschaften des Controls per Rechtsklick aufgerufen werden. Die eingefügten Bilder bekommen eine fortlaufende Nummerierung über die sie angesprochen werden können. Es kann aber auch ein alphanumerischer Schlüssel dafür vergeben werden (siehe Beispiele).

In älteren Versionen (vor 5.0a)des Treeview Controls war es möglich das Treeview und das ImageList Control visuell miteinander zu verbinden. Verbindungen, die auf diese Art erstellt wurden bleiben erhalten auch wenn die neuen Controls eingesetzt werden. Sobald aber dort einmal eine Veränderung vorgenommen wurde, geht die Verbindung verloren und muß manuell, z.B. im Init einer Maske vorgenommen werden. Dazu wird das Imagelist ‚object‘ der Treeview.ImageList Eigenschaft zugewiesen:

Achtung: Es muß das object des ImageList Controls sein, da in die Eigenschaft des Treeviews(ImageList) keine VFP Objekte eingetragen werden können, sondern nur ActiveX Objekte.

Beispiele

Die ersten beiden Beispiele arbeiten auf der Dateistruktur eines Laufwerkes. Es wird zuerst ein Verzeichnis bestimmt, ab dem ein Verzeichnisbaum erstellt werden soll und dann wird mit den Elementen das Treeview gefüllt.

Beispiel 1

Im ersten Beispiel werden alle Verzeichnisse und Dateien direkt eingelesen und das Treeview wird im Speicher komplett aufgebaut. Es werden jedoch nur die Einträge der ersten Ebene aufgeklappt. Durch ‘aufklappen’ der Einträge werden die weiteren Dateien und Verzeichnisse angezeigt.

Diese Vorgehen hat den Vorteil, daß es recht einfach funktioniert. Der Baum muß nur einmal aufgebaut werden und kann dann bearbeitet werden.

Der Nachteil bei einem derartigen Vorgehen ist, daß sich dam,it nur eine begrenzte Anzahl von Elementen sinnvoll verwalten lassen. Wenn mehr als 200 Knoten auf diese Art verwaltet werden sollen wird der ‘Füllprozess’ zu langsam.

Beispiel 2

Im 2.Beispiel werden die Elemente ‘nach Bedarf’ in die Ebenen eingefüllt. Das bedeutet erst beim expandieren der Knoten wird das nächste Verzeichnis eingelesen. Dadurch wird der Baum nach und nach gefüllt und es entsteht keine lange Wartezeit zu Beginn wenn viele Elemente verwaltet werden müssen.

Diese Vorgehen erfordert allerdings mehr Aufwand: Man muß jeweils prüfen ob die Ebene schon gefüllt ist und sie gegebenenfalls aufbauen. Wenn man noch die Anzeige haben möchte daß weitere Ebenen vorhanden sind (Pluszeichen!), so muß man noch eine Ebene weiterlesen und ein ‘Dummy’ Element einbauen, das man wieder entfernen muß, wenn man die Ebene tatsächlich füllt.

Beispiel 3

Bei komplexeren Applikationen kann es vorteilhaft sein die Elemente des Treeviews zusätzlich in einem Array (oder Cursor) verwaltet, das dann weitere Informationen über oder für den Knoten enthält. Man kann dann separat das Array pflegen. Bei einem Refresh werden dann alle Elemente gelöscht und das Treeview mit den benötigten Elementen neu gefüllt.

Der Nachteil bei dieser Methode ist, daß der Aufwand dafür hoch ist. Es kann damit auch nur eine begrenzte Anzahl von sichtbaren Elementen verwaltet werden. Dies ist allerdings kein großer Nachteil, da meist nur wenige Elemente einer Struktur zu sehen sind (aufgeklappt).

Tips und Tricks

Versionen

Beim Arbeiten mit dem Treeview sollte man genau darauf achten welche Versionen des Control man einsetzt und entsprechend bei der Installation beim Anwender das richtige Control installieren. Vorsicht: Keine neueren Versionen überschreiben. Wenn man Versionen von Dateien mit VFP abzufragen möchte, sollte man sich das Beispiel in den Solution Samples (WinApi) anschauen.

Timing Probleme

Es hat sich beim Arbeiten mit dem TreeView (aber auch mit anderen OCX Controls) gezeigt, daß es Schwierigkeiten mit den verschiedenen Threads des Systems geben kann. ActiveX Controls führen ein Eigenleben außerhalb des Eventhandlings von VFP. Deshalb kann es zu Schwierigkeiten (hauptsächlich bei der ersten Instanziierung von Controls) kommen. Eine mögliche Abhilfe ist vor dem Aufbau (Einfügen von Knoten) des Treeviews ‘einen Moment’ zu warten.

Label Edit

Man sollte daran denken die LabelEdit Eigenschaft auf manual zu stellen, damit die Anwender nicht in den Texten des TreeViews schreiben können (kann zu unangenehmen Effektenführen).

Klicks und Knoten

Der Klick oder Doppelklick Event kann auch ausgelöst werden wenn kein Knoten angewählt wurde. deshalb sollte man, wenn man z.B. im Doppelklick eine Aktion mit dem gewählten Knoten auslösen möchte prüfen ob es einen angewählten Knoten (selecteditem) gibt.

Rechtsklick

Das TreeView Control hat keinen Rechtsklick Event. Man kann diesen jedoch simulieren, indem man im MouseUp Event auf die rechte Maustaste abfragt (button = 2).