Главная »Статьи »AutoCAD и Delphi » |
Способ №1 – раннее связывание. В Delphi из меню Project выберите Import Type Library…, в окне Import Type Library нажмите Add и укажите acad.tlb в каталоге AutoCAD (для AutoCAD 2000 — 2002) или acax16enu.tlb в каталоге …Common Files\Autodesk Shared (для AutoCAD 2004 — 2006). Нажмите Install и установите предлагаемые компоненты. Итак, для AutoCAD 2002 на палитре ActiveX появятся компоненты: TAcadDatabase, TAcadDocument, TAcadLayerStateManager из которых наибольшую ценность представляет TAcadDocument. Теперь, когда подготовительные операции завершены, начните новое приложение, добавьте на форму компонент TAcadDocument, поставьте его свойство AutoConnect в True, добавьте кнопку и на ее событие Click следующий код: |
|||||||||||||||||||||||||||||||||||||
var StartPoint, EndPoint: OleVariant; begin // начальная точка отрезка StartPoint:= VarArrayCreate([0, 2], varDouble); StartPoint[0]:= 0; // X-координата StartPoint[1]:= 0; // Y-координата StartPoint[2]:= 0; // Z-координата // конечная точка отрезка EndPoint:= VarArrayCreate([0, 2], varDouble); EndPoint[0]:= 100; EndPoint[1]:= 100; EndPoint[2]:= 0; // добавление отрезка AcadDocument1.ModelSpace.AddLine(StartPoint, EndPoint); AcadDocument1.Application.Update; end; При запуске созданного примера происходит присоединение к запущенному экземпляру AutoCAD или загрузка, если AutoCAD не был ранее запущен. Нажмите кнопку – AutoCAD нарисует отрезок. Вот собственно и все… Импортирование и использование библиотеки типов удобно
по нескольким причинам:
Имеется и недостаток: вы всегда жестко привязаны именно к той версии AutoCAD, от которой взяли tlb за счет включенных в Type Library GUID. По этой причине далее я не буду использовать библиотеку типов. Важно! В основновном по этой причине приводимые в статьях определения
методов и свойств не всегда имеют типы данных, совпадающие с определенными
в импортированной AutoCAD Type Library. Так, например, в AutoCAD_TLB.pas определение
метода AddLine таково: Способ №2 – позднее связывание. Для его использования не требуется библиотека типов, но нужно хорошее знание объектной модели AutoCAD и в этом помогает справка: acad.chm => ActiveX and VBA => ActiveX and VBA Reference => Object Model. Подключение можно выполнить с помощью такой функции: uses ComObj, ActiveX; resourcestring rsAcadNotFound = 'AutoCAD не найден!'; var Acad: OleVariant; procedure AcConnect(const acClassName: String; const acNewInstance: Boolean; const acVisible: Boolean); var IU: IUnknown; ClassID: TCLSID; IsCreate: Boolean; ErrorCode: HResult; begin if VarIsClear(Acad) then // если еще не присоединились… begin // если AutoCAD не установлен — произойдет ошибка ErrorCode:= CLSIDFromProgID(PWideChar(WideString(acClassName)), ClassID); if not Succeeded(ErrorCode) then raise EOleSysError.Create(rsAcadNotFound, ErrorCode, 0); // пытаемся присоединиться к уже запущенному экземпляру AutoCAD IsCreate:= acNewInstance or (not Succeeded(GetActiveObject(ClassID, nil, IU))); if IsCreate then try // запускаем новый экземпляр AutoCAD Acad:= CreateComObject(ClassID) as IDispatch; except raise EOleSysError.Create(rsAcadNotFound, ErrorCode, 0); end else Acad:= IU as IDispatch; // управляем видимостью AutoCAD if not VarIsClear(Acad) then Acad.Visible:= acVisible; end; end; Где-то в программе: AcConnect('AutoCAD.Application', True, False); |
|||||||||||||||||||||||||||||||||||||
Но сначала посмотрим как спрятать: procedure AcHide; begin if not VarIsClear(Acad) then Acad.Visible:= False; end; А теперь покажем. Вот здесь начинаются хитрости. Казалось бы надо просто написать: Acad.Visible:= True; Я делаю так: procedure AcShow(WndState: AcWindowState = acMax); begin if not VarIsClear(Acad) then begin Acad.Visible:= True; Acad.WindowState:= WndState; end; end; Зачем нужен Acad.WindowState:= WndState? Закомментируйте эту строку и запустите пример. Нажимайте кнопки Connect, Show, Hide. Все работает. Сделайте его видимым, затем минимизируйте. И нажмите Show — AutoCAD не вернется из минимизированного состояния. Можете нажимать Hide и Show — это будет приводить только к скрытию/появлению кнопки AutoCAD в панели задач. Вот это и исправляет Acad.WindowState:= WndState. Константа acMax взята из AutoCAD_TLB.pas, так что говоря выше, что не буду использовать библиотеку типов я немного слукавил. Cовсем отказаться от нее не получится. Тип AcWindowState определен в AutoCAD_TLB.pas как TOleEnum.
Сам же TOleEnum определен в ActiveX.pas. В Delphi 5 он был определен как Integer,
что неверно и создавало трудности, например при задании весов линий (LineWeight)
по-слою, когда LineWeight = acLnWtByLayer ($FFFFFFFF). В Delphi 7 TOleEnum верно
определен как синоним LongWord. |
|||||||||||||||||||||||||||||||||||||
procedure AcRelease; begin if not VarIsClear(Acad) then begin Acad.Quit; Acad:= Unassigned; end; end; Примечания:
|
|||||||||||||||||||||||||||||||||||||
Если AutoCAD-ов несколько, то в функции AcConnect параметру acClassName необходимо задать соответствующее значение имени класса. Мне известны такие версии под Windows:
Если имя класса задать AutoCAD.Application, то присоединение будет производится к той версии, которая была использована последней. Выяснить какая версия последняя, можно в реестре по ветке: HKEY_CURRENT_USER\Software\Classes\AutoCAD.Application. Для этого пригодится функция: function GetCurrAutoCADClassName: String; var reg: TRegistry; res: Boolean; begin Result:= EmptyStr; reg:= TRegistry.Create; try with reg do begin RootKey:= HKEY_CURRENT_USER; res:= OpenKeyReadOnly('\Software\Classes\AutoCAD.Application\CurVer'); if not res then Exit; Result:= ReadString(''); end; finally FreeAndNil(reg); end; end; Чтобы узнать какие версии AutoCAD установлены, необходимо в реестре смотреть ветку HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD. Для этого предлагается следующая функция: function EnumAutoCAD(Items: TStrings): Boolean; var reg: TRegistry; begin reg:= TRegistry.Create; try with reg do begin RootKey:= HKEY_LOCAL_MACHINE; Result:= OpenKeyReadOnly('\SOFTWARE\Autodesk\AutoCAD'); if not Result then Exit; GetKeyNames(Items); end; finally FreeAndNil(reg); end; end; Для AutoCAD 2002 и AutoCAD 2006 она возвращает следующий список: Для преобразования символических имен в имена класса пригодится функция: function AutoCADFamilyNameToClassName(const AFamilyName: String): String; var p: Integer; begin Result:= AFamilyName; p:= Pos('.', Result); if Copy(Result, p, MaxInt) = '.0' then Delete(Result, p, MaxInt); Result:= StringReplace(Result, 'R', 'AutoCAD.Application.', [rfIgnoreCase]); end; Иногда нужно достать до настроек AutoCAD, профилей. Все это лежит в ветке HKEY_CURRENT_USER\Software\Autodesk\AutoCAD, однако добраться туда не так просто. Дело в том, что внутри ветки AutoCAD лежит ветка R15.0, а внутри ее, например, ACAD-1:409 и уже там заветная ветка Profiles. Для AutoCAD 2006 путь может быть таким: \R16.2\ACAD-4001:409\Profiles. Имена веток ACAD-XX:YY могут меняться. Значения XX:YY, в моем случае, формируются по принципу ProductId:LocaleId. Чтобы знать их наверняка нужно читать ветку: HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\Hardcopy, например такой функцией: function EnumAutoCADHardcopy(Items: TStrings): Boolean; var reg: TRegistry; begin reg:= TRegistry.Create; try with reg do begin RootKey:= HKEY_LOCAL_MACHINE; Result:= OpenKeyReadOnly('SOFTWARE\Autodesk\Hardcopy'); if not Result then Exit; GetValueNames(Items); end; finally FreeAndNil(reg); end; end; Функция возвращает относительные пути к веткам, например: К статье прилагаются примеры на Delphi 7. Внимание! Запрещается воспроизведение
данной статьи или ее части без согласования с автором. Если вы желаете разместить
эту статью на своем сайте или издать в печатном виде, свяжитесь с автором. |