![]() |
| Главная »Статьи »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. Внимание! Запрещается воспроизведение
данной статьи или ее части без согласования с автором. Если вы желаете разместить
эту статью на своем сайте или издать в печатном виде, свяжитесь с автором. |
|||||||||||||||||||||||||||||||||||||