Опубликован: 21.02.2012 | Уровень: специалист | Доступ: платный
Лекция 9:

Работа с элементами ActiveX

< Лекция 8 || Лекция 9: 12 || Лекция 10 >

Создание объектов с помощью функций 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 являются реакторы, задающие отклик на события.

Вопросы

  1. Что такое объектная модель AutoCAD?
  2. В чем проявляется алгоритм реализации объекта в AutoCAD?
  3. Работа с каждым из объектов в технологии ActiveX ведется на уровне указателей (VLA-объектов). Поясните это на конкретных примерах.
  4. Назовите примененные в лекции функции доступа и функции модификации.
  5. В каком порядке можно извлекать объекты при работе с интерфейсом AutoCAD?
  6. Возможна ли работа с примитивами не только в активном документе, но и в других открытых чертежах?
< Лекция 8 || Лекция 9: 12 || Лекция 10 >
Алексей Тимонин
Алексей Тимонин
Алексей Потапкин
Алексей Потапкин

Здравствуйте.

Подскажите, пожалуйста, каким образом можно передать параметры в макрос написанный в Autocad на VBA? Например, есть процедура, которая отрисовывает заштрихованный прямоугольник (см. ниже). Как её изменить, чтобы на входе от пользователя требовалось ввести также в качестве параметров координаты углов прямоугольника?

Public Sub DrawHatchedBox()

...

End Sub

Сергей Ивков
Сергей Ивков
Россия, Геленджик
Юлия Мягчилова
Юлия Мягчилова
Россия