Четыре правила для работы с ActiveX в VisualLisp
Независимо от среды исполнения - AutoCAD / nanoCAD / BricsCAD (надеюсь)... Клон страницы http://www.cad.dp.ua/stats/vla_doc.php. Кроме картинок - их скачать пока не удалось.
Уточнение: для использования справки по ActiveX в текущих реалиях придется либо использовать VPN для доступа к онлайн-справке AutoCAD, либо разыскивать VBA-enabler для соответствующей версии и устанавливать его.
Размышления о объектах, свойствах и методах не свойственно для традиционного программиста AutoLISP. Недостаток доступной в изложении документации по по vla- функциям заставляет многих избегать интерфейса ActiveX. Так где же документация? Прежде чем я сообщу вам об этом давайте сначала рассмотрим некоторые базовые понятия.
Объекты, свойства и методы
Объект, это “ что-то воображаемое или физическое к которому направлено действие” В AutoCAD, объект может быть видимым, как линии, дуги и текст. Он так же может быть не видимым, как слой или стиль текста. Другой, связаный термин, коллекция, просто ссылка к совокупности схожих объектов, к примеру коллекция слоев.
Очевидно, что объекты имеют свойства. К примеру, вы интуитивно знаете, что линия имеет начальную и конечную точку. Она так же имеет другие свойства в AutoCAD, к примеру, слой. Некоторые свойства доступны для изменения (TrueColor) а другие доступны только для чтения (управляемые объектом).
Объекты так же имеют методы. Методы это действия, которые поддерживают объекты. К примеру, линия поддерживает методы перемещения, копирования и вращения. Различные объекты поддерживат различные методы.
Теперь вы понимаете базовые термины, которые используются в интерфейсе ActiveX. Пришло время показать документацию на функции vla- и мои 4 простых правила.
4 Простых правила
Документация по функциям vla- всегда расположена в руководстве по ActiveX и VBA. Проблема в том, что она была написана для программистов на VBA, а не для программистов Visual LISP. Однако, Autodesk знает что “перевод” VBA-документации в Visual LISP был бы настолько прост, что нет реальной необходимости ее дублировать.
Потратьте одну минуту, чтобы посмотреть на карту объектной модели в руководстве (рис. 1). Эта карта - лучший способ начать ознакомление с документацией. Вы можете кликнуть на любой из объектов или коллекций, чтобы напрямую перейти в описание этого объекта или коллекции. Это так же даст вам понимание иерархии объектов в интерфейсе ActiveX. Обратите внимание, что объект Application - начало для большинства объектных моделей.
Когда вы видите карту объектной модели на экране, выберите объект Line. Отобразится список всех методов и свойств (так же событий, мы еще не говорили о них), доступных для этого объекта (рис. 2). Это говорит вам о том, что объекты могут содержать линию. Там же показываются возможные "владельцы" объекта Line. Мы не видим ничего о Visual LISP здесь. Однако, перевод “VBA-языка” в функции vla- требует только эти четыре правила:
1. Вы должны всегда описывать объект как первый аргумент.
Помните, свойства и методы не могут существовать без объектов. Каждая vla-функция будет требовать объект. Поэтому, первый параметр каждой функции vla- будет объектом непосредственно.
2. Ваш запрос значения значения свойства должен осуществляться добавлением имени свойства к vla-Get-
Все свойства запрашиваеются в Visual LISP потем добавления имени свойства к vla-Get-, к примеру, vla-Get-Layer. Поскольку вы только запрашиваете свойство, здесь только один аргумент - объект.
3. Модификация значение свойства осуществляется добавлением имени свойства к vla-Put-
Все свойства, которые доступны не только для чтения, модифицируются в Visual LISP добавлением имени свойства к vla-Put-, к примеру, vla-Put-Layer. Так как вы модифицируете свойство, вам необходимо два аргумента: объект, и данные для изменения свойства. Тип данных, необходимый для изменения свойства описан в разделе Signature.
4. Выполнение метода осуществляется добавлением имени метода к vla-
Все методы доступны в Visual LISP путем добавления имени метода к vla-, к примеру, vla-Delete. Количество аргументов будет зависеть от конкретного метода и будет включать объект как первый аргумент, наряду с описанными в документации параметрами. Типы данных, необходимый для аргументов методов описаны в разделе Signature.
Запрос свойства
Как вы увидели, задача "перевода" руководства ActiveX тривиальна. Теперь рассмотрим несколько примеров.
Начертим единичную линию в AutoCAD. Мы будем использовать эту линию для примера кода, размещенного ниже. Сохраним объект line в переменной AutoLISP. (vl-Load-Com) загружает интерфейс ActiveX и vlax-EName->vla-Object переводит имя примитива в объект.
1 2 3 | Command: (vl-Load-Com) Command: (setq myLine (vlax-EName->vla-Object (entlast))) #<VLA-OBJECT IAcadLine 05e8d054> |
Посмотрим что руководство по ActiveX и VBA говорит нам о том, что мы можем сделать с нашим объектом. Выберем объект Line в карте объектной модели. Это вызовет переход к документации по объекту line. Предположим, что мы хотим узнать, на каком слое находится линия, используя при этом средства ActiveX. Выберем свойство Layer в документации. Теперь применим наши четыре правила.
Мы работаем с методом или со свойством? Это свойство, используем правило 2. Значить нам нужно добавить имя свойства Layer к vla-Get-, т.е., используем функцию vla-Get-Layer. Так как мы только запрашиваем свойство Layer мы можем пропустить правила 3 (модификация свойства) и 4 (префикс метода). Правило 1 гофорит нам, что первым аргументом является непосредственно сам объект. Таким образом выражение AutoLISP, которое будет возвращать имя слоя, на котором расположена линия будет:
1 | Command: (vla-Get-Layer myLine) "0" |
Какой тип данных мы ожидаем, когда запрашиваем свойство? Обратите внимание, что документация в разделе Signature указывает что свойство layer имеет тип string. Различные своства будут иметь различные типы данных. К примеру, свойство StartPoint имеет тип variant, и будет содержать массив чисел. В Visual LISP массив называется SafeArray.
1 2 | Command: (vla-Get-StartPoint myLine) #<variant 8197 ...> |
Однако, тип variant, который содержит SafeArray необходимо обследовать глубже, чтобы получить актулаьные для нас числа. Две функции используются для того чтобы получить данные, сохраненные в типе variant и SafeArray, это: vlax-Variant-Value и vlax-SafeArray->List. Большинство программистов на Visual LISP предпочитают объединять эти две функции в одну и использовать простую функцию, типа показаной ниже.
1 2 3 | (defun i:Array->List (variant) (vl-Load-Com) (vlax-SafeArray->List (vlax-Variant- Value variant))) |
Теперь мы можем использовать эту функцию чт обы получить список чисел, которые нам нужны:
1 2 | Command: (i:Array->List (vla-Get- StartPoint myLine)) (15.4375 16.1814 0.0) |
Модификация свойства
В этом примере мы будем изменить свойство, в данном случае слой, на котором расположена линия. Теперь мы применим правила 1 и 3. Правило 3 говорит, что нам нужно добавить перфикс - имя свойства (Layer в нашем случае) к vla-Put-, таким образом вызываем функцию vla-Put-Layer. У нее будут два аргумента. Не забудьте правило 1! Первый агрумент всегда является сам объект. Так как мы изменяем свойство, имеет смысл что бы второй параметр был бы значением непосредственно. В документации написано, что его тип string, т.о. мы должны предоставить строку. Перед тем как мы введем код, показанный ниже, создайте слой с именем “Test” который бы визуально отстоял от текущего слоя, на котором расположена линия.
1 2 | Command: (vla-Put-Layer myLine "Test") nil |
Обратите внимание на то, что после успешного выполнения данное выражение возвращает nil. Если выражение завершается с ошибкой (к примеру, слой не существует) возвращается сообщение “Automation Error”. Строки и простые числа, такие как типы integer и double (выражаясь в терминах AutoLISP) легко обеспечить. Но некоторые свойства требуют тип variant, в обльшинстве случае это точки для объектов, к примеру линий и полилиний. В этом случае, многие программисты на Visual LISP пишут функцию подобную показанной ниже для быстрой конвертации списка вещественных чисел в SafeArray.
1 2 3 4 | (defun i:Points (ptList) (vl-Load-Com) (vlax-SafeArray-Fill (vlax-Make-SafeArray vlax-vbDouble (cons 0 (1- (length ptList)))) ptList)) |
Мы используем эту функцию чтобы изменить свойств линии StartPoint на 0,0,0.
1 2 | Command: (vla-Put-StartPoint myLine (i:Points '(0.0 0.0 0.0))) nil |
Выполнение метода объекта
И наконец, используем метод для того чтобы переместить линию. Перейдем к методу Move в руководстве по ActiveX и VBA. Обратите внимание, что этот метод содержит два аргумента, Point1 и Point2. Не забывайте правило 1. Объект - всегда первый аргумент. Т.о. в Visual LISP мы будем иметь три аргумента: объект, первую точку и вторую точку. Правило 4 говорит что имя метода будет идти за префиксом vla-, т.о., мы будем использовать функцию vla-Move.
Используем то, что мы изучили, чтобы переместить линию.
1 2 | Command: (vla-Move myLine (vlax-3d-point '(0.0 0.0 0.0)) (vlax-3d-point '(12.0 0.0 0.0))) nil |
Если выражение отработало верно, возвращается nil.