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

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

Отслеживание событий

Существует три типа событий - уровня приложения, уровня документа и уровня объекта. События первого типа связаны с открытием, сохранением, закрытием и печатью документа, загрузкой-выгрузкой приложений, изменением системных переменных. События второго типа связаны с добавлением, удалением, изменением объектов, активацией меню, изменением размеров окна рисунка, регенерацией, открытием, закрытием, печатью чертежа и др. И события уровня объекта возникают только тогда, когда объект изменился.

Написание обработчиков событий

События дают информацию о состоянии или активности. Хотя обработчики событий написаны специально для того, чтобы отвечать на события, AutoCAD часто вмешивается в обработку событий. Следовательно, обработчики событий имеют ограничения для выполнения безопасных операций в союзе с AutoCAD и его базой данных. Не стоит надеяться на последовательность событий, т.к. они могут случиться в любом порядке, что следует учитывать в обработчике. К примеру, при вызове команды Open происходят события BeginCommand, BeginOpen, EndOpen и EndCommand, но случиться они могут в любом порядке, кроме пожалуй только события начала и события завершения. Не надейтесь также на последовательность операций (например, при удалении двух объектов не обязательно, что событие удаления объекта 1 будет после 2). Не пытайтесь применять в обработчиках любые интерактивные функции, например ввод от пользователя. Не запускайте диалоговые окна, можно только окна сообщений. Писать данные можно в любой объект базы чертежа, кроме того, который вызвал событие. Любой объект, вызвавший событие, остается открытым для AutoCADа, но запись в него может быть фатальной, читать же можно без ограничений. Не выполняйте в обработчике событий действий, которые вызывают подобный обработчик. (например открытие документа из обработчика события BeginOpen.

Обработчики событий уровня приложения

Данные события не становятся автоматически доступны при загрузке VBA, поэтому они должны быть разрешены вручную. После этого будут доступны следующие события:

  • AppActivate - происходит сразу перед активацией главного окна приложения;
  • AppDeactivate - происходит сразу перед деактивацией главного окна приложения;
  • ARXLoaded - происходит при загрузке ARX-приложения;
  • ARXUnLoaded - происходит при выгрузке ARX-приложения;
  • BeginCommand - происходит как только начала выполняться команда, но еще не завершена;
  • BeginFileDrop - происходит когда файл "сброшен" в главное окно приложения;
  • BeginLISP - происходит когда AutoCAD получает запрос на выполнение выражения LISP;
  • BeginModal - происходит сразу перед появлением модального окна;
  • BeginOpen - происходит сразу после того как AutoCAD получает запрос на открытие файла;
  • BeginPlot - происходит сразу после того как AutoCAD получает запрос на печать;
  • BeginQuit - происходит сразу перед тем как завершается сессия;
  • BeginSave - происходит сразу после получения AutoCADом запроса на сохранение;
  • EndCommand - происходит сразу при завершении команды;
  • EndLISP - происходит сразу при завершении вычисления выражения LISP;
  • EndModal - происходит сразу после закрытия модального окна диалога;
  • EndOpen - происходит сразу после окончания процесса открытия чертежа;
  • EndPlot - происходит сразу после завершения отправки на принтер;
  • EndSave - происходит сразу по завершении сохранения;
  • LISPCancelled - происходит при отмене выражения LISP;
  • NewDrawing - происходит сразу перед созданием чертежа;
  • SysVarChanged - происходит когда меняется значение системной переменной;
  • WindowChanged - происходит при изменении окна приложения;
  • WindowMovedOrResized - происходит при перемещении или изменении размера окна приложения.

Как разрешить события уровня приложения

Перед тем как начать использовать события уровня приложения следует создать новый модуль класса и объявить объект типа AcadApplication с применением ключевого слова WithEvents. Порядок работы следующий:

  1. В VBA IDE вставить модуль класса
  2. Выбрать новый модуль класса в окне проекта
  3. Изменить имя на EventClassModule
  4. В окне кода для класса добавить строку:
Public WithEvents App As AcadApplication

После того как новый объект объявлен с событиями он появится в окне списка объектов в модуле класса и можно выбирать процедуры событий для вновь созданного объекта из выпадающего списка. Однако перед тем как запустить процедуру нужно соединить объявленный объект с объектом Application, делается это с помощью такого кода в окне основного модуля:

Dim X As New EventClassModule

Sub InitializeEvents()
    Set X.App = ThisDrawing.Application
End Sub
' далее в коде основного модуля
Call InitializeEvents

После того как выполнится процедура InitializeEvents объект App модуля класса будет указывать на объект Приложение (Application) Пример перехвата процесса загрузки, когда файл методом Drag-And-Drop перенесен в окно AutoCAD, выводящее окно сообщения с именем файла

' * * * В модуле класса * * *
Option Explicit
Public WithEvents App As AcadApplication
Sub Example_AcadApplication_Events()
  ' Инициализируем глобальную переменную App
  ' которая будет использоваться для перехвата событий AcadApplication
  ' Обязательно запустить ее в начале
  Set App = GetObject(, "AutoCAD.Application")
End Sub

Private Sub App_BeginFileDrop(ByVal FileName As String, Cancel As Boolean)
 ' Пример перехвата события BeginFileDrop, каркас данной процедуры
 ' получен выбором из списка методов объекта App модуля класса в окне кода.
 ' Событие возникает как только файл перетащен в окно AutoCAD.
 '
 If MsgBox("AutoCAD загружает " & FileName & vbCrLf _
          & "продолжить загрузку?", vbYesNoCancel + vbQuestion) <> vbYes Then
     Cancel = True
 End If
End Sub

' * * * В основной процедуре * * *
Option Explicit
Dim X As New EventClassModule
Sub InitializeEvents()
    Set X.App = ThisDrawing.Application
End Sub

Sub main()
Call InitializeEvents
End Sub

Обработка событий уровня документа

События уровня документа постоянно происходят в процессе работы AutoCADа. Это значит, что они автоматически делаются доступными при загрузке проекта VBA, однако не доступны, например, для VB. То есть для других ActiveX Automation приложений их надо разрешать вручную. Доступны следующие события:

  • Activate - происходит в момент активации документа;
  • BeginClose - происходит перед закрытием документа;
  • BeginCommand - происходит сразу после начала выполнения команды, но до ее завершения;
  • BeginDoubleClick - происходит в момент двойного щелчка мышью;
  • BeginLISP - происходит сразу после получения AutoCADом запроса на вычисление выражения LISP;
  • BeginPlot - происходит сразу после получения AutoCADом запроса на печать документа;
  • BeginRightClick - происходит после "правого щелчка" мышью в окне документа;
  • BeginSave - происходит сразу после получения AutoCADом запроса на сохранение документа;
  • BeginShortcutMenuCommand - происходит после "правого щелчка" мышью, но до появления всплывающего меню в режиме команд;
  • BeginShortcutMenuDefault - происходит после "правого щелчка" мышью, но до появления всплывающего меню в режиме по-умолчанию;
  • BeginShortcutMenuEdit - происходит после "правого щелчка" мышью, но до появления всплывающего меню в режиме редактирования;
  • BeginShortcutMenuGrip - происходит после "правого щелчка" мышью, но до появления всплывающего меню в режиме "ручки";
  • BeginShortcutMenuOsnap - происходит после "правого щелчка" мышью, но до появления всплывающего меню в режиме объектной привязки;
  • Deactivate - происходит при деактивации окна документа;
  • EndCommand - происходит сразу после завершения команды;
  • EndLISP - происходит при завершении вычисления выражения LISP;
  • EndPlot - происходит после отправки документа на печать;
  • EndSave - происходит когда окончено сохранение документа;
  • EndShortcutMenu - происходит после появления всплывающего меню;
  • LayoutSwitched - происходит после переключения на другой Layout;
  • LISPCancelled - происходит когда прервано вычисление выражения LISP;
  • ObjectAdded - происходит когда добавлен объект;
  • ObjectErased - происходит когда удален объект;
  • ObjectModified - происходит когда изменен объект;
  • SelectionChanged - присходит когда изменен выбор;
  • WindowChanged - происходит когда изменено окно документа;
  • WindowMovedOrResized - происходит сразу после изменения размера или перемещения окна документа.

Пример кодирования обработчиков событий уровня документа

Для этого нужно просто выбрать объект AutocadDocument из выпадающего меню в окне кода среды VBA IDE. Доступные события появятся в окне процедур, после выбора любой из них будет вставлен каркас процедуры обработки события. Данные процедуры будут касаться только активного документа. Пример обновления всплывающего меню при возникновении событий BeginShortcutMenuDefault и EndShortcutMenu путем добавления к нему пункта. Изменение не затрагивает файлы меню.

' это в модуле класса
Option Explicit
Public WithEvents mydoc As AcadDocument

Private Sub mydoc_BeginShortcutMenuDefault(ShortcutMenu As IAcadPopupMenu)
  On Error Resume Next
  ' Добавим пункт меню
  Dim newMenuItem As AcadPopupMenuItem
  Dim openMacro As String
  openMacro = Chr(27) + Chr(27) + Chr(95) + "open" + Chr(32)
  Set newMenuItem = ShortcutMenu.AddMenuItem(0, Chr(Asc("&")) + "OpenDWG", openMacro)
End Sub

Private Sub mydoc_EndShortcutMenu(ShortcutMenu As IAcadPopupMenu)
  On Error Resume Next
  ShortcutMenu.Item("OpenDWG").Delete
End Sub

' это в основном модуле
Option Explicit
Dim X As New EventClass
Sub InitializeEvents()
    Set X.mydoc = ThisDrawing
End Sub
Sub main()
  Call InitializeEvents
End Sub

Обработка событий уровня объекта

События уровня объекта не доступны на момент загрузки VBA. После того как они сделаны доступны становится доступно событие Modified. Следующий пример создает полилинию с обработчиком события, который показывает новую площадь при изменении полилинии.

' в модуле класса с именем EventClass
Option Explicit
Public WithEvents Object As AcadCircle

Private Sub Object_Modified(ByVal pObject As IAcadObject)
On Error GoTo errmsg
MsgBox "Площадь " & pObject.ObjectName & " " & pObject.Area
Exit Sub
errmsg:
MsgBox Err.Description
End Sub

' В основой программе
Dim X As New EventClass
Sub main()
Call InitializeEvents
End Sub

Sub InitializeEvents()
   Dim MyCircle As AcadCircle
   Dim centerPoint(0 To 2) As Double
   Dim radius As Double
   centerPoint(0) = 0#: centerPoint(1) = 0#: centerPoint(2) = 0#: radius = 5#
   Set MyCircle = ThisDrawing.ModelSpace.AddCircle(centerPoint, radius)
   Set X.Object = MyCircle
   ZoomExtents
End Sub
Алексей Тимонин
Алексей Тимонин
Что возвращает функция chr() в таком примере (chr (- 65 1))?
Алексей Потапкин
Алексей Потапкин
как передать параметры в макрос
Александр Яковлев
Александр Яковлев
Россия, г. Москва
Александр Захаров
Александр Захаров
Россия, Рязань