Программирование в AutoCAD

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

Разбить на страницы
Показывать лекцию целиком

Цель лекции: приобрести простейшие навыки работы с элементами ActiveX.

Объектная модель AutoCAD

Объекты ActiveX в системе AutoCAD рассматриваются как иерархия, содержащая примитивы, символьные таблицы, словари и пр. Однотипные объекты объединяются в семейства (collections).

Высшим элементом в иерархии является объект Application (AcadApplication) . Этот объект является родительским для следующих объектов:

  • Preferences (Настройки);
  • VBE (объект интегрированной среды VBA-приложений);
  • Documents (Документы);
  • MenuBar (Строка меню);
  • MenuGroups (Группы меню).
  • Эти объекты, в свою очередь, являются родительскими для объектов более низких уровней. Семейство Documents включает в себя объекты Document - открытые документы или рисунки. В семейство MenuGroups входят объекты типа MenuGroup (Группа меню или Группа адаптации). В семейство MenuBar входят объекты типа PopupMenu (Падающие меню, загруженные в строку меню).

    Наиболее важным для практики является объект Document. Он включает в себя, в частности, такие семейства:

  • Blocks (Блоки);
  • ModelSpase (Пространство модели);
  • PaperSpace (Пространство листа);
  • Dictionaries (Словари);
  • DimStyles (Размерные стили);
  • Groups (Группы);
  • Layers (Слои);
  • Layouts (Листы);
  • Linetypes (Типы линий);
  • Plot (Печать);
  • PlotConfigurations (Конфигурации печати);
  • Preferences (Настройки чертежа);
  • RegisteredApplications (Зарегистрированные приложения);
  • SummaryInfo (Свойства чертежа);
  • SelectionSets (Выделенные наборы);
  • TextStyles (Текстовые стили);
  • UCSs (Пользовательские системы координат);
  • Utility (Утилита);
  • Viewports (Видовые экраны);
  • Views (Виды).
  • Полностью список объектов показан на рис. 9.1.

    (рис 9.1) Список объектов AutoCAD

    В семейства Blocks, ModelSpase и PaperSpace входят объекты, которые соответствуют графическим примитивам. Pис. 9.1 взят из справочной службы AutoCAD: ActiveX and VBA Reference - Object Model.

    Для реализации базовых инструментов объектной технологии в модели предусмотрены компоненты, называемые интерфейсами. В базовом интерфейсе описываются все типичные свойства и методы. Например, базовым интерфейсом всех графических примитивов является IAcadEntity. Он является родительским для интерфейса IAcadLine. С помощью этого интерфейса создаются объекты семейства AcDLine, представителем которого является объект Line.

    Каждый объект в технологии ObjectX имеет свои свойства и методы. Свойства можно читать или изменять с помощью соответствующих функций. Функции, соответствующие методам, реализуются в командах с соответствующими параметрами. Элементами объектной модели являются также события. Они возникают в результате действий пользователя (Click) или при изменениях в программе (onLoad). Программа может отслеживать события и реализовать сценарий отклика на события.

    С полным перечнем объектов, свойств, методов и событий можно познакомиться в справочной службе AutoCAD.

    Функции и типы данных

    Функции, реализующие технологию ActiveX в Visual LISP, имеют префиксы vla-, vlax-, vlr. Доступ к этим функциям можно получить только после выполнения в данном сеансе AutoCAD функции vl-load-com.

    Работа с каждым из объектов в технологии ActiveX ведется на уровне указателей. Они носят название VLA-объекты. VLA-объектами являются указатели не только графических примитивов, но и документов, пространства модели и приложений.

    Практически обязательной для всех приложений, использующих ActiveX, является следующая структура функций:

    (defun begin_activex ( / )
    (vl-load-com)
    (setq acad_app (vlax-get-acad-object))
    (setq active_doc (vla-get-activedocument acad_app))
    (setq model_space (vla-get-modelspace active_doc))
    (setq paper_space (vla-get-paperspace active_doc))
    ); defun
    

    В результате выполнения функции begin_activex будут получены следующие VLA-объекты:

  • acad_app приложение AutoCAD;
  • active_doc активный документ;
  • model_space пространство модели;
  • paper_space пространство листа.
  • После получения основных VLA-объектов можно через них обращаться к другим элементам иерархии системы AutoCAD (примитивам, таблицам и пр.) для получения или модификации их свойств и методов. Основным средством получения VLA-объекта для примитива является функция vlax-ename->vla-object. Обратная функция vlax-vla-object->ename.

    Кроме VLA-объектов, в ActiveX используют новые типы данных: безопасные массивы и варианты.

    Безопасные массивы являются массивами однотипных объектов. Они создаются с помощью функций

  • vlax-make-safearray;
  • vlax-safearray-put-element;
  • vlax-safearray-fill.
  • Для извлечения данных из безопасных массивов с целью использования обычных LISP-функций применяются функции:

    vlax-safearray-get-dim;
    vlax-safearray-get-l-bound;
    vlax-safearray-get-u-bound;
    vlax-safearray-get-element;
    vlax-safearray-type.
    

    Для преобразования массива в список используют функцию

    vlax-safearray->list.

    Варианты - это структуры, которые могут хранить однотипные данные. Тип данных является типом варианта. Создание варианта выполняется с помощью функции (vlax-make-variant [<данное> [<целое>]]).

    В качестве второго аргумента передается целое число, задающее тип варианта. Если оно опущено, то тип варианта определяется по типу первого аргумента. В качестве значения аргумента <целое> используются зарезервированные константы.

    Константа Значение Описание
    Vlax-vbEmpty 0 Неинициализированный (значение по умолчанию)
    Vlax-vbNull 1 Пустой (без данных)
    Vlax-vbInteger 2 Короткое целое число
    Vlax-vbLong 3 Длинное целое число
    Vlax-vbSingle 4 Вещественное число
    Vlax-vbDouble 5 Вещественное число с двойной точностью
    Vlax-vbString 8 Строка
    Vlax-vbObject 9 Объект
    Vlax-vbBoolean 11 Булево значение
    Vlax-vbArray 8192 Массив

    Примеры функций, выполняющих операции с вариантами:

  • vlax-variant-type - получение типа варианта;
  • vlax-variant-value - получение значения варианта;
  • vlax-variant-change-type - изменение типа варианта;
  • vlax-variant-type - оформление трехмерной точки как варианта.
  • Использование элементов ActiveX в Visual LISP

    Элементы ActiveX - это программный интерфейс, который используется в поддерживающих его языках программирования. Элементы ActiveX обеспечивают взаимодействие между объектами, с одной стороны, и пользователем или приложением, с другой стороны. Технология ActiveX позволяет получать информацию об объектах чертежа с помощью функций доступа (get functions) и модифицировать объекты с помощью функций модификации (put functions).

    Выше было рассмотрено, как извлекать и модифицировать информацию об объектах с помощью функций-интерфейсов на языке AutoLISP. Элементы ActiveX обеспечивают аналогичный способ получения и модификации информации. Однако для этого необходима определенная подготовка.

    AutoCAD предоставляет все свои объекты, включая функции доступа и модификации, в распоряжение элементов ActiveX. Вначале в Visual LISP необходимо перед началом сеанса работы загрузить все функции ActiveX с помощью функции (vl-load-com)

    При этом все функции-интерфейсы ActiveX станут доступными. Загрузив интерфейс ActiveX, можно выполнить необходимые действия над созданным ранее отрезком. Но вначале нужно преобразовать имя сущности в объект vla. Этот объект ActiveX практически ничем не отличается от имени сущности, но содержит ряд свойств, которые отсутствуют в его аналоге в языке AutoLISP. Для преобразования используется функция vlax-ename->vla-object. Пример обращения к этой фунции:

    (setq vla-line (vlax-ename->vla-object (entlast)))↵
    Среда Visual LISP возвратит следующее выражение:
    #<VLA-OBJECT IAcadLine 03612b14>
    

    Протокол операций будет выглядеть следующим образом:

    Command: _line Specify first point: 5,5,0
    Specify next point or [Undo]: 15,-5,0
    Specify next point or [Undo]: *Cancel*
    Command: '_.zoom _e
    Command: (vl-load-com)
    Command: (setq vla-line (vlax-ename->vla-object (entlast)))
    #<VLA-OBJECT IAcadLine 01f1bb4c>
    

    Возвращаемое значение переменной есть объект vla. Теперь можно визуально отслеживать значения этой переменной, выделив ее и выбрав команду VIEW - INSPECT. То же самое можно сделать в окне CONSOLE, запустив функцию (vlax-dump-object vla-line)

    Возникающее окно инспектора показано на рис. 9.2.

    (рис 9.2) Окно инспектора объекта VLA

    Для получения начальной точки объекта используется функция VLA-GET-STARTPOINT. В рассматриваемом примере отрезок был преобразован в объект vla, свойства которого содержит переменная vla-line. Для получения начальной точки можно ввести следующее выражение:

    (setq Starting (vla-get-startpoint vla-line))↵

    В ответ будет выдано сообщение:

    #<variant 8197 …>

    Чтобы преобразовать координаты начальной точки из типа данных variant к координатному формату, введите следующую строку кода:

    (safe-array-value (vlax-variant-value Starting))↵

    Теперь Visual LISP возвратит координаты начальной точки отрезка: (5.0 5.0 0)

    Чтобы изменить значение свойства StartPoint на (0,0,0), напишите выражение:

    (vla-put-startpoint vla-line (vlax-3d-point '(0 0 0)))↵

    Проверьте отрезок в окне AutoCAD. Для проверки значения свойства StartPoint можно также воспользоваться функцией VLA-GET-STARTPOINT.

    (safe-array-value (vlax-variant-value (vla-get-startpoint vla-line)))↵

    Теперь Visual LISP возвратит такое значение: 1. 0.0 0.0

    Задание 9.1

    Получение и модификация свойств объектов

  • На новом чертеже постройте отрезок (5,5,0)-(15,5,0).
  • В окне CONSOLE редактора AutoLISP введите команду загрузки функции ActiveX (vl-load-com)
  • Для преобразования имени сущности в объект vla введите: (setq vla-line (vlax-ename->vla-object (entlast)))
  • Чтобы просмотреть свойства объекта введите (vlax-dump-object vla-line)
  • Для получения начальной точки отрезка введите: (setq Starting (vla-get-startpoint vla-line))
  • Для преобразования координат начальной точки из типа данных variant к формату отображения координат введите: (safearray-value (vlax-variant-value Starting))
  • Чтобы изменить координаты начальной точки отрезка на 0,0,0, введите: (vla-put-startpoint vla-line (vlax-3d-point '(0 0 0)))
  • Проверьте отрезок - его начальная точка находится в начале координат.
  • Создание объектов с помощью функций 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?
  • Возможна ли работа с примитивами не только в активном документе, но и в других открытых чертежах?
  • Страницы:

    Цель лекции: приобрести простейшие навыки работы с элементами ActiveX.

    Объектная модель AutoCAD

    Объекты ActiveX в системе AutoCAD рассматриваются как иерархия, содержащая примитивы, символьные таблицы, словари и пр. Однотипные объекты объединяются в семейства (collections).

    Высшим элементом в иерархии является объект Application (AcadApplication) . Этот объект является родительским для следующих объектов:

  • Preferences (Настройки);
  • VBE (объект интегрированной среды VBA-приложений);
  • Documents (Документы);
  • MenuBar (Строка меню);
  • MenuGroups (Группы меню).
  • Эти объекты, в свою очередь, являются родительскими для объектов более низких уровней. Семейство Documents включает в себя объекты Document - открытые документы или рисунки. В семейство MenuGroups входят объекты типа MenuGroup (Группа меню или Группа адаптации). В семейство MenuBar входят объекты типа PopupMenu (Падающие меню, загруженные в строку меню).

    Наиболее важным для практики является объект Document. Он включает в себя, в частности, такие семейства:

  • Blocks (Блоки);
  • ModelSpase (Пространство модели);
  • PaperSpace (Пространство листа);
  • Dictionaries (Словари);
  • DimStyles (Размерные стили);
  • Groups (Группы);
  • Layers (Слои);
  • Layouts (Листы);
  • Linetypes (Типы линий);
  • Plot (Печать);
  • PlotConfigurations (Конфигурации печати);
  • Preferences (Настройки чертежа);
  • RegisteredApplications (Зарегистрированные приложения);
  • SummaryInfo (Свойства чертежа);
  • SelectionSets (Выделенные наборы);
  • TextStyles (Текстовые стили);
  • UCSs (Пользовательские системы координат);
  • Utility (Утилита);
  • Viewports (Видовые экраны);
  • Views (Виды).
  • Полностью список объектов показан на рис. 9.1.

    (рис 9.1) Список объектов AutoCAD

    В семейства Blocks, ModelSpase и PaperSpace входят объекты, которые соответствуют графическим примитивам. Pис. 9.1 взят из справочной службы AutoCAD: ActiveX and VBA Reference - Object Model.

    Для реализации базовых инструментов объектной технологии в модели предусмотрены компоненты, называемые интерфейсами. В базовом интерфейсе описываются все типичные свойства и методы. Например, базовым интерфейсом всех графических примитивов является IAcadEntity. Он является родительским для интерфейса IAcadLine. С помощью этого интерфейса создаются объекты семейства AcDLine, представителем которого является объект Line.

    Каждый объект в технологии ObjectX имеет свои свойства и методы. Свойства можно читать или изменять с помощью соответствующих функций. Функции, соответствующие методам, реализуются в командах с соответствующими параметрами. Элементами объектной модели являются также события. Они возникают в результате действий пользователя (Click) или при изменениях в программе (onLoad). Программа может отслеживать события и реализовать сценарий отклика на события.

    С полным перечнем объектов, свойств, методов и событий можно познакомиться в справочной службе AutoCAD.

    Функции и типы данных

    Функции, реализующие технологию ActiveX в Visual LISP, имеют префиксы vla-, vlax-, vlr. Доступ к этим функциям можно получить только после выполнения в данном сеансе AutoCAD функции vl-load-com.

    Работа с каждым из объектов в технологии ActiveX ведется на уровне указателей. Они носят название VLA-объекты. VLA-объектами являются указатели не только графических примитивов, но и документов, пространства модели и приложений.

    Практически обязательной для всех приложений, использующих ActiveX, является следующая структура функций:

    (defun begin_activex ( / )
    (vl-load-com)
    (setq acad_app (vlax-get-acad-object))
    (setq active_doc (vla-get-activedocument acad_app))
    (setq model_space (vla-get-modelspace active_doc))
    (setq paper_space (vla-get-paperspace active_doc))
    ); defun
    

    В результате выполнения функции begin_activex будут получены следующие VLA-объекты:

  • acad_app приложение AutoCAD;
  • active_doc активный документ;
  • model_space пространство модели;
  • paper_space пространство листа.
  • После получения основных VLA-объектов можно через них обращаться к другим элементам иерархии системы AutoCAD (примитивам, таблицам и пр.) для получения или модификации их свойств и методов. Основным средством получения VLA-объекта для примитива является функция vlax-ename->vla-object. Обратная функция vlax-vla-object->ename.

    Кроме VLA-объектов, в ActiveX используют новые типы данных: безопасные массивы и варианты.

    Безопасные массивы являются массивами однотипных объектов. Они создаются с помощью функций

  • vlax-make-safearray;
  • vlax-safearray-put-element;
  • vlax-safearray-fill.
  • Для извлечения данных из безопасных массивов с целью использования обычных LISP-функций применяются функции:

    vlax-safearray-get-dim;
    vlax-safearray-get-l-bound;
    vlax-safearray-get-u-bound;
    vlax-safearray-get-element;
    vlax-safearray-type.
    

    Для преобразования массива в список используют функцию

    vlax-safearray->list.

    Варианты - это структуры, которые могут хранить однотипные данные. Тип данных является типом варианта. Создание варианта выполняется с помощью функции (vlax-make-variant [<данное> [<целое>]]).

    В качестве второго аргумента передается целое число, задающее тип варианта. Если оно опущено, то тип варианта определяется по типу первого аргумента. В качестве значения аргумента <целое> используются зарезервированные константы.

    Константа Значение Описание
    Vlax-vbEmpty 0 Неинициализированный (значение по умолчанию)
    Vlax-vbNull 1 Пустой (без данных)
    Vlax-vbInteger 2 Короткое целое число
    Vlax-vbLong 3 Длинное целое число
    Vlax-vbSingle 4 Вещественное число
    Vlax-vbDouble 5 Вещественное число с двойной точностью
    Vlax-vbString 8 Строка
    Vlax-vbObject 9 Объект
    Vlax-vbBoolean 11 Булево значение
    Vlax-vbArray 8192 Массив

    Примеры функций, выполняющих операции с вариантами:

  • vlax-variant-type - получение типа варианта;
  • vlax-variant-value - получение значения варианта;
  • vlax-variant-change-type - изменение типа варианта;
  • vlax-variant-type - оформление трехмерной точки как варианта.
  • Использование элементов ActiveX в Visual LISP

    Элементы ActiveX - это программный интерфейс, который используется в поддерживающих его языках программирования. Элементы ActiveX обеспечивают взаимодействие между объектами, с одной стороны, и пользователем или приложением, с другой стороны. Технология ActiveX позволяет получать информацию об объектах чертежа с помощью функций доступа (get functions) и модифицировать объекты с помощью функций модификации (put functions).

    Выше было рассмотрено, как извлекать и модифицировать информацию об объектах с помощью функций-интерфейсов на языке AutoLISP. Элементы ActiveX обеспечивают аналогичный способ получения и модификации информации. Однако для этого необходима определенная подготовка.

    AutoCAD предоставляет все свои объекты, включая функции доступа и модификации, в распоряжение элементов ActiveX. Вначале в Visual LISP необходимо перед началом сеанса работы загрузить все функции ActiveX с помощью функции (vl-load-com)

    При этом все функции-интерфейсы ActiveX станут доступными. Загрузив интерфейс ActiveX, можно выполнить необходимые действия над созданным ранее отрезком. Но вначале нужно преобразовать имя сущности в объект vla. Этот объект ActiveX практически ничем не отличается от имени сущности, но содержит ряд свойств, которые отсутствуют в его аналоге в языке AutoLISP. Для преобразования используется функция vlax-ename->vla-object. Пример обращения к этой фунции:

    (setq vla-line (vlax-ename->vla-object (entlast)))↵
    Среда Visual LISP возвратит следующее выражение:
    #<VLA-OBJECT IAcadLine 03612b14>
    

    Протокол операций будет выглядеть следующим образом:

    Command: _line Specify first point: 5,5,0
    Specify next point or [Undo]: 15,-5,0
    Specify next point or [Undo]: *Cancel*
    Command: '_.zoom _e
    Command: (vl-load-com)
    Command: (setq vla-line (vlax-ename->vla-object (entlast)))
    #<VLA-OBJECT IAcadLine 01f1bb4c>
    

    Возвращаемое значение переменной есть объект vla. Теперь можно визуально отслеживать значения этой переменной, выделив ее и выбрав команду VIEW - INSPECT. То же самое можно сделать в окне CONSOLE, запустив функцию (vlax-dump-object vla-line)

    Возникающее окно инспектора показано на рис. 9.2.

    (рис 9.2) Окно инспектора объекта VLA

    Для получения начальной точки объекта используется функция VLA-GET-STARTPOINT. В рассматриваемом примере отрезок был преобразован в объект vla, свойства которого содержит переменная vla-line. Для получения начальной точки можно ввести следующее выражение:

    (setq Starting (vla-get-startpoint vla-line))↵

    В ответ будет выдано сообщение:

    #<variant 8197 …>

    Чтобы преобразовать координаты начальной точки из типа данных variant к координатному формату, введите следующую строку кода:

    (safe-array-value (vlax-variant-value Starting))↵

    Теперь Visual LISP возвратит координаты начальной точки отрезка: (5.0 5.0 0)

    Чтобы изменить значение свойства StartPoint на (0,0,0), напишите выражение:

    (vla-put-startpoint vla-line (vlax-3d-point '(0 0 0)))↵

    Проверьте отрезок в окне AutoCAD. Для проверки значения свойства StartPoint можно также воспользоваться функцией VLA-GET-STARTPOINT.

    (safe-array-value (vlax-variant-value (vla-get-startpoint vla-line)))↵

    Теперь Visual LISP возвратит такое значение: 1. 0.0 0.0

    Задание 9.1

    Получение и модификация свойств объектов

  • На новом чертеже постройте отрезок (5,5,0)-(15,5,0).
  • В окне CONSOLE редактора AutoLISP введите команду загрузки функции ActiveX (vl-load-com)
  • Для преобразования имени сущности в объект vla введите: (setq vla-line (vlax-ename->vla-object (entlast)))
  • Чтобы просмотреть свойства объекта введите (vlax-dump-object vla-line)
  • Для получения начальной точки отрезка введите: (setq Starting (vla-get-startpoint vla-line))
  • Для преобразования координат начальной точки из типа данных variant к формату отображения координат введите: (safearray-value (vlax-variant-value Starting))
  • Чтобы изменить координаты начальной точки отрезка на 0,0,0, введите: (vla-put-startpoint vla-line (vlax-3d-point '(0 0 0)))
  • Проверьте отрезок - его начальная точка находится в начале координат.
  • Создание объектов с помощью функций 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?
  • Возможна ли работа с примитивами не только в активном документе, но и в других открытых чертежах?
  • Вернуться к учебному плану