Ein paar Worte vorabHome   Letzte MeldungenNews   Index der Kapitel und der besprochenen FunktionenIndex   Wer ich bin, warum ich diese Seiten mache, KontaktImpressum   Ich freue mich über jeden Eintrag im Gästebuch!Gästebuch   Einige Links zu anderen AutoLisp-SeitenLinks   Copyrights und DisclaimerRechts
Hier können die kompletten Seiten als ZIP-File heruntergeladen werden!

Einführung zum Programmieren mit VisualLisp Welcome to...
Das ActiveX-Objektmodell - Grundlage der vl-Programmierung in AutoCAD Das Objekt
Die vla-Funktionen: Viel ActiveX - wenig Dokumentation Knielang
Funktionen für den schnellen Zugriff in VisualLisp Breiter Gürtel
Variants - der Gummi-Datentyp von VBA Damenhandtasche
Collections - VB-Sammelbehälter in VisualLisp Kommste mit rauf?
Das Auffangen von Fehlern in VisualLisp Plumps
Berechnen von Schnittpunkten zwischen Entities mit ActiveX Windschnittig!
Ein erster, einfacher Reaktor, der viel Arbeit sparen kann Faulheit
Importieren von Views aus einer geschlossenen Zeichnung mit DBX Deutsche Bahn


Zum Einsteiger-Tutorial

Zu den Seiten für Fortgeschrittene

Meine Private HP mit Fotos, Gedichten, Musik und Postkartenversand

Mein Online-Lexikon der Fotografie

Mein völlig abgedrehtes Reisebüro










Wer sich mit der ActiveX-Programmierung in AutoCAD befassen möchte, wird zwangsläufig vor einen Baum rennen - man kommt einfach nicht dran vorbei. Es ist der (natürlich nicht physikalische, sondern strukturelle) Baum der ActiveX-Objekthierachie. Hier eine Abbildung, etwas verkleinert und zudem noch ein bisschen schmaler gemacht, aber ansonsten genau so, wie man ihn in der Online-Hilfe von VisualLisp findet (ActiveX and VBA Reference):

Das ActiveX-Modell in AutoCAD

Beulen an der Stirn oder Schwellungen am Knie sind also infolge der Virtualität dieses Gewächses nicht zu befürchten, leichte Kopfschmerzen könnten aber beim Zusammenprall doch entstehen - wer das erste Mal damit zu tun hat, muss mit den Folgen des 'impact' leben - ich benutze hier mal das englische Wort, und das völlig im Einklang mit AutoDesk: Auch die können sich offensichtlich keine Übersetzung leisten.

Dabei handelt es sich bei diesem Baum doch um ein völlig harmloses Gewächs - man muss ihn nur einmal verstanden haben! Betrachten wir das Ganze einmal farblich: Cyanfarben sind die geometrischen Datenbank-Objekte (also das, was wir normalerweise 'Zeichnungs-Elemente' nennen), hellgrün die nichtgrafischen Datenbank-Objekte (vorwiegend die Inhalte von Tabellen wie z.B. die Layertabelle, aber auch Dictionaries, Gruppen, Layouts usw.), und das Braun-Orange zeigt an, dass es hier um Dinge geht, die weder das eine noch das andere sind: Hier geht's um die AutoCAD-Konfiguration, die Menüs, das Plotten, Auswahlsätze usw.

Die einzelnen Elemente des Baums lassen sich aber auch nach der Form unterscheiden, wobei hier nur zwei Fälle auftreten: Rechteckig sind die 'Collection Objects' - sagen wir mal, das sind Sammelbehälter für Einzelobjekte. Die Einzelobjekte sind die mit den abgerundeten Seiten. Ein einzelner Layer hat also runde Seiten, die Layertabelle als Ganzes ist eckig.

Die Original-Abbildung in der AutoLisp-Hilfe hat allerdings einen ganz entscheidenden Vorteil gegenüber meiner verkleinerten Abbildung: Sie ist interaktiv - d.h. dass jeder Klick auf eines der abgebildeten Elemente weiterführt. Allerdings landet man dann unweigerlich in der Hilfe für Visual Basic - wer in Lisp programmieren möchte, ist darauf angewiesen, sich so manches selbst 'zusammenreimen' zu müssen.

Wir lassen uns aber einfach nicht entmutigen und beleuchten die Dinge noch ein wenig: Was sind denn diese Objekte, die das Objektmodell ausmachen? Ich will hier gar nicht zu viel Theorie ins Spiel bringen - unter Objekten versteht man im Sinne der objektorientierten Programmierung erst einmal nichts weiter als zusammengesetzte Daten. Ein solches Objekt repräsentiert etwas, z.B. einen Layer, und es hat zum Einen Eigenschaften (z.B. einen Namen oder die Farbe des Layers) und zum Anderen sog. Methoden - die Eigenschaften entsprechen immer einem Variablenwert, der zum Objekt gehört, die Methoden sind ein bisschen komplexer.

Wir kennen aus der AutoLisp-Programmierung Variablen und Funktionen, neu ist hier nur der Ansatz, dass eine Variable (Eingenschaft) oder eine Funktion (Methode) nicht mehr frei im Raum stehen und von jedem Programmteil beliebig genutzt werden können, sondern dass sie an ein Objekt gebunden sind und dann auch nur in diesem Zusammenhang nutzbar sind. Als Drittes kommen dann noch die Ereignisse ins Spiel, die ebenfalls zu den Objekten gehören - diese bleiben aber zunächst 'draussen' und werden erst später unter dem Stichwort 'Reaktoren' behandelt.

Auf keinen Fall sollte man diese 'Objekte' mit den AutoCAD-Entities verwechseln - die Objekte in diesem Baum gehen darüber hinaus. Die Menüs sind z.B. genauso Objekte in diesem Baum wie die Voreinstellungen oder auch die ganze Zeichnung (und alle anderen gleichzeitig geöffneten Zeichnungen). Das 'alleroberste' Objekt ist übrigens die AutoCAD-Applikation, wobei hier durchaus noch andere Objekte auf gleicher Ebene geben kann, wenn andere Applikationen wie Excel mit ins Spiel kommen.

Wir werden zunächst einmal klären, wie man nun überhaupt auf diese Objekte zugreifen kann und zunächst einmal versuchen, ihnen ein paar Werte zu entlocken. Wir bleiben einfach mal bei den Layern: Aus der Grafik können wir sehen, dass der Weg bei 'Application' beginnt (da beginnt er immer, weil das - wie gesagt - das oberste Objekt ist). Von da aus müssen wir weiter nach 'Documents', dann zu einem bestimmten 'Document', und von da aus dann zu 'Layers'. Dieser Weg ist nachvollziehbar: In der AutoCAD-Sitzung (Application) sind mehrere Zeichnungen (Documents) geöffnet, und in einer davon, nämlich der, die gerade bearbeitet wird (Document), finden wir die Layertabelle (Layers), um die es uns geht.

Um an das Ober-Objekt 'Application' zu kommen, benutzen wir immer die Funktion (vlax-get-acad-object) - an dieser Funktion führt kein weg vorbei. Und ebenso kommen wir um einen Aufruf von (vl-load-com) vorbei - dieser Aufruf lädt erst die ganze ActiveX-Unterstützung und ist daher in jedem ActiveX-Programm zwingend notwendig. Machen wir uns eine kleine Testfunktion und schauen mal, was dabei herauskommt:
(defun test1( / )
  (vl-load-com)
  (vlax-get-acad-object)
)

(test1) = > #<VLA-OBJECT IAcadApplication 00b07a68>
                  
Die Rückgabe beruhigt, weil 'IAcadApplication' sehr danach aussieht, als hätte alles geklappt, und gleichzeitig beunruhigt sie etwas, da wir es hier mit dem völlig neuen Datentyp 'VLA_OBJECT' zu tun haben. Wenn wir in der AutoCAD-Hilfe auf 'Application' klicken, gelangen wir auf die Seite, auf der die Methoden und Properties(= Eigenschaften) von 'Application' aufgelistet sind: Unser Interesse wird von der Eigenschaft 'ActiveDocument' geweckt. Tatsächlich können wir uns damit den Umweg über 'Documents' sparen und direkt zur aktiven Zeichnung springen. Um eine Eigenschaft eines Objekts auszulesen, benötigen wir (vlax-get-property). Erstes Argument ist das Objekt, das zweite Argument ist der Name der Eigenschaft:
(defun test2( / )
  (vl-load-com)
  (vlax-get-property
    (vlax-get-acad-object)
    "ActiveDocument"
  )
)

(test2) = > #<VLA-OBJECT IAcadDocument 00bd0bcc>
                  
Auch das sieht gut aus und lässt hoffen - ein weiterer Klick auf die Original-Grafik in der Online-Hilfe zeigt uns, dass das gesuchte Layer-Objekt eine Eigenschaft von 'Document' ist. Folgerichtig müssen wir also einen weiteren Aufruf von (vlax-get-property) in unsere Funktion einbauen:
(defun test3( / )
  (vl-load-com)
  (vlax-get-property
    (vlax-get-property
      (vlax-get-acad-object)
      "ActiveDocument"
    )
    "Layers"
  )
)

(test3) = > #<VLA-OBJECT IAcadLayers 00c254d4>
                  
Nun zeigt uns allerdings ein neuer Klick auf 'Layers', dass hier erst einmal das Ende der Fahnenstange erreicht ist: 'Layers' hat keine Eigenschaften, die wir jetzt nutzen könnten, um irgendwie einen Layernamen oder ähnliches herauszufinden. Das liegt daran, dass 'Layers' ein Collection-Objekt ist - das waren doch die Objekte, die in der Grafik abgerundet sind. Auch 'Documents' ist ein solches Collection-Objekt, aber das haben wir ja ganz geschickt übersprungen.

Collection-Objekte sind immer nichts weiter als Sammelbehälter für andere Objekte. Um einen Blick in den Topf zu werfen, stellt VisualLisp verschiedene Möglichkeiten zur Verfügung. Z.B. verfügt jedes Collection-Objekt über die Methode 'Item', mit der man auf ein darin enthaltenes einzelnes Objekt zugreifen kann - vorausgesetzt, man kennt den Namen. Bei den Layern wissen wir, dass "0" immer ein gültiger Name ist - dieser Layer muss in jeder Zeichnung vorhanden sein.

Während (vlax-get-property) für den Zugriff auf Eigenschaften zuständig ist, dient die Funktion (vlax-invoke-method) dazu, Objektmethoden aufzurufen und auszuführen. Die Syntax ist hier etwas variabler: Als erstes Argument wird wieder das Objekt übergeben, dann folgt der Name der Methode als Zeichenkette, und daran kann sich dann eine variable Anzahl von weiteren Argumenten anfügen, die davon abhängt, wie viele Argumente die auszuführende Methode erwartet. In unserem Fall geht es nur um ein drittes Argument, nämlich den Layernamen:
(defun test4( / )
  (vl-load-com)
  (vlax-invoke-method
    (vlax-get-property
      (vlax-get-property
        (vlax-get-acad-object)
        "ActiveDocument"
      )
      "Layers"
    )
    "Item"
    "0"
  )
)

(test4) = > #<VLA-OBJECT IAcadLayer 00c26064>
                  
Nun, wir haben tatsächlich einen Layer zurückerhalten! Versuchen wir doch einmal, die Eigenschaft 'Freeze' auszulesen (diese finden wir natürlich wieder durch einen Klick auf 'Layer' in der grossen bunten Grafik in der Hilfe):
(defun test5( / )
  (vl-load-com)
  (vlax-get-property
    (vlax-invoke-method
      (vlax-get-property
        (vlax-get-property
          (vlax-get-acad-object)
          "ActiveDocument"
        )
        "Layers"
      )
      "Item"
      "0"
    )
    "Freeze"
  )
)

(test5) = > :vlax-false
                  
Sieh da, zur Abwechslung kein Objekt, sondern ein Symbol! An dem Doppelpunkt stören wir uns nicht, er ist ohne Relevanz und nur aus einer Laune der Autodesk-Programmierer in den Symbolnamen hineingeraten. Nun, das bedeutet einfach: Der Layer ist nicht gefroren. Sollte er bei Ihnen gefroren gewesen sein, dann muss das Ergebnis natürlich :vlax-true lauten.

Schöner und einfacher wäre es, wenn in solchen Situationen wie gewohnt T oder nil zurückkäme - aber auf diesen Luxus müssen wir verzichten! All die ActiveX-Funktionen werden doch überhaupt nicht vom AutoLisp-Interpreter evaluiert, sondern von in C/C++ geschriebenem Code innerhalb von AutoCAD. Lisp ist hier nur noch Schnittstelle. Wir haben uns also mit den im AutoCAD-Code herrschenden Datentypen abzufinden - da gibt es den Datentyp 'boolean' mit den Werten 'true' und 'false'. Die beiden Symbole ':vlax-true' und ':vlax-false' spiegeln das wider.

Zum Abschluss des Kapitels gönnen wir uns noch ein Erfolgserlebnis und lesen die Farbe des Layers "0" aus:
(defun test6( / )
  (vl-load-com)
  (vlax-get-property
    (vlax-invoke-method
      (vlax-get-property
        (vlax-get-property
          (vlax-get-acad-object)
          "ActiveDocument"
        )
        "Layers"
      )
      "Item"
      "0"
    )
    "Color"
  )
)

(test6) = > 7
                  
7 (weiss) war der Layer "0" jedenfalls bei mir. Na also, klappt doch! Im nächsten Kapitel werden wir dann versuchen, den Code ein bisschen zu kürzen!