Библиотека Интернет Индустрии I2R.ru |
|||
|
VBA взрослеет. Cоздание утилиты для AutoCAD 2000 с помощью VBAС появлением AutoCAD 2000, VBA в AutoCAD достиг совершеннолетия. Новая версия избавилась от многих ограничений начальной реализации VBA в AutoCAD R14, и добавила реальные функциональные возможности непосредственно к AutoCAD. Чтобы почуствовать, что Вы можете теперь делать с помощью VBA, эта статья, представляет простую утилиту MRU +. Эта утилита, показанная на Рис.1, сохраняет список последних открытых чертежей, показывает Вам те, которые загружены в настоящее время, и позволяет Вам загружать и выгружать чертежы просто устанавливая галочку рядом с названием чертежа. Хотя это простая утилита, но MRU + демонстрирует многие из новых возможнстей VBA в AutoCAD, и должна помочь научить вас владеть средой VBA в AutoCAD Рис.1 MRU+ - утилита, которая позволяет следить за недавно использоваными файлами AutoCAD Добро пожаловать в VBA AutoCAD Как уже было сказано, на примере MRU +, вы сможете увидеть многие из новых возможностей AutoCAD 2000. Эта статья не является обзором этого программного продукта, так что я не буду пытаться описать их всех; акцент ставится на предметах, которые важны разработчикам VBA. Однако, это отображает нескольких из основных усовершенствований в этой версии AutoCAD:
Два типа проектов в VBA AutoCAD 2000 позволяет хранить VBA, проекты или как часть документа (указывается как внедренный проект), или как отдельный файл (указывается как Глобальный проект). Каждый загруженный рисунок может иметь единственный внедренный проект, или не иметь внедренного проекта вообще. Кроме того, Вы можете иметь любое число глобальных проектов, загруженных в AutoCAD. Чтобы управлять этими двумя типами проектов, AutoCAD включает Диспетчер VBA (в падающем меню - Tools | Macro | VBA Manager). Этот инструмент, показанный на Рис.2, позволяет Вам выполнять следующие операции:
Рис.2. Диалоговое окно VBA Manager позволяет Вам манипулировать внедренными и глобальными проектами VBA Конечно, глобальный проект более предпочтителен для утилиты, разработанной, чтобы фиксировать информацию относительно множества чертежей. В случае MRU +, глобальный проект это фалй MRUPlus.dvb. Расширение "dvb" используется AutoCAD для глобальных проектов, сохраненных на диске. Загрузка при запуске AutoCAD 2000 автоматически не инициализирует VBA всякий раз, когда Вы его запускаете. Скорее, VBA загружается по требованию. Однако, имеются два способа когда Вы можете загружать и запускать код VBA при запуске. Во первых, Вы можете создавать глобальный проект VBA, с названием acad.dvb, и сохранять его в вашем каталоге AutoCAD. Любой проект с этим названием будет автоматически загружен при запуске AutoCAD. Далее, если это содержит макроc ( процедуру Sub ) с названием AcadStartup, эта макрокоманда будет автоматически выполняться, как только файл acad.dvb загружен. Как вариант, Вы можете расположить команды AutoLisp в файле acad.lsp, который также должен быть в каталоге AutoCAD. Любая функция AutoLisp названая STARTUP в этом файле будет автоматически выполняться, когда файл загружен. Как вы будете видеть в этой статье, Autodesk сделала хорошую работу по созданию связи между старшим языком Lisp и более новым языком VBA, что бы стало возможно для кода Lisp, вызвать код VBA и наоборот. Для приложения, хорошая мысль, модифицировать файл acad.lsp, чтобы загружать приложение при запуске. Большинство пользователей AutoCAD знакомы с изменением этого файла и с языком Autolisp, так что добавление строки кода, чтобы загрузить ваше приложение должно быть для них просто. Вы можете просто загружать приложение, или можете загружать приложение и запускать макрос из него в то же самое время. Чтобы загрузить приложение, Вы можете использовать код Autolisp, чтобы вызвать команду AutoCAD vbaload: (defun S::STARTUP() (command "_vbaload" "myproject.dvb") ) Или, чтобы запустить процесс инициализации в приложении, Вы можете вызывать команду vbarun: (defun S::STARTUP() (command "_-vbarun" "MRUPlus.dvb!basMRUPlus.LoadMRUPlus") ) Аргумент команды vbarun может быть полностью квалифицирован в форме: FileName!ModuleName.MacroName Если указанный файл не загружен, он будет сначала загружен, и затем будет выполнен макрос. По умолчанию, команды vbarun или vbaload загружают файлы только из главного каталога AutoCAD. Если ваша утилита сохранена в другом месте, вы будете должны указать полный путь и имя файла в аргументе. В этом случае, Вы нуждаетесь в "escape" из знаков наклонной черты влево, удваивая их. Например, это имело силу бы в файле acad.lsp: (defun S::STARTUP() (command "_vbaload" "c:\\Utilities\\myproject.dvb") ) Управление Меню Как часть своего загрузочного кода, MRU + добавляет себя к меню AutoCAD File, только выше встроенного списка последних использованных файлов. В предыдущих версиях AutoCAD, эта операция была полностью невозможна для кода VBA. Теперь новая ветвь объектной модели AutoCAD делает такие вещи тривиальными. Рис.3 показывает новый объекты AutoCAD, доступные для манипулирования инструментальной панелью и меню. Объект MenuBar контролирует все меню, в настоящее время отображенные в главной строке меню AutoCAD. Вы можете вставилять и удалять меню, вызывая методы InsertInMenuBar и RemoveFromMenuBar объекта PopupMenu. Рис.3. Объекты для манипуляции меню и панелями инструментов Объект PopupMenu представляет стандартное падающее меню, или меню вызываемое по правой кнопке мыши. Объект PopupMenuItem представляет единственный пункт меню. Система MenuGroups содержит набор объектов MenuGroup. Каждый MenuGroup может содержать меню и панели инструментов. Вы можете загружать группы меню из файла на диске. После того, как вы загрузили группу меню, ее содержание станет доступным, чтобы загрузиться в MenuBar или сокращенные меню. Система Toolbars содержит объекты Toolbar, каждый из которых представляет панель инструментов. Индивидуальные кнопки панели представлены объектами ToolbarItem. Утилита MRU + делает самую простую возможную операцию с этими объектами: Она прибавляет пункт меню, который отображает интерфейс пользователя к файловому меню. Это делается одной строкой кода: Application.MenuBar(0).AddMenuItem 19, "MRU+", _ "_-vbarun ShowMRUPlus " Этот код добавляет новый пункт к 20-й позиции (считая с нуля) системы PopupMenuItems на крайнем левом PopupMenu в установленному по умолчанию MenuBar (другими словами, к меню File). Второй аргумент - текст, который будет отображаться в меню, и третий аргумент - макрос меню AutoCAD, который вызывается, когда этот пункт меню выбран. Использование макросов меню AutoCAD имеет почти тот же самый синтаксис как команды AutoCAD, но и имеет некоторые различия. Один из них - вызов команды vbarun, используя синтаксис подчеркивания и черты чтобы подавить показ диалогового окна, которое это обычно вызвало бы. Заметьте присутствие пробела после имени макроса VBA, для выполнения. В макросах меню, конечные пробелы интерпретируется как конец фрагмента входа. Без этого, название макрокоманды VBA было бы внесено в командную строку AutoCAD, но не выполненно. Использование ThisDrawing Хотя можно иметь несколько одновременно загруженных глобальных проектов VBA, они все используют единственный объект названный ThisDrawing. Этот объект представляет собой активный документ в интерфейсе пользователя AutoCAD, и имеет класс AcadDocument. (В отличие от многих других объектных моделей, в модели AutoCAD имена всех объектов начинаються с префикса "Acad", чтобы гарантировать однозначность в операциях). Если несколько проектов VBA включают обработчики для событий для объекта ThisDrawing, каждый из обработчиков событий вызывается по очереди. Использование событий ThisDrawing просто. Каждый глобальный проект VBA, который Вы создаете автоматически, содержит пример объекта ThisDrawing который не может быть удален. В приложении MRU + событие ThisDrawing.BeginClose используется, чтобы сообщить главной форме, когда рисунок выгружается из пользовательского интерфейса. Это событие содержит минимум кода, чтобы вызвать метод public формы интерфейса пользователя, чтобы расположить соответствующий ListItem в ListView и не контролировать это. Таблица ниже содержит списки событий, поддерживаемые ThisDrawing. Как Вы можете видеть, многие из этих событий - новые в AutoCAD. В частности события BeginShortcutMenu, BeginLisp, и Object позволяют осуществлять новые способы взаимодействия с другими языками программирования в AutoCAD. События объекта AcadDocument
Зацепление объекта Application Помимо наличия ThisDrawing, который представляет активный документ, утилита MRU + также должна контролировать события объекта AcadApplication (представляющего непосредственно AutoCAD) чтобы знать, когда новый рисунок был открыт. В отличие от объекта ThisDrawing, однако, глобальные VBA объекты не получают автоматически образец объекта AcadApplication. К счастью, Вы можете использовать в VBA ключевое слово WithEvents, чтобы создать ваш собственный. Последовательность событий, что использует MRU+, чтобы зацепить cобытие EndOpen объекта AcadApplication, который испольняется всякий раз, когда открывается новый рисунок, выделенный в следующих абзацах. Файл acad.lsp, как Вы уже видели, содержит код вызова процедуры LoadMRUPlus в basMRUPlus. Наряду с другим загрузочным кодом, эта процедура устанавливает образец частного класса называемого CApp и устанавливает одно из его свойств: ' Private class used to grab the application events. Private mApp As CApp Public Sub LoadMRUPlus() ... ' Get our event hook into the Application. Set mApp = New CApp Set mApp.App = ThisDrawing.Application Класс CApp существует исключительно как оболочка для объекта AcadApplication. Встроенный объект ThisDrawing содержит свойство Application что указывает на единственный образец объекта AcadApplication, что позволяет просто коду запуска находить это. Ниже показан код для класса CApp. Важным является здесь - то, что частная переменная типа AcadApplication объявлена WithEvents. Это специальное ключевое слово делает события AcadApplication доступными для кодирования в модули класса. Распечатка кода для утилиты MRU + в конце статьи. Option Explicit ' This object will let us intercept events ' for the Application object. Private WithEvents mApp As AcadApplication Private Sub mapp_EndOpen(ByVal FileName As String) ' When a drawing is opened, add it to our MRU list. frmMRUPlus.AddFile FileName, Now, True End Sub Public Property Set App(NewApp As AcadApplication) ' This property must be set to hook things up. Set mApp = NewApp End Property FIGURE 5: The CApp class module. События объекта AcadApplication полностью новые в AutoCAD 2000. В таблице ниже показан список новыех событий предмета AcadApplication. События объекта AcadApplication
Заключение С AutoCAD 2000, VBA в AutoCAD перестал быть являющийся интересным "доказательство концепции", и стал довольно полезным средством. Добавление структурированной объектной модели, способность загружать несколько VBA-проектов и выполнять код при загрузке, а так же интегрирование с Lisp, командной строкой, меню, и панелями инструментов - все это делает возможным писать полезные утилиты, объединенные со стандартным интерфейсом AutoCAD. Хотя MRU + утилита, показанная здесь только как доказательство концепции, она демонстрирует все схемы, которые вы были бы должны делать с любой утилитой для AutoCAD. Autodesk вложил много усилия в создании VBA как первоклассной средой окружения для AutoCAD. Код MRU+ ' ********************************************************* Option Explicit Private Sub AcadDocument_BeginClose() ' Whenever the user closes a drawing, uncheck ' its name on the MRU form. frmMRUPlus.UnCheck ThisDrawing.FullName End Sub ' ********************************************************* ' Code attached to frmMRUPlus. ' ********************************************************* Option Explicit ' Arbitrary counter for generating unique ' keys for ListItems. Private mintDoc As Integer Public Property Let Entries(NewEntries As Integer) ' Set the maximum number of entries to display. txtEntries.Text = NewEntries sbEntries.Value = NewEntries End Property Public Sub AddFile(strFileName As String, _ dblTime As Double, fChecked As Boolean) ' Add a file to the MRU list. Specifies the file name, ' time, and whether it should be checked. If there are ' more than the specified number of entries on the list, ' drops the oldest entry. Dim li As ListItem Dim intI As Integer ' Check for a few common errors and fix 'em up. If Len(strFileName) = 0 Then Exit Sub End If If Val(txtEntries.Text) < 1 Then txtEntries.Text = 10 End If ' Look for an existing item with this name. For intI = 1 To lvwMRU.ListItems.Count If lvwMRU.ListItems(intI).Text = strFileName Then Set li = lvwMRU.ListItems(intI) Exit For End If Next intI ' If there is no such item, we need to add one. If li Is Nothing Then ' Check first to see whether we need to drop an item. If lvwMRU.ListItems.Count >= txtEntries.Text Then Set li = lvwMRU.ListItems(1) ' Find the oldest item to drop. For intI = 2 To lvwMRU.ListItems.Count If CDate(lvwMRU.ListItems(intI).SubItems(1)) < _ CDate(li.SubItems(1)) Then Set li = lvwMRU.ListItems(intI) End If Next intI lvwMRU.ListItems.Remove li.Index End If ' Add the new item with an arbitrary key. Set li = lvwMRU.ListItems.Add(, "K" & mintDoc, _ strFileName) li.SubItems(1) = CDate(dblTime) mintDoc = mintDoc + 1 End If ' Whether the item was new or existed already, check it ' if it wasn't checked and should be checked. If Not li.Checked Then li.Checked = fChecked End If End Sub Public Sub UnCheck(strFileName As String) ' Clears the checkmark next to an item. Dim intI As Integer Dim li As ListItem ' Find the item to clear by comparing names. For intI = 1 To lvwMRU.ListItems.Count If lvwMRU.ListItems(intI).Text = strFileName Then Set li = lvwMRU.ListItems(intI) Exit For End If Next intI ' And if we found it, uncheck it. If Not li Is Nothing Then li.Checked = False End If End Sub Private Sub cmdClose_Click() ' This form stays resident, just hide it. Me.Hide End Sub Private Sub lvwMRU_ItemCheck( _ ByVal Item As MSComctlLib.ListItem) ' When the user checks or unchecks an item, load or ' unload the corresponding drawing. Dim doc As AcadDocument If Not Item Is Nothing Then If Item.Checked Then ' Opening is a method of the Documents collection. Application.Documents.Open Item.Text Else ' Closing is a method of the document. For Each doc In Application.Documents If doc.FullName = Item.Text Then doc.Close Exit For End If Next doc End If End If End Sub Private Sub sbEntries_Change() ' Tie together the textbox and the spin button. txtEntries.Text = sbEntries.Value End Sub Private Sub txtEntries_Change() ' Tie together the textbox and the spin button. sbEntries.Value = txtEntries.Text End Sub Private Sub UserForm_Terminate() ' Write changes in settings to the registry. Dim li As ListItem Dim intI As Integer SaveSetting "MRUPlus", "Options", "Entries", _ txtEntries.Text For intI = 1 To lvwMRU.ListItems.Count Set li = lvwMRU.ListItems(intI) SaveSetting "MRUPlus", "Files", _ "FileName" & intI, li.Text SaveSetting "MRUPlus", "Files", _ "FileTime" & intI, li.SubItems(1) Next intI End Sub ' ********************************************************* ' Code attached to basMRUPlus. ' ********************************************************* Option Explicit ' Private class used to grab the application events. Private mApp As CApp Public Sub LoadMRUPlus() ' Startup code, meant to be called from acad.lsp. Dim doc As AcadDocument Dim intI As Integer Dim intEntries As Integer Dim strName As String ' Get our event hook into the Application. Set mApp = New CApp Set mApp.App = ThisDrawing.Application ' Add our menu item, ignoring error if it already exists. On Error Resume Next Application.MenuBar(0).AddMenuItem 19, "MRU+", _ "_-vbarun ShowMRUPlus " On Error GoTo 0 ' Load the form. Load frmMRUPlus ' Load any open drawings. For Each doc In Application.Documents frmMRUPlus.AddFile doc.FullName, Now, True Next doc ' And load any names we saved in the registry from a ' previous session. On Error Resume Next intEntries = GetSetting("MRUPlus", "Options", _ "Entries", "10") If Err.Number <> 0 Then intEntries = 10 End If On Error GoTo 0 frmMRUPlus.Entries = intEntries For intI = 1 To intEntries strName = GetSetting("MRUPlus", "Files", _ "FileName" & intI) If Len(strName) > 0 Then frmMRUPlus.AddFile strName, CDate(GetSetting( _ "MRUPlus", "Files", "FileTime" & intI)), False End If Next intI End Sub Public Sub ShowMRUPlus() ' Make the form visible. frmMRUPlus.show End SubCApp Option Explicit ' This object will let us intercept events ' for the Application object. Private WithEvents mApp As AcadApplication Private Sub mapp_EndOpen(ByVal FileName As String) ' When a drawing is opened, add it to our MRU list. frmMRUPlus.AddFile FileName, Now, True End Sub Public Property Set App(NewApp As AcadApplication) ' This property must be set to hook things up. Set mApp = NewApp End Property Mike Gunderloy, перевод Виктор Ткаченко |
|
2000-2008 г. Все авторские права соблюдены. |
|