Работа с элементами ActiveX
Создание объектов с помощью функций ActiveX
При работе с интерфейсом ActiveX объекты можно извлекать только в порядке, соответствующем их иерархии. Прежде чем получить объект, необходимо извлечь следующие элементы:
- Acad-object - представляет программу AutoCAD;
- ActiveDocument - представляет активный чертеж;
- ModelSpace/PaperSpace - представляет рабочее пространство AutoCAD.
В AutoLISP вначале извлекается тип пространства, затем чертеж и последним - объект AutoCAD. Возьмем простую программу создания отрезка и модифицируем ее с использованием функций ActiveX.
;;; Эта функция создает отрезок с использованием Visual LISP и ActiveX ;;; и возвращает отрезок в виде объекта vla (defun ax-make-aline () (vla-addLine (vla-get-ModelSpace;извлечение объекта пространства модели; (vla-get-ActiveDocument;извлечение текущего документа; (vla-get-Acad-object) ; извлечение объекта AutoCAD; )) (vlax-3d-point '(5 5 0));_начальная точка (vlax-3d-point '(15 5 0));_конечная точка ) )
Введите этот код в окне редактора Visual LISP и загрузите его в чертеж. Чтобы посмотреть, как работает функция, введите в окно Console команду
(ax-make-aLine)↵ Visual LISP возвратит выражение #<VLA-OBJECT IAcadLine 03614934>
Ознакомиться с другими функциями ActiveX, предназначенными для создания объектов, можно в справочной системе Visual LISP: HELP - Visual LISP HELP TOPICS - CONTENT - ACTIVEX and VBA REFERENCE - METHODS. Чтобы создать функцию Visual LISP, добавьте к имени метода префикс vla-. Например, для добавления окружности используйте функцию vla-AddCircle.
Доступ к документам
Работа с примитивами возможна как в активном документе, так и в других открытых чертежах. Некоторые программы выполняют операции не с одним чертежом, а с несколькими. Тогда при выполнении программы активным должен оставаться один и тот же документ. LISP-программа загружается в пространство имен текущего чертежа.
В следующем примере функция opendocs_name возвращает список с именами открытых в данный момент чертежей.
(defun opendocs_names ( / _OpenDocs _nlist _d) (vl-load-com) ; Семейство открытых документов (setq _OpenDocs (vla-get-documents (vlax-get-acad-object))) ; _nlist - пустой список (nil) как локальная переменная (vlax-for _d _OpenDocs (setq _nlist (append _nlist (list (strcat (vla-get-path _d) "\\" (vla-get-name _d)))) );setq );vlax-for );defun
VLA-объект приложения AutoCAD, получаемый с помощью функции vlax-get-acad-object, имеет свойство Documents. Оно возвращает VLA-объект семейства открытых документов.
Для того, чтобы использовать это свойство Documents, нужно вызвать функцию с таким же именем, но прибавить префикс vla-get-. Поэтому с помощью выражения (setq _OpenDocs (vla-get-documents (vlax-get-acad-object))) Переменной _OpenDocs присваивается VLA-объект семейства открытых в данном сеансе документов.
Для перебора элементов запускается цикл, выполняемый функцией vlax-for. В этом цикле рабочая переменная _d используется как обозначение текущего из перебираемых элементов семейства. Строки с именами открытых чертежей накапливаются в списке _nlist. Начальное значение этой локальной переменной равно нулю. Для добавления к списку нового элемента использована функция append.
Функция vla-get-fullname соответствует свойству FullName. Она возвращает полное имя открытого dwg-файла. Однако если новый чертеж не сохранялся, то вместо имени будет возвращена пустая строка, хотя в заголовке окна стоит имя Drawing1.dwg. Поэтому в примере полное имя файла получается с помощью свойств Path и Name.
Когда одновременно открыто несколько чертежей, то с помощью LISP-программы, запущенной в активном чертеже, можно получить доступ ко всем другим документам. Нельзя только активизировать другой документ, так как выполнение программы прервется. Все семейства имеют метод Item, который предоставляет доступ к элементам по номеру или по имени. Нумерация элементов начинается с нуля.
Для примера рассмотрим текст функции, которая для открытого документа с номером N возвращает имя его текущего слоя.
(defun anydoc_clayer (N / _OpenDocs) (vl-load-com) ; Семейство открытых документов (setq _OpenDocs (vla-get-documents (vlax-get-acad-object))) ; Проверка номера документа и возврат имени текущего слоя (if (and (= 'INT (type N)) (>= N 0) (< N (vla-get-count _OpenDocs))) (vla-get-name (vla-get-ActiveLayer (vla-item _OpenDocs N))) );if );defun
После получения семейства открытых документов проверяется тип аргумента N (он должен быть целым) и правильность значения. Значение должно быть положительным и меньше количества элементов семейства (свойство семейства count). В случае ошибки программа возвращает ноль, иначе - имя текущего слоя указанного документа.
Создание реакторов
VLR-объекты или реакторы - особые объекты ActiveX. Они задают отклик системы на события. Выполняемые действия описываются функциями на языке AutoLISP, которые имеют префикс vlr-. Для того, чтобы эти функции были доступны, необходимо выполнить функцию vl-load-com. Она загружает расширение языка LISP.
Основные типы реакторов приведены ниже:
Обозначение Название Описание
- :VLR-AcDb-Reactor Реактор базы Отслеживают изменения базы объектов
- :VLR-DocManager-Reactor Реактор документа Действия с документом
- :VLR-Linker-Reactor Реактор связи Загрузка и выгрузка ARX-приложений
- :VLR-Object-Reactor Реакторобъекта Состояние объектов
- :VLR-Editor-Reactor Реактор редактирования
Реакторы редактирования могут быть заменены на реакторы, приведенные в нижеследующей таблице:
Обозначение НазваниеM
- :VLR-Command-Reactor Реакторы команд
- :VLR-DeepClone-Reactor Реакторы клон7ирования
- :VLR-DWG-Reactor DWG-реакторы
- :VLR-DXF-Reactor DXF-реакторы
- :VLR-Insert-Reactor Реакторы команды INSERT
- :VLR-Lisp-Reactor Реакторы LISP-событий
- :VLR-Miscellaneous-Reactor Реакторы других событий редактирования
- :VLR-Mouse-Reactor Реакторы действий мышью
- :VLR-Sysvar-Reactor Реакторы изменения системных переменных
- :VLR-Toolbar-Reactor Реакторы изменения размеров кнопок панелей инструментов
- :VLR-Undo-Reactor Реакторы команды UNDO
- :VLR-Wblock-Reactor Реакторы команды WBLOCK
- :VLR-Window-Reactor Реакторы изменения формы и размеров окна AutoCAD
- :VLR-XREF-Reactor Реакторы вставки и редактирования внешних ссылок
Реакторы создаются по такой схеме. Вначале нужно выполнить функцию вида: (vlr->тип>-reactor <данные> <реакции>)
Тип реактора указан в таблицах (acdb, docmanager). У реакторов объекта (тип Object) перед аргументом <данные> присутствует аргумент <владелец>, по которому определяется, какой объект вызвал реактор.
Аргумент <данные> - это LISP-данное любого вида (число, список, строка, nil и пр.). При срабатывании реактора это данное передается функции действия. Она может получить это данное из реактора с помощью специальной функции vlr-data.
Аргумент <реакции> - это список, в котором задаются события, отслеживаемые реактором, и функции, вызываемые в качестве реакции при получении уведомления о совершении события. Список должен иметь такой вид: (list '(<событие1>. <функция1>) '(<событие2>.< функция2>)…)
Здесь для каждого из отслеживаемых событий создается точечная пара. Вторым элементом этой пары является соответствующая функция действия. Например, для реактора базы рисунка
(list (:vlr-objectAppended. funA) '((:vlr-objectModified. funM))
Пример
Запретить удаление примитивов по команде ERASE (Стереть).
(defun cmsr ( / ) ; Создание реактора команд (setq commandr (vlr-command-reactor "Реактор команд: " (list '(:vlr-commandEnded . cme))) );setq );defun cmsr (defun cme (reac cname / _ad) (princ (strcat "\n" (vlr-data reac) " контролирую ")) (princ cname) (setq _ad (vla-get-activedocument (vlax-get-acad-object))) ; Проверка имени команды (if (member (getcname (car cname)) (list "ERASE" "_ERASE")) (progn (vla-sendcommand _ad "_.undo ") (vla-sendcommand _ad "1 ") ) );if );defun cme
Программа содержит две функции: cmsr, cme. Первая создает в чертеже реактор команд, вторая является функцией действия, которую запускает реактор. Формирование реактора выполняется с помощью выражения
(setq commandr (vlr-command-reactor "Реактор команд:" (list '(:vlr-commandEnded . cme)))
Здесь <данные> - это строка, а <реакции> - это список. В списке указано только одно событие: :vlr-commandEnded, которое генерируется при окончании команды. В ответ на это событие должна запускаться функция cme.
Функция cme имеет два аргумента: reac и cname. Первый из них - это VLR-объект реактора (т.е. значение глобальной переменной commandr из функции cmsr). Второй - список с именем команды, которую только что выполнила система AutoCAD.
Функция действия с помощью выражения (vlr-data reac) извлекает данные, записанные в реактор (строка "Реактор команд"). Эта строка используется затем функцией princ при печати.
При окончании каждой команды AutoCAD в чертеже происходит событие :vlr-commandEnded. Функция действия cme извлекает имя этой команды из списка cname и проверяет, является ли команда заданной (ERASE). При совпадении выполняется команда UNDO с опцией 1, которая отменяет последнее действие. Поэтому удаленные объекты сразу же восстанавливаются.
Ключевые термины
COM (Component Object Model) - спецификация метода создания компонентов, из которых строятся приложения.
ActiveX Automation - технология автоматизации встраивания и связывания объектов в разных приложениях, реализующая принципы объектно-ориентированного программирования.
Базовые интерфейсы - компоненты, предназначенные для реализации базовых инструментов объектной технологии. В них описываются все типичные свойства и методы базовых объектов. Например, базовым интерфейсом всех графических примитивов является IAcadEntity. Он является родительским для интерфейса IAcadLine. С помощью этого интерфейса создаются объекты семейства AcDLine, представителем которого является объект Line.
vla-, vlax-, vlr-функции - функции, реализующие технологию ActiveX в Visual LISP. Доступ к этим функциям можно получить только после выполнения в данном сеансе AutoCAD функции vl-load-com.
Реактор - отклик системы на события, обеспечиваемые функциями vlr-.
Краткие итоги
В модели ActiveX Automation работающее приложение представляется совокупностью объектов, свойств, методов и событий. С помощью функций ActiveX можно создавать объекты, извлекать и модифицировать информацию об объектах, получать доступ к документам. Особыми объектами ActiveX являются реакторы, задающие отклик на события.
Вопросы
- Что такое объектная модель AutoCAD?
- В чем проявляется алгоритм реализации объекта в AutoCAD?
- Работа с каждым из объектов в технологии ActiveX ведется на уровне указателей (VLA-объектов). Поясните это на конкретных примерах.
- Назовите примененные в лекции функции доступа и функции модификации.
- В каком порядке можно извлекать объекты при работе с интерфейсом AutoCAD?
- Возможна ли работа с примитивами не только в активном документе, но и в других открытых чертежах?