ObjectARX, AutoCAD. Среда программирования библиотеки C++

         

ObjectARX, AutoCAD. Среда программирования библиотеки C++


GS маркеры главным образом полезен в объектном поспешном выполнении примитива.

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

GS маркеры также используются в сочетании с функциями acedSSGet () и acedSSNameX () чтобы разрешить вашему приложению редактировать или работать на произвольных секциях ваших заказных объектов примитива. Для детального описания того, как использовать GS

маркеры (не как устанавливать их), включая использование acedSSGet (), acedSSNameX (), и AcDbEntity:: getSubentPathsAtGsMarker () функции, видят “ GS Маркеры и Подпримитивы ” на странице 111.

Примеры в главе 6, “примитивах”, устанавливают GS

маркер для каждого края примитива. Ваш заказной примитив может использовать маркеры, чтобы идентифицировать набор произвольных секций примитива — то есть любой последовательно выполнился, группа примитивов может быть идентифицирована единственным маркером. Секция примитива, сгенерированного группой примитивной функции вызывает,  идентифицирован,  предшествуя примитивам с запросом к функции AcGiSubEntityTraits setSelectionMarker (), определяя номер маркера, уникальный к объекту примитива. Ваше выполнение getSubentPathsAtGsMarker () свяжет соответствующие примитивы с данным маркером, основанным на том, как Вы устанавливаете ваши маркеры.

Полезные AcGi

Константы

Следующие константы полезны, когда Вы устанавливаете или запрашиваете свойства примитива:

// Color

//

static const Adesk::UInt16 kColorByBlock = 0;

static const Adesk::UInt16 kRed = 1;

static const Adesk::UInt16 kYellow = 2;

static const Adesk::UInt16 kGreen = 3;

static const Adesk::UInt16 kCyan = 4;

static const Adesk::UInt16 kBlue = 5;

static const Adesk::UInt16 kMagenta = 6;

static const Adesk::UInt16 kWhite = 7;

static const Adesk::UInt16 kColorByLayer = 256;



// Linetype

//

static const char* const kNoLinetyping = "CONTINUOUS";

static const char* const kLinetypeByLayer = "BYLAYER";

static const char* const kLinetypeByBlock = "BYBLOCK";

// Layer

//

static const char* const kLayerZero = "0";

ОБРАТИТЕ ВНИМАНИЕ, что константа kWhite белая, если это не находится в противоречии с цветом фона, когда становится черно так, чтобы это осталось видимым. Если Вы назначаете цвет блока (setColor (0)) или цвет уровня (setColor (256)), вы будете должны сделать запрос блока или уровня для фактического номера цвета.



ObjectARX, AutoCAD. Среда программирования библиотеки C++


Чтобы тянуть{*рисовать*} себя, каждый примитив делает запросы к графическим примитивам типа ломаных линий, кругов, и дуг, содержащихся в AcGi библиотеке. Любой класс, полученный из AcDbEntity может связывать систему графики (GS) маркер с векторами дисплея, которые это использует, чтобы тянуть{*рисовать*} себя. Каждый подкласс примитива управляет, где это вставляет его GS маркеры. Когда пользователь выбирает примитив, GS маркер используется, чтобы выделить, которая часть примитива была выбрана.

Solids полученный из AcDb3dSolid составлены из вершины, граней, и лиц.

Каждый из этих элементов может быть идентифицирован GS маркером. Создатель класса примитива решает, где GS маркеры должны быть вставлены, в зависимости от того, что является наиболее естественным для примитива. Поле, например, создает GS маркер для каждой строки, имел обыкновение тянуть{*рисовать*} поле. Цилиндр создает три GS маркеры — один для его вершины, основания, и вне лиц.

Примитив составлен из подпримитивов следующего типа: вершина, край, или лицо. В настоящее время, единственные примитивы, которые поддерживают подпримитивы - тела, области{*регионы*}, solids, и mlines. Используйте getSubentPathsAtGsMarker () функция, чтобы получить пути к подпримитивам, которые связаны с частностью GS маркер.

Больше чем один подпримитив могут быть связаны с одиночным маркером. В случае поля, например, маркер 4 идентифицирует более низкий передний край поля.

Если Вы просите о вершине, связанной с этим маркером, две вершина, которая формируется,  оконечные точки этой строки возвращены. Если Вы просите о гранях, связанных с этим маркером, один примитив — строка — возвращен. Если Вы просите о лицах, связанных с этим маркером, данные для лицевой поверхности и нижней поверхности поля возвращены.



Характеристики


Кривые имеют следующие характеристики:

§

Ориентация

§          Периодичность

§          Замкнутое выражение

§          Planarity

§          Длина

Ориентация кривой определена направлением, в котором его параметр увеличивается. Вы можете использовать AcGeCurve2d:: reverseParam () или AcGeCurve3d:: reverseParam () функция, чтобы полностью изменить ориентацию кривой.

Некоторые кривые периодические, что означает, что они повторяют себя после некоторого интервала. Например, период круга - 2p. Используйте эти функции, чтобы определить,является ли кривая периодической:

Adesk::Boolean

AcGeCurve2d::isPeriodic(double& period) const;

Adesk::Boolean

AcGeCurve3d::isPeriodic(double& period) const;

Замкнутая кривая имеет точки начала и оконечные точки, которые являются тем же самый. Кривые могут быть или закрыты или открытый. Используйте эти функции, чтобы определить, закрыта ли кривая:

Adesk::Boolean

AcGeCurve2d::isClosed(

const AcGeTol&=AcGeContext::gTol) const;

Adesk::Boolean

AcGeCurve3d::isClosed(

const AcGeTol&=

AcGeContext::gTol) const;

Кривая 3D может быть плоска (значение, что все его точки постоянно находятся в том же самом плане) или неплоский. Используйте эту функцию, чтобы определить,является ли кривая 3D плоской:

Adesk::Boolean

AcGeCurve3d::isPlanar(

AcGePlane&,

const AcGeTol&=AcGeContext::gTol) const;

Учитывая два значения параметра, Вы можете получить длину кривой между этими двумя значениями, использующими следующие функции:

double

AcGeCurve2d::length(

double fromParam, double toParam,

double=AcGeContext::gTol.equalPoint()) const;

double

AcGeCurve3d::length(

double fromParam, double toParam,

double=AcGeContext::gTol.equalPoint()) const;

Вы можете использовать AcGeCurve2d:: evalPoint () и AcGeCurve3d:: evalPoint () функции, чтобы получить точку пространства модели, которая соответствует данному параметрическому значению. Если ваше приложение исполняет оценку часто, вы вероятно найдете AcGePointOnCurve3d, и AcGePointOnCurve2d классифицирует более эффективный (см. “ Специальные Классы Оценки ” на странице 738). Функции кривой для оценки точек следующие:

AcGePoint2d

AcGeCurve2d::evalPoint(double param) const;

AcGePoint2d

AcGeCurve2d::evalPoint(

double param, int numDeriv,

AcGeVector2dArray& derivArray) const;

AcGePoint3d

AcGeCurve3d::evalPoint(double param) const;

AcGePoint3d

AcGeCurve3d::evalPoint(

double param, int numDeriv,

AcGeVector3dArray& derivArray) const;



IAcadBaseObject


IAcadBaseObject - интерфейс, имел обыкновение управлять связью от объекта COM до объекта резидента базы. Это - ответственность объекта COM сбросить связь от AcDbObject до объекта COM, когда объект COM разрушается. Это сделано, используя AcAxOleLinkManager класс, обсужденный ниже, обычно в деструкторе класса COM:

interface DECLSPEC_UUID("5F3C54C0-49E1-11cf-93D5-0800099EB3B7")

IAcadBaseObject : public IUnknown

{

// IUnknown methods

//

STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;

STDMETHOD_(ULONG, AddRef)(THIS) PURE;

STDMETHOD_(ULONG, Release)(THIS) PURE;

// IAcadBaseObject methods

//

STDMETHOD(SetObjectId)(THIS_ AcDbObjectId& objId,

AcDbObjectId ownerId = AcDbObjectId::kNull,

TCHAR* keyName = NULL) PURE;

STDMETHOD(GetObjectId)(THIS_ AcDbObjectId* objId) PURE;

STDMETHOD(Clone)(THIS_ AcDbObjectId ownerId,

LPUNKNOWN* pUnkClone) PURE;

STDMETHOD(GetClassID)(THIS_ CLSID& clsid) PURE;

STDMETHOD(NullObjectId)(THIS) PURE;

STDMETHOD(OnModified)(THIS) PURE;

};



ICategorizeProperties Интерфейс


Этот интерфейс используется OPM, чтобы категоризировать свойства, показанные в контроле. Это необязательно, но строго рекомендовано. Если объект не осуществляет этот интерфейс, все свойства категоризированы под “Генералом”. OPM

не поддерживает вложение категорий.

OPM будет использовать QueryInterface для этого интерфейса, когда это собирает информацию свойства. Типично это произойдет, когда пользователь выбирает объекты, вызывая набор pickfirst измениться. Если QueryInterface преуспевает, это вызывает MapPropertyToCategory для каждого свойства, определенного информацией типа для объекта. Если категория (PROPCAT) возвращенный - не одно из предопределенных значений, это вызывает GetCategoryName, чтобы определить которую категорию разместить свойство в. Если Вы только заинтересованы категоризацией использования предопределенных значений, Вы можете возвращать E_NOTIMPL от GetCategoryName. Это требует, чтобы Вы знали DISPID для каждого из ваших свойств. Активная Библиотека Шаблонов (ATL) автоматически назначает значения DISPID на свойства в файлах IDL, которые определяют ваш интерфейс. Они - числа рядом с ключевым словом “id” в списке атрибута свойства.



Идентификация Класса Во время выполнения


Каждый класс в ObjectARX иерархии, которая получена из AcRxObject, имеет соответствующий объект описателя класса, который является образцом AcRxClass, который держит информацию для идентификации типа во время выполнения. Объект описателя класса, gpDesc, является статическим компонентом данных класса — например, AcDbEllipse:: gpDesc. Объекты описателя Класса созданы при инициализации, когда классы зарегистрированы с ObjectARX и добавлены к словарю с  системным уровнем, acrxClassDictionary. Макрокоманды, описанные здесь облегчают объявление и выполнение некоторых функций, связанных с идентификацией во время выполнения и функциями инициализации. Они включают подпрограмму инициализации класса также как desc (), cast (), isKindOf (), и isA () функции для заказного класса.

Важные функции, обеспеченные AcRxObject классом для идентификации типа во время выполнения включают следующее:

·

desc (), статическая функция элемента, которая возвращает объект описателя класса частности (известный) класс.

·         cast (), статическая функция элемента, которая возвращает объект указанного типа, или NULL если объект не имеет требуемый класс (или полученный класс).

·         isKindOf () возвращается, принадлежит ли объект указанному классу (или полученный класс).

·         isA () возвращает объект описателя класса объекта, чей класс неизвестен.

Когда Вы хотите знать, каков классифицируют объект, использование AcRxObject:: isA (). Эта функция возвращает объект описателя класса (образец AcRxClass) для объекта базы данных. Его сигнатура

AcRxClass* isA() const;

Когда Вы уже знаете, каков классифицируют объект, Вы можете использовать desc () функция, чтобы получить объект описателя класса:

static AcRxClass* desc();

Следующий пример ищет образцы AcDbEllipse или любого класса, полученного из этого, используя isKindOf () и AcDbEllipse:: desc() статическая функция элемента:

AcDbEntity* curEntity = somehowGetAndOpenAnEntity();

                if (curEntity->isKindOf(AcDbEllipse::desc())) {

                               // Got some kind of AcDbEllipse instance.

                }

Этот пример показывает другому пути поиска образцов AcDbEllipse, или любого класса, полученного из этого, использование AcDbEllipse:: приведение () статическая функция элемента:

AcDbEllipse* ellipseEntity = AcDbEllipse::cast(curEntity);

if (ellipseEntity != NULL) {

                // Got some kind of AcDbEllipse instance.

}

Следующий пример ищет образцы AcDbEllipse, но не образцы классов, полученных из AcDbEllipse, используя isA () и AcDbEllipse:: desc ():

if (curEntity->isA() == AcDbEllipse::desc()) {

                // Got an AcDbEllipse, no more, no less.



Идентификация типа во время выполнения


Каждый подкласс AcRxObject имеет связанный объект описателя класса (типа

AcRxClass), который используется для идентификации типа во время выполнения. ObjectARX обеспечивает

·         Функции для испытания, имеет ли объект специфический класс или полученный класс,

·         Функции для определения, имеют ли два объекта тот же самый класс, и

·         Функции для возвращения объекта описателя класса для данного класса.

Для получения дополнительной информации при использовании AcRx классов см. главу 3, “ ObjectARX Прикладные Основы, ” глава 11, при Получении Заказного ObjectARX Класса, ” и Глава 19, “ Расширение Протокола. ”



Иерархические (Местные) Исследования


Иерархический traversers обеспечивают способность идти через местные области твердых, или нисходящего или восходящего. Несколько из этих traversers, типа AcBrLoopEdgeTraverser и AcBrLoopVertexTraverser, также обеспечивают запросы, чтобы различить между множественными использованиями того же самого края или вершины.

Например, край имеет, никакое свойственное знание которого лицо это упомянуто от. Так, параметр изгибает данные, который зависит от основной поверхности, на которой край определен, делается запрос от AcBrLoopEdgeTraverser.

Вниз иерархический traversers дают доступ к топологически смежным подпримитивам, которые составляют границу данного топологического объекта (то есть traverser перечисляют владельца).



Иерархия Классов


Следующее - поддержанные классы в AdUi и AcUi библиотеках. Имеется подарок{*настоящее*} классов в файлах заголовка, которые не показываются и - для внутреннего использования только и не поддержаны для использования с ObjectARX.



Имена примитивов и наборов выбора


В AutoLISP имена примитивов и наборов выбора - пары длинных целых чисел.

ObjectARX

сохраняет этот стандарт,  определяя такие имена как тип массива, следующим образом:

typedef long ads_name[2];

Как с ads_point переменными, ads_name переменные всегда проходят ссылкой, но должен быть назначенный элемент элементом.

Вы можете также копировать примитив или имя набор выбора,  вызывая ads_name_set () макрокоманда. Как с ads_point_set () и функциями ObjectARX, результат - второй параметр к макрокоманде.

Следующие типовые кодовые наборы имя newname, чтобы равняться oldname.

ads_name oldname, newname;

if (acdbEntNext(NULL, oldname) == RTNORM)

ads_name_set(oldname, newname);

ОБРАТИТЕ ВНИМАНИЕ на макрокоманду This, подобно ads_point_set () макрокоманда, определен по-другому, в зависимости от того, действительно ли символ __ STDC __ (который замещает стандарт C),  определен. Стандартная версия C ads_name_set () требует, чтобы ваша программа включила string.h.

Ads_name_equal () макрокоманда сравнивает названия{*имена*} в следующем примере:

if (ads_name_equal (oldname, newname))

...

Чтобы назначать null значение имени, вызовите ads_name_clear () макрокомандой, и испытанием на null примитив или имя набора выбора с макрокомандой ads_name_nil().

Следующий типовой код очищает набор oldname в предыдущем примере:

Ads_name_clear (oldname);

И следующий код проверяет,является ли имя NULL:

Если (ads_name_nil (oldname))

...

ObjectARX создает следующий тип данных для ситуаций, которые требуют, чтобы имя было указателем скорее чем массив:

typedef long *ads_namep;



Имя Примитива и Функции Данных


Обрабатывающие примитив функции организованы в две категории: функции, которые восстанавливают{*отыскивают*} имя специфического примитива и функций, которые восстанавливают{*отыскивают*} или изменяют данные примитива.



Имя Расширения


Вся информация потребности Дизайн-центра AutoCAD от довольного средства доступа, участвующего в его настольном режиме сохранена под этим ключом. Ключ расширения может иметь любое число дополнительных ключей. Имя дополнительного ключа представляет имя расширений файла, которые показываются в Дизайн-центре AutoCAD.

Имеются два типа расширений, сохраненных в системном реестре, удовлетворяют тип и контейнерный тип. Под ключом Extension Name может быть следующие дополнительные клавиши:

Содержательный тип

Если ключ расширения не имеет никаких дополнительных ключей, рассматривается быть расширением содержательного типа, если содержательное средство доступа определенно не устанавливает ключ контейнерный в значение одних.

Контейнерный тип

Если ключ расширения имеет дополнительные ключи, рассматривается быть контейнерным расширением типа. Значения, сохраненные на этом уровне ключа игнорируются. Контейнерный ключ может иметь любое число дополнительных клавиш. Каждая дополнительная клавиша представляет тип содержания, которое контейнер может обрабатывать.

Следующие значения системного реестра демонстрируют отрасль системного реестра расширений:

[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:

xxx\AutodeskApps\AcadDC\Extensions]

[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:

xxx\AutodeskApps\AcadDC\Extensions\.dwg]

"Default_CLSID"="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"

"Default_IconIndex"=dword:00000002

"Container"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R15.0\ACAD-x:

xxx\AutodeskApps\AcadDC\Extensions\.dwg\Blocks]

"CLSID"="{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"

"IconIndex"=dword:00000000

"Prefix"="AcDc"

"LocalName"="Blocks"



Индексы и Фильтры


Индекс и классы фильтра и функции обеспечивают схему приложений, чтобы определить заказные индексы и заказную фильтрацию блочных данных. Приложение может определять его создания заказных ИС AcDbFilter, AcDbIndex, и AcDbFilteredBlockIterator. Это регистрирует AcDbFilter с блочной ссылкой{*справочниками*} через AcIndexFilterManager:: addFilter (), и AcDbIndex с соответствующим блочным отчетом{*записью*} таблицы через AcIndexFilterManager:: addIndex (). После того, как это, regens таблиц перекрестных ссылок и блоков будет уважать запрос, определенный AcDbFilter, и использовать AcDbFilteredBlockIterator, чтобы решить то, что объект IDs будет обработан в течение перегенерального. Индексы будут сохраняться современными через или приложением, явно вызывающим AcIndexFilterManager:: updateIndexes (), или приложение может полагаться на AutoCAD, сохраняют{*экономят*} операцию, вызывающую AcIndexFilterManager:: updateIndexes () на сохраняемом AcDbDatabase.

AcDbIndex:: rebuildFull () или AcDbIndex:: rebuildModified () вызывается в течение AcIndexFilterManager:: updateIndexes () запрос.

Текущее использование схемы индексации в AutoCAD - быстрая загрузка запроса подрезанных таблиц перекрестных ссылок. Пространственный индекс (объект AcDbSpatialIndex) сохранен в рисунке refed. Объект AcDbSpatialFilter определяет том{*объем*} зажима блочной ссылки{*справочников*} к таблице перекрестных ссылок в ведущем рисунке. Когда загрузка запроса включена для таблицы перекрестных ссылок, пространственный том{*объем*} фильтра используется, чтобы пересечь данные таблицы перекрестных ссылок через пространственный индекс, чтобы к странице в от DWG файла только те объекты, чей графика пересекает том{*объем*} зажима.

Эти классы и функции обеспечивают интерфейс для:

N Модифицирующие индексы

N Добавление и удаление индексов, чтобы блокировать отчеты{*записи*} таблицы

N Добавление и удаление фильтров, чтобы блокировать ссылки{*справочники*}

N Запрос для индексов от блочных отчетов{*записей*} таблицы

N Запрос для фильтров от блочных ссылок{*справочников*}

N Выполняющий итерации через блокируют отчеты{*записи*} таблицы и посещение только подмножество объектов

Основные классы и вовлеченные функции

N AcDbIndexFilterManager namespace

N AcDbIndex класс

N AcDbFilter класс

N AcDbFilteredBlockIterator класс

N AcDbCompositeFilteredBlockIterator класс



Инициализация базы данных


Когда сеанс AutoCAD начинается, база данных содержит следующие элементы:

§

N набор девяти таблиц идентификаторов.

Block table (AcDbBlockTable)

Dimension style table (AcDbDimStyleTable)

Layer table (AcDbLayerTable)

Linetype table (AcDbLinetypeTable)

Registered applications table (AcDbRegAppTable)

Text style table (AcDbTextStyleTable)

User Coordinate System table (AcDbUCSTable)

Viewport table (AcDbViewportTable)

View table (AcDbViewTable)

Некоторые из таблиц идентификаторов уже содержат один или большее количество записей. Таблица уровня содержит уровень 0. Блочная таблица первоначально содержит три записи: *MODEL_SPACE, *PAPER_SPACE, и *PAPER_SPACE0.  Linetype таблица всегда имеет НЕПРЕРЫВНЫЙ, BY_LAYER, и BY_BLOCK linetype. Таблица зарегистрированных приложений всегда имеет ACAD. Текстовая таблица стиля всегда имеет СТАНДАРТНЫЙ.

§         словарь имен объектов. Когда база данных создана, этот словарь уже содержит два словаря баз данных: словарь ГРУППЫ и MLINE словарь стиля. В пределах MLINE словаря стиля, СТАНДАРТНЫЙ стиль - всегда имеется.

§         N фиксированный набор переменных заголовка. (Они - не объекты базы данных.)



Инициализация ObjectARX Приложения


Вы должны инициализировать любые заказные классы и команды, что ваше приложение определяет. Эта инициализация может иметь место в любом AcRx::kInitAppMsg случае вашего acrxEntryPoint () или в функции, называемой от этого случая.

Инициализация приложения ObjectARX

1, если Вы определили,  заказной класс, вызывает его rxInit () функция.

Определение заказных классов обсуждено подробно в главе 11, при Получении a

Заказной ObjectARX Класс. ”

2, если Вы определили заказные классы, вызывают acrxBuildClassHierarchy() для восстановления ObjectARX дерева классов во время выполнения. Для эффективности вызовите acrxBuildClassHierarchy() однажды после запроса Rxinit()  для каждого из ваших заказных классов.

3 Исполняют любую другую инициализацию, в которой Вы нуждаетесь.

4 Регистрируют сервисное название{*имя*}.

Регистрация сервисного названия{*имени*} предложена, будут ли другие приложения зависеть

На ваше приложение. Регистрация сервисного названия{*имени*} позволяет другие приложения

Регистрироваться в зависимости от обслуживания{*службы*}, и позволять вашему приложению проверять{*отмечать*} если Это имеет любые зависимости перед разгрузкой. Регистрация сервисного названия{*имени*} для Ваше приложение также необходимо, если Вы собираетесь экспортировать символические функции от вашего приложения, использующего ObjectARX механизм. Вы можете использовать acrxRegisterService(), или использование AcRxService класс. Для больше Информация относительно регистрирующих услуг, см. документацию по AcRxService В ObjectARX справочниках.

5 Регистра командует с механизмом команды AutoCAD.

Используйте AcedRegCmds- > addCommand () чтобы делать AutoCAD, знающий команды

Это ваше приложение определяет. Для получения дополнительной информации, см. “ Регистрация Нового

Команды ” на странице 40.



Интерактивный Вывод


Основные функции вывода - acedPrompt(), который отображает сообщение на линии подсказки AutoCAD, и acutPrintf(), который отображает текст на текстовом экране. AcutPrintf() последовательность запроса функции эквивалентен функции стандартной библиотеки для C printf(). Это обеспечивается как отдельная функция, потому что на некоторых платформах стандартный C printf () заставляет сообщение вывода корежить экран графики AutoCAD. (Помните, что acdbFail() функция также отображает сообщения на текстовом экране.)

Размер строки, отображенной acedPrompt() не должен превысить длину линии подсказки графического экрана; типично это - не больше, чем 80 символов.

Размер строки, отображенной acutPrintf() не должен превысить 132 символа, потому что это - размер строкового буфера, используемого acutPrintf() функция (133 байта, с последним байтом, зарезервированным для символа пустого указателя).

AcedMenuCmd () функция обеспечивает контроль относительно дисплея графического экранного меню. AcedMenuCmd () функция активизирует один из подменю текущего меню. Требуется строковый параметр, str, который состоит из двух частей, отделенных знаком "=", в форме:

"section=submenu"

Где секция указывает секцию меню, и подменю указывает который подменю активизировать в пределах той секции.

Например, следующий функциональный запрос заставляет OSNAP подменю, определенный в текущем файле меню появляться на экране.

acedMenuCmd ("S=OSNAP");

Подобным способом, следующий функциональный запрос назначает подменю MY-BUTTONS на меню BUTTONS, и активизирует это.

acedMenuCmd ("B=MY-BUTTONS");

В Выпуске 12 и более ранних версий AutoCAD, Вы могли назначать любой вид меню для любой другой. Например, Вы могли назначать меню SCREEN для меню POP. С Выпуском 13 и более поздних версий AutoCAD, Вы можете назначать меню для других меню на платформе Windows только, если они имеют тот же самый тип. Меню POP может быть назначено только на другое меню POP, и меню SCREEN для другого меню SCREEN. Вы можете определить меню подробно, потому что Windows загружает частичные меню.

Запрос acedMenuCmd () и при принятии “P1=test.numeric” назначает меню 12 POP для меню 2 POP, при предположении, что следующие определения файла меню существуют.

*** MENUGROUP=test

*** POP12

**NUMERIC

[Numeric Menu]

[First item]

[Second

item]

Следующие показы запроса, как активизировать раскрывающееся меню и затем отображают это.

AcedMenuCmd ("P1=NUMERIC");

Запрос к acedMenuCmd () назначает подменю NUMERIC на раскрывающееся меню 1 (в левом верхнем углу графического экрана).

См. Руководство Настройки AutoCAD для подробной информации относительно заказных меню.



Интерфейс IAcDcContentBrowser


Этот интерфейс осуществлен в структуре Дизайн-центра AutoCAD и используется компонентами, чтобы связаться, получают и устанавливают информацию. Указатель на этот интерфейс будет даваться компонентам, когда их метод инициализации вызван{*назван*}, и компоненты, как ожидается,  будут кэшировать этот указатель, чтобы возразить к структуре.

Этот интерфейс подобен интерфейсу IShellBrowser Windows namespace расширение{*продление*}.



Интерфейс IAcDcContentFinder


Этот интерфейс осуществлен компонентами и используется структурой Дизайн-центра AutoCAD, чтобы получить информацию поиска от компонентов. Компоненте, который зарегистрировал себя как довольное средство доступа к Дизайн-центру AutoCAD,  делали бы запрос для этого интерфейса в соответствующее время, и будет попросить инициализировать себя. После того, как инициализированный, функции в этом интерфейсе будут вызваны в различные времена, чтобы статься информационными соответствующими диалогу Средства поиска в Дизайн-центре AutoCAD.



Интерфейс IAcDcContentFinderSite


Этот интерфейс осуществлен в структуре Дизайн-центра AutoCAD и используется компонентами, чтобы обеспечить результатов поиска довольного типа.



Интерфейс IAcDcContentView


Этот интерфейс осуществлен компонентами и используется структурой Дизайн-центра AutoCAD, чтобы получить довольную информацию от компонента. Компоненте, который зарегистрировал себя как довольное средство доступа к Дизайн-центру AutoCAD,  делали бы запрос для этого интерфейса в соответствующее время, и будет попросить инициализировать себя. После того, как инициализированный, функции в этом интерфейсе будут вызваны{*названы*} в различные времена, чтобы получить или установить информацию в Дизайн-центре AutoCAD.

Этот интерфейс подобен интерфейсу IShellView Windows namespace расширение{*продление*}.



Интерфейс IAcPostDrop


Этот интерфейс осуществлен компонентами и используется во время щелкнул правой кнопкой мыши, перетащат и опустить довольных примитивов.



Интерфейс пользователя и Доступ к базе данных


ObjectDBX позволяет Вам записывать отдельный binaries для интерфейса пользователя (UI) и базы данных (DB) части вашего приложения. Файл, содержащий UI компонент имел бы расширение .arx и будет содержать код, который выпускает подсказки, отображает диалоги, изменяет меню в AutoCAD, и т.д.

DB составляющий файл имел бы расширение .dbx и будет содержать код, который осуществляет ваши заказные объекты,  создавая их, отображая их, преобразовывая их, и так далее. Если ваше приложение отделено в интерфейс пользователя и части базы данных, ваши заказные объекты будут все еще обрабатываться должным образом без ObjectARX-приложения, которое обеспечило интерфейс пользователя, являющийся существующим.

Например, предположите, что Вы осуществляете заказной объект по имени “Слив”, и что код, чтобы отображать и изменить Слив находится в sink.dbx, в то время как код, чтобы запросить пользователя относительно значений создания Слива находится в sink.arx. Ваш пользователь может загружать sink.arx от AutoCAD и использовать это (с sink.dbx, который будет загружен автоматически) чтобы создать заказной слив в рисунке. Позже, это, рисунок может быть загружен любым другим приложением главного компьютера (включая AutoCAD), и если пользователь имеет копию sink.dbx доступного файла, объекты Sink,  отобразит должным образом, вместо как proxies.



IOPMPropertyExpander Интерфейс


Основная цель этого класса состоит в том, чтобы позволить одному свойству вспыхиваться в несколько свойств в OPM. Например, Автоматизация имеет свойство по имени StartPoint для AcadLine. Это свойство получает или устанавливает ВАРИАНТ, который содержит массив,  удваивается (технически ВАРИАНТ содержит указатель на SAFEARRAY,  удваивает) представление точки начала линии. Это несколько более эффективно и более чисто с точки зрения API чем наличие свойств Автоматизации по имени StartX, StartY, StartZ на AcadLine. Однако, OPM должен отобразить свойства, расширялся из этим способом. В добавлении к разбиванию одного свойства в массив свойств, Вы можете также группировать элементы в том массиве. Например, для вершины ломаной линии, имеется одно свойство Автоматизации, “Координаты”, который возвращается,  массив удваивает, каждая последовательная пара, представляющая X, Y вершину 2-ой ломаной линии. Определяя группировку, OPM автоматически создаст контроль spinner для свойства, позволяя пользователю перечислять и изменить значения вершины.

Эти методы необязательные, с тех пор в большинстве случаев, Вы можете создавать отдельные свойства в IDL.

Реализация Статические Интерфейсы OPM

Чтобы осуществлять обертки объекта COM, определяющие статические свойства для заказных объектов,  самый простой метод состоит в том, чтобы использовать ATL. ATL делает это очень простым создать объекты COM та поддержка IDispatch. Наиболее трудная часть интегрирует ObjectARX заказной объектный код с ActiveX Сервером DLLs, что ATL генерирует.

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



IOPMPropertyExtension Интерфейс


IOPMPropertyExtension - коллекция других flavoring функциональных возможностей.

GetDisplayName используется, чтобы перегрузить имя свойства от этого в информации типа. Доступно для редактирования используется, чтобы делать свойства, которые могут быть установлены в информации типа к только для чтения в OPM. ShowProperty  временно удаляет свойство из отображения в OPM.



IPerPropertyBrowsing Интерфейс


IPerPropertyBrowsing - стандарт интерфейс Microsoft. Пожалуйста см. документацию Microsoft для детального объяснения. Это типично используется подручными меню (типа OPM) чтобы отобразить вкладки для объектов, которые имеют их. Это имеет две основных функции. Первый должен связать вкладку или другой диалог со специфическим свойством через кнопку замещающего знака на OPM диалоге. Вторая цель IPerPropertyBrowsing

состоит в том, чтобы поддержать заказные раскрывающиеся списки свойства в контроле OPM.



Isolines


Isoline используется, чтобы дать визуальный ключ форме объекта. AcGiWorldDraw:: isolines () функция позволяет примитиву отображать тот же самый номер isolines в поверхность как определено пользователем. Это значение - целое число между 0 и 2047. Заданный по умолчанию номер isolines - 4. AcGiViewportDraw класс обеспечивает аналогичную функцию:

virtual Adesk::UInt32

AcGiWorldDraw::numberOfIsolines() const;



Использование acedCmd ()


AcedCmd() функция эквивалентна acedCommand(), но передает значения к AutoCAD в форме списка буфера результата. Это полезно в ситуациях, где сложная логика вовлечена в построение списка команд AutoCAD. AcutBuildList () функция полезен для построения списков команд.

AcedCmd() функция также имеет преимущество, что список команд может изменяться во время выполнения скорее чем быть установленным во времени компиляции. Его недостаток - то, что требуется слегка дольше, чтобы выполниться. Для получения дополнительной информации, см. ObjectARX Ссылку.

Следующий типовой кодовый фрагмент заставляет AutoCAD исполнять REDRAW на экране графики потока (или область просмотра).

struct resbuf *cmdlist;

cmdlist = acutBuildList(RTSTR, "redraw", 0);

if (cmdlist == NULL) {

acdbFail("Couldn’t create list\n");

return BAD;

}

acedCmd(cmdlist);

acutRelRb(cmdlist);



Использование AcEdJig


AcEdJig класс используется, чтобы исполнить, перемещаются{*перетаскивают*} последовательности, обычно приобретать, создавать, редактировать, и прибавлять новый объект к базе данных. Если Вы получаете новый класс объекта, Вы будете обычно хотеть осуществить вашу собственную версию AcEdJig. Этот класс дает возможность пользователю AutoCAD определить некоторые аспекты объекта, используя устройство управления позицией, и это дает программисту, обращаются к AutoCAD, перемещаются{*перетаскивают*} механизм. (Класс берет его название{*имя*} от “ монтажное приспособление, ” устройство имел обыкновение проводить{*держать*} машинную часть, которая изгибается{*склоняется*} или molded на месте)

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

§

курсор указанного типа

§         графика Примитива, возвращенная вашим объектом AcEdJig

AcEdJig вообще используется на объектах, которые не постоянно находятся в базе данных. Это работает на одиночном объекте. Не используйте AcEdJig, чтобы работать на комплексных объектах типа ломаных линий.



Использование AdUi и AcUi с VC ++ AppWizard


Теперь, когда Вы видели краткий обзор для AdUi и AcUi поддержки диалога, мы представим пример использования этих систем. Диалог, который мы создадим, будет появляться следующим образом. Исходный текст для этого примера может быть найден в ObjectARX SDK docsamps\AsdkAcUiSample каталогом. Этот пример, однако, опишет, как установить ваш проект с начала.



Использование appendAcDbEntity () В течение Клонирования


AcDbBlockTableRecord:: appendAcDbEntity () требует имеющий силу AcDbObjectIds, чтобы делать добавляющийся должным образом. В течение клонирования, примитив может быть добавлен в конец к AcDbBlockTableRecord только если

AcDbBlockTableRecord:: isObjectIdsInFlux () возвращает Adesk:: kFalse. Это указывает, что сам AcDbBlockTableRecord в настоящее время не клонируется.

Одно исключение к этому правилу происходит, когда клонированный AcDbBlockTableRecord пуст. Поскольку пустой AcDbBlockTableRecord не содержит никакой неоттранслированный AcDbObjectIds, добавляющийся будет работать должным образом.

Эта ситуация возникает в течение некоторых форм wblock (), и описана более подробно коротко{*вскоре*}.

Если глубоко клонируются,  - обратился к индивидуальным примитивам, то их имитирует, должен быть добавлен в конец адресату АкДбБлокТаблеРекорду. Однако, когда сам AcDbBlockTableRecord глубоко клонируется, тогда все его примитивы клонированы с этим, и запрос к AcDbBlockTableRecord:: appendAcDbEntity () не будет только ненужен, но разрушил бы клонированный AcDbBlockTableRecord.

Заданные по умолчанию выполнение deepClone () и wblockClone () знают, когда вызвать AcDbBlockTableRecord:: appendAcDbEntity () проверяя значение isPrimary. Когда примитив глубоко клонируется отдельно, isPrimary истинен, и добавлять,  вызван. Если примитив клонируется как результат глубокого клонирования AcDbBlockTableRecord, то isPrimary ложный, и добавлять, не вызван.

Обычно, приложения не должны быть обеспокоены этой подробностью и могут полагаться на заданное по умолчанию выполнение deepClone () и wblockClone () чтобы обработать примитивы. Однако, ситуации могут возникать, когда приложения могут хотеть добавить примитивы в течение клонирования, или использовать жесткие ссылки к примитивам. Жесткий упомянутый примитив будет иметь значение isPrimary Adesk:: kFalse и не будет вызывать, добавляют, даже, когда можете требоваться делать так. Эта ситуация охвачена в следующей секции.

Следующие примеры и правила иллюстрируют важные аспекты клонирования.



Использование базовых геометрических типов


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

Заданный по умолчанию конструктор для точек и векторов инициализирует все координаты к 0.

Точки и векторы могут также быть созданы,  определяя их координаты следующим образом:

AcGePoint3d p1 (2.0,5.0, -7.5), p2, p3 (1.0,2.0,3.0);

AcGeVector3d v1 (3.0,4.0,5.0), v2 (0.0,1.0, -1.0), v3;

Точка и векторные классы обеспечивают +, + =, -, и - = операторы. Эти операторы позволяют точки и векторы использоваться аналогичным способом, поскольку встроенные типы, типа удваиваются и целые числа. Следующее - примеры добавления и вычитания точек и векторов:

p2 = p1 + v1;          // Set p2 to sum of p1 and v1.

p1 += v1;                // Add v1 to p1.

p3 -= v1;                 // Subtract v1 from p3.

v3 = v1 + v2;          // Set v3 to sum of v1 and v2.

v1 + = v2;               // Прибавляют v2 к v1.

v3 = v1 - v2;           // Набор v3 к различию v1 и v2.

Не имеется никакого + оператор для добавления двух точек; однако, точка может быть преобразована к вектору, который может тогда быть добавлен к другой точке:

p1 + = p2.asVector ();

Следующее - примеры того, как получить негатив вектора:

v2 = -v1; // Набор v2 к негативу v1.

v1.negate (); // Это эквивалентен v1 = -v1.

Следующее - примеры различных способов масштабировать вектор:

v1 * = 2.0;               // Удваивает длину v1.

v3 = v1 / 2.0;          // Набор v3 к половине длины v1.

v1.normalize ();     // Делают v1 единичным вектором.

Точка и векторные классы содержат множество функций запроса для вычислительных расстояний и длин:

double len = v2.length();     // Длина v2.

len = p1.distanceTo (p2);    // Расстояние от p1 до p2.

Следующая функция очень полезна для вычисления угла между двумя трехмерными векторами. Следующие возвращения угол между v1 и v2, где угол принят, чтобы быть против часовой стрелки относительно v3 (v3,  приняты, чтобы быть перпендикулярными к v1 и v2):


angle = v1.angleTo (v2, v3);

Следующие функции возвращают Булево значение (TRUE или FALSE) и могут использоваться внутренние условные операторы:

if (v1.isZeroLength ())

if (v1.isParallelTo (v2))

if (v1.isPerpendicularTo (v2))

Векторный класс содержит функции для обычных векторных операций:

len = v1.dotProduct (v2);

v3 = v1.crossProduct (v2);

Заданный по умолчанию конструктор для матрицы инициализирует матрицу к единичной матрице:

AcGeMatrix3d mat1, mat2, mat3;

Следующее вращает p3 90 градусов относительно линии, определенной p1 и v1:

mat1.setToRotation (kPi/2.0, v1, p1);

p3 = mat1 * p2;

Матрица может быть инвертирована, если это не сингулярно:

if (!mat2.isSingular())

mat2.invert();

* оператор определен для связывания матриц:

mat3 = mat1 * mat2;

Следующие испытания, содержит ли матрица равное масштабирование во всех трех координатах (то есть это не изменяет форму любого примитива, к которому это применяется):

if (mat.isUniScaledOrtho ())


Использование clone() против deepClone()


AcRxObject::clone() функция клонирует единственный объект. AcDbObject:: deepClone() функция клонирует объект и любые объекты, принадлежащие тому объекту. DeepClone() функция также транслирует ссылки клонированного объекта.

Вообще, deepClone () функция более безопасный из двух функций. Если Вы клонируете простой объект типа эллипса, две функции могут быть эквивалентны. Но если Вы клонируете сложный объект типа ломаной линии, клон () функция не адекватна, потому что это клонирует только объект ломаной линии.

С deepClone () функция, Вы клонируете ломаную линию также как его вершину.



Использование COM, чтобы обратиться к AutoCAD ActiveX Автоматизация


Этот метод требует большего количества кодирования, но не полагается НА MFC.

Вызывать ActiveX Автоматизацию связывает с помощью интерфейса без MFC

1 типовая программа будет использовать COM ActiveX интерфейсы Автоматизации, чтобы добавить новое всплывающее меню к строке меню AutoCAD. Visual C++ Начала и создает новый Win32 проект Динамически компонуемой библиотеки по имени AsdkComDocSamp.

2 Добавляют соответствующие значения к проектным{*строительным*} назначениям, чтобы делать проектную{*строительную*} компоновку как программа ObjectARX. Эта программа должна связаться со следующими библиотеками:

Acad.lib

Rxapi.lib

Acrx15.lib

Acutil15.lib

Acedapi.lib

3 Добавляют новый файл определения к проекту по имени AsdkComDocSamp.def и добавляют следующие линии:

DESCRIPTION ’Autodesk AsdkCom ARX test application’

LIBRARY AsdkComDocSamp

EXPORTS acrxEntryPoint

_SetacrxPtp

acrxGetApiVersion

4 Добавляют новый исходный файл к проекту по имени AsdkComDocSamp.cpp и добавляют следующий код, чтобы делать программу ObjectARX совместимой:

#include <rxregsvc.h>

#include <aced.h>

#include <adslib.h>

// Used to add/remove the menu with the same command.

//

static bool bIsMenuLoaded = false;

void

addMenuThroughCom()

{

}

static void initApp()

{

acedRegCmds->addCommand(

"ASDK_PLAIN_COM",

"AsdkComMenu",

"ComMenu",

ACRX_CMD_MODAL,

addMenuThroughCom);

}

static void unloadApp()

{

acedRegCmds->removeGroup("ASDK_PLAIN_COM");

}

extern "C" AcRx::AppRetCode acrxEntryPoint

(AcRx::AppMsgCode msg, void* appId)

{

switch( msg )

{

case AcRx::kInitAppMsg:

acrxDynamicLinker->unlockApplication(appId);

acrxDynamicLinker->registerAppMDIAware(appId);

initApp();

break;

case AcRx::kUnloadAppMsg:

unloadApp();

break;

default:

break;

}

return AcRx::kRetOK;

}

5 Импортируют AutoCAD, напечатают библиотеку, чтобы приобрести определения для объектов COM. Добавьте следующую линию к вершине AsdkComDocSamp.cpp файла.


Удостоверитесь, чтобы использовать путь для AutoCAD, установленного на вашей системе:

#import "c:\\acad\\acad.tlb" no_implementation \

Raw_interfaces_only named_guids

6 Решают, который связывает с помощью интерфейса Вас, будет должен обратиться. Так как этот пример использует строку меню AutoCAD, это требует большинства объектов меню. Они объявлены в функции addMenuThroughCom следующим образом:

AutoCAD::IAcadApplication *pAcad;

AutoCAD::IAcadMenuBar *pMenuBar;

AutoCAD::IAcadMenuGroups *pMenuGroups;

AutoCAD::IAcadMenuGroup *pMenuGroup;

AutoCAD::IAcadPopupMenus *pPopUpMenus;

AutoCAD::IAcadPopupMenu *pPopUpMenu;

AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;

7 более прямой подход COM обращаться к интерфейсам Автоматизации использует QueryInterface. Следующий код возвращает IUNKNOWN для AutoCAD:

HRESULT hr = NOERROR;

CLSID clsid;

LPUNKNOWN pUnk = NULL;

LPDISPATCH pAcadDisp = NULL;

hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);

if (SUCCEEDED(hr))

{

if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)

{

if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &pAcadDisp) != S_OK)

return;

pUnk->Release();

}

}

8 Использования IUnknown, чтобы получить объект приложения AutoCAD. Также, удостоверитесь, что AutoCAD видим и получать объекты IACADMENUBAR И IACADMENUGROUPS.

Этому показывают в следующем коде:

if (SUCCEEDED(pAcadDisp->QueryInterface (AutoCAD::IID_IAcadApplication,(void**)&pAcad)))

{

pAcad->put_Visible(true);

}

else {

acutPrintf("\nQueryInterface trouble.");

return;

}

9 С приложением AutoCAD, получите строку меню и коллекции групп меню.

Определите, сколько меню текущие на строке меню:

pAcad->get_MenuBar(&pMenuBar);

pAcad->get_MenuGroups(&pMenuGroups);

pAcad->Release();

long numberOfMenus;

pMenuBar->get_Count(&numberOfMenus);

pMenuBar->Release();

10 Получают первое меню от коллекции групп меню. Это будет обычно ACAD, но могло быть кое-что еще. Тогда получите коллекцию всплывающих меню от первой группы меню:



VARIANT index;

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 0;

pMenuGroups->Item(index, &pMenuGroup);

pMenuGroups->Release();

pMenuGroup->get_Menus(&pPopUpMenus);

pMenuGroup->Release();

11 В зависимости от того, создано ли меню уже, или создает новое всплывающее меню или удаляют предварительно созданный. Следующий код заканчивает пример:

WCHAR wstrMenuName[256];

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,

"AsdkComAccess", -1, wstrMenuName, 256);

if (!bIsMenuLoaded) {

pPopUpMenus->Add(wstrMenuName, &pPopUpMenu);

if (pPopUpMenu != NULL) {

pPopUpMenu->put_Name(wstrMenuName);

WCHAR wstrMenuItemName[256];

MultiByteToWideChar(CP_ACP, 0,"&Add A ComCircle",

-1, wstrMenuItemName, 256);

WCHAR wstrMenuItemMacro[256];

MultiByteToWideChar(CP_ACP, 0, "AsdkComCircle ",

-1, wstrMenuItemMacro, 256);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 0;

pPopUpMenu->AddMenuItem(index, wstrMenuItemName,

wstrMenuItemMacro, &pPopUpMenuItem);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 1;

pPopUpMenu->AddSeparator(index,

&pPopUpMenuItem);

MultiByteToWideChar(CP_ACP, 0,

"Auto&LISP Example", -1,

wstrMenuItemName, 256);

MultiByteToWideChar(CP_ACP, 0,

"(prin1 \"Hello\") ", -1,

wstrMenuItemMacro, 256);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 2;

pPopUpMenu->AddMenuItem(index, wstrMenuItemName,

wstrMenuItemMacro, &pPopUpMenuItem);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = numberOfMenus - 2;;

pPopUpMenu->InsertInMenuBar(index);

pPopUpMenu->Release();

pPopUpMenuItem->Release();

bIsMenuLoaded = true;

}else {

acutPrintf("\nMenu not created.");

}

}

else {

VariantInit(&index);

V_VT(&index) = VT_BSTR;

V_BSTR(&index) = wstrMenuName;

pPopUpMenus->RemoveMenuFromMenuBar(index);



bIsMenuLoaded = false;

}

pPopUpMenus->Release();

Полная функция должна теперь напомнить

void

addMenuThroughCom()

{

AutoCAD::IAcadApplication *pAcad;

AutoCAD::IAcadMenuBar *pMenuBar;

AutoCAD::IAcadMenuGroups *pMenuGroups;

AutoCAD::IAcadMenuGroup *pMenuGroup;

AutoCAD::IAcadPopupMenus *pPopUpMenus;

AutoCAD::IAcadPopupMenu *pPopUpMenu;

AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;

HRESULT hr = NOERROR;

CLSID clsid;

LPUNKNOWN pUnk = NULL;

LPDISPATCH pAcadDisp = NULL;

hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);

if (SUCCEEDED(hr))

{

if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)

{

if (pUnk->QueryInterface(IID_IDispatch, (LPVOID*) &pAcadDisp) != S_OK)

return;

pUnk->Release();

}

}

if (SUCCEEDED(pAcadDisp->QueryInterface (AutoCAD::IID_IAcadApplication,(void**)&pAcad))) {

pAcad->put_Visible(true);

}

else {

acutPrintf("\nQueryInterface trouble.");

return;

}

pAcad->get_MenuBar(&pMenuBar);

pAcad->get_MenuGroups(&pMenuGroups);

pAcad->Release();

long numberOfMenus;

pMenuBar->get_Count(&numberOfMenus);

pMenuBar->Release();

VARIANT index;

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 0;

pMenuGroups->Item(index, &pMenuGroup);

pMenuGroups->Release();

pMenuGroup->get_Menus(&pPopUpMenus);

pMenuGroup->Release();

WCHAR wstrMenuName[256];

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,

"AsdkComAccess", -1, wstrMenuName, 256);

if (!bIsMenuLoaded) {

pPopUpMenus->Add(wstrMenuName, &pPopUpMenu);

if (pPopUpMenu != NULL) {

pPopUpMenu->put_Name(wstrMenuName);

WCHAR wstrMenuItemName[256];

MultiByteToWideChar(CP_ACP, 0,"&Add A ComCircle",

-1, wstrMenuItemName, 256);

WCHAR wstrMenuItemMacro[256];

MultiByteToWideChar(CP_ACP, 0, "AsdkComCircle ",

-1, wstrMenuItemMacro, 256);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 0;

pPopUpMenu->AddMenuItem(index, wstrMenuItemName,



wstrMenuItemMacro, &pPopUpMenuItem);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 1;

pPopUpMenu->AddSeparator(index,

&pPopUpMenuItem);

MultiByteToWideChar(CP_ACP, 0,

"Auto&LISP Example", -1,

wstrMenuItemName, 256);

MultiByteToWideChar(CP_ACP, 0,

"(prin1 \"Hello\") ", -1,

wstrMenuItemMacro, 256);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = 2;

pPopUpMenu->AddMenuItem(index, wstrMenuItemName,

wstrMenuItemMacro, &pPopUpMenuItem);

VariantInit(&index);

V_VT(&index) = VT_I4;

V_I4(&index) = numberOfMenus - 2;;

pPopUpMenu->InsertInMenuBar(index);

pPopUpMenu->Release();

pPopUpMenuItem->Release();

bIsMenuLoaded = true;

} else {

acutPrintf("\nMenu not created.");

}

}

else {

VariantInit(&index);

V_VT(&index) = VT_BSTR;

V_BSTR(&index) = wstrMenuName;

pPopUpMenus->RemoveMenuFromMenuBar(index);

bIsMenuLoaded = false;

}

pPopUpMenus->Release();

}

Оба из этих примеров могут быть найдены в ObjectARX SDK. Они расположены в docsamps\COM каталоге. Каждая выборка содержит код для добавления круга и меню, используя или Win32 API или MFC программирование методов.

Так как эти методы обращаются К AutoCAD через COM, связывает с помощью интерфейса, эти методы программирования могут использоваться от других программ C++ (не только ObjectARX). Также, другие языки типа Java и Visual Basic могут использоваться.


Использование COMMONFILES


Не примите имена диска и пути при определении, где установить Общие файлы Autodesk. InstallShield константа системы COMMONFILES возвратит имя пути, которое указывает на кое-что подобно c:\Program Files\Common Files. Вы должны тогда добавить Autodesk Общедоступное имя. Это может быть сделано в a .rul сценарий со следующей линией:

szSharedPath = COMMONFILES ^ "Autodesk Shared";

С всеми файлами, которые Вы перераспределяете от каталога ObjectDBX\release вашей инсталляции SDK, нужно обращаться как Общие файлы Autodesk для инсталляционных целей.



Использование Drawables в Вашем Объекте


В дополнение к предопределенным примитивам, Вы можете усиливать абстрактные объекты в вашем worldDraw () и viewportDraw () выполнение. Любой объект, который поддерживает AcGiDrawable протокол, может использоваться как под-объект. С тех пор AcDbObject происходит от AcGiDrawable, любой объект базы данных может использоваться таким образом, если это имеет смысл.

Drawable не должны быть графическим. Например, drawable мог бы только устанавливать черты подпримитива в специфическую комбинацию и не осуществлять worldDraw () или viewportDraw () вообще.

Эта архитектура позволяет разработчику распределять исполнение, закодируют более эффективно.

Например, worldDraw () выполнение AcDbBlockReference просто помещает трансформанту вставки на стек, вызывает draw() пропускающий в указателе на его AcDbBlockTableRecord, и выталкивает матричный стек. WorldDraw () AcDbBlockTableRecord выполняет итерации по примитивам на определении. Выгода этой методики - то, что графика для данного примитива должна только быть сгенерированной однажды, и может кэшироваться на объекте и эффективно многократно использоваться для последующих ссылок.

ПРЕДУПРЕЖДЕНИЕ! Любой drawables прошел в, рисуют () должен иметь срок службы{*продолжительность жизни*}, равняются или превышение таковой внешнего объекта. Это требовано, потому что графика drawable могла бы кэшироваться в AcGsNode, приложенном к drawable. В течение дисплея графическая система могла бы возвращаться, чтобы получить этот кэш, и если объект был разрушен, ошибка во время выполнения программы произойдет.



Использование DWG файлов более ранних версий


Когда ObjectDBX открывает любой чертежный файл, это преобразовывает файл к формату AutoCAD. ObjectDBX может читать им в и сохранять их, отступает как Выпуск 13, Выпускает 14, или AutoCAD 2000, и данные не будут изменяться всегда. Это означает, что рисунок оригинала и копия, созданная с ObjectDBX смотрят тот же самый когда открыто в AutoCAD.

Для Выпуска 12 и более ранних рисунков, однако, различия в формате рисунка делают преобразование намного более обширным. Из-за этого, когда Выпуск 12 или ранее DWG файл преобразован и затем сохраненный ObjectDBX, это может появляться "от центра" первый раз, когда это открыто в AutoCAD. Причина для этого - та часть конверсионного процесса, использования AutoCAD вовлекают установление вида, основанного на ситуации работы с окнами. ObjectDBX не имеет окна, и так не может устанавливать то же самое вид. Выполнение ZOOM ALL или Изменяют масштаб изображения Степеней от подменю ZOOM меню AutoCAD View, будет более недавний рисунок.

При оценке выполнения ObjectDBX, пожалуйста имеют в виду, что чтение Выпуска AutoCAD, 14 и более ранних рисунков заставляют преобразование иметь место, который воздействует на открытое время.



Использование и распространение Системы Диалога Позиции табуляции AdUi


Все табулированные диалоги, которые используют CADUITABMAINDIALOG и CADUITABCHILDDIALOG, могут быть легко сделаны расширяемой позицией табуляции. Не имеется никакого предела для числа позиций табуляции, которые могут быть добавлены к расширяемому по позиции табуляции диалогу. Если основной диалог изменяемого размера, добавленные позиции табуляции могут участвовать в этом, изменяя размеры использования тех же самых директив, выделенных в документации по диалогам изменяемого размера. Все диалоги в использовании AutoCAD, листающем позиции табуляции в противоположность помещенным в стек позициям табуляции.

Это важно для Вас, чтобы установить грязный бит для расширенной{*продленной*} позиции табуляции, используя SetDirty () функция члена CADUITABCHILDDIALOG, когда данные должны быть инициализированы или модифицирован через DoDataExchange.



Использование Класса Versioning


В примере выше, объект AcDbDictionaryWithDefault должен быть зарегистрирован из с версией AutoCAD 2000 его данных, так как это становится полномочным во всех предыдущих версиях, и никто не будет читать ее данные (если бы не данные, зарегистрированные из на уровне AcDbObject).

Чтобы устанавливать это, механизм было представлено, где объект может отменять версию регистратора и диктовать то, с какой версией требуется быть зарегистрированным из или в.

Следующие правила применяются:

1, если версия регистратора старшая чем версия AutoCAD что объект сначала появился в (версия “рождения”), использование версия рождения объекта.

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

Соответствующее правило{*правление*} должно использоваться листовым классом, также как всеми его базовыми классами, к данным файла в и из. В примере, данном выше, правило 2{*правление*} применяется{*обращается*} (регистратор - от AutoCAD 2000, в то время как объект - от Выпуска 14), так что мы регистрируем из использования версии AutoCAD 2000. Если имелся новый класс, представленный в Выпуске 14, чей данные также изменяются в AutoCAD 2000, и операция должна сохранить{*экономить*} как Выпуск 13, правило 1{*правление*} применяется{*обращается*}, и мы регистрируем из использования Выпуска 14 версии (рождения).

Два новых виртуальных метода AcDbObject были представлены классу орудия versioning, один для DWG и один для DXF файлов:

virtual Acad::ErrorStatus

getObjectSaveVersion(

const AcDbDwgFiler* pFiler,

AcDb::AcDbDwgVersion& ver,

AcDb::MaintenanceReleaseVersion& maintVer);

virtual Acad::ErrorStatus

getObjectSaveVersion(

const AcDbDxfFiler* pFiler,

AcDb::AcDbDwgVersion& ver,

AcDb::MaintenanceReleaseVersion& maintVer);

В методах регистратора, вместо звонящего filer- >dwgVersion (), звонят self()- >getObjectSaveVersion (filer, ...) чтобы позволить объекту указывать которую версию использовать, чтобы разгрузить данные. Точно так же вызовите{*назовите*} тот метод в dwgInFields () и dxfInFields () чтобы выяснить, в которой версии данные возвращаются.

С тех пор не все объекты имеют потребность отменить версию filer те, которые должны делать, так определите их намерение,  устанавливая немного на объекте. Это обычно сделалось бы в конструкторе класса. Бит используется как быстрая проверка, чтобы определить, необходимо ли отменить версию регистратора. Методы, связанные с этим были добавлены к AcDbObject:

bool

hasSaveVersionOverride();

void

setHasSaveVersionOverride(

bool bSetIt);

Имеется также новый AcDbObject метод получить версию рождения объекта:

Acad::ErrorStatus

getObjectBirthVersion(

AcDb::AcDbDwgVersion& ver,

AcDb::MaintenanceReleaseVersion& maintVer);

Этот метод возвращает два номера версии, сохраненные AcRxClass этого объекта, которые определены при регистрации класса, используя макрокоманду ACRX_DXF_DEFINE_MEMBERS.



Использование классов линии и плоскостей


Следующие примеры показывают некоторых из обычно используемых функций в классах плана и линии. Эти примеры показывают, как использовать линию и классы плана для основных линейных операций алгебры. Хотя примеры используют классы 3D, большинство функций, которые не вовлекают класс плана - также могут использоваться в классах 2D. Эти примеры также используют бесконечную линию и классы плана, но они одинаково имеют силу для долей линии, лучей, и ограниченных планов.

Заданный по умолчанию конструктор линии создает линию по X оси. Заданный по умолчанию конструктор плана создает план XY:

AcGePoint3d p1 (2.0,5.0, -7.5), p2;

AcGeLine3d line1 (p1, v1), line2;

AcGePlane plane1 (p1, v1), plane2;

Вышеупомянутый конструктор для line1 создает линию через p1 в направлении v1. Конструктор для plane1 создает план через p1 и нормаль к v1. Таким образом, line1 перпендикулярен к plane1.

Следующие функции возвращают определение плана или линию:

p1 = line1.pointOnLine (); // Произвольная точка на линии.

v1 = line1.direction (); // вектор Руководства{*направления*} линии.

p1 = plane1.pointOnPlane (); // Произвольная точка на плане.

v1 = plane1.normal (); // Нормальный вектор плана.

direction() и normal() функции всегда возвращает единичные векторы.

Следующие функции возвращают самую близкую точку на линии или плане к сути p1:

p2 = line1.closestPointTo (p1);

p2 = plane1.closestPointTo (p1);

Следующие функции возвращают расстояние между точкой и линией, или план (эти расстояния будет тот же самый как расстояния между p1 и p2 выше):

double len = line1.distanceTo (p1);

len = plane1.distanceTo (p1);

Следующие функции возвращают Булево значение (TRUE или FALSE) и могут использоваться внутри условного оператора. Первый два испытательный, если точка p1 находится на line1 или plane1, и третьих испытаниях если line1 находится на plane1:

if (line1.isOn (p1))

if (plane1.isOn (p1))

if (line1.isOn (plane1))

Следующие функции проверяют, если линии или планы параллельны, перпендикулярны, или совпадающие:

if (line1.isParallelTo (line2))

if (line1.isParallelTo (plane1))

if (line1.isPerpendicularTo (line2))

if (line1.isPerpendicularTo (plane1))

if (line1.isColinearTo (line2))

if (plane1.isParallelTo (plane2))

if (plane1.isPerpendicularTo (plane2))

if (plane1.isCoplanarTo (plane2))

Следующие функции возвращают пересечения линий и планов:

if (line1.intersectWith (line2, p1))

if (line1.intersectWith (plane1, p1))

if (plane1.intersectWith (plane2, line1))



Использование Меток в Расширенных данных


Расширенные данные могут содержать метки (группа 1005) чтобы сохранить относительные структуры в пределах рисунка. Один примитив может ссылка другая,  сохраняя метку другого примитива в ее расширенных данных. Метка может быть возвращена{*восстановлена;отыскана*} позже и проходить к acdbHandEnt () чтобы получить другой примитив. Поскольку больше чем один примитив могут, ссылка другой, метки расширенных данных не обязательно уникальна; команда AUDIT требует, чтобы метки в расширенных данных были или NULL или допустимые метки примитива (в пределах текущего рисунка). Лучший способ гарантировать, который расширил метки примитива,  допустим, должен получить метку упомянутого примитива непосредственно от ее данных определения, посредством acdbEntGet (). ( Значение метки находится в группе 5 или 105.)

К примитивам ссылки в других рисунках (например, примитивы, которые приложены посредством таблицы перекрестных ссылок), Вы могут избегать протестов от РЕВИЗИИ,  используя расширенные строки примитива (группа 1000) скорее чем метки (группа 1005), потому что метки перекрестно сосланных примитивов или не допустимы в текущем рисунке или конфликте с допустимыми метками. Однако, если XREF Присоединяется, изменения{*замены*} к XREF Связывают, или объединен с текущим рисунком в другим способом, это - до приложения, чтобы пересмотреть ссылки примитива соответственно.

ОБРАТИТЕ ВНИМАНИЕ, когда рисунки объединены посредством ВСТАВКИ, ВСТАВЬТЕ *, XREF Связывает (XBIND), или частичный DXFIN, метки оттранслированы так, чтобы они стали правильными{*допустимыми*} в текущем рисунке. (Если рисунок прихода не использовал{*нанимал*} метки, новые назначены.) Расширенные метки примитива, которые обращаются{*относятся*} к входящим примитивам,  также оттранслированы, когда эти команды вызваны.

Когда примитив помещен на блочном определении (посредством команды BLOCK), примитив в пределах блока назначен новые метки. (Если первоначальный примитив восстановлен с OOPS, это сохраняет его первоначальные метки.) значение любых меток расширенных данных остается неизменным. Когда блок вз (с, ВЗРЫВАЮТ), метки расширенных данных оттранслированы, способом, подобным пути, которым они оттранслированы, когда рисунки объединены. Если метка расширенных данных обращается{*относится*} к примитиву не в пределах блока, это неизменно; но если метка расширенных данных обращается{*относится*} к примитиву в пределах блока, это назначено

Значение метки нового (вырезанного) примитива.



Использование MFC и ClassWizard, чтобы Обратиться К AutoCAD ActiveX Автоматизация


Этот метод использует MFC, и Visual C++ ClassWizard, чтобы читать AutoCAD напечатает библиотеку (acad.tlb).

Вызов ActiveX Автоматизацию связывает с помощью интерфейса использование MFC и систему Импорта Библиотеки Типа ClassWizard

1 типовая программа будет использовать COM ActiveX интерфейсы Автоматизации AutoCAD, чтобы создать круг в пространстве модели. В Visual C++ создают новый MFC AppWizard (dll) проект по имени AsdkComMfcDocSamp.

2 Выбирают Регулярный DLL использование общедоступного MFC DLL.

ПРИМЕЧАНИЕ Вы можете фактически выбирать любую из опций, но различных назначений и кода, будет требовано в зависимости от вашего выбора. Этот пример будет использовать Регулярный DLL использование общедоступного MFC DLL. См. главу 8, “MFC Темы”, для подробной информации относительно опций, чтобы выбрать для различных задач.

3 Выберите Finish и затем Ok для создания проекта.

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

Acad.lib

Rxapi.lib

Acedapi.lib

5 Добавляют соответствующие строки к файлу DEF в секцию EXPORTS:

AcrxEntryPoint

_SetacrxPtp

AcrxGetApiVersion

6 Открывают AsdkComMfcDocSamp.cpp исходный файл и добавляют следующий код, чтобы делать программу ObjectARX совместимой. Обратите внимание, что  макрокоманда вызывает acrxEntryPoint () функция для AFX_MANAGE_STATE(AfxGetStaticModuleState()):

static void initApp()

{

acedRegCmds->addCommand(

"ASDK_MFC_COM",

"AsdkMfcComCircle",

"MfcComCircle",

ACRX_CMD_MODAL,

addCircleThroughMfcCom);

}

static void unloadApp()

{

acedRegCmds->removeGroup("ASDK_MFC_COM");

}

extern "C" AcRx::AppRetCode acrxEntryPoint

(AcRx::AppMsgCode msg, void* appId)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

switch(msg)

{

case AcRx::kInitAppMsg:

acrxDynamicLinker->unlockApplication(appId);


acrxDynamicLinker->registerAppMDIAware(appId);

initApp();

break;

case AcRx::kUnloadAppMsg:

unloadApp();

break;

default:

break;

}

return AcRx::kRetOK;

}

7 следующий шаг должен решить, который интерфейсы являются необходимыми получить круг в пространство модели. В этом случае, IACADAPPLICATION, IAcadDocument, и интерфейсы IACADMODELSPACE требованы. Чтобы получить определения этих интерфейсов, используйте AutoCAD, напечатают библиотеку (acad.tlb). Сначала выберите ClassWizard из меню VIEW. Тогда выберите, добавляют Класс и указку От Библиотеки Типов. В Импорте от диалога Библиотеки Типа, выберите acad.tlb файл из корневого каталога AUTOCAD, и выберите Открытый. От Подтверждающегося диалога Классов, мультивыберите IACADAPPLICATION, IAcadDocument, и IACADMODELSPACE Классы интерфейса. Заголовок и файл выполнения будут по умолчанию к acad.h и acad.cpp, соответственно. Нажмите OK, и ClassWizard импортирует эти классы интерфейса от библиотеки типов.

8 Открывают acad.cpp и acad.h файлы и исследуют классы и методы, которые были импортированы.

ОБРАТИТЕ ВНИМАНИЕ, что все ActiveX интерфейсы Автоматизации зарегистрированы в ActiveX и VBA Ссылке.

9 Открывают AsdkComMfcDocSamp.cpp файл и добавляют следующую функцию к file:

void addCircleThroughMfcCom

()

{

}

10 Добавляют объявления для трех классов интерфейса:

IAcadApplication IApp;

IAcadDocument IDoc;

IAcadModelSpace IMSpace;

11 Используют acedGetAcadWinApp, чтобы получить объект CWinApp MFC для AutoCAD и вызывать GetIDispatch метод.

IDispatch *pDisp = acedGetAcadWinApp()->GetIDispatch (TRUE);

12, как только Вы имеете,  объект IDispatch, прикрепляет это к локально определенному объекту IAcadApplication и удостоверится, что AutoCAD видим:

IApp. AttachDispatch (pDisp);

IApp. SetVisible (true);

13 Получают активный документ, посылают и прикрепляют это к локально определенному объекту IAcadDocument:

pDisp = IApp. GetActiveDocument ();

IDoc. AttachDispatch (pDisp);



14 Сделают запрос активного документа для пространства модели.

pDisp = IDoc. GetModelSpace ();

IMSpace. AttachDispatch (pDisp);

15 круг требует средней точки и радиуса. Чтобы делать этот эффективным и прозрачным к различным языкам программирования, интерфейс COM использует РАЗЛИЧНЫЙ тип. Точка сохранена в ВАРИАНТЕ как SAFEARRAY. Следующие кодовые наборы SAFEARRAY и память это в ВАРИАНТЕ:

SAFEARRAYBOUND rgsaBound;

rgsaBound.lLbound = 0L;

rgsaBound.cElements = 3;

SAFEARRAY* pStartPoint = NULL;

pStartPoint = SafeArrayCreate(VT_R8, 1, &rgsaBound);

// X value.

//

long i = 0;

double value = 4.0;

SafeArrayPutElement(pStartPoint, &i, &value);

// Y value.

//

i++;

value = 2.0;

SafeArrayPutElement(pStartPoint, &i, &value);

// Z value.

//

i++;

value = 0.0;

SafeArrayPutElement(pStartPoint, &i, &value);

VARIANT pt1;

VariantInit(&pt1);

V_VT(&pt1) = VT_ARRAY | VT_R8;

V_ARRAY(&pt1) = pStartPoint;

16 Вызывают AddCircle метод от объекта IAcadModelSpace:

IMSpace. AddCircle (pt1, 2.0);

Полная функция должна теперь напомнить

void addCircleThroughMfcCom()

{

IAcadApplication IApp;

IAcadDocument IDoc;

IAcadModelSpace IMSpace;

IDispatch *pDisp = acedGetAcadWinApp()->GetIDispatch(FALSE);

IApp.AttachDispatch(pDisp);

IApp.SetVisible(true);

pDisp = IApp.GetActiveDocument();

IDoc.AttachDispatch(pDisp);

pDisp = IDoc.GetModelSpace();

IMSpace.AttachDispatch(pDisp);

SAFEARRAYBOUND rgsaBound;

rgsaBound.lLbound = 0L;

rgsaBound.cElements = 3;

SAFEARRAY* pStartPoint = NULL;

pStartPoint = SafeArrayCreate(VT_R8, 1, &rgsaBound);

// X value

long i = 0;

double value = 4.0;

SafeArrayPutElement(pStartPoint, &i, &value);

// Y value

i++;

value = 2.0;

SafeArrayPutElement(pStartPoint, &i, &value);

// Z value

i++;

value = 0.0;

SafeArrayPutElement(pStartPoint, &i, &value);

VARIANT pt1;

VariantInit(&pt1);

V_VT(&pt1) = VT_ARRAY | VT_R8;

V_ARRAY(&pt1) = pStartPoint;

IMSpace.AddCircle(pt1, 2.0);

}


Использование MFC с Приложениями ObjectArx


Вы имеете выбор формирования Приложений ObjectArx с любым a

Динамически связанный MFC

библиотека или статически связанная MFC библиотека. Вы также

Имейте выбор использования регулярного DLL или расширения{*продления*} DLL.

ПРИМЕЧАНИЮ Это строго рекомендуют динамически связать ваш MFC ObjectARX

Приложение И делает это расширением{*продлением*} DLL, так как это - единственный метод, который позволяет

Вы, чтобы использовать Autodesk AdUi и AcUi

базовые классы MFC.

Для законченной информации относительно MFC, см. интерактивную справку Microsoft и

Технические примечания. В частности см. примечания 11 и 33 для информации относительно

Использование MFC

как{*поскольку*} часть DLL, который является важной концепцией для ObjectARX.



Использование Объектного Реактора


Заставлять один объект базы данных реагировать на другой объект базы данных

1 Получают класс из AcDbObject (или любой из его подклассов).

2 Осуществляют функции уведомления.

3 Инициализируют объект класса.

4 Добавляют объект к базе данных, и назначают владельца.

5 Добавляют это к объекту уведомителя с AcDbObject:: addPersistentReactor () функция.

Этот механизм позволяет Вам определять зависимости в пределах базы данных, которые сохраняются, когда база данных сохранена и освежена всякий раз, когда это - узда - stantiated.

Используйте макрокоманды ObjectARX, когда Вы получаете новый объектный реакторный класс так, чтобы объект описателя класса был создан для этого. (Если Вы не используете макрокоманды ObjectARX, ваш класс наследует описание класса его родителя, когда это сохранено, и его тождество будет потеряно, когда файл читается в.)



Использование Объектов COM AutoCAD от ObjectARX и Других Сред


AutoCAD обеспечивает обертки COM для большинства ObjectARX

среды.

Эти объекты - ActiveX послушная Автоматизация, который поддерживает Visual Basic, Java, C++, и любую другую среду Windows, которая может обращаться к объектам ActiveX. Также, AutoCAD обеспечил некоторые API, которые являются доступными ТОЛЬКО через механизм интерфейса COM. См. ActiveX и Руководство VBA Разработчика для документации, касающейся ActiveX Объектной Модели.

Следующие особенности AutoCAD обеспечивают аспекты их API как интерфейсы COM:

§

Твердая копия

§         Меню

§         Опции



Использование ObjectDBX


Разработка приложений с ObjectDBX

очень похожа к развивающимся приложениям с ObjectARX. API C++, найденный в иерархии классов ObjectARX

- в значительной степени тот же самый в ObjectDBX. Ваша основная задача как разработчик должна понять точно, какое подмножество ObjectARX является в вашем распоряжении.



Использование Определенных Подпримитивов


Создайте соответствующий объект AcBr (AcBrFace, AcBrEdge, или AcBrVertex), и инициализируйте это с набором () функция, используя AcDbFullSubentPath, который был предварительно установлен, используя подпримитив и объект AutoCAD обладания ID.



Использование расширения протокола в приложении


Чтобы использовать функциональные возможности расширения протокола, Вы должны получить объект описателя класса для специфического класса. Как только Вы получили указатель на объект описателя класса, Вы можете вызывать любой из методов для того класса. Следующее - пример использования AsdkEntTemperature расширения протокола для класса AcDbEntity:

AcDbEntity *pEnt;

AsdkEntTemperature *pTemp;

pTemp = AsdkEntTemperature::cast ( pEnt->x(AsdkEntTemperature::desc()));

double eTemp = pTemp -> reflectedEnergy (pEnt);

Вы можете использовать макрокоманду ACRX_X_CALL, чтобы упростить этот код следующим образом:

double eTemp = ACRX_X_CALL(pEnt, AsdkEntTemperature)->reflectedEnergy(pEnt);



Использование Реактора Базы данных


Следующий пример использует реактор, полученный из AcDbDatabaseReactor, чтобы следить за числом объектов в настоящее время в базе данных. Это осуществляет три функции уведомления для реакторного класса: objectAppended (), objectModified (), и objectErased (). Watch_db () функция добавляет реактор к текущей базе данных. Clear_reactors () функция удаляет реактор из базы данных и удаляет реактор базы данных.

class AsdkDbReactor;

long gEntAcc = 0; // Global entity count

AsdkDbReactor *gpDbr = NULL; // Pointer to database reactor

// Custom AcDbDatabaseReactor class for database

// event notification.

//

class AsdkDbReactor : public AcDbDatabaseReactor

{

public:

virtual void objectAppended(const AcDbDatabase* dwg,

const AcDbObject* dbObj);

virtual void objectModified(const AcDbDatabase* dwg,

const AcDbObject* dbObj);

virtual void objectErased(const AcDbDatabase* dwg,

const AcDbObject* dbObj, Adesk::Boolean pErased);

};

// Called whenever an object is added to the database.

//

void

AsdkDbReactor::objectAppended(const AcDbDatabase* db,

const AcDbObject* pObj)

{

printDbEvent(pObj, "objectAppended");

acutPrintf(" Db==%lx\n", (long) db);

gEntAcc++;

acutPrintf("Entity Count = %d\n", gEntAcc);

}

// Called whenever an object in the database is modified.

//

void

AsdkDbReactor::objectModified(const AcDbDatabase* db, const AcDbObject* pObj)

{

printDbEvent(pObj, "objectModified");

acutPrintf(" Db==%lx\n", (long) db);

}

// Called whenever an object is erased from the database.

//

void

AsdkDbReactor::objectErased(const AcDbDatabase* db, const AcDbObject* pObj, Adesk::Boolean pErased)

{

if (pErased) {

printDbEvent(pObj, "objectErased");

gEntAcc--;

} else {

printDbEvent(pObj, "object(Un)erased");

gEntAcc++;

}

acutPrintf(" Db==%lx\n", (long) db);

acutPrintf("Entity Count = %d\n", gEntAcc);

}

// Prints the message passed in by pEvent; then


// calls printObj() to print the information about

// the object that triggered the notification.

//

void printDbEvent(const AcDbObject* pObj, const char* pEvent)

{

acutPrintf(" Event: AcDbDatabaseReactor::%s ", pEvent);

printObj(pObj);

}

// Prints out the basic information about the object pointed

// to by pObj.

//

void printObj(const AcDbObject* pObj)

{

if (pObj == NULL) {

acutPrintf("(NULL)");

return;

}

AcDbHandle objHand;

char handbuf[17];

// Get the handle as a string.

//

pObj->getAcDbHandle(objHand);

objHand.getIntoAsciiBuffer(handbuf);

acutPrintf(

"\n (class==%s, handle==%s, id==%lx, db==%lx)",

pObj->isA()->name(), handbuf,

pObj->objectId().asOldId(), pObj->database());

}

// Adds a reactor to the database to monitor changes.

// This can be called multiple times without any ill

// effect because subsequent calls will be ignored.

//

void watchDb()

{

if (gpDbr == NULL) {

gpDbr = new AsdkDbReactor();

}

acdbHostApplicationServices()->workingDatabase()->addReactor(gpDbr);

acutPrintf(

" Added Database Reactor to "

"acdbHostApplicationServices()->workingDatabase().\n");

}

// Removes the database reactor.

//

void clearReactors()

{

if (acdbHostApplicationServices()->workingDatabase() != NULL) {

acdbHostApplicationServices()->workingDatabase()->removeReactor(gpDbr);

delete gpDbr;

gpDbr = NULL;

}

}

// ObjectARX entry point function

//

AcRx::AppRetCode

acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)

{

switch (msg) {

case AcRx::kInitAppMsg:

acrxDynamicLinker->unlockApplication(appId);

acrxDynamicLinker->registerAppNotMDIAware(appId);

acedRegCmds->addCommand("ASDK_NOTIFY_TEST",

"ASDK_WATCH",

"WATCH",

ACRX_CMD_TRANSPARENT,

watchDb);

acedRegCmds->addCommand("ASDK_NOTIFY_TEST",

"ASDK_CLEAR",

"CLEAR",

ACRX_CMD_TRANSPARENT,

clearReactors);

break;

case AcRx::kUnloadAppMsg:

clearReactors();

acedRegCmds->removeGroup("ASDK_NOTIFY_TEST");

break;

}

return AcRx::kRetOK;

}


Использование Реакторов


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

AcRxDLinkerReactor

ObjectARX-приложение Мониторов загрузка и разгрузка.

AcEditorReactor

Контролирует AutoCAD-специфичные события типа оценок AutoLISP и Команд.

AcDbDatabaseReactor

Создание Мониторов, модификация, и стирание объектов базы данных.

AcTransactionReactor

События Мониторов, связанные с операционным менеджером — начало, аварийное прекращение работы, или конец сделки.

AcDbObjectReactor

События Мониторов, имеющие отношение к определенному созданию объекта — базы данных, модификации, стиранию.

AcDbEntityReactor

Контролирует дополнительное, примитив-определенное событие, типа изменяемой графики.

В большинстве случаев, только стандартные методы C++ необходимы для создания новых переходных реакторных классов. Макрокоманды ObjectARX, которые создают объект описателя класса для нового реакторного класса, не обычно используются, чтобы происходить от этих реакторных классов.

Каждый родительский класс содержит набор виртуальных функций уведомления, которые могут быть осуществлены вашим новым полученным классом. Например, AcDbObjectReactor класс содержит следующие функции уведомления, которые отвечают на связанные объектом события:

§          cancelled()

§          copied()

§          erased()

§          goodbye()

§          openedForModify()

§          modified()

§          subObjModified()

§          modifyUndone()

§          modifiedXData()

§          unappended()

§          reappended()


§          objectClosed()

Каждая из этих функций требует указателя на уведомителя события. Базовый класс, AcDbObjectReactor, имеет выполнение NULL для всех этих функций. В вашем полученном реакторном классе, осуществьте функции, соответствующие{*передающие*} типу уведомлений, которыми Вы заинтересованы. Тогда инициализируйте реактор, и добавьте это к любому числу объектов базы данных, использующих AcDbObject:: addReactor() функция. Чтобы добавлять или удалять переходный реактор к объекту уведомителя, объект может быть открытый в любом состоянии (чтение, записывать, или уведомлять).

Добавление или удаление переходного реактора не проверено механизмом отмены. (Для постоянных реакторов, объект уведомителя должен быть открыт для записи, и добавления, или удаление реакторов проверено механизмом отмены.)

Поскольку Вы создавали переходный реакторный объект, Вы также ответствены за удаление этого.

Когда объект стерт, например, это вызывает стертую передачу () функцией уведомления на каждом реакторе в его списке. Если Вы осуществили стертый () функция для вашего реактора, та функция будет вызвана{*названа*} объектом базы данных, и Вы можете тогда брать любое специальное действие,  соответствующий вашему приложению, когда объект стерт.


Использование Редактора Реактор


AcEditorReactor класс обеспечивает много функций для ответа на различные события. Несколько из этих функций - beginClose (), beginDxfIn (), dxfInComplete (), beginSave (), и saveComplete (). Никакое взаимодействие AutoLISP не может быть выполнено в пределах функции уведомления.

См. главу 18, при Глубоко Имитации, ” для обсуждения редактора, реакторные функции, касающиеся глубокого аналога и wblock

имитируют операции.



Использование Топологических Объектов в Вашей Программе


Надлежащее использование AcBr библиотеки возводит в степень взаимодействия между несколькими внутренними и внешними объектами: AcBrEntity, AcBrTraverser, и их полученные классы; AcDbFullSubentityPath и его компоненты от AcDb библиотеки (AcDbObjectId, AcDbSubentId, и так далее); и объекты геометрии от AcGe библиотеки (AcGeSurface, AcGeCurve3d, AcGePoint3d, и так далее).

В контурном представлении образцовые, топологические объекты используются как “клей”, который скрепляет модель, и геометрические данные упомянуты топологическими объектами. Чтобы обращаться к подробностям формы модели контурного представления, Вы можете или пересекать топологические объекты (использование traverser) или переходить непосредственно к топологическому объекту, представляющему интерес (использование AcDbFullSubentPath, передающего экранной указке).



Использование Топологического Traversers в Вашей Программе


Traversers используются, чтобы идти через топологическую структуру твердых.

Они являются или глобальной переменной или иерархические.



Использование Твердых Объектов


Создайте объект AcBrBrep, и инициализируйте это с набором () функция, используя AcDbFullSubentPath, который был предварительно установлен, используя kNullSubentId и объект AutoCAD обладания ID. Создайте AcBrBrepFaceTraverser, чтобы получить доступ к лицам полных твердого, и инициализировать с setBrep (). Для каждой позиции топологического списка смежных вершин traverser's (использование повторного вызывает к следующему () функция), getFace () обеспечивает AcBrFace, который может использоваться, чтобы обратиться к геометрии. Другой traversers

обеспечивают доступ, чтобы иерархически понизить топологические объекты и их связанную геометрию.



Использование заказного объектного менеджера привязок


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

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

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

AcDbCustomOsnapManager *

acdbCustomOsnapManager() const;

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



Использования Монопольного использования


Когда объект написан к DXF или DWG файлу, все объекты, принадлежащие этому объекту также выписаны. Глубокая операция аналога также рекурсивно копирует каждый объект, принадлежащий имитируемому объекту. См. главу 18, при Глубоко Имитации. ” Жесткие отношения монопольного использования защищают находящийся в собственности объект от чистки.



Используя Данные Сети Brep, Комплекса, Оболочки, или Лица


Создайте AcBrMesh2dFilter, используя соответствующий объект AcBr

и объект AcBrMesh2dControl, и запрос генерируют () на инициализированном объекте AcBrMesh2d, чтобы генерировать поверхностную сеть. Эта сеть может быть пересечена, чтобы обратиться к узловой геометрии и другим данным.



Используя Геометрию Лица, Края, или Вершины


Вызовите функции get* соответствующий и инициализированный объект AcBr, чтобы создать связанный AcGeSurface, AcGeCurve3d, или AcGePoint3d.



Iterators


Каждая таблица идентификаторов имеет передачу iterator, что Вы можете создавать с

 AcDb##BASE_NAME##Table::newIterator () функция.

Acad::ErrorStatus

AcDb##BASE_NAME##Table::newIterator(

AcDb##BASE_NAME##TableIterator*& pIterator,

Adesk::Boolean atBeginning = Adesk::kTrue,

Adesk::Boolean skipErased = Adesk::kTrue) const;

NewIterator () функция создает объект, который может использоваться, чтобы шагнуть через содержание таблицы и заставляет pIterator указывать на iterator объект. Если atBeginning - kTrue, запуски iterator в начале таблицы; если kFalse, это начинается в конце таблицы. Если skipErased параметр - kTrue, iterator позиционирован первоначально в первый (или последний{*прошлый*}) нестертая запись; если kFalse, это позиционировано в первый (или последний{*прошлый*}) запись, независимо от того, было ли это стерто. Для описания функций, доступных для каждого iterator класса, см. ObjectARX Ссылку.

Когда Вы создаете новый iterator, Вы также ответствены за удаление этого. Таблица идентификаторов не должна быть закрыта, пока все iterators, который это создало, не были удалены.

В дополнение к таблицам идентификаторов, запись таблицы блоков имеет iterator, который работает на примитивах, которые это имеет. AcDbBlockTableRecord класс возвращает объект класса AcDbBlockTableRecordIterator, когда Вы спрашиваете это относительно нового iterator. Этот iterator дает возможность Вам шагнуть через примитивы, содержащиеся в записи таблицы блоков и искать специфические примитивы.



Изменение Режимов Повторного вызова и Значений


При повторном вызове время, Вы можете проверять значение поля ввода. Если приложение вызывает для этого, Вы можете использовать ads_set_tile () снова, чтобы изменить это значение. В течение повторных вызовов, Вы можете также использовать ads_mode_tile () чтобы изменить состояние поля ввода. Следующая таблица показывает значения ads_mode_tile () параметр режима:

Значения режима поля ввода

Значение

Символ

Описание

0

MODE_ENABLE

Позволяют поле ввода

1

MODE_DISABLE

Отключают поле ввода

2

MODE_SETFOCUS

Набор сосредотачивается к полю ввода

3

MODE_SETSEL

Выбор части содержания окна редактирования

4

MODE_FLIP

Зеркальное изображение, высвечивающее вкл. или выкл.

Когда Вы используете ads_mode_tile () чтобы отключить поле ввода, которое имеет текущий фокус, Вы должны вызвать ads_mode_tile () снова, чтобы установить фокус в отличное поле ввода (в большинстве случаев, следующий табулятор в диалоговом окне). Иначе, фокус останется на заблокированном поле ввода, которое является нелогичным и может вызывать ошибки.

Пример поля ввода “отключение” является рядом диалогового окна “страницы”, что пользователь шагает через,  выбирая кнопку Next или Previous. Когда пользователь нажимает Затем на предпоследней странице, кнопка заблокирована. Тот же самый случается после нажима Предыдущего на второй странице. В обоих случаях, код должен отключить кнопку, которая была нажата, и затем устанавливала фокус в различное поле ввода.

Следующий пример управляет кластером названным “группа”. Когда переключатель установлен в От, поля ввода в кластере неактивны и не должны измениться:

static void CALLB group_on_off(ads_callback_packet *cbpkt)

{

ads_hdlg hdlg = cbpkt->dialog;

char value[TILE_STR_LIMIT];

strcpy(value, cbpkt->value);

if (strcmp(value, "0") == 0) { // Cluster is disabled.

ads_mode_tile(hdlg, "group", MODE_DISABLE);

} else { // The value must equal "1".

ads_mode_tile(hdlg, "group", MODE_ENABLE);

}

}

Вы можете осматривать другие атрибуты помимо значения поля ввода с get_attr () функция. Следующий пример отыскивает метку кнопки, вызвал “pressme”:

char label_str[TILE_STR_LIMIT];

ads_get_attr(hdlg, "pressme", "label", label_str, TILE_STR_LIMIT);

Если Вы используете ads_get_attr () чтобы отыскать атрибут значения, это сохраняет атрибут значения в файле DCL (начальное значение поля ввода). Ads_get_tile () функция, однако, получает текущее значение во время выполнения поля ввода. Два значения - не обязательно тот же самый.

Ads_get_attr () функция возвращает значение атрибута в строковом параметре (значение). Поскольку эта функция устанавливает значение строки, Вы должны разместить пространство для этого, как показано в предшествующем примере.



Известные Ограничения


Пожалуйста делайте обзор секции “Советов” для AcDbDimension класса в ObjectARX Ссылке, которая документирует поведение AcDbDimension примитивов во внешней базе данных. С целью изменения или создания новых AcDbDimension примитивов API, каждая ObjectDBX база данных ведет себя как внешняя база данных. Таким образом, недавно созданный или изменяемый объект AcDbDimension будет иметь его набор dimBlockId к NULL. При запросе acdbMakeDatabaseCurrent () функция не достаточна изменить поведение, зарегистрированное в ObjectARX Readme. Это не предотвращает создание имеющего силу рисунка, поскольку AutoCAD способен к производству правильного dimBlockID для AcDbDimension в перегенеральное время.



Явная блокировка документа


Имеются два типа контекстов выполнения, приложения и документа. Все зарегистрированные команды и реакторные повторные вызовы выполнены в пределах контекста выполнения документа. Сообщения Windows и повторные вызовы, и некоторый acrxEntryPoint () сообщения выполнены в пределах прикладного контекста.

Явная блокировка требуется только в прикладном контексте выполнения. Блокировка и разблокирование автоматически обработаны для команд, выполняющихся в контексте документа.

Любые команды, которые должны работать вне активного документа, должны вручную исполнить документ блокировка использование следующих типов блокировки.

§

Доступный только для чтения

§         Исключительное чтение

§         Общедоступная запись

§         Исключительная запись

Блокировка в прикладном контексте выполнения может быть сделана,  вызывая acDocManager- > lockDocument (). Следующая таблица описывает четыре уровня блокировки опций:

Типы блокировки Команды

Блокировка Команды

 Режим Блокировки

 Флажки Команды

 Описание

Read only

(not locked)

ACRX_CMD_DOCREADLOCK

Для доступа только для чтения к объектам, блокировка не необходима. Например, чтобы открыть AcDbObject для Acad:: kForRead, или вызывать acedGetVar

(), блокировка не необходима.

Exclusive read

AcAp::kRead

ACRX_CMD_DOCREADLOCK, ACRX_CMD_DOCEXCLUSIVELOCK

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

Shared write

AcAp::kWrite

(default)

Заданный по умолчанию режим блокировки. Множественные контексты выполнения могут держать одновременные общедоступные блокировки записи. Команда может делать изменения к документу, и когда команда приостановлена, другие команды могут делать изменения к документу.

Exclusive write

AcAp::kXWrite

ACRX_CMD_DOCEXCLUSIVELOCK

Гарантирует, что ваш контекст выполнения имеет монопольный доступ, чтобы изменить ресурсы документа



Эффективное использование вычислителей кривой и поверхности


 Чтобы получать максимальную эффективность от кривой и поверхностных вычислителей, Вы должны многократно использовать AcGePointOnCurve2d, AcGePointOnCurve3d, и объекты AcGePointOnSurface в максимально возможной степени, когда Вы выполняете много оценок на той же самой кривой или поверхности. Например, предположите, что func1 и func2 и исполняют оценки на той же самой поверхности srf, и func1 вызывает func2. Тогда объект AcGePointOnSurface, что func1 использования для оценок нужно пройти к func2:

void func1 (const AcGeSurface& srf)

{

AcGePointOnSurface pntOnSrf (srf);

.

. // Evaluate some points and derivatives.

.

func2 ( pntOnSrf );

.

.

}

void func2 (AcGePointOnSurface& pntOnSrf)

{

// Evaluate some points and derivatives using pntOnSrf

// passed in from func1.

}

Пропуская pntOnSrf к func2, вычислитель может продолжать использовать ту же самую область данных, которая использовалась для всех оценок в func1. Если func1 не передает объект AcGePointOnSurface к func2, то func2 должен объявить новый объект AcGePointOnSurface, который создаст новую область данных и повторно вычислит данные, который был вычислен в func1. Следующий код выполняется правильно; однако, это менее эффективно чем предыдущий код:

void func1 (const AcGeSurface& srf)

{

AcGePointOnSurface pntOnSrf (srf);

...

func2 (srf);

...

}

void func2 (const AcGeSurface& srf)

{

AcGePointOnSurface pntOnSrf (srf);

.

. // Оценивает некоторые точки и производные, используя новый pntOnSrf, объявленный выше.

.

}

Многократное использование того же самого объекта AcGePointOnSurface важно для вычислитель-интенсивных приложений, типа поверхностно - поверхностных межсекторов или проекционно-разностных генераторов сети. В случае поверхностно - поверхностного межсектора, функция верхнего уровня должна объявить два объекта AcGePointOnSurface (один для каждой поверхности) и передавать эти объекты через все подпрограммы низшего уровня. Таким образом, приложение получает максимальное использование данных, который сохранен между оценками и получает максимальную эффективность от ее поверхностных вычислителей.

Чтобы получить лучшее использование AcGePointOnCurve2d, AcGePointOnCurve3d, и классов AcGePointOnSurface, большое количество этих объектов никогда не должно быть в контексте в то же самое время для той же самой кривой или поверхности. В большинстве местоположений, только один из этих объектов должен быть в контексте для специфической кривой или поверхности.



Калибровка Таблетки


Пользователи AutoCAD с таблеткой отцифровывания могут калибровать таблетку,  используя команду TABLET. С acedTablet () функция, приложения может управлять калибровками,  устанавливая их непосредственно и сохраняя назначения калибровки для будущего использования. Функция берет два параметра, список и результат, каждый из которых - список буфера результата. Первый буфер результатов в первом списке - целочисленный код, который должен быть 0, чтобы отыскать текущую калибровку (в результате), или 1, чтобы установить калибровку согласно остающимся буферам в списке. Калибровки выражены как четыре трехмерных точки (в дополнение к коду). Первые три из них - направляющие — row1, row2, и row3 —  три строки матрицы преобразования таблетки. Четвертая точка - вектор, направление, которое является нормальным на план поверхности таблетки (выраженное в WCS).

ОБРАТИТЕ ВНИМАНИЕ На TABMODE средство управления переменной системы, установлен ли режим Tablet в На (1) или От (0). Вы можете управлять это,  используя acedSetVar().

Следующая последовательность кода отыскивает текущую калибровку таблетки, и сохраняет это в calibr2. В этом примере, пользователь использовал команду TABLET, чтобы калибровать матрицу, и режим Tablet включен.

struct resbuf *calibr1, *calibr2;

struct resbuf varbuf, rb;

// Retrieve the current calibration.

calibr1 = acutBuildList(RTSHORT, 0, RTNONE);

if (acedTablet(calibr1, &calibr2) != RTNORM) {

acdbFail("Calibration not obtainable\n");

return BAD;

}

Код, возвращенный в параметре результата, calibr2 в примере, автоматически установлен в 1. Чтобы сбрасывать калибровку к значениям, отысканным предшествующим примером, Вы могли использовать следующий код:

if (acedTablet(calibr2, &calibr1) != RTNORM) {

acdbFail("Couldn’t reset calibration\n");

return BAD;

}

rb.restype = RTSHORT;

rb.resval.rint = 1;

acedSetVar("TABMODE", &rb);

acedGetVar("TABMODE" &varbuf);

if (varbuf.resval.rint == 0) {


acdbFail("Couldn’t set TABMODE\n");

return BAD;

}

В этом примере, calibr1 теперь содержит результат калибровки. Поскольку это возможно идентично calibr2 (который был инициализирован acedTablet ()), Вы не обязательно нуждаетесь в этом результате. Когда Вы устанавливаете калибровку, Вы можете определить результат NULL, который заставляет acedTablet () устанавливать калибровку “ тихо. ”

if (acedTablet(calibr2, NULL) != RTNORM) { . . . }

Матрица преобразования прошла, поскольку row1, row2, и row3 - 3x3, матрица преобразования хотела преобразовать 2-ую точку. 2-ая точка выражена как вектор столбца в гомогенных координатах (добавляя 1.0 как третий элемент), так что преобразование напоминает это:

X'

M 00 M 01 M 02

X'

Y'

=

M 10 M 11 M 12

x

Y'

D'

M 20 M 21   1.0

1.0

Вычисление точки подобно трехмерному случаю. AutoCAD преобразовывает точку,  используя следующие формулы:

X' = M 00 X + M 01 Y + M 02

Y' = M 10 X + M 11 Y + M 12

D' = M 20 X + M 21 Y + 1.0

Чтобы поворачивать заканчивающийся вектор назад в 2-ую точку, первые два компонента разделены третью, коэффициентом масштаба, выдавая точку D ' (X '/D ', Y '/D ').

Для проективного преобразования, которое является,  большинство общего случая, acedTablet () делает полное вычисление. Но для афинных и ортогональных преобразований, и - оба 0, удет быть 1.0 - также.

Вычисление опущено; заканчивающаяся 2-ая точка - просто.

Афинное преобразование - специальный, однородный случай проективного преобразования. Ортогональное преобразование - специальный случай афинного преобразования: не только являются и 0, но и  и.

М. 20 М. 21 D '

( X ', Y ')

М. 20 М. 21 М. 00 = М. 11

М. 10 = - М. 01

ОБРАТИТЕ ВНИМАНИЕ, когда Вы устанавливаете калибровку, результат не равняется параметру списка, если направление в списке не было нормализовано; AutoCAD нормализует вектор направления прежде, чем это возвращает это. Также, это гарантирует, что третий элемент в третьем столбце (row3 [Z]) равен 1. Эта ситуация не должна возникнуть, если Вы устанавливаете калибровку, используя значения, отысканные из AutoCAD посредством acedTablet (). Однако, это может случаться, если ваша программа вычисляет преобразование непосредственно.


Категоризировать свойства


Вы не можете хотеть, чтобы все ваши свойства обнаружились под “Общей” категорией, так что эта следующая секция демонстрирует, как использовать встроенные категории.

1 Идут к Представлению Класса в IDE Visual C++, щелкают правой кнопкой мыши на заказном интерфейсе примитива (типа IAsdkSquareWrapper), и выбирают AddProperty. Добавьте свойства для квадратного центра и номера ID.

2 Затем изменяют образование из объекта COM, чтобы включить IOPMPropertyExtensionImpl и IOPMPropertyExpander:

public IOPMPropertyExtensionImpl<CAsdkSquareWrapper>,

public IOPMPropertyExpander

3 Добавляют интерфейсы к карте интерфейса COM:

COM_INTERFACE_ENTRY(IOPMPropertyExtension)

COM_INTERFACE_ENTRY(ICategorizeProperties)

COM_INTERFACE_ENTRY(IPerPropertyBrowsing)

COM_INTERFACE_ENTRY(IOPMPropertyExpander)

4 Добавляют объявление для интерфейса IOPMPropertyExtension:

// IOPMPropertyExtension

//

BEGIN_OPMPROP_MAP()

OPMPROP_ENTRY(0, 0x00000001, PROPCAT_Data, \

0, 0, 0, "", 0, 1, IID_NULL, IID_NULL, "")

OPMPROP_ENTRY(0, 0x00000003, PROPCAT_Geometry, \

0, 0, 0, "", 0, 1, IID_NULL, IID_NULL, "")

END_OPMPROP_MAP()

5 Добавляют следующий две подставляемых функции к классу:

STDMETHOD(GetCategoryName)(

THIS_

/* [in] */ PROPCAT propcat,

/* [in] */ LCID lcid,

/* [out] */ BSTR* pbstrName)

{return S_FALSE;}

virtual HINSTANCE GetResourceInstance()

{

return _Module.GetResourceInstance();

}

6 Добавляют объявления для следующих функций:

STDMETHOD(GetElementValue)(

/* [in] */ DISPID dispID,

/* [in] */ DWORD dwCookie,

/* [out] */ VARIANT * pVarOut) ;

// Used for property expansion (currently variant types)

//

STDMETHOD(SetElementValue)(

/* [in] */ DISPID dispID,

/* [in] */ DWORD dwCookie,

/* [in] */ VARIANT VarIn) ;

// Used for property expansion (currently variant types)

//

STDMETHOD(GetElementStrings)(

/* [in] */ DISPID dispID,

/* [out] */ OPMLPOLESTR __RPC_FAR *pCaStringsOut,

/* [out] */ OPMDWORD __RPC_FAR *pCaCookiesOut) ;


//Used for property expansion (currently variant types)

//

STDMETHOD(GetElementGrouping)(

/* [in] */ DISPID dispID,

/* [out] */ short *groupingNumber) ;

// Used for property expansion (currently variant types)

//

STDMETHOD(GetGroupCount)(

/* [in] */ DISPID dispID,

/* [out] */ long *nGroupCnt) ;

STDMETHOD(GetPredefinedStrings)(

/* [in] */ DISPID dispID,

/* [out] */ CALPOLESTR *pCaStringsOut,

/* [out] */ CADWORD *pCaCookiesOut);

STDMETHOD(GetPredefinedValue)(

/* [in] */ DISPID dispID,

/* [out] */ DWORD dwCookie,

/* [out] */ VARIANT *pVarOut);

7 Добавляют выполнение для функции в CPP исходном файле. Эти примеры - для объекта AsdkSquare:

STDMETHODIMP CAsdkSquareWrapper::GetElementValue(

/* [in] */ DISPID dispID,

/* [in] */ DWORD dwCookie,

/* [out] */ VARIANT * pVarOut)

{

if (pVarOut == NULL)

return E_POINTER;

AcDbObjectPointer<AsdkSquare> pSq(m_objId, AcDb::kForRead);

if (pSq.openStatus() != Acad::eOk)

return E_ACCESSDENIED;

if (dispID == 0x03) {

AcGePoint3d acgePt;

pSq->squareCenter(acgePt);

AcAxPoint3d acaxPt(acgePt);

::VariantCopy(pVarOut,&CComVariant(acaxPt[dwCookie]));

}

return S_OK;

}

STDMETHODIMP CAsdkSquareWrapper::SetElementValue(

/* [in] */ DISPID dispID,

/* [in] */ DWORD dwCookie,

/* [in] */ VARIANT VarIn)

{

AcDbObjectPointer<AsdkSquare> pSq(m_objId, AcDb::kForRead);

if (pSq.openStatus() != Acad::eOk)

return E_ACCESSDENIED;

if (dispID == 0x03) {

AcGePoint3d acgePt;

pSq->squareCenter(acgePt);

AcAxPoint3d acaxPt(acgePt);

acaxPt[dwCookie] = V_R8(&VarIn);

pSq->upgradeOpen();

pSq->setSquareCenter(acaxPt);

}

return S_OK;

}

STDMETHODIMP CAsdkSquareWrapper::GetElementStrings(

/* [in] */ DISPID dispID,

/* [out] */ OPMLPOLESTR __RPC_FAR *pCaStringsOut,

/* [out] */ OPMDWORD __RPC_FAR *pCaCookiesOut)

{

if (dispID == 0x03)

{

long size;

size = 3;

pCaStringsOut->pElems =

(LPOLESTR *)::CoTaskMemAlloc(sizeof(LPOLESTR) * size);

pCaCookiesOut->pElems =



(DWORD *)::CoTaskMemAlloc(sizeof(DWORD) * size);

for (long i=0;i<size;i++)

pCaCookiesOut->pElems[i] = i;

pCaStringsOut->cElems = size;

pCaCookiesOut->cElems = size;

pCaStringsOut->pElems[0] = ::SysAllocString(L"Center X");

pCaStringsOut->pElems[1] = ::SysAllocString(L"Center Y");

pCaStringsOut->pElems[2] = ::SysAllocString(L"Center Z");

}

return S_OK;

}

STDMETHODIMP CAsdkSquareWrapper::GetElementGrouping(

/* [in] */ DISPID dispID,

/* [out] */ short *groupingNumber)

{

return E_NOTIMPL;

}

STDMETHODIMP CAsdkSquareWrapper::GetGroupCount(

/* [in] */ DISPID dispID,

/* [out] */ long *nGroupCnt)

{

return E_NOTIMPL;

}

STDMETHODIMP CAsdkSquareWrapper::GetPredefinedStrings(

DISPID dispID, CALPOLESTR *pCaStringsOut,

CADWORD *pCaCookiesOut)

{

return E_NOTIMPL;

}

STDMETHODIMP CAsdkSquareWrapper::GetPredefinedValue(

DISPID dispID, DWORD dwCookie, VARIANT *pVarOut)

{

return E_NOTIMPL;

}

Динамические Свойства и OPM

Проблема с информацией типа состоит в том, что это является статическим. Это определено во времени компиляции в .idl файлах и не может изменяться легко во время выполнения. Microsoft обеспечивает интерфейсы, наиболее особенно ITypeInfo2 и ICreateTypeInfo, для так называемого динамического создания информации типа. Однако, эти интерфейсы только позволяют Вам добавлять информацию типа от существующей структуры ITypeInfo, которая относится к существующему интерфейсу отправки. Не имеется никакого метода во время выполнения для опроса объекта относительно его информации свойства. Чтобы заполнять этот промежуток и позволять любому DLL добавлять свойства к OPM, IDynamicProperty интерфейс был определен. Это позволяет Вам осуществлять IDynamicProperty полученный класс для каждого свойства, которое Вы желаете добавить к OPM. OPM может тогда вызывать методы этого класса, чтобы получить всю информацию, которую требоваться отобразить любой тип свойства.

IPropertyManager управляет, как OPM может получить указатели на эти интерфейсы свойства во время выполнения. Для каждого объекта AcRxClass в AutoCAD, клиент может получить указатель на объект, который осуществляет IPropertyManager. Это обработано внутренне через расширения протокола. Как только Вы имеете менеджера свойства для AcRxClass, Вы заинтересованы, Вы можете добавлять ваши классы свойства к этому через IPropertyManager:: AddProperty (). Когда пользователь выбирает объект того класса, OPM получит менеджера свойства для того класса, перечислит все классы свойства, и опрашивать те классы для их информации свойства, которую это тогда отобразит наряду с статическими свойствами того объекта. Обратите внимание, что класс IDynamicProperty не делает никакие предположения относительно того, где данные свойства сохранены. Это просто требует, чтобы  реализация IDynamicProperty обеспечила это, когда GetCurrentValueData () вызван. Точно так же, когда пользователь изменяет динамическое свойство, OPM назовет SetCurrentValueData () с новым значением, оставляя это до реализации, чтобы решить, как установить то значение. Это оставляет это до Вы, чтобы решить, как делать динамические данные свойства постоянными.



OPM использует IPropertyManager и IDynamicProperty не только для свойств объектов, но также и для отображающихся свойств текущего пространства, когда никакой объект не отобран. Например, когда никакой объект не отобран в рисунке, OPM должен отобразить свойства, касающиеся UCS. Также, некоторые команды требуют, чтобы  OPM отобразил информацию свойства (типа команд ОРБИТЫ). Эти ситуации требуют определяющих специальных менеджеров свойства для этих определенных “режимов”. Получение менеджеров свойства для режимов требует слегка различного механизма чем процедура для получения менеджеров свойства для выбираемых объектов. Как упомянуто ранее для свойств объектов, имеется расширение протокола для каждого класса объекта. Этот объект расширения протокола может использоваться разработчиком, чтобы получить менеджера свойства и добавлять его классы свойства. Для модальных ситуаций, будет иметься набор предопределенных расширений протокола на базе данных, что разработчик может использовать, чтобы отыскать менеджера свойства для той модальной ситуации.

IDynamicProperty

Как упомянуто ранее, Вы должны осуществить образец этого класса для каждого свойства, которое Вы желаете добавить к примитивам специфического класса.


Класс и Функциональный Краткий обзор


Основные классы и функции

§

AcDbLongTransaction класс

§         AcDbLongTransWorkSetIterator класс

§         AcApLongTransactionReactor класс

§         AcApLongTransactionManager класс

§         AcDbDatabase:: wblockCloneObjects () функция



Класс Реализации Versioning


1, если Вы получаете,  класс от любых классов ObjectARX, если бы не AcDbObject и AcDbEntity, вызывает{*называет*} setHasSaveVersionOverride (истину) в конструкторе так, чтобы AcDbObject:: getObjectSaveVersion () заданное по умолчанию выполнение знало не, только возвращают версию регистратора, но и  вместо этого свериться с вашей версией класса и возвращаются соответствующий “ объект, сохраняют{*экономят*} версию ” согласно правилам, описанным выше. GetObjectSaveVersion () не делает это, если этот бит не установлен.

2 Вы можете отменять AcDbObject:: getObjectSaveVersion () чтобы определить, в которой версии объектные данные должны быть сохранены. Не имеется никакой потребности к supermes-sage, потому что Вы полностью занимаете.

3 Не используют регистратора - > dwgVersion () в вашем dwgInFields (), dwgOutFields (), dxfInFields (), или dxfOutFields () методы. Использование сам () - > getObjectSaveVersion () вместо этого. Его заданное по умолчанию выполнение должно возвратить регистратора - > dwgVersion () если объект не хочет отменить сохраняющуюся{*экономящуюся*} версию.

Если Вы используете регистратора - > dwgVersion (), вы отключаете надлежащий выбор регистратора для классов, полученных из вашего.

4 Убеждаются, что регистрировал ваши классы, использующие ACRX_DXF_DEFINE_MEMBERS в AutoCAD 2000 с “ версия рождения ” использование двух новых параметров. Помните ту версию рождения, означает версию AutoCAD, что класс был представлен в, и это будет не всегда AutoCAD 2000, но могло быть Выпуск 13 или Выпускать 14.



Класс Versioning


Начинаясь с AutoCAD 2000, каждый класс пользователя должен обеспечить рисунок и эксплуатационный номер версии. Значение рисунка соответствует выпуску AutoCAD, который был текущий, когда класс был создан. Эксплуатационное значение может быть установлено в то, что является соответствующим вашему классу. Для классов ObjectARX, эксплуатационное значение будет установлено на нуль, каждый раз версия рисунка изменяется из-за нового выпуска AutoCAD. Значения версии определены в acdb.h файле заголовка. Макрокоманда ACRX_DXF_DEFINE_MEMBERS изменилась в AutoCAD 2000, чтобы брать два новых параметра, DWG_VERSION и MAINTENANCE_VERSION:

#define ACRX_DXF_DEFINE_MEMBERS(CLASS_NAME,PARENT_CLASS,\

DWG_VERSION,MAINTENANCE_VERSION,PROXY_FLAGS,DXF_NAME,APP)

Эти два параметра нужно обеспечить, и не имеется никаких значений по умолчанию. Новые параметры определяют версию, когда класс был представлен. Они станут компонентами данных AcRxClass, но они не постоянны, то есть они не сохранены в разделе класса DWG и DXF файлов.



Класс Versioning Пример


Новые параметры ACRX_DXF_DEFINE_MEMBERS определяют, из которой версии использовать, когда объект должен к файлу непосредственно. Когда рисунок сохранен, Вы можете определять которую DWG версию сохранить{*экономить*} к,  вызывая dwgVersion () метод регистратора. Не необходимо что объектный файл непосредственно из как та же самая версия как регистратор. Предыдущие выпуски AutoCAD сделали точно, что, который вел к проблемам, которые являются лучшими описанными следующим примером.

В Выпуске 14, новый компонент данных (mTreatElementsAsHard) был добавлен к AcDbDictionary. В AutoCAD 2000, класс по имени AcDbDictionaryWithDefault был получен из AcDbDictionary. Когда

Используя acdbSaveAsR13 (), mTreatElementsAsHard элемент не выписан, так как Выпуск 13 не знает относительно элемента. Если рисунок, сохраненный acdbSavedAsR13 () затем открыт на Выпуск 14, образец AcDbDictionaryWithDefault становится полномочным, так как Выпускают 14, не включает этот класс. Когда AcDbObject становится полномочным, все данные ниже уровня AcDbObject сохраняются неповрежденными в соответствии с AutoCAD как “ полномочные данные ” и не изменены{*заменены*}. Когда рисунок сохранен Выпуском 14, данные разгружаются назад к DWG файлу, поскольку это читалось в. Результат - Выпуск 14 DWG файл, который имеет образец AcDbDictionaryWithDefault, но пропускает mTreatElementsAsHard данные. При считывании этого рисунка к AutoCAD 2000, AutoCAD (определенно, AcDbDictionary:: dwgInFields ()) ищет тот компонент данных, так как это признает регистратора, являющегося Выпуском 14 типа, который должен иметь mTreatElementsAsHard данные. Однако, данные - не, подарок{*настоящее*}, последовательность потерян, и рисунок коррумпирован.

Это не определенно к AcDbDictionaryWithDefault. Новые классы в AutoCAD 2000, уже представленном ObjectARX или это будет представлено третьими лицами, может страдать от этой проблемы, особенно, если один из их супер-классов изменил{*заменил*} данные.



Классы cпециальной оценки


Следующий раздел описывает классы в AcGe библиотеке, с которой Вы можете оценивать точки на кривых и поверхностях. Эти классы - AcGePointOnCurve2d, AcGePointOnCurve3d, и AcGePointOnSurface.

Параметрическая кривая определена непрерывной функцией, которая отображает некоторый интервал реальной линии (возможно полная реальная линия) или в 2D

или  3D пространство, в зависимости от того, является ли кривая 2D или 3D. Параметрическая поверхность определена непрерывной функцией, которая отображает некоторое связанное подмножество uv

плана (возможно полный uv план) в пространство 3D. Точка на параметрической кривой или поверхности, которая соответствует специфическому значению параметра, может быть получена,  оценивая функцию в том значении параметра. Для кривых значение параметра - скаляр, и для поверхностей,  значение параметра - точка 2D.

Много геометрических систем моделирования, которые поддерживают параметрические кривые и поверхности, содержат функции вычислителя для вычисления точек на параметрических кривых и поверхностях. Эти вычислители типично имеют входные параметры для значения параметра, в котором кривая или поверхность должна быть оценена и для числа производных, которые должны быть возвращены. Они также вывели параметры для оцененной точки и массива векторов для производных.

Иногда вычислители содержат дополнительные параметры для требования и возвращения нормального вектора в специфическом значении параметра.

В дополнение к таким функциям вычислителя (методы вызвал evalPoint ()) для каждой кривой и поверхностного класса, AcGe библиотека содержит вычислитель, классифицирует AcGePointOnCurve2d, AcGePointOnCurve3d, и AcGePointOnSurface, через который к  кривой и поверхностные вычислители можно обращаться. К  кривой и поверхностные вычислители можно также обращаться через AcGePointOnCurve2d, AcGePointOnCurve3d, и классы AcGePointOnSurface. Эти классы обслуживают две основных цели:

§         Они формируют всю геометрическую информацию относительно специфической точки на кривой или поверхности типа значения параметра, координат пространства модели, производных, и искривления.


§         Они обеспечивают интерфейс к кривой и поверхностным вычислителям, который является более простым и более эффективным чем традиционный интерфейс вычислителя большинства систем АВТОМАТИЗИРОВАННОГО ПРОЕКТИРОВАНИЯ.

Общественный интерфейс к AcGePointOnCurve2d, AcGePointOnCurve3d, и классам AcGePointOnSurface идентичен если бы не незначительные различия в именах функции элемента. Например, AcGePointOnCurve3d класс содержит функцию deriv (), который возвращает производный вектор, в то время как AcGePointOnSurface класс содержит две функции, uDeriv () и vDeriv (), возвращать u и v частные производные. Остаток от этого раздела описывает, как использовать AcGePointOnSurface класс, но это описание обращается к AcGePointOnCurve2d и классам AcGePointOnCurve3d также, потому что их интерфейс очень похож к таковому AcGePointOnSurface класса.

Чтобы использовать AcGePointOnSurface класс, чтобы оценить точки и производные, Вы должны определить, которая поверхность должна быть оценена и значение параметра, в котором оценка должна быть сделана. Следующий две функции элемента устанавливают поверхность и значение параметра объекта AcGePointOnSurface:

AcGePointOnSurface& setSurface (const AcGeSurface&);

AcGePointOnSurface& setParameter (const AcGePoint2d&);

После того, как Вы вызываете setSurface (), все последующие оценки выполнены на той поверхности, пока Вы не вызываете setSurface () снова для различной поверхности. Точно так же после того, как Вы вызываете setParameter (), все последующие функции запроса возвращают информацию, имеющую отношение к тому значению параметра, пока setParameter () не вызван{*назван*} снова для различного значения параметра. Например, рассмотрите,является ли srf

объект AcGeSurface, param - объект AcGePoint2d, и pntOnSrf - объект AcGePointOnSurface, то следующий код оценивает точку, и первые производные на srf

в параметре оценивают param:

pntOnSrf.setSurface (srf);

pntOnSrf.setParameter (param);



AcGePoint3d pnt3d = pntOnSrf.point();

AcGeVector3d uFirstPartial = pntOnSrf.uDeriv(1), vFirstPartial = pntOnSrf.vDeriv(1);

Практически, Вы редко, если когда-либо, вызываете setSurface () или setParameter () непосредственно.

Вместо этого Вы вызываете эти функции косвенно через функции элемента AcGePointOnSurface класса. Например, point() функция, которая возвращает точку пространства модели в специфическом значении параметра, имеет три различных сигнатуры:

AcGePoint3d point () const;

AcGePoint3d point (const AcGePoint2d& param);

AcGePoint3d point (

const AcGeSurface& srf,

const AcGePoint2d& param);

Первая сигнатура не берет никакие параметры и предполагает, что поверхность и значение параметра уже были установлены предыдущим, вызывает к setSurface () и setParameter (). Вторая сигнатура предполагает, что поверхность уже была установлена предыдущим запросом к setSurface (), но это вызывает setParameter (param), чтобы установить значение параметра перед оценкой. Третья сигнатура вызывает setSurface (srf) и setParameter (param), чтобы установить поверхность и значение параметра перед оценкой. Только функция левой части объявлена как константа; другой два изменяют объект,  устанавливая поверхность и-или значение параметра. Прямой вызов к setSurface () и setParameter () может теперь быть удален из предыдущего кода следующим образом:

AcGePoint3d pnt3d = pntOnSrf.point ( srf, param );

AcGeVector3d uFirstPartial = pntOnSrf.uDeriv(1),

vFirstPartial = pntOnSrf.vDeriv(1);

Первые операторные причины setSurface (srf) и setParameter (param), чтобы быть вызван перед оценкой выполнены. Последующие оценки выполнены на той же самой поверхности и в том же самом значении параметра, пока setSurface () или setParameter () не вызван снова, или непосредственно или косвенно.

Поэтому, вторая инструкция не должна повторно определить или srf

или param параметры. Все функции оценки AcGePointOnSurface класса следуют за тем же самым образцом наличия трех различных сигнатур:



AcGeVector3d uDeriv (int order) const;

AcGeVector3d uDeriv (int order, const AcGePoint2d& param);

AcGeVector3d uDeriv (

int order, const AcGeSurface& srf,

const AcGePoint2d& param);

AcGeVector3d vDeriv (int order) const;

AcGeVector3d vDeriv (int order, const AcGePoint2d& param);

AcGeVector3d vDeriv (

int order, const AcGeSurface& srf,

const AcGePoint2d& param);

AcGeVector3d mixedPartial () const;

AcGeVector3d mixedPartial (const AcGePoint2d& param);

AcGeVector3d mixedPartial (

const AcGeSurface& srf,

const AcGePoint2d& param);

AcGeVector3d normal () const;

AcGeVector3d normal (const AcGePoint2d& param);

AcGeVector3d normal (

const AcGeSurface& srf,

const AcGePoint2d& param);

Точно так же имеются три конструктора для AcGePointOnSurface класса:

AcGePointOnSurface ();

AcGePointOnSurface (const AcGeSurface& srf);

AcGePointOnSurface (

const AcGeSurface& srf,

const AcGePoint2d& param);

При использовании первого конструктора, Вы не определяете значение параметра или поверхность. Возможно, Вы устанавливаете поверхность и значение параметра перед первой оценкой. Чтобы предотвращать построение неинициализированного объекта, первый конструктор устанавливает поверхность в AcGePlane:: kXYPlane, который является только планом XY, и устанавливает значение параметра в значение по умолчанию (0,0). Второй конструктор вызывает setSurface (srf) и устанавливает значение параметра в значение по умолчанию (0,0). Третий конструктор вызывает setSurface (srf) и setParameter (param). Второй конструктор особенно полезен в функциях

В котором в поверхность пропускают как параметр:

void func (const AcGeSurface& srf)

{

AcGePointOnSurface

pntOnSrf (srf);

.

.

.

}

Конструктор вызывает setSurface (srf) так, чтобы все последующие оценки в этой функции были выполнены на srf.

Поскольку AcGePointOnSurface класс формирует, и параметрический и информация пространства модели относительно специфической точки на поверхности, это полезно для функций, которые должны возвратить информацию относительно одних или более отличных точек на поверхности. Например, AcGeSurface класс содержит функцию элемента:



void getClosestPointTo (

const AcGePoint3d& pnt3d,

AcGePointOnSurface& closestPoint,

const AcGeTol& =AcGeContext::gTol) const;

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

библиотеке, которые возвращают объект AcGePointOnSurface как параметр вывода (не-константа),  уже вызвали setSurface () и setParameter () для того параметра. Поэтому, после запроса такой функции, Вы не должны сбросить значение параметра или поверхность. Например, следующий код получает значение параметра, точку пространства модели, и первые производные самой близкой точки на поверхности srf к сути pnt3d:

// Вычислить самую близкую точку на поверхности к pnt3d.

AcGePointOnSurface closestPoint;

srf.getClosestPointTo (pnt3d, closestPoint);

// Получить значение параметра, точку пространства модели, и первую производную

// Векторы самой близкой точки.

AcGePoint2d param = closestPoint.parameter ();

AcGePoint3d pnt3d = closestPoint.point ();

AcGeVector3d uFirstPartial = closestPoint.uDeriv (1),

vFirstPartial = closestPoint.vDeriv (1);

Ни один из вызывов point (), uDeriv (), или vDeriv () не должен определить поверхность или значение параметра, потому что они были уже установлены getClosestPointTo(). Вообще, setSurface () и setParameter () не должен быть вызван, если Вы явно не намереваетесь изменить поверхность или значение параметра объекта AcGePointOnSurface. Например, первая инструкция в следующем коде косвенно вызывает setSurface () и setParameter (). Вторые и третьи инструкции неэффективны, потому что они делают ненужным, вызывает к setSurface () и setParameter (), используя точный те же самые параметры как первая инструкция.

AcGePoint3d pnt3d = pntOnSrf.point (srf, param);

AcGeVector3d uFirstPartial = pntOnSrf.uDeriv (1, srf, param);



AcGeVector3d vFirstPartial = pntOnSrf.uDeriv (1, param);

Этот код выполняется правильно; однако более эффективно записать это следующим образом:

AcGePoint3d pnt3d = pntOnSrf.point (srf, param);

AcGeVector3d uFirstPartial = pntOnSrf.uDeriv ();

AcGeVector3d vFirstPartial = pntOnSrf.uDeriv ();

AcGePointOnCurve2d, AcGePointOnCurve3d, и классы AcGePointOnSurface не только обеспечивают способ формировать пространство параметра и информацию пространства модели точки на кривой или поверхности, они также обеспечивают более простой и более естественный интерфейс к кривой и поверхностным вычислителям чем традиционные вычислители. Типичный вычислитель поверхности Стиля C смотрит кое-что вроде следующего:

void evaluate (

int numDeriv, double u, double v, Point& pnt,

Vector[] derivArray);

 Здесь, Вы определяете, что  значение параметра (значение параметра поверхности - точка 2D, чей координаты - u, v) и запрос, сколько производных должны быть возвращены. Вычислитель тогда вычисляет точку и требуемые производные в указанном значении параметра. При требовании производных, Вы должны знать порядок, в котором они возвращены. Например, является ли смешанным частичным сохраненным в четвертом или пятом элементе массива? Вы должны также удостовериться, что Вы не проходите в массиве, который является слишком маленьким, иначе наложение записей памяти произойдет. Это может быть проблема, когда вычислитель первоначально вызван для нулевых производных или одной производной (с размером массива 2 для derivArray) и позже измененный, чтобы возвратить две производной. Если Вы забываете увеличивать размер derivArray, то наложение записей памяти происходит, потому что вычислитель возвращает пять производных векторов (две первых производной и три вторых производной) в массив, который может только держать два вектора.

С AcGePointOnSurface классом, Вы запрашиваете точку, производную, и нормальную информацию в простом способе использовать point(), uDeriv (), vDeriv (), mixedPartial (), и normal() функции. Названия этих функций указывают ясно, который оценивает, они возвращаются, и не имеется никакой опасности наложения записей памяти. Вы не должны индексировать в массив, чтобы получить производные векторы и подверг риску создания ошибки и использования неправильного индекса для одного или большего количества векторов. AcGePointOnSurface класс обеспечивает интерфейс на поверхностный вычислитель, который результаты в более простом коде, который является также более читаемым и понятным другим программистам.



В дополнение к обеспечению более простого и более естественного интерфейса к кривой и поверхностным вычислителям, AcGePointOnCurve2d, AcGePointOnCurve3d, и классы AcGePointOnSurface обеспечивают более эффективный интерфейс также по традиционным вычислителям. Это - то, потому что каждый из этих классов содержит указатель на область данных, которая может использоваться вычислителями, чтобы сохранить информацию между оценками. Например, вычислитель НЕОДНОРОДНОГО РАЦИОНАЛЬНОГО В-СПЛАЙНА использует эту область, чтобы сохранить матрицы основания мощности, которые не сохранены как часть поверхностного определения. Используя эту область данных, вычислители могут избегать повторно вычислять те же самые данные, который был вычислен в предыдущей оценке и таким образом работать более эффективно. Эти данные - не часть кривой или поверхностных классов, потому что оценки могли бы иметь место в больше чем одной области чередующимся способом, который приведет к неэффективной потере местных данных оценки в переключении контекста.

Эта область данных также позволяет вычислителям быть намного более эффективной, когда преобразование применилось к объекту AcGePointOnSurface. Если transformBy () функция вызвана на объект AcGePointOnSurface, это заставляет последующие оценки быть преобразованным указанным преобразованием без фактически преобразования основной поверхности. Это означает, что вычислители должны применить преобразование к каждой точке, производной, и нормальному вектору, который они вычисляют. Используя область данных объекта AcGePointOnSurface, вычислители могут избегать иметь фактически, чтобы применить это преобразование для каждой оценки. Например, AcGePlane класс содержит компоненты данных mPoint, mUAxis, и mVAxis, которые определяют начало координат и оси плана. AcGePlane вычислитель оценивает точку со следующей инструкцией:

AcGePoint3d pnt3d = mPoint + param.x * mUAxis + param.y * mVAxis;

Если transformBy () запросили объект AcGePointOnSurface, то это преобразование должно примениться к pnt3d прежде, чем это возвращено вызывающей программе.

Вычислитель может избегать, чтобы  расход матрицы умножился,  сохраняя преобразованный mPoint, mUAxis, и mVAxis в AcGePointOnSurface области данных.

Тогда вышеупомянутая инструкция оценит точку в преобразованном местоположении без дополнительного расхода матрицы, умножают. Это - особенно полезная способность в приложениях типа моделирования трансляции{*блока*}, где кривые и поверхности были преобразованы в пространство{*пробел*} трансляции{*блока*} преобразованием позиционирования.


Классы Примитива


Объекты Контурного представления типично формируются, используя по умолчанию AcBr конструктор и затем инициализированы или с набором () функция или с traverser и одной из его функций get*.

Весь AcBr классифицирует конструкторы копии поддержки; операторы назначения; isEqualTo (), isNull (), и набор () и получают () семантику; и другие функции и запросы.

Классы примитива включают следующее:

§

AcBrEntity

§          AcBrBrep

§          AcBrComplex

§          AcBrShell

§          AcBrFace

§          AcBrLoop

§          AcBrEdge

§          AcBrVertex



Классы Сдерживания


Объекты Сдерживания никогда не сформированы непосредственно пользователем. Они возвращены запросами сдерживания линии на примитивах, полученных из AcBrEntity.

AcBrHit класс - класс сдерживания.



Классы Сети


Объекты Сети никогда не сформированы непосредственно пользователем, кроме где отмечено в ObjectARX Ссылке. Они возвращены запросами обхода сети.

Классы сети включают следующее:

§

AcBrMeshEntity

§          AcBrMesh

§          AcBrMesh2d

§          AcBrElement

§          AcBrElement2d

§          AcBrNode

§          AcBrMesh2dFilter

§          AcBrMeshControl

§          AcBrMesh2dControl



Классы Управления Документа


ObjectARX обеспечивает набор классов, чтобы управлять документами в пределах ObjectARX-приложения. Каждый открытый рисунок имеет связанный объект AcApDocument. AcApDocManager класс управляет всеми объектами AcApDocument, связанными с приложением.



Ключевые концепции Клонирования


Эта секция описывает некоторых из ключевых терминов и концепций, используемых в течение этого обсуждения глубокого клона и клона wblock: запись в файл, монопольное использование, карта ID, и клонирование и шаги трансляции.



Ключи приложений


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



Ключи расширений


Этот ключ - для довольных средств доступа, кто хотят регистрировать себя и участвовать в режиме рабочего стола Дизайн-центра AutoCAD. Эти довольные средства доступа обрабатывают только специфические типы расширений, и они не заинтересованы участием в заказной установке режима Дизайн-центра AutoCAD.



Клонирование и Карта ID


Карта ID - механизм для слежения за операцией клона. Карта состоит из пар объектных ID — ID объекта источника (упомянутый как “ ID ключ”) и ID клонированного, или адресат, объект (упомянутый как “ значение ID”). Карта ID также содержит дополнительные пары ID неклонированных объектов, которые необходимы для трансляции ID (см. “ Стадия Трансляции ” на странице 477).

Когда deepCloneObjects () - обратился к некоторым объектам, дополнительные объекты клонировались{*имитируются*} из-за их подключения{*связи*} монопольного использования с первичным набором клонированных{*имитируемых*} объектов. Вы можете смотреть на карту ID, чтобы видеть то, какие дополнительные объекты клонируются.



Клонирование и Монопольное использование


Отношения между объектами сохранены в объекте как компонент данных AcDbObjectId класса. Имеются четыре различных типа отношений между объектами — жесткие владельцы, мягкие владельцы, жесткие указатели, и мягкие указатели. Например, если Вы создаете примитив, который требует текстового стиля, тот примитив имел бы компонент данных класса AcDbObjectId, который обратится{*отнесется*} к AcDbTextStyleTableRecord, и это было бы зарегистрировано из как жесткий указатель ID.

Путем Вы регистрируете из AcDbObjectId, решает{*определяет*}, как глубокий клон и операции клона wblock используют объект ID. Для подробной информации, см. “ Объектные Ссылки ” на странице 310. Глубоко клон следует интенсивно и мягкие подключения{*связи*} владельца, и клон wblock следует за жестким владельцем и подключениями{*связями*} указателя, как показано в следующем числе{*рисунке*}:

Hard Owner

deep clone

wblock clone

Hard Pointer

wblock clone

Soft Owner

deep clone

Soft Pointer



Клонирование и Трансляция


Глубокий клон и операции клона wblock фактически состоят из двух шагов: клонирование и трансляция. Шаг клонирования - то, где dwgOut () и dwgIn () вызваны, и объекты скопированы. Второй шаг - шаг трансляции, который использует карту ID, чтобы повторно связать все объекты, чтобы отразить новые отношения.

В течение трансляции, все четыре типа объектных ID должны быть оттранслированы. Некоторые объекты клонировались и находятся в карте ID, в то время как другие не клонировались и не в карте. В течение трансляции ID, если пара ID, соответствующая ссылке не найдена в карте ID, одна из двух вещей случается. Если ссылка находится в той же самой базе данных как объект, который является что касается этого, это оставлено один. Иначе, это установлено в NULL. См. “ Стадия Трансляции ” на странице 477.



Клонирование и Запись в файл


Глубокий клон и операции клона wblock оба объект использования, регистрирующие, чтобы копировать (клонировать) объект. Новый объект создан, который будет клон. Затем, первоначальный объект зарегистрирован из к памяти, используя dwgOut (). Наконец, данные зарегистрированы в к новому клонированному объекту, используя dwgIn ().



Клонируемая Стадия


В течение клонируемой стадии, когда Вы вызываете, deepClone () на объекте, AutoCAD выясняет, если клонированный объект (первичный объект) имеет любые другие объекты. Если это делает, это вызывает deepClone () на тех объектах также. Этот процесс продолжается, пока все находящиеся в собственности объекты не клонировались. И интенсивно и мягкие связи монопольного использования сопровождаются.

Когда Вы вызываете wblockClone () на объекте, AutoCAD следует за жестким владельцем и жесткими связями указателя и вызывает wblockClone () на тех объектах также.



Клонируемые Объекты от Различных Владельцев


Если Вы клонируемые набор объектов от различных владельцев, вы будете должны делить набор объектных ID в отдельные группы для каждого владельца. (Клонированные объекты и их владельцы должны принадлежать той же самой базе данных.) В примере в этой секции, объекты пространства модели, которые нужно клонировать добавлены к objListMS, и объекты пространства листа, которые нужно клонировать добавлены к objListPS:

objListMS.append(objId);

objListPS.append(objId);

DeepCloneObjects () функция тогда вызвана дважды, используя ту же самую карту ID. Необходимо делать все клонирование, используя единственную карту ID для трансляции ссылки, которая будет сделана должным образом. На первом запросе, deferXlation параметр установлен в kTrue. В секунде (последний) вызывают к deepCloneObjects (), deferXlation значения по умолчанию к kFalse:

acdbHostApplicationServices()->workingDatabase()->DeepCloneObjects (mslist, modelSpaceId, idMap, Adesk::kTrue);

acdbHostApplicationServices()->workingDatabase()->DeepCloneObjects (pslist, paperSpaceId, idMap);

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

void

cloneDiffOwnerObjects()

{

// Step 1: Obtain the set of objects to be cloned.

// For the two owners we’ll use model space and

// paper space, so we must perform two acedSSGet() calls.

// calls.

//

acutPrintf("\nSelect entities to be cloned to"

" Model Space");

ads_name ssetMS;

acedSSGet(NULL, NULL, NULL, NULL, ssetMS);

long lengthMS;

acedSSLength(ssetMS, &lengthMS);

acutPrintf("\nSelect entities to be cloned to"

" Paper Space");

ads_name ssetPS;

if (acedSSGet(NULL, NULL, NULL, NULL, ssetPS) != RTNORM && lengthMS == 0)

{

acutPrintf("\nNothing selected");

return;

}

long lengthPS;

acedSSLength(ssetPS, &lengthPS);

// Step 2: Add obtained object IDs to the lists of


// objects to be cloned: one list for objects to

// be owned by model space and one for those to

// be owned by paper space.

AcDbObjectId ownerId = AcDbObjectId::kNull;

// For model space

//

AcDbObjectIdArray objListMS;

for (int i = 0; i < lengthMS; i++) {

ads_name ent;

acedSSName(ssetMS, i, ent);

AcDbObjectId objId;

acdbGetObjectId(objId, ent);

// Check to be sure this has the same owner as the first

// object.

//

AcDbObject *pObj;

acdbOpenObject(pObj, objId, AcDb::kForRead);

if (pObj->ownerId() == ownerId)

objListMS.append(objId);

else if (i == 0) {

ownerId = pObj->ownerId();

objListMS.append(objId);

}

pObj->close();

}

acedSSFree(ssetMS);

// For paper space

//

ownerId = AcDbObjectId::kNull;

AcDbObjectIdArray objListPS;

for (i = 0; i < lengthPS; i++) {

ads_name ent;

acedSSName(ssetPS, i, ent);

AcDbObjectId objId;

acdbGetObjectId(objId, ent);

// Check to be sure this has the same owner as the first

// object.

//

AcDbObject *pObj;

acdbOpenObject(pObj, objId, AcDb::kForRead);

if (pObj->ownerId() == ownerId)

objListPS.append(objId);

else if (i == 0) {

ownerId = pObj->ownerId();

objListPS.append(objId);

}

pObj->close();

}

acedSSFree(ssetPS);

// Step 3: Get the object ID of the desired owners for

// the cloned objects. We’re using model space and

// paper space for this example.

//

AcDbBlockTable *pBlockTable;

acdbHostApplicationServices()->workingDatabase()

->getSymbolTable(pBlockTable, AcDb::kForRead);

AcDbObjectId modelSpaceId, paperSpaceId;

pBlockTable->getAt(ACDB_MODEL_SPACE, modelSpaceId);

pBlockTable->getAt(ACDB_PAPER_SPACE, paperSpaceId);

pBlockTable->close();

// Step 4: Create a new ID map.

//

AcDbIdMapping idMap;

// Step 5: Call deepCloneObjects().

//

acdbHostApplicationServices()->workingDatabase()

->deepCloneObjects(objListMS, modelSpaceId, idMap, Adesk::kTrue);

acdbHostApplicationServices()->workingDatabase()

->deepCloneObjects(objListPS, paperSpaceId, idMap);

// Now we can go through the ID map and do whatever we’d

// like to the original and/or clone objects.

//

// For this example we’ll print out the object IDs of

// the new objects resulting from the cloning process.

//

AcDbIdMappingIter iter(idMap);

for (iter.start(); !iter.done(); iter.next()) {

AcDbIdPair idPair;

iter.getMap(idPair);

if (!idPair.isCloned())

continue;

acutPrintf("\nObjectId is: %Ld", idPair.value().asOldId());

}

}


Код, вызванный под прикладным контекстом выполнения


Приложение руководителя закодирует конструкции, которые обычно вызываются под прикладным контекстом выполнения:

§

VBA-ИНИЦИАЛИЗИРОВАЛ запросы ActiveX (осуществленный в ObjectARX).

§         ActiveX запросы, сделанные от внешних процессов, включая Visual Basic.

§         диалоговые окна Modeless, зарегистрированные ObjectARX-приложениями, или любым DLL, загруженным в соответствии с AutoCAD.

§         Все службы ObjectARX вызывает сделанным от прикладного контекста, включая любые ObjectARX-определенные окна вызова разделов, которые могут быть вызваны от них, включая заказной объект и примитив виртуальные члены, AcDb *, AcRx* реакторные члены, и AcEditorReactor члены относительно объектов базы данных.



Коды Служебного бита Ввода пользователя


Коды служебного бита ввода пользователя, перечисленные в следующей таблице пропускают как первый параметр к acedInitGet () функция, чтобы управлять поведение функций ввода пользователя acedGetxxx, acedEntSel, acedNEntSelP, acedNEntSel, и acedDragGen:

Коды служебного бита Ввода пользователя

Код

 Описание

RSG_NONULL

 Отвергают нулевой{*пустой*} ввод

RSG_NOZERO

 Отвергают нулевые значения

RSG_NONEG

 Отвергают отрицательные значения

RSG_NOLIM

 Не проверяют{*отмечают*} пределы рисунка, даже если LIMCHECK включен

RSG_DASH

 Пунктирные линии Использования при рисунке резиновой полосы выравнивают или поле

RSG_2D

 Игнорируют координату Z трехмерных точек (acedGetDist () только)

RSG_OTHER

 Позволяют произвольный ввод (безотносительно типов пользователя)



Коды Состояния


Ads_start_dialog () функция имеет параметр состояния, который это устанавливает, чтобы указать, как диалоговое окно закончилось. Значения для этого состояния показываются в следующей таблице:

Значения кода Состояния

Символ

 Описание

DLGOK

 Пользователь выбрал кнопку OK или ее эквивалент.

DLGCANCEL

 Пользователь выбрал Отмену или ее эквивалент.

DLGALLDONE

 Диалоговое окно неактивно; ads_term_dialog был вызван.

DLGSTATUS

Если состояние большее чем или равно DLGSTATUS, это - определенный приложением код состояния.

Код причины прошел в пакете повторного вызова (cpkt->reason)  - целое число, которое указывает, почему повторный вызов произошел (то есть какое действие пользователя генерировало повторный вызов). Коды причины повторного вызова показываются в следующей таблице:

Причина Повторного вызова закодирует значения

Символ

Описание

CBR_SELECT

Пользователь выбрал неперекрывающее расположение (поле ввода).

CBR_LOST_FOCUS

Окна редактирования пользователь передвигал в другое неперекрывающее расположение, но не делали заключительный выбор.

CBR_DRAG

 Для слайдеров, пользователь изменил значение,  перемещая индикатор (или эквивалент) но не делал заключительный выбор.

CBR_DOUBLE_CLICK

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

Символы, описанные в этом разделе используются с ads_mode_tile () и ads_start_list () функции.

Функция ads_start_list () начинает обрабатывать список для списка или всплывающего списка. Символы, чтобы использовать показываются в следующей таблице:

Функция Списка закодирует значения

Символ

 Описание

LIST_CHANGE

 Изменение отобранного содержания списка.

LIST_APPEND

 Добавляют новый вход списка.

LIST_NEW

 Удаляют старый список и создают новый список.

Функция ads_mode_tile () управляет фокусом поля ввода и определяет, позволяется ли это. Символы и их описания показываются в следующей таблице.



Коды Типа Результата, определенные ObjectARX


Restype поле буфера результатов - короткий целочисленный код, который указывает, которые напечатают ценный,  сохранен в resval поле буфера. Поскольку результаты прошли к и от функций ObjectARX, ObjectARX определяет коды типа результата, перечисленные в следующей таблице:

Коды типа Результата

Код

 Описание

RTNONE

 Никакое значение результата

RTREAL

 Реальное значение (с плавающей точкой)

RTPOINT

 2-ая точка (X и Y; Z == 0.0)

RTSHORT

 Короткое (16-разрядное) целое число

RTANG

 Угол

RTSTR

 Строка

RTENAME

 Имя Примитива

RTPICKS

 Имя набора Выбора

RTORINT

 Ориентация

RT3DPOINT

 Трехмерная точка (X, Y, и Z)

RTLONG

 Долго (32-разрядное) целое число

RTVOID

 Пустой (blanc) символ

RTLB

 Список начинается (для вложенного списка)

RTLE

 Список конец (для вложенного списка)

RTDOTE

 Точка (для точечной пары)

RTT

 AutoLISP t (истина)

RTNIL

 Ноль AutoLISP

RTDXF0

 Группа закодирует нуль для списков DXF (используемый только с acutBuildList ())



Коды возврата ошибки


AcBr:: ErrorStatus перечисление возвращен всей не-булевой переменной оцененные функции.

Код ошибки может быть или глобальная переменная код ошибки AutoCAD (как перечислено в Acad:: ErrorStatus перечисление), приводить к местному AcBr:: ErrorStatus перечисление, или местный код ошибки библиотеки контурного представления. Местные коды ошибки определены, используя стартовое ядро 3000, чтобы, чтобы не найтись в противоречии с AutoCAD, AutoCAD Механический API, или Autodesk Механическая Настольная ошибка закодирует.



Количество баз данных.


Множество баз данных могут быть загружены в одном сеансе AutoCAD. Каждый объект в сеансе имеет метку и ID. Метка уникально идентифицирует объект в пределах специфической базы данных. ID уникально идентифицирует объект во всех базах данных, загруженных в одно время. ID сохраняется только в течение сеанса редактирования, но метка сохраняется с рисунком. В отличие от ID объекта, метка может быть неуникальна, когда множество баз данных загружены в сеансе AutoCAD.



Команда


Повсюду этой главы, термин “команда” относится к разнообразию конструкций AutoCAD. Команда состоит из последовательности программы, выполненной как логический модуль работы, которая может требоваться пользователем или одним из AutoCAD, пишущего сценарий двигатели. Независимо от того, какой конструкция используется, команда может быть уничтожена независимо от других действий, выполненных в течение операции системы.

Определенно для API MDI, команда - последовательность кода, который начинается,  блокируя документ и концы,  разблокируя документ. В общих{*обычных*} случаях, эта блокировка и разблокирование будет выполнена ObjectARX, но в течение других времен,  приложение должно делать блокировку и разблокирование непосредственно. Все после конструкций AutoCAD - команды:

§

AutoCAD встроенные команды.

§         Встроенные команды, выполненные непосредственно от командного процессора, типа F2 для экрана изменения. Это включает функцию и клавиши CTRL.

§         обращения функции AutoLISP, которые могут быть определены или в AutoLISP или в ObjectARX-приложении, используя acedDefun ().

§         команды программы External, определенные в acad.pgp.

§         AcEd-зарегистрированные команды, зарегистрированные из AutoCAD.

§         Действия, принятые от немодального окна диалога или некоторого другого внешнего процесса, типично, которому оказывает гостеприимство ObjectARX-приложение.

§         набор действий, принятых от приложения ActiveX во внешнем процессе.

§         Действия, принятые от VBA до интерфейса ActiveX.

§         Щелкают правой кнопкой мыши обращения меню контекста.



Команда и Функциональные Списки Обращения


Наконец, acutBuildList () вызван в сочетании с acedCmd (), который берет список буфера результата, чтобы вызвать AutoCAD, командует, и с acedInvoke (), который вызывает внешнюю функцию от различного

ObjectARX-приложение.

Следующий типовой кодовый фрагмент вызывает acutBuildList () и acedInvoke () чтобы вызвать команду RESET, определенную приложением выборки gravity.c:

struct resbuf *callist, *results = NULL;

callist = acutBuildList(RTSTR, "c:reset", 0);

if (acedInvoke(callist, &results) == RTERROR)

acdbFail("Cannot run RESET -- GRAVITY program may not be loaded\n");

acutRelRb(callist);

acutRelRb(results);

Эксклюзивные типы для расширенных данных

Расширенные данные (xdata) могут включать двоичные данные, организованные в куски переменной длины. Они обработаны структурой ads_binary, следующим образом:

struct ads_binary { // Binary data chunk structure

short clen; // Length of chunk in bytes

char *buf; // Binary data

};

Значение clen поля должно быть в диапазоне от 0 до 127. Если приложение требует больше чем 127 байтов двоичных данных, это должно организовать данные в множественные куски.

С Выпуском 13, DXF представление таблицы идентификаторов может включать расширенные данные примитива. Xdata

возвращен как метка.

ОБРАТИТЕ ВНИМАНИЕ, что не имеется никакого механизма для возвращения двоичных данных к AutoLISP. Двоичные куски можно пропускать к другим внешним функциям посредством acedInvoke (), но только, когда они принадлежат группам (1004 в пределах расширенных данных примитива.

Вы не можете проходить, изолировал двоичные куски.

Xdata может также включать длинные целых числа. Ads_u_val объединение resval поля буфера результатов включает, и ads_binary и длинного члена для обработки расширенных данных примитива.

ОБРАТИТЕ ВНИМАНИЕ, что не имеется никакого механизма для возвращения длинного целого числа к AutoLISP. Длинные целых числа можно пропускать к другим внешним функциям посредством acedInvoke (), но только, когда они принадлежат группам (1071 в пределах расширенных данных примитива. В AutoLISP, 1071 группы поддержаны как реальные значения.



Выпуск AutoCAD 13 был расширен


Проблемы глобализации текстовых строк

Выпуск AutoCAD 13 был расширен с поддержкой локализации, чтобы делать AutoCAD более подходящим для международных клиентов. С этой поддержкой, пользователь AutoCAD может вводить команды в местные не-английские языки, и дисплей показывает сообщения на местном языке. Поддержка для наборов символов с  множественным языком вовлекает из символы из других кодовых страниц.

Иногда строки кодовой страницы системы в a .dwg файл имеют из -code-page символов, чтобы отобразить сообщения на другом языке. Эти символы не имеют никакого нормального представления в наборе символов родной системы. “\U+XXXX” и “\M+XXXX” escape-последовательности представляют эти специальные символы в строках кодовой страницы системы. XXXX - последовательность четырех шестнадцатеричных цифр, которые определяют или Уникод (единственно - символьное кодирование) идентификатор или Многобайтовый Формат обмена (MIF) закодированного символа.

Как часть усилия глобализации Autodesk, следующие функции ObjectARX существования ранее были изменены, чтобы улучшить обработку рисунков, созданных с различными версиями языка AutoCAD:

AcdbXdSize         Возвращает число байтов памяти, необходимой для списка расширенных  данных примитива.

AcdbXdRoom      Возвращает число байтов памяти, которую примитив имеет доступный для расширенных данных.

Эти функции рассчитывают из -code-page символов по-другому.

AcdbXdSize () и acdbXdRoom () функции теперь признают “\U+XXXX” как 1 байт, но другие функции ObjectARX признают “\U+XXXX” как 7 байтов. Азиатская версия AutoCAD признает “\M+XXXX” как 2 байта.

ОБРАТИТЕ ВНИМАНИЕ На ObjectARX-приложения, которые делают явные предположения относительно предела строковой длины имен таблицы идентификаторов, и НА ТЕКСТОВЫЕ примитивы воздействуют символы " из страницы коды ".


Команда, MDI


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



Команда, повторно неиспользуемая


Команда, которая не может быть выполнена в больше чем одном документе одновременно.

Неповторная входимость может использоваться для команд, которые не должны быть доступны для больше чем одного документа одновременно, или когда требования  поддержки множественной реализации слишком большие, чтобы стоить верхние.



Командный процессор


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

ОБРАТИТЕ ВНИМАНИЕ На команды, которые выполняются вне контекста единственного{*отдельного*} документа, типа немодальных диалогов и инструментальных панелей, зарегистрированных приложениями AutoCAD или ObjectARX, выполняются изнутри прикладного контекста.



Команды AutoCAD для использования глубокого клона и Wblock-клона


Множество команд AutoCAD использует deepClone () функция, чтобы создать новые объекты от старых. В некоторых случаях, одна версия команды исполняет глубоко клонирование, в то время как другая версия делает нет. Команды, использующие deepClone() и wblockClone() следующие:

COPY

Использует deepClone ().

ARRAY

Использует deepClone ().

MIRROR

Если и оригинал и отраженные объекты сохраняются, использует deepClone (). Если первоначальные объекты удалены, deepClone () не используется (первоначальные объекты только отражены).

BLOCK

Использует deepClone (). Эта команда копирует примитивы в другое пространство и стирает первоначальные примитивы.

INSERT

Когда Вы вставляете рисунок, эта команда использует deepClone () чтобы копировать примитивы в рисунок.

WBLOCK

Использует wblockClone (). Эта функция следует за жестким монопольным использованием и жесткими связями указателя только. Вся другая копия командует, чтобы использование deepClone () следовало, и интенсивно и мягкие связи монопольного использования от первичного объекта.

XREF BIND XBIND

Использует wblockClone () чтобы принести упомянутые примитивы в ваш текущий рисунок.

EXPLODE

Когда Вы взрываете объект в его части, никакое клонирование не выполнено.

Когда Вы взрываете блок-ссылку, AutoCAD удаляет примитив блок-ссылки и копирует индивидуальные примитивы в рисунок. Эта версия EXPLODE использует deepClone ().



Команды AutoLISP


Команды AutoLISP должны знать, что имеется отдельный стек AutoLISP для каждого документа. Это означает, что переменные AutoLISP должны быть обработаны таким же образом как другая глобальная переменная " в документ " и статические данные. Для большего количества информации, см. “ Данные " в документ " ” на странице 424.

AcRx:: kLoadDwgMsg сообщение в acrxEntryPoint () послан для каждого документа, открытого, когда приложение сначала загружено, и когда любые новые документы открыты, в то время как приложение выполняется. Сообщения посланы от контекста выполнения соответствующего документа.



Компоненты Средства просмотра


ObjectDBX

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

AcGix библиотека разработок

SimpleView производят выборку векторного берущего, использующего HDC

WhipView берущий вектора дисплейного файла

Типовое приложение ObjectDBX ViewAcDb

демонстрирует использование этих компонентов. Это снабжено в двоичной форме и в полной исходной форме с файлом проекта Microsoft Visual C++.

Хотя не принудительно, что приложение использует любой из этих компонентов, принимается, что большинство приложений будет хотеть использовать AcGix

библиотеку и что существенное число их будет хотеть использовать или приспособить код SimpleView. WhipView

библиотечный Autodesk использований частная технология дисплейного файла, чтобы обеспечить уровень “перегенерально - свободного” панорамирования и изменения масштаба изображения.



Контекст примитива и координатное преобразовывание данных


AcedNEntSelP () функция подобна acedEntSel (), за исключением того, что это передает два дополнительных параметра результата, чтобы облегчить обработку примитивов, которые вложены в пределах блок-ссылок.

ОБРАТИТЕ ВНИМАНИЕ На другое различие между acedNEntSelP () и acedEntSel () - то, что, когда пользователь отвечает на acedNEntSelP () запрос,  выбирая сложный примитив, acedNEntSelP () возвращает выбранный подпримитив а не, заголовок сложного примитива как acedEntSel () делает. Например, когда пользователь выбирает ломаную линию, acedNEntSelP () возвращает подпримитив вершины вместо заголовка ломаной линии. Чтобы восстановить{*отыскивать*} заголовок ломаной линии, приложение должно использовать acdbEntNext () чтобы идти вперед к Seqend подпримитиву и получать имя заголовка от -2 группы Seqend подпримитива. Это истинно также, когда пользователь выбирает атрибуты во вложенной блок-ссылке и когда точка указки определена в acedNEntSelP () запрос.

Координатное Преобразование

Первый из дополнительных параметров, возвращенных acedNEntSelP () - 4x4 матрица преобразования типа ads_matrix. Эта матрица известна как Модель к Мировой Матрице преобразования. Это дает возможность приложению преобразовать точки в данные определения примитива (и расширенные{*продленные*} данные, если это присутствует) от образцовой системы координат примитива (MCS) в Мировую систему координат (WCS). MCS применяется{*обращается*} только к вложенным примитивам. Начало координат MCS - точка вставки блока, и его ориентация - таковой ВЕРХНИХ РЕГИСТРОВ, который был в действительности, когда блок был создан.

Если выбранный примитив - не,  вложенный примитив, матрица преобразования установлен в единичную матрицу. Преобразование выражено следующим матричным умножением:

Индивидуальные координаты преобразованной точки получены от уравнений, где М. mn - Модель к Мировой Матрице преобразования, координирует, (X, Y, Z) - точка данных определения примитива, выраженная в координатах MCS, и (X ’, Y ’, Z ’) - заканчивающаяся точка данных определения примитива, выраженная в координатах WCS. См. “ Матрицы Преобразования ” на странице 535.


ПРИМЕЧАНИЕ, чтобы преобразовать вектор скорее чем точка, не добавьте вектор сдвига [М. 03 М. 13 М. 23] (от четвертого столбца матрицы преобразования).

Следующий типовой код определяет функцию, mcs2wcs (), который исполняет преобразования, описанные предшествующими уравнениями. Требуется матрица преобразования, возвращенная acedNEntSelP () и одиночной точкой (возможно от данных определения вложенного примитива), и возвращает оттранслированную точку.

Если третий параметр к mcs2wcs (), is_pt, установлен в 0 (ЛЖИ), последний{*прошлый*} столбец матрицы преобразования — вектор сдвига, или смещение — не добавлено к результату. Это дает возможность функции транслировать вектор также как точку.

 

X ’

М00 М01 М02 М03

X

Y ’

=

М10 М11 М12 М13

x

Y

Z ’

М20 М21 М22 М23

Z

1.0

  0.0   0.0   0.0   1.0

 

1.0

 

X ' = М. 00 X + М. 01 Y + М. 02 Z + М. 03

Y ' = М. 10 X + М. 11 Y + М. 12 Z + М. 13

Z ' = М. 20 X + М. 21 Y + М. 22 Z + М. 23.

Индивидуальные координаты преобразованной точки получены от уравнений, где М. mn - Модель к Мировой Матрице преобразования, координирует, (X, Y, Z) - точка данных определения примитива, выраженная в координатах MCS, и (X ’, Y ’, Z ’) - заканчивающаяся точка данных определения примитива, выраженная в координатах WCS. См. “ Матрицы Преобразования ” на странице 535.

ПРИМЕЧАНИЕ, чтобы преобразовать вектор скорее чем точка, не добавьте вектор сдвига [М. 03 М. 13 М. 23] (от четвертого столбца матрицы преобразования).

Следующий типовой код определяет функцию, mcs2wcs (), который исполняет преобразования, описанные предшествующими уравнениями. Требуется матрица преобразования, возвращенная acedNEntSelP () и одиночной точкой (возможно от данных определения вложенного примитива), и возвращает оттранслированную точку.

Если третий параметр к mcs2wcs (), is_pt, установлен в 0 (ЛЖИ), последний столбец матрицы преобразования — вектор сдвига, или смещение — не добавлено к результату. Это дает возможность функции транслировать вектор также как точку.



void mcs2wcs(xform, entpt, is_pt, worldpt)

ads_matrix xform;

ads_point entpt, worldpt;

int is_pt;

{

int i, j;

worldpt[X] = worldpt[Y] = worldpt[Z] = 0.0;

for (i=X; i<=Z; i++)

for (j=X; j<=Z; j++)

worldpt[i] += xform[i][j] * entpt[j];

if (is_pt) // If it’s a point, add in the displacement

for (i=X; i<=Z; i++)

worldpt[i] += xform[i][T];

}

Следующий кодовый фрагмент показывает, как mcs2wcs () мог бы использоваться в конъюнкции с acedNEntSelP () чтобы транслировать значения точки в поток WCS.

ads_name usrent, containent;

ads_point usrpt, defpt, wcspt;

ads_matrix matrix;

struct resbuf *containers, *data, *rb, *prevrb;

status = acedNEntSelP(NULL, usrent, usrpt, FALSE, matrix,

&containers);

if ((status != RTNORM) || (containers == NULL))

return BAD;

data = acdbEntGet(usrent);

// Extract a point (defpt) from the data obtained by calling

// acdbEntGet() for the selected kind of entity.

.

.

.

mcs2wcs(matrix, defpt, TRUE, wcspt);

AcedNEntSelP () функция также позволяет программе определять точку указки. Pickflag параметр определяет, действительно ли acedNEntSelP () называется в интерактивном режиме.

В следующем примере, acedNEntSelP () запрос определяет его собственную точку для выбора примитива и не запрашивает пользователя. Pickflag параметр ИСТИНЕН, чтобы указать, что запрос поставляет{*снабжает*} его собственному значению точки (также, подсказка - NULL).

ads_point ownpoint;

ownpoint[X] = 2.7; ownpoint[Y] = 1.5; ownpoint[Z] = 0.0;

status = acedNEntSelP(NULL, usrent, ownpt, TRUE, matrix, &containers);

AcedNEntSel () функция обеспечивается для совместимости с существующими ObjectARX-приложениями. Новые приложения должны быть написаны, используя acedNEntSelP ().

Модель к Мировой Матрице преобразования, возвращенной запросом к acedNEntSel () имеет ту же самую цель как возвращенное acedNEntSelP (), но это - 4x3, матрица — прошла как массив четырех точек —, который использует соглашение, что точка - строка скорее чем столбец. Преобразование описано следующим матричным умножением:



М00 М01 М02 М03

X' Y' Z' 1.0    =   X Y Z 1.0    x  

М10 М11 М12 М13

М20 М21 М22 М23

  0.0   0.0   0.0   1.0

Хотя матричный формат различен, формулы эквивалентны, те для типа ads_matrix, и единственного изменения{*замены*}, требуемого, чтобы приспособить mcs2wcs () для использования с acedNEntSel () должны объявить матричный параметр как массив четырех точек.

void mcs2wcs(xform, entpt, is_pt, worldpt);

ads_point xform[4]; // 4x3 version

ads_point entpt, worldpt;

int is_pt;

Форма тождества 4x3 матрица следующие:

1 0 0

0 1 0

0 0 1

0 0 0

В дополнение к использованию различного матричного соглашения, acedNEntSel () не позволяет программе определять точку указки.

Контекстные Данные

Функция acedNEntSelP () обеспечивает параметр для контекстных данных, refstkres. (Это - другая особенность, не обеспеченная acedEntSel ()). Refstkres параметр - указатель на список связей буферов результатов, который содержит названия{*имена*} контейнерных блоков примитива. Список заказывается{*упорядочивает*} от самого низкого до самого высокого. Другими словами, имя в списке - имя блока, содержащего выбранный примитив, и фамилия в списке - имя блока, который был непосредственно вставлен в рисунок. Следующий рисунок показывает формат этого списка.



Если выбранный примитив entres - не,  вложенный примитив, refstkres - указатель NULL. Это - удобный способ проверить, действительно ли координаты примитива должны быть оттранслированы. (Поскольку xformres возвращен как единичная матрица для примитивов, которые не вложены, применяя это к координатам таких примитивов не никакой вред, но стоит некоторое бесполезное время выполнения.)

Используя объявления от предыдущего acedNEntSelP () пример, имя блока, который немедленно содержит выбранный пользователем примитив, может быть найден следующим кодом (в acedNEntSelP () запрос, pickflag параметр - FALSE для интерактивного выбора).



status = acedNEntSelP(NULL, usrent, usrpt, FALSE, matrix,

&containers);

if ((status != RTNORM) || (containers == NULL))

return BAD;

containent[0] = containers->resval.rlname[0];

containent[1] = containers->resval.rlname[1];

Имя наиболее удаленного контейнера ( то есть примитив, первоначально вставленный в рисунок) может быть найдено последовательностью типа следующего:

// Проверить это, контейнеры не уже NULL.

rb = containers;

while (rb != NULL) {

prevrb = rb;

rb = containers->rbnext;

}

// Буфер результатов, указанный prevrb теперь содержит имя наиболее удаленного блока.

В следующем примере, текущая система координат - WCS. Использование AutoCAD, создайте блок по имени КВАДРАТ, состоящий из четырех линий.

Command: line

From point: 1,1

To point: 3,1

To point: 3,3

To point: 1,3

To point: c

Command: block

Block name (or ?): square

Insertion base point: 2,2

Select objects: Select the four lines you just drew

Select objects: ENTER

Тогда вставьте блок в UCS, вращал 45 градусов относительно Z оси.

Command: ucs

Origin/ZAxis/3point/Entity/View/X/Y/Z/Prev/Restore/Save/Del/?/

<World>: z

Rotation angle about Z axis <0>: 45

Command: insert

Block name (or ?): square

Insertion point: 7,0

X scale factor <1> / Corner / XYZ: ENTER

Y scale factor (default=X): ENTER

Rotation angle: ENTER

Если ObjectARX-приложение вызывает acedNEntSelP () (или acedNEntSel ()) и

пользователь выбирает левую нижнюю сторону квадрата, эти функции заставляют entres параметр равняться имени выбранной линии. Они устанавливают точку указки (ptres) в (6.46616, -1.0606,0.0) или близлежащее значение точки. Они возвращают матрицу преобразования (xformres) как показано в следующем рисунке.

Наконец, они заставляют список контейнерных примитивов (refstkres) направлять на одиночный буфер результатов содержащий имени примитива блока SQUARE.

0.707107

-0.707107

0.0

4.94975

0.707107

0.707107

0.0

0.707107

0.707107

-0.0

4.94975

-0.707107

0.707107

0.0

0.0

0.0

1.0

0.0

0.0

-0.0

1.0

0.0

0.0

0.0

1.0

4.94975

4.94975

0.0

ads_nentselp() result                                                 ads_nentsel() result


Контекст выполнения приложения


Состояние команды, которое является активным когда новый Windows сообщения ожидают.

Это независимо от всех контекстов выполнения документа. Следующие типы команд выполняются от этого контекста:

§

Внешние ActiveX запросы Автоматизации (типа Visual Basic)

§         VBA

§         диалоговые окна Modeless

Эти типы команд типично работают на активном документе, хотя они не связаны, чтобы делать так. Намерение состоит в том, чтобы обработать документ блокировка и разблокирование разумно очевидно для внешних приложений ActiveX и VBA. Однако, ObjectARX-приложения, переносящие немодальные диалоги будут требоваться, чтобы блокировать и разблокировать документы, явно чтобы взаимодействовать с их базами данных.